From 9c333ade1a1b694fc6ce22e483f5de3e952c17ad Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 22 May 2017 17:50:30 +0200 Subject: move everying into sources/shiboken2 (5.9 edition) in preparation for a subtree merge. this should not be necessary to do in a separate commit, but git is a tad stupid about following history correctly without it. --- .gitattributes | 2 - .gitignore | 8 - AUTHORS | 12 - ApiExtractor/AUTHORS | 8 - ApiExtractor/CMakeLists.txt | 90 - ApiExtractor/COPYING | 342 -- ApiExtractor/abstractmetabuilder.cpp | 3459 ------------ ApiExtractor/abstractmetabuilder.h | 106 - ApiExtractor/abstractmetabuilder_p.h | 194 - ApiExtractor/abstractmetalang.cpp | 2784 ---------- ApiExtractor/abstractmetalang.h | 1976 ------- ApiExtractor/abstractmetalang_typedefs.h | 50 - ApiExtractor/apiextractor.cpp | 317 -- ApiExtractor/apiextractor.h | 111 - ApiExtractor/apiextractormacros.h | 41 - ApiExtractor/clangparser/clangbuilder.cpp | 770 --- ApiExtractor/clangparser/clangbuilder.h | 58 - ApiExtractor/clangparser/clangdebugutils.cpp | 150 - ApiExtractor/clangparser/clangdebugutils.h | 48 - ApiExtractor/clangparser/clangparser.cpp | 266 - ApiExtractor/clangparser/clangparser.h | 93 - ApiExtractor/clangparser/clangutils.cpp | 227 - ApiExtractor/clangparser/clangutils.h | 101 - ApiExtractor/clangparser/compilersupport.cpp | 155 - ApiExtractor/clangparser/compilersupport.h | 40 - ApiExtractor/cmake_uninstall.cmake | 21 - ApiExtractor/dependency.h | 43 - ApiExtractor/doc/CMakeLists.txt | 10 - ApiExtractor/doc/_templates/index.html | 27 - ApiExtractor/doc/_templates/layout.html | 41 - ApiExtractor/doc/_themes/pysidedocs/searchbox.html | 12 - .../doc/_themes/pysidedocs/static/bg_header.png | Bin 36012 -> 0 bytes .../doc/_themes/pysidedocs/static/bg_topo.jpg | Bin 14237 -> 0 bytes .../doc/_themes/pysidedocs/static/fakebar.png | Bin 101 -> 0 bytes .../doc/_themes/pysidedocs/static/logo_indt.jpg | Bin 3138 -> 0 bytes .../_themes/pysidedocs/static/logo_openbossa.png | Bin 4702 -> 0 bytes .../doc/_themes/pysidedocs/static/logo_python.jpg | Bin 2660 -> 0 bytes .../doc/_themes/pysidedocs/static/logo_qt.png | Bin 4618 -> 0 bytes .../doc/_themes/pysidedocs/static/pysidedocs.css | 409 -- .../doc/_themes/pysidedocs/static/pysidelogo.png | Bin 12969 -> 0 bytes .../doc/_themes/pysidedocs/static/relbar_bg.png | Bin 130 -> 0 bytes ApiExtractor/doc/_themes/pysidedocs/theme.conf | 7 - ApiExtractor/doc/conf.py.in | 163 - ApiExtractor/doc/contents.rst | 9 - ApiExtractor/doc/dependency-apiextractor.svg | 360 -- ApiExtractor/doc/overview.rst | 15 - ApiExtractor/doc/ownership.rst | 85 - ApiExtractor/doc/typesystem.rst | 29 - ApiExtractor/doc/typesystem_arguments.rst | 192 - ApiExtractor/doc/typesystem_conversionrule.rst | 113 - ApiExtractor/doc/typesystem_documentation.rst | 43 - .../doc/typesystem_manipulating_objects.rst | 132 - ApiExtractor/doc/typesystem_modify_function.rst | 78 - .../doc/typesystem_solving_compilation.rst | 70 - ApiExtractor/doc/typesystem_specifying_types.rst | 371 -- ApiExtractor/doc/typesystem_templates.rst | 55 - ApiExtractor/docparser.cpp | 174 - ApiExtractor/docparser.h | 127 - ApiExtractor/doxygenparser.cpp | 198 - ApiExtractor/doxygenparser.h | 43 - ApiExtractor/fileout.cpp | 231 - ApiExtractor/fileout.h | 62 - ApiExtractor/graph.cpp | 135 - ApiExtractor/graph.h | 72 - ApiExtractor/header_paths.h | 62 - ApiExtractor/icecc.cmake | 11 - ApiExtractor/include.cpp | 71 - ApiExtractor/include.h | 92 - ApiExtractor/merge.xsl | 82 - ApiExtractor/parser/codemodel.cpp | 1207 ---- ApiExtractor/parser/codemodel.h | 687 --- ApiExtractor/parser/codemodel_enums.h | 38 - ApiExtractor/parser/codemodel_fwd.h | 82 - ApiExtractor/qtdocparser.cpp | 189 - ApiExtractor/qtdocparser.h | 44 - ApiExtractor/reporthandler.cpp | 149 - ApiExtractor/reporthandler.h | 71 - ApiExtractor/symbols.filter | 7 - ApiExtractor/tests/CMakeLists.txt | 74 - ApiExtractor/tests/a.xml | 13 - ApiExtractor/tests/testabstractmetaclass.cpp | 527 -- ApiExtractor/tests/testabstractmetaclass.h | 55 - ApiExtractor/tests/testabstractmetatype.cpp | 216 - ApiExtractor/tests/testabstractmetatype.h | 47 - ApiExtractor/tests/testaddfunction.cpp | 453 -- ApiExtractor/tests/testaddfunction.h | 54 - ApiExtractor/tests/testarrayargument.cpp | 130 - ApiExtractor/tests/testarrayargument.h | 42 - ApiExtractor/tests/testcodeinjection.cpp | 106 - ApiExtractor/tests/testcodeinjection.h | 45 - ApiExtractor/tests/testcontainer.cpp | 105 - ApiExtractor/tests/testcontainer.h | 41 - ApiExtractor/tests/testconversionoperator.cpp | 188 - ApiExtractor/tests/testconversionoperator.h | 44 - ApiExtractor/tests/testconversionruletag.cpp | 250 - ApiExtractor/tests/testconversionruletag.h | 43 - ApiExtractor/tests/testctorinformation.cpp | 76 - ApiExtractor/tests/testctorinformation.h | 44 - ApiExtractor/tests/testdroptypeentries.cpp | 145 - ApiExtractor/tests/testdroptypeentries.h | 44 - ApiExtractor/tests/testdtorinformation.cpp | 86 - ApiExtractor/tests/testdtorinformation.h | 46 - ApiExtractor/tests/testenum.cpp | 416 -- ApiExtractor/tests/testenum.h | 47 - ApiExtractor/tests/testextrainclude.cpp | 85 - ApiExtractor/tests/testextrainclude.h | 42 - ApiExtractor/tests/testfunctiontag.cpp | 97 - ApiExtractor/tests/testfunctiontag.h | 42 - ApiExtractor/tests/testimplicitconversions.cpp | 163 - ApiExtractor/tests/testimplicitconversions.h | 46 - ApiExtractor/tests/testinserttemplate.cpp | 130 - ApiExtractor/tests/testinserttemplate.h | 44 - ApiExtractor/tests/testmodifydocumentation.cpp | 80 - ApiExtractor/tests/testmodifydocumentation.h | 41 - ApiExtractor/tests/testmodifyfunction.cpp | 249 - ApiExtractor/tests/testmodifyfunction.h | 45 - ApiExtractor/tests/testmultipleinheritance.cpp | 75 - ApiExtractor/tests/testmultipleinheritance.h | 43 - ApiExtractor/tests/testnamespace.cpp | 96 - ApiExtractor/tests/testnamespace.h | 44 - ApiExtractor/tests/testnestedtypes.cpp | 128 - ApiExtractor/tests/testnestedtypes.h | 41 - ApiExtractor/tests/testnumericaltypedef.cpp | 119 - ApiExtractor/tests/testnumericaltypedef.h | 42 - ApiExtractor/tests/testprimitivetypetag.cpp | 60 - ApiExtractor/tests/testprimitivetypetag.h | 41 - ApiExtractor/tests/testrefcounttag.cpp | 100 - ApiExtractor/tests/testrefcounttag.h | 42 - ApiExtractor/tests/testreferencetopointer.cpp | 59 - ApiExtractor/tests/testreferencetopointer.h | 41 - ApiExtractor/tests/testremovefield.cpp | 62 - ApiExtractor/tests/testremovefield.h | 41 - ApiExtractor/tests/testremoveimplconv.cpp | 69 - ApiExtractor/tests/testremoveimplconv.h | 41 - ApiExtractor/tests/testremoveoperatormethod.cpp | 117 - ApiExtractor/tests/testremoveoperatormethod.h | 41 - ApiExtractor/tests/testresolvetype.cpp | 64 - ApiExtractor/tests/testresolvetype.h | 41 - ApiExtractor/tests/testreverseoperators.cpp | 139 - ApiExtractor/tests/testreverseoperators.h | 41 - ApiExtractor/tests/testtemplates.cpp | 439 -- ApiExtractor/tests/testtemplates.h | 51 - ApiExtractor/tests/testtoposort.cpp | 69 - ApiExtractor/tests/testtoposort.h | 42 - ApiExtractor/tests/testtyperevision.cpp | 71 - ApiExtractor/tests/testtyperevision.h | 42 - ApiExtractor/tests/testutil.h | 78 - ApiExtractor/tests/testvaluetypedefaultctortag.cpp | 64 - ApiExtractor/tests/testvaluetypedefaultctortag.h | 41 - ApiExtractor/tests/testvoidarg.cpp | 87 - ApiExtractor/tests/testvoidarg.h | 42 - ApiExtractor/tests/utf8code.txt | 1 - ApiExtractor/typedatabase.cpp | 745 --- ApiExtractor/typedatabase.h | 186 - ApiExtractor/typedatabase_typedefs.h | 49 - ApiExtractor/typeparser.cpp | 318 -- ApiExtractor/typeparser.h | 60 - ApiExtractor/typesystem.cpp | 2737 ---------- ApiExtractor/typesystem.h | 1975 ------- ApiExtractor/typesystem_enums.h | 86 - ApiExtractor/typesystem_p.h | 176 - ApiExtractor/typesystem_typedefs.h | 49 - CMakeLists.txt | 285 - COPYING | 342 -- COPYING.libsample | 501 -- COPYING.libshiboken | 501 -- Doxyfile | 311 -- LICENSE.GPLv3 | 686 --- LICENSE.LGPLv21 | 514 -- LICENSE.LGPLv3 | 175 - LICENSE.PREVIEW.COMMERCIAL | 630 --- README.md | 19 - cmake_uninstall.cmake | 21 - data/CMakeLists.txt | 28 - data/GeneratorRunnerConfig.cmake.in | 17 - data/GeneratorRunnerConfigVersion.cmake.in | 10 - data/Shiboken2Config-spec.cmake.in | 29 - data/Shiboken2Config.cmake.in | 5 - data/Shiboken2ConfigVersion.cmake.in | 10 - data/docgenerator.1 | 1 - data/generatorrunner.1 | 76 - data/generatorrunner.pc.in | 13 - data/shiboken2.pc.in | 13 - doc/CMakeLists.txt | 24 - doc/_templates/index.html | 35 - doc/_templates/layout.html | 29 - doc/_themes/pysidedocs/searchbox.html | 12 - doc/_themes/pysidedocs/static/bg_header.png | Bin 36012 -> 0 bytes doc/_themes/pysidedocs/static/bg_topo.jpg | Bin 14237 -> 0 bytes doc/_themes/pysidedocs/static/fakebar.png | Bin 101 -> 0 bytes doc/_themes/pysidedocs/static/logo_python.jpg | Bin 2660 -> 0 bytes doc/_themes/pysidedocs/static/logo_qt.png | Bin 1032 -> 0 bytes doc/_themes/pysidedocs/static/pysidedocs.css | 475 -- doc/_themes/pysidedocs/static/pysidelogo.png | Bin 12969 -> 0 bytes doc/_themes/pysidedocs/static/relbar_bg.png | Bin 130 -> 0 bytes doc/_themes/pysidedocs/theme.conf | 7 - doc/codeinjectionsemantics.rst | 397 -- doc/commandlineoptions.rst | 105 - doc/conf.py.in | 166 - doc/contents.rst | 17 - doc/dependency-pyqtb.svg | 600 -- doc/dependency-pyside.svg | 527 -- doc/faq.rst | 67 - doc/images/.directory | 3 - doc/images/bindinggen-development.png | Bin 34333 -> 0 bytes doc/images/bindinggen-development.svg | 543 -- doc/images/boostgen.png | Bin 153473 -> 0 bytes doc/images/boostqtarch.png | Bin 34257 -> 0 bytes doc/images/boostqtarch.svg | 226 - doc/images/converter.dot | 14 - doc/images/converter.png | Bin 37485 -> 0 bytes doc/images/genrunnerarch.png | Bin 68761 -> 0 bytes doc/images/genrunnerarch.svg | 654 --- doc/overview.rst | 46 - doc/ownership.rst | 153 - doc/projectfile.rst | 65 - doc/sequenceprotocol.rst | 23 - doc/shiboken2.1 | 73 - doc/shibokenmodule.rst | 79 - doc/typeconverters.rst | 288 - doc/typesystemvariables.rst | 336 -- doc/wordsofadvice.rst | 109 - generator/CMakeLists.txt | 40 - generator/generator.cpp | 864 --- generator/generator.h | 448 -- generator/main.cpp | 552 -- generator/qtdoc/CMakeLists.txt | 21 - generator/qtdoc/qtdocgenerator.cpp | 1715 ------ generator/qtdoc/qtdocgenerator.h | 235 - generator/shiboken2/CMakeLists.txt | 28 - generator/shiboken2/cppgenerator.cpp | 5755 -------------------- generator/shiboken2/cppgenerator.h | 370 -- generator/shiboken2/headergenerator.cpp | 569 -- generator/shiboken2/headergenerator.h | 67 - generator/shiboken2/overloaddata.cpp | 1092 ---- generator/shiboken2/overloaddata.h | 163 - generator/shiboken2/shibokengenerator.cpp | 2728 ---------- generator/shiboken2/shibokengenerator.h | 556 -- generator/shibokenconfig.h.in | 6 - generatorrunnerconfig.h.in | 13 - generatorrunnermacros.h | 48 - generators/shiboken/shiboken.cpp | 32 - header.COMM | 20 - header.LGPL-ONLY | 22 - header.LGPL21 | 33 - header.LGPL3 | 36 - header.LGPL3-COMM | 28 - icecc.cmake | 11 - libshiboken/CMakeLists.txt | 69 - libshiboken/autodecref.h | 115 - libshiboken/basewrapper.cpp | 1516 ------ libshiboken/basewrapper.h | 451 -- libshiboken/basewrapper_p.h | 287 - libshiboken/bindingmanager.cpp | 341 -- libshiboken/bindingmanager.h | 109 - libshiboken/conversions.h | 731 --- libshiboken/debugfreehook.cpp | 194 - libshiboken/debugfreehook.h | 61 - libshiboken/gilstate.cpp | 68 - libshiboken/gilstate.h | 63 - libshiboken/helper.cpp | 142 - libshiboken/helper.h | 136 - libshiboken/python25compat.h | 104 - libshiboken/sbkconverter.cpp | 571 -- libshiboken/sbkconverter.h | 367 -- libshiboken/sbkconverter_p.h | 574 -- libshiboken/sbkdbg.h | 124 - libshiboken/sbkenum.cpp | 618 --- libshiboken/sbkenum.h | 118 - libshiboken/sbkmodule.cpp | 111 - libshiboken/sbkmodule.h | 115 - libshiboken/sbkpython.h | 74 - libshiboken/sbkstring.cpp | 202 - libshiboken/sbkstring.h | 75 - libshiboken/sbkversion.h.in | 50 - libshiboken/shiboken.h | 60 - libshiboken/shibokenbuffer.cpp | 96 - libshiboken/shibokenbuffer.h | 85 - libshiboken/shibokenmacros.h | 63 - libshiboken/threadstatesaver.cpp | 69 - libshiboken/threadstatesaver.h | 66 - libshiboken/tmp-referencetopython/sbkconverter.cpp | 213 - libshiboken/tmp-referencetopython/sbkconverter.h | 191 - libshiboken/typeresolver.cpp | 160 - libshiboken/typeresolver.h | 139 - shibokenmodule/CMakeLists.txt | 40 - shibokenmodule/nothing.h | 0 shibokenmodule/shibokenmodule.txt.in | 16 - shibokenmodule/typesystem_shiboken.xml | 120 - sources/shiboken2/.gitattributes | 2 + sources/shiboken2/.gitignore | 8 + sources/shiboken2/AUTHORS | 12 + sources/shiboken2/ApiExtractor/AUTHORS | 8 + sources/shiboken2/ApiExtractor/CMakeLists.txt | 90 + sources/shiboken2/ApiExtractor/COPYING | 342 ++ .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 3459 ++++++++++++ .../shiboken2/ApiExtractor/abstractmetabuilder.h | 106 + .../shiboken2/ApiExtractor/abstractmetabuilder_p.h | 194 + .../shiboken2/ApiExtractor/abstractmetalang.cpp | 2784 ++++++++++ sources/shiboken2/ApiExtractor/abstractmetalang.h | 1976 +++++++ .../ApiExtractor/abstractmetalang_typedefs.h | 50 + sources/shiboken2/ApiExtractor/apiextractor.cpp | 317 ++ sources/shiboken2/ApiExtractor/apiextractor.h | 111 + .../shiboken2/ApiExtractor/apiextractormacros.h | 41 + .../ApiExtractor/clangparser/clangbuilder.cpp | 770 +++ .../ApiExtractor/clangparser/clangbuilder.h | 58 + .../ApiExtractor/clangparser/clangdebugutils.cpp | 150 + .../ApiExtractor/clangparser/clangdebugutils.h | 48 + .../ApiExtractor/clangparser/clangparser.cpp | 266 + .../ApiExtractor/clangparser/clangparser.h | 93 + .../ApiExtractor/clangparser/clangutils.cpp | 227 + .../ApiExtractor/clangparser/clangutils.h | 101 + .../ApiExtractor/clangparser/compilersupport.cpp | 155 + .../ApiExtractor/clangparser/compilersupport.h | 40 + .../shiboken2/ApiExtractor/cmake_uninstall.cmake | 21 + sources/shiboken2/ApiExtractor/dependency.h | 43 + sources/shiboken2/ApiExtractor/doc/CMakeLists.txt | 10 + .../ApiExtractor/doc/_templates/index.html | 27 + .../ApiExtractor/doc/_templates/layout.html | 41 + .../doc/_themes/pysidedocs/searchbox.html | 12 + .../doc/_themes/pysidedocs/static/bg_header.png | Bin 0 -> 36012 bytes .../doc/_themes/pysidedocs/static/bg_topo.jpg | Bin 0 -> 14237 bytes .../doc/_themes/pysidedocs/static/fakebar.png | Bin 0 -> 101 bytes .../doc/_themes/pysidedocs/static/logo_indt.jpg | Bin 0 -> 3138 bytes .../_themes/pysidedocs/static/logo_openbossa.png | Bin 0 -> 4702 bytes .../doc/_themes/pysidedocs/static/logo_python.jpg | Bin 0 -> 2660 bytes .../doc/_themes/pysidedocs/static/logo_qt.png | Bin 0 -> 4618 bytes .../doc/_themes/pysidedocs/static/pysidedocs.css | 409 ++ .../doc/_themes/pysidedocs/static/pysidelogo.png | Bin 0 -> 12969 bytes .../doc/_themes/pysidedocs/static/relbar_bg.png | Bin 0 -> 130 bytes .../ApiExtractor/doc/_themes/pysidedocs/theme.conf | 7 + sources/shiboken2/ApiExtractor/doc/conf.py.in | 163 + sources/shiboken2/ApiExtractor/doc/contents.rst | 9 + .../ApiExtractor/doc/dependency-apiextractor.svg | 360 ++ sources/shiboken2/ApiExtractor/doc/overview.rst | 15 + sources/shiboken2/ApiExtractor/doc/ownership.rst | 85 + sources/shiboken2/ApiExtractor/doc/typesystem.rst | 29 + .../ApiExtractor/doc/typesystem_arguments.rst | 192 + .../ApiExtractor/doc/typesystem_conversionrule.rst | 113 + .../ApiExtractor/doc/typesystem_documentation.rst | 43 + .../doc/typesystem_manipulating_objects.rst | 132 + .../doc/typesystem_modify_function.rst | 78 + .../doc/typesystem_solving_compilation.rst | 70 + .../doc/typesystem_specifying_types.rst | 371 ++ .../ApiExtractor/doc/typesystem_templates.rst | 55 + sources/shiboken2/ApiExtractor/docparser.cpp | 174 + sources/shiboken2/ApiExtractor/docparser.h | 127 + sources/shiboken2/ApiExtractor/doxygenparser.cpp | 198 + sources/shiboken2/ApiExtractor/doxygenparser.h | 43 + sources/shiboken2/ApiExtractor/fileout.cpp | 231 + sources/shiboken2/ApiExtractor/fileout.h | 62 + sources/shiboken2/ApiExtractor/graph.cpp | 135 + sources/shiboken2/ApiExtractor/graph.h | 72 + sources/shiboken2/ApiExtractor/header_paths.h | 62 + sources/shiboken2/ApiExtractor/icecc.cmake | 11 + sources/shiboken2/ApiExtractor/include.cpp | 71 + sources/shiboken2/ApiExtractor/include.h | 92 + sources/shiboken2/ApiExtractor/merge.xsl | 82 + .../shiboken2/ApiExtractor/parser/codemodel.cpp | 1207 ++++ sources/shiboken2/ApiExtractor/parser/codemodel.h | 687 +++ .../ApiExtractor/parser/codemodel_enums.h | 38 + .../shiboken2/ApiExtractor/parser/codemodel_fwd.h | 82 + sources/shiboken2/ApiExtractor/qtdocparser.cpp | 189 + sources/shiboken2/ApiExtractor/qtdocparser.h | 44 + sources/shiboken2/ApiExtractor/reporthandler.cpp | 149 + sources/shiboken2/ApiExtractor/reporthandler.h | 71 + sources/shiboken2/ApiExtractor/symbols.filter | 7 + .../shiboken2/ApiExtractor/tests/CMakeLists.txt | 74 + sources/shiboken2/ApiExtractor/tests/a.xml | 13 + .../ApiExtractor/tests/testabstractmetaclass.cpp | 527 ++ .../ApiExtractor/tests/testabstractmetaclass.h | 55 + .../ApiExtractor/tests/testabstractmetatype.cpp | 216 + .../ApiExtractor/tests/testabstractmetatype.h | 47 + .../ApiExtractor/tests/testaddfunction.cpp | 453 ++ .../shiboken2/ApiExtractor/tests/testaddfunction.h | 54 + .../ApiExtractor/tests/testarrayargument.cpp | 130 + .../ApiExtractor/tests/testarrayargument.h | 42 + .../ApiExtractor/tests/testcodeinjection.cpp | 106 + .../ApiExtractor/tests/testcodeinjection.h | 45 + .../shiboken2/ApiExtractor/tests/testcontainer.cpp | 105 + .../shiboken2/ApiExtractor/tests/testcontainer.h | 41 + .../ApiExtractor/tests/testconversionoperator.cpp | 188 + .../ApiExtractor/tests/testconversionoperator.h | 44 + .../ApiExtractor/tests/testconversionruletag.cpp | 250 + .../ApiExtractor/tests/testconversionruletag.h | 43 + .../ApiExtractor/tests/testctorinformation.cpp | 76 + .../ApiExtractor/tests/testctorinformation.h | 44 + .../ApiExtractor/tests/testdroptypeentries.cpp | 145 + .../ApiExtractor/tests/testdroptypeentries.h | 44 + .../ApiExtractor/tests/testdtorinformation.cpp | 86 + .../ApiExtractor/tests/testdtorinformation.h | 46 + sources/shiboken2/ApiExtractor/tests/testenum.cpp | 416 ++ sources/shiboken2/ApiExtractor/tests/testenum.h | 47 + .../ApiExtractor/tests/testextrainclude.cpp | 85 + .../ApiExtractor/tests/testextrainclude.h | 42 + .../ApiExtractor/tests/testfunctiontag.cpp | 97 + .../shiboken2/ApiExtractor/tests/testfunctiontag.h | 42 + .../ApiExtractor/tests/testimplicitconversions.cpp | 163 + .../ApiExtractor/tests/testimplicitconversions.h | 46 + .../ApiExtractor/tests/testinserttemplate.cpp | 130 + .../ApiExtractor/tests/testinserttemplate.h | 44 + .../ApiExtractor/tests/testmodifydocumentation.cpp | 80 + .../ApiExtractor/tests/testmodifydocumentation.h | 41 + .../ApiExtractor/tests/testmodifyfunction.cpp | 249 + .../ApiExtractor/tests/testmodifyfunction.h | 45 + .../ApiExtractor/tests/testmultipleinheritance.cpp | 75 + .../ApiExtractor/tests/testmultipleinheritance.h | 43 + .../shiboken2/ApiExtractor/tests/testnamespace.cpp | 96 + .../shiboken2/ApiExtractor/tests/testnamespace.h | 44 + .../ApiExtractor/tests/testnestedtypes.cpp | 128 + .../shiboken2/ApiExtractor/tests/testnestedtypes.h | 41 + .../ApiExtractor/tests/testnumericaltypedef.cpp | 119 + .../ApiExtractor/tests/testnumericaltypedef.h | 42 + .../ApiExtractor/tests/testprimitivetypetag.cpp | 60 + .../ApiExtractor/tests/testprimitivetypetag.h | 41 + .../ApiExtractor/tests/testrefcounttag.cpp | 100 + .../shiboken2/ApiExtractor/tests/testrefcounttag.h | 42 + .../ApiExtractor/tests/testreferencetopointer.cpp | 59 + .../ApiExtractor/tests/testreferencetopointer.h | 41 + .../ApiExtractor/tests/testremovefield.cpp | 62 + .../shiboken2/ApiExtractor/tests/testremovefield.h | 41 + .../ApiExtractor/tests/testremoveimplconv.cpp | 69 + .../ApiExtractor/tests/testremoveimplconv.h | 41 + .../tests/testremoveoperatormethod.cpp | 117 + .../ApiExtractor/tests/testremoveoperatormethod.h | 41 + .../ApiExtractor/tests/testresolvetype.cpp | 64 + .../shiboken2/ApiExtractor/tests/testresolvetype.h | 41 + .../ApiExtractor/tests/testreverseoperators.cpp | 139 + .../ApiExtractor/tests/testreverseoperators.h | 41 + .../shiboken2/ApiExtractor/tests/testtemplates.cpp | 439 ++ .../shiboken2/ApiExtractor/tests/testtemplates.h | 51 + .../shiboken2/ApiExtractor/tests/testtoposort.cpp | 69 + .../shiboken2/ApiExtractor/tests/testtoposort.h | 42 + .../ApiExtractor/tests/testtyperevision.cpp | 71 + .../ApiExtractor/tests/testtyperevision.h | 42 + sources/shiboken2/ApiExtractor/tests/testutil.h | 78 + .../tests/testvaluetypedefaultctortag.cpp | 64 + .../tests/testvaluetypedefaultctortag.h | 41 + .../shiboken2/ApiExtractor/tests/testvoidarg.cpp | 87 + sources/shiboken2/ApiExtractor/tests/testvoidarg.h | 42 + sources/shiboken2/ApiExtractor/tests/utf8code.txt | 1 + sources/shiboken2/ApiExtractor/typedatabase.cpp | 745 +++ sources/shiboken2/ApiExtractor/typedatabase.h | 186 + .../shiboken2/ApiExtractor/typedatabase_typedefs.h | 49 + sources/shiboken2/ApiExtractor/typeparser.cpp | 318 ++ sources/shiboken2/ApiExtractor/typeparser.h | 60 + sources/shiboken2/ApiExtractor/typesystem.cpp | 2737 ++++++++++ sources/shiboken2/ApiExtractor/typesystem.h | 1975 +++++++ sources/shiboken2/ApiExtractor/typesystem_enums.h | 86 + sources/shiboken2/ApiExtractor/typesystem_p.h | 176 + .../shiboken2/ApiExtractor/typesystem_typedefs.h | 49 + sources/shiboken2/CMakeLists.txt | 285 + sources/shiboken2/COPYING | 342 ++ sources/shiboken2/COPYING.libsample | 501 ++ sources/shiboken2/COPYING.libshiboken | 501 ++ sources/shiboken2/Doxyfile | 311 ++ sources/shiboken2/LICENSE.GPLv3 | 686 +++ sources/shiboken2/LICENSE.LGPLv21 | 514 ++ sources/shiboken2/LICENSE.LGPLv3 | 175 + sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL | 630 +++ sources/shiboken2/README.md | 19 + sources/shiboken2/cmake_uninstall.cmake | 21 + sources/shiboken2/data/CMakeLists.txt | 28 + .../shiboken2/data/GeneratorRunnerConfig.cmake.in | 17 + .../data/GeneratorRunnerConfigVersion.cmake.in | 10 + .../shiboken2/data/Shiboken2Config-spec.cmake.in | 29 + sources/shiboken2/data/Shiboken2Config.cmake.in | 5 + .../shiboken2/data/Shiboken2ConfigVersion.cmake.in | 10 + sources/shiboken2/data/docgenerator.1 | 1 + sources/shiboken2/data/generatorrunner.1 | 76 + sources/shiboken2/data/generatorrunner.pc.in | 13 + sources/shiboken2/data/shiboken2.pc.in | 13 + sources/shiboken2/doc/CMakeLists.txt | 24 + sources/shiboken2/doc/_templates/index.html | 35 + sources/shiboken2/doc/_templates/layout.html | 29 + .../doc/_themes/pysidedocs/searchbox.html | 12 + .../doc/_themes/pysidedocs/static/bg_header.png | Bin 0 -> 36012 bytes .../doc/_themes/pysidedocs/static/bg_topo.jpg | Bin 0 -> 14237 bytes .../doc/_themes/pysidedocs/static/fakebar.png | Bin 0 -> 101 bytes .../doc/_themes/pysidedocs/static/logo_python.jpg | Bin 0 -> 2660 bytes .../doc/_themes/pysidedocs/static/logo_qt.png | Bin 0 -> 1032 bytes .../doc/_themes/pysidedocs/static/pysidedocs.css | 475 ++ .../doc/_themes/pysidedocs/static/pysidelogo.png | Bin 0 -> 12969 bytes .../doc/_themes/pysidedocs/static/relbar_bg.png | Bin 0 -> 130 bytes .../shiboken2/doc/_themes/pysidedocs/theme.conf | 7 + sources/shiboken2/doc/codeinjectionsemantics.rst | 397 ++ sources/shiboken2/doc/commandlineoptions.rst | 105 + sources/shiboken2/doc/conf.py.in | 166 + sources/shiboken2/doc/contents.rst | 17 + sources/shiboken2/doc/dependency-pyqtb.svg | 600 ++ sources/shiboken2/doc/dependency-pyside.svg | 527 ++ sources/shiboken2/doc/faq.rst | 67 + sources/shiboken2/doc/images/.directory | 3 + .../doc/images/bindinggen-development.png | Bin 0 -> 34333 bytes .../doc/images/bindinggen-development.svg | 543 ++ sources/shiboken2/doc/images/boostgen.png | Bin 0 -> 153473 bytes sources/shiboken2/doc/images/boostqtarch.png | Bin 0 -> 34257 bytes sources/shiboken2/doc/images/boostqtarch.svg | 226 + sources/shiboken2/doc/images/converter.dot | 14 + sources/shiboken2/doc/images/converter.png | Bin 0 -> 37485 bytes sources/shiboken2/doc/images/genrunnerarch.png | Bin 0 -> 68761 bytes sources/shiboken2/doc/images/genrunnerarch.svg | 654 +++ sources/shiboken2/doc/overview.rst | 46 + sources/shiboken2/doc/ownership.rst | 153 + sources/shiboken2/doc/projectfile.rst | 65 + sources/shiboken2/doc/sequenceprotocol.rst | 23 + sources/shiboken2/doc/shiboken2.1 | 73 + sources/shiboken2/doc/shibokenmodule.rst | 79 + sources/shiboken2/doc/typeconverters.rst | 288 + sources/shiboken2/doc/typesystemvariables.rst | 336 ++ sources/shiboken2/doc/wordsofadvice.rst | 109 + sources/shiboken2/generator/CMakeLists.txt | 40 + sources/shiboken2/generator/generator.cpp | 864 +++ sources/shiboken2/generator/generator.h | 448 ++ sources/shiboken2/generator/main.cpp | 552 ++ sources/shiboken2/generator/qtdoc/CMakeLists.txt | 21 + .../shiboken2/generator/qtdoc/qtdocgenerator.cpp | 1715 ++++++ sources/shiboken2/generator/qtdoc/qtdocgenerator.h | 235 + .../shiboken2/generator/shiboken2/CMakeLists.txt | 28 + .../shiboken2/generator/shiboken2/cppgenerator.cpp | 5755 ++++++++++++++++++++ .../shiboken2/generator/shiboken2/cppgenerator.h | 370 ++ .../generator/shiboken2/headergenerator.cpp | 569 ++ .../generator/shiboken2/headergenerator.h | 67 + .../shiboken2/generator/shiboken2/overloaddata.cpp | 1092 ++++ .../shiboken2/generator/shiboken2/overloaddata.h | 163 + .../generator/shiboken2/shibokengenerator.cpp | 2728 ++++++++++ .../generator/shiboken2/shibokengenerator.h | 556 ++ sources/shiboken2/generator/shibokenconfig.h.in | 6 + sources/shiboken2/generatorrunnerconfig.h.in | 13 + sources/shiboken2/generatorrunnermacros.h | 48 + sources/shiboken2/generators/shiboken/shiboken.cpp | 32 + sources/shiboken2/header.COMM | 20 + sources/shiboken2/header.LGPL-ONLY | 22 + sources/shiboken2/header.LGPL21 | 33 + sources/shiboken2/header.LGPL3 | 36 + sources/shiboken2/header.LGPL3-COMM | 28 + sources/shiboken2/icecc.cmake | 11 + sources/shiboken2/libshiboken/CMakeLists.txt | 69 + sources/shiboken2/libshiboken/autodecref.h | 115 + sources/shiboken2/libshiboken/basewrapper.cpp | 1516 ++++++ sources/shiboken2/libshiboken/basewrapper.h | 451 ++ sources/shiboken2/libshiboken/basewrapper_p.h | 287 + sources/shiboken2/libshiboken/bindingmanager.cpp | 341 ++ sources/shiboken2/libshiboken/bindingmanager.h | 109 + sources/shiboken2/libshiboken/conversions.h | 731 +++ sources/shiboken2/libshiboken/debugfreehook.cpp | 194 + sources/shiboken2/libshiboken/debugfreehook.h | 61 + sources/shiboken2/libshiboken/gilstate.cpp | 68 + sources/shiboken2/libshiboken/gilstate.h | 63 + sources/shiboken2/libshiboken/helper.cpp | 142 + sources/shiboken2/libshiboken/helper.h | 136 + sources/shiboken2/libshiboken/python25compat.h | 104 + sources/shiboken2/libshiboken/sbkconverter.cpp | 571 ++ sources/shiboken2/libshiboken/sbkconverter.h | 367 ++ sources/shiboken2/libshiboken/sbkconverter_p.h | 574 ++ sources/shiboken2/libshiboken/sbkdbg.h | 124 + sources/shiboken2/libshiboken/sbkenum.cpp | 618 +++ sources/shiboken2/libshiboken/sbkenum.h | 118 + sources/shiboken2/libshiboken/sbkmodule.cpp | 111 + sources/shiboken2/libshiboken/sbkmodule.h | 115 + sources/shiboken2/libshiboken/sbkpython.h | 74 + sources/shiboken2/libshiboken/sbkstring.cpp | 202 + sources/shiboken2/libshiboken/sbkstring.h | 75 + sources/shiboken2/libshiboken/sbkversion.h.in | 50 + sources/shiboken2/libshiboken/shiboken.h | 60 + sources/shiboken2/libshiboken/shibokenbuffer.cpp | 96 + sources/shiboken2/libshiboken/shibokenbuffer.h | 85 + sources/shiboken2/libshiboken/shibokenmacros.h | 63 + sources/shiboken2/libshiboken/threadstatesaver.cpp | 69 + sources/shiboken2/libshiboken/threadstatesaver.h | 66 + .../tmp-referencetopython/sbkconverter.cpp | 213 + .../tmp-referencetopython/sbkconverter.h | 191 + sources/shiboken2/libshiboken/typeresolver.cpp | 160 + sources/shiboken2/libshiboken/typeresolver.h | 139 + sources/shiboken2/shibokenmodule/CMakeLists.txt | 40 + sources/shiboken2/shibokenmodule/nothing.h | 0 .../shiboken2/shibokenmodule/shibokenmodule.txt.in | 16 + .../shibokenmodule/typesystem_shiboken.xml | 120 + sources/shiboken2/tests/CMakeLists.txt | 102 + .../shiboken2/tests/dumpcodemodel/CMakeLists.txt | 5 + sources/shiboken2/tests/dumpcodemodel/main.cpp | 82 + sources/shiboken2/tests/libminimal/CMakeLists.txt | 13 + .../shiboken2/tests/libminimal/libminimalmacros.h | 46 + sources/shiboken2/tests/libminimal/listuser.cpp | 124 + sources/shiboken2/tests/libminimal/listuser.h | 75 + sources/shiboken2/tests/libminimal/minbool.h | 68 + sources/shiboken2/tests/libminimal/obj.cpp | 44 + sources/shiboken2/tests/libminimal/obj.h | 59 + sources/shiboken2/tests/libminimal/typedef.cpp | 75 + sources/shiboken2/tests/libminimal/typedef.h | 54 + sources/shiboken2/tests/libminimal/val.h | 59 + sources/shiboken2/tests/libother/CMakeLists.txt | 18 + .../tests/libother/extendsnoimplicitconversion.h | 45 + sources/shiboken2/tests/libother/libothermacros.h | 46 + sources/shiboken2/tests/libother/number.cpp | 59 + sources/shiboken2/tests/libother/number.h | 57 + sources/shiboken2/tests/libother/otherderived.cpp | 61 + sources/shiboken2/tests/libother/otherderived.h | 65 + .../tests/libother/othermultiplederived.cpp | 50 + .../tests/libother/othermultiplederived.h | 46 + .../shiboken2/tests/libother/otherobjecttype.cpp | 36 + sources/shiboken2/tests/libother/otherobjecttype.h | 49 + sources/shiboken2/tests/libsample/CMakeLists.txt | 57 + sources/shiboken2/tests/libsample/abstract.cpp | 97 + sources/shiboken2/tests/libsample/abstract.h | 107 + sources/shiboken2/tests/libsample/blackbox.cpp | 131 + sources/shiboken2/tests/libsample/blackbox.h | 67 + sources/shiboken2/tests/libsample/bucket.cpp | 86 + sources/shiboken2/tests/libsample/bucket.h | 59 + sources/shiboken2/tests/libsample/bytearray.cpp | 214 + sources/shiboken2/tests/libsample/bytearray.h | 89 + sources/shiboken2/tests/libsample/collector.cpp | 62 + sources/shiboken2/tests/libsample/collector.h | 71 + sources/shiboken2/tests/libsample/complex.cpp | 54 + sources/shiboken2/tests/libsample/complex.h | 55 + sources/shiboken2/tests/libsample/ctorconvrule.h | 45 + sources/shiboken2/tests/libsample/cvlist.h | 53 + sources/shiboken2/tests/libsample/derived.cpp | 119 + sources/shiboken2/tests/libsample/derived.h | 92 + sources/shiboken2/tests/libsample/echo.cpp | 29 + sources/shiboken2/tests/libsample/echo.h | 55 + sources/shiboken2/tests/libsample/expression.cpp | 137 + sources/shiboken2/tests/libsample/expression.h | 64 + sources/shiboken2/tests/libsample/filter.cpp | 73 + sources/shiboken2/tests/libsample/filter.h | 99 + sources/shiboken2/tests/libsample/functions.cpp | 214 + sources/shiboken2/tests/libsample/functions.h | 93 + sources/shiboken2/tests/libsample/handle.cpp | 44 + sources/shiboken2/tests/libsample/handle.h | 72 + sources/shiboken2/tests/libsample/implicitconv.cpp | 66 + sources/shiboken2/tests/libsample/implicitconv.h | 83 + sources/shiboken2/tests/libsample/injectcode.cpp | 108 + sources/shiboken2/tests/libsample/injectcode.h | 65 + .../shiboken2/tests/libsample/libsamplemacros.h | 46 + sources/shiboken2/tests/libsample/list.h | 106 + sources/shiboken2/tests/libsample/listuser.cpp | 91 + sources/shiboken2/tests/libsample/listuser.h | 74 + sources/shiboken2/tests/libsample/main.cpp | 244 + sources/shiboken2/tests/libsample/mapuser.cpp | 69 + sources/shiboken2/tests/libsample/mapuser.h | 65 + sources/shiboken2/tests/libsample/modelindex.h | 72 + .../shiboken2/tests/libsample/modifications.cpp | 151 + sources/shiboken2/tests/libsample/modifications.h | 142 + .../tests/libsample/modified_constructor.cpp | 42 + .../tests/libsample/modified_constructor.h | 46 + .../shiboken2/tests/libsample/multiple_derived.cpp | 64 + .../shiboken2/tests/libsample/multiple_derived.h | 195 + .../tests/libsample/noimplicitconversion.h | 49 + sources/shiboken2/tests/libsample/nondefaultctor.h | 75 + sources/shiboken2/tests/libsample/null.h | 44 + sources/shiboken2/tests/libsample/objectmodel.cpp | 42 + sources/shiboken2/tests/libsample/objectmodel.h | 58 + sources/shiboken2/tests/libsample/objecttype.cpp | 311 ++ sources/shiboken2/tests/libsample/objecttype.h | 176 + .../shiboken2/tests/libsample/objecttypebyvalue.h | 46 + .../shiboken2/tests/libsample/objecttypeholder.cpp | 52 + .../shiboken2/tests/libsample/objecttypeholder.h | 51 + .../shiboken2/tests/libsample/objecttypelayout.cpp | 68 + .../shiboken2/tests/libsample/objecttypelayout.h | 56 + .../tests/libsample/objecttypeoperators.cpp | 63 + .../tests/libsample/objecttypeoperators.h | 61 + sources/shiboken2/tests/libsample/objectview.cpp | 54 + sources/shiboken2/tests/libsample/objectview.h | 58 + sources/shiboken2/tests/libsample/oddbool.h | 83 + sources/shiboken2/tests/libsample/onlycopy.cpp | 57 + sources/shiboken2/tests/libsample/onlycopy.h | 59 + sources/shiboken2/tests/libsample/overload.cpp | 50 + sources/shiboken2/tests/libsample/overload.h | 143 + sources/shiboken2/tests/libsample/overloadsort.cpp | 30 + sources/shiboken2/tests/libsample/overloadsort.h | 88 + sources/shiboken2/tests/libsample/pairuser.cpp | 57 + sources/shiboken2/tests/libsample/pairuser.h | 55 + sources/shiboken2/tests/libsample/pen.cpp | 67 + sources/shiboken2/tests/libsample/pen.h | 62 + sources/shiboken2/tests/libsample/photon.cpp | 50 + sources/shiboken2/tests/libsample/photon.h | 140 + sources/shiboken2/tests/libsample/point.cpp | 155 + sources/shiboken2/tests/libsample/point.h | 99 + sources/shiboken2/tests/libsample/pointerholder.h | 45 + sources/shiboken2/tests/libsample/pointf.cpp | 126 + sources/shiboken2/tests/libsample/pointf.h | 88 + sources/shiboken2/tests/libsample/polygon.cpp | 75 + sources/shiboken2/tests/libsample/polygon.h | 66 + sources/shiboken2/tests/libsample/privatector.h | 55 + sources/shiboken2/tests/libsample/privatedtor.h | 60 + sources/shiboken2/tests/libsample/protected.cpp | 32 + sources/shiboken2/tests/libsample/protected.h | 151 + sources/shiboken2/tests/libsample/rect.h | 86 + sources/shiboken2/tests/libsample/reference.cpp | 78 + sources/shiboken2/tests/libsample/reference.h | 81 + .../shiboken2/tests/libsample/removednamespaces.h | 68 + sources/shiboken2/tests/libsample/sample.cpp | 39 + sources/shiboken2/tests/libsample/sample.h | 48 + .../shiboken2/tests/libsample/samplenamespace.cpp | 128 + .../shiboken2/tests/libsample/samplenamespace.h | 162 + sources/shiboken2/tests/libsample/sbkdate.cpp | 48 + sources/shiboken2/tests/libsample/sbkdate.h | 50 + sources/shiboken2/tests/libsample/simplefile.cpp | 108 + sources/shiboken2/tests/libsample/simplefile.h | 56 + sources/shiboken2/tests/libsample/size.cpp | 39 + sources/shiboken2/tests/libsample/size.h | 206 + sources/shiboken2/tests/libsample/sometime.cpp | 99 + sources/shiboken2/tests/libsample/sometime.h | 92 + sources/shiboken2/tests/libsample/str.cpp | 185 + sources/shiboken2/tests/libsample/str.h | 78 + sources/shiboken2/tests/libsample/strlist.cpp | 57 + sources/shiboken2/tests/libsample/strlist.h | 65 + sources/shiboken2/tests/libsample/templateptr.cpp | 33 + sources/shiboken2/tests/libsample/templateptr.h | 43 + sources/shiboken2/tests/libsample/transform.cpp | 65 + sources/shiboken2/tests/libsample/transform.h | 45 + .../shiboken2/tests/libsample/valueandvirtual.h | 47 + .../shiboken2/tests/libsample/virtualmethods.cpp | 59 + sources/shiboken2/tests/libsample/virtualmethods.h | 139 + sources/shiboken2/tests/libsample/voidholder.h | 50 + sources/shiboken2/tests/libsmart/CMakeLists.txt | 11 + sources/shiboken2/tests/libsmart/libsmartmacros.h | 46 + sources/shiboken2/tests/libsmart/smart.cpp | 174 + sources/shiboken2/tests/libsmart/smart.h | 210 + .../shiboken2/tests/minimalbinding/CMakeLists.txt | 38 + sources/shiboken2/tests/minimalbinding/global.h | 33 + .../tests/minimalbinding/listuser_test.py | 323 ++ .../shiboken2/tests/minimalbinding/minbool_test.py | 64 + .../tests/minimalbinding/minimal-binding.txt.in | 15 + sources/shiboken2/tests/minimalbinding/obj_test.py | 114 + .../shiboken2/tests/minimalbinding/typedef_test.py | 116 + .../tests/minimalbinding/typesystem_minimal.xml | 93 + sources/shiboken2/tests/minimalbinding/val_test.py | 115 + .../shiboken2/tests/otherbinding/CMakeLists.txt | 48 + .../collector_external_operator_test.py | 58 + ..._for_class_without_implicit_conversions_test.py | 73 + .../extended_multiply_operator_test.py | 64 + sources/shiboken2/tests/otherbinding/global.h | 35 + .../tests/otherbinding/module_reload_test.py | 61 + .../tests/otherbinding/new_ctor_operator_test.py | 56 + .../tests/otherbinding/objtypehashes_test.py | 53 + .../tests/otherbinding/other-binding.txt.in | 18 + .../tests/otherbinding/otherderived_test.py | 120 + .../tests/otherbinding/test_module_template.py | 40 + .../tests/otherbinding/typediscovery_test.py | 64 + .../tests/otherbinding/typesystem_other.xml | 15 + .../usersprimitivefromothermodule_test.py | 52 + .../shiboken2/tests/otherbinding/wrongctor_test.py | 53 + sources/shiboken2/tests/py3k.py | 2 + sources/shiboken2/tests/py3kcompat.py | 54 + .../shiboken2/tests/samplebinding/CMakeLists.txt | 145 + .../shiboken2/tests/samplebinding/__del___test.py | 50 + .../shiboken2/tests/samplebinding/abstract_test.py | 111 + .../tests/samplebinding/addedfunction_test.py | 62 + .../addedfunction_with_container_args_test.py | 51 + .../samplebinding/argumentmodifications_test.py | 111 + .../shiboken2/tests/samplebinding/bug_554_test.py | 45 + .../shiboken2/tests/samplebinding/bug_704_test.py | 68 + .../samplebinding/bytearray_bufferprotocol.cpp | 55 + .../tests/samplebinding/bytearray_test.py | 151 + .../tests/samplebinding/child_return_test.py | 58 + .../tests/samplebinding/class_fields_test.py | 168 + .../tests/samplebinding/collector_test.py | 81 + .../shiboken2/tests/samplebinding/complex_test.py | 84 + .../samplebinding/conversion_operator_test.py | 55 + sources/shiboken2/tests/samplebinding/copy_test.py | 86 + .../tests/samplebinding/ctorconvrule_test.py | 49 + .../shiboken2/tests/samplebinding/cyclic_test.py | 109 + sources/shiboken2/tests/samplebinding/date_test.py | 58 + .../shiboken2/tests/samplebinding/decisor_test.py | 65 + .../shiboken2/tests/samplebinding/delete_test.py | 47 + .../tests/samplebinding/deprecated_test.py | 44 + .../shiboken2/tests/samplebinding/derived_test.py | 153 + .../tests/samplebinding/duck_punching_test.py | 176 + sources/shiboken2/tests/samplebinding/echo_test.py | 52 + sources/shiboken2/tests/samplebinding/enum_test.py | 168 + .../samplebinding/enumfromremovednamespace_test.py | 53 + .../samplebinding/event_loop_call_virtual_test.py | 70 + .../tests/samplebinding/event_loop_thread_test.py | 96 + .../shiboken2/tests/samplebinding/filter_test.py | 45 + sources/shiboken2/tests/samplebinding/global.h | 90 + .../tests/samplebinding/handleholder_test.py | 57 + .../tests/samplebinding/hashabletype_test.py | 54 + .../tests/samplebinding/ignorederefop_test.py | 38 + .../samplebinding/implicitconv_numerical_test.py | 151 + .../tests/samplebinding/implicitconv_test.py | 66 + .../samplebinding/inheritanceandscope_test.py | 48 + .../tests/samplebinding/injectcode_test.py | 132 + .../tests/samplebinding/innerclass_test.py | 42 + .../shiboken2/tests/samplebinding/intlist_test.py | 98 + .../samplebinding/invalid_virtual_return_test.py | 65 + .../tests/samplebinding/keep_reference_test.py | 81 + sources/shiboken2/tests/samplebinding/list_test.py | 121 + sources/shiboken2/tests/samplebinding/lock_test.py | 95 + sources/shiboken2/tests/samplebinding/map_test.py | 80 + .../tests/samplebinding/metaclass_test.py | 61 + .../tests/samplebinding/mi_virtual_methods_test.py | 88 + .../shiboken2/tests/samplebinding/mixed_mi_test.py | 76 + .../tests/samplebinding/modelindex_test.py | 53 + .../tests/samplebinding/modelview_test.py | 78 + .../tests/samplebinding/modifications_test.py | 224 + .../samplebinding/modified_constructor_test.py | 49 + .../samplebinding/modifiedvirtualmethods_test.py | 248 + .../samplebinding/multi_cpp_inheritance_test.py | 105 + .../tests/samplebinding/multiple_derived_test.py | 221 + .../tests/samplebinding/namespace_test.py | 69 + .../tests/samplebinding/newdivision_test.py | 42 + .../tests/samplebinding/nondefaultctor_test.py | 71 + .../shiboken2/tests/samplebinding/nonzero_test.py | 43 + .../tests/samplebinding/numericaltypedef_test.py | 56 + .../shiboken2/tests/samplebinding/numpy_test.py | 58 + .../tests/samplebinding/objecttype_test.py | 122 + .../objecttype_with_named_args_test.py | 72 + .../tests/samplebinding/objecttypebyvalue_test.py | 42 + .../tests/samplebinding/objecttypelayout_test.py | 302 + .../samplebinding/objecttypeoperators_test.py | 60 + ...ecttypereferenceasvirtualmethodargument_test.py | 49 + .../shiboken2/tests/samplebinding/oddbool_test.py | 78 + .../samplebinding/oldstyleclass_as_number_test.py | 82 + .../tests/samplebinding/onlycopyclass_test.py | 57 + .../shiboken2/tests/samplebinding/overflow_test.py | 87 + .../tests/samplebinding/overload_sorting_test.py | 92 + .../shiboken2/tests/samplebinding/overload_test.py | 209 + .../samplebinding/overloadwithdefault_test.py | 64 + .../ownership_argument_invalidation_test.py | 62 + .../ownership_delete_child_in_cpp_test.py | 54 + .../ownership_delete_child_in_python_test.py | 60 + .../samplebinding/ownership_delete_parent_test.py | 82 + .../ownership_invalidate_after_use_test.py | 110 + .../ownership_invalidate_child_test.py | 69 + .../ownership_invalidate_nonpolymorphic_test.py | 53 + .../ownership_invalidate_parent_test.py | 68 + .../samplebinding/ownership_reparenting_test.py | 130 + .../samplebinding/ownership_transference_test.py | 85 + sources/shiboken2/tests/samplebinding/pair_test.py | 105 + sources/shiboken2/tests/samplebinding/pen_test.py | 63 + .../shiboken2/tests/samplebinding/point_test.py | 109 + .../tests/samplebinding/pointerholder_test.py | 59 + .../shiboken2/tests/samplebinding/pointf_test.py | 69 + .../primitivereferenceargument_test.py | 49 + .../tests/samplebinding/privatector_test.py | 84 + .../tests/samplebinding/privatedtor_test.py | 99 + .../tests/samplebinding/protected_test.py | 357 ++ .../shiboken2/tests/samplebinding/pstrlist_test.py | 50 + .../shiboken2/tests/samplebinding/pystr_test.py | 49 + .../tests/samplebinding/python_thread_test.py | 116 + .../samplebinding/receive_null_cstring_test.py | 54 + .../tests/samplebinding/reference_test.py | 122 + .../tests/samplebinding/referencetopointer_test.py | 97 + .../tests/samplebinding/return_null_test.py | 59 + .../tests/samplebinding/richcompare_test.py | 46 + .../tests/samplebinding/sample-binding.txt.in | 15 + .../shiboken2/tests/samplebinding/sample_test.py | 78 + .../tests/samplebinding/simplefile_glue.cpp | 34 + .../tests/samplebinding/simplefile_test.py | 81 + sources/shiboken2/tests/samplebinding/size_test.py | 119 + .../samplebinding/static_nonstatic_methods_test.py | 109 + sources/shiboken2/tests/samplebinding/str_test.py | 115 + .../shiboken2/tests/samplebinding/strlist_test.py | 112 + .../samplebinding/templateinheritingclass_test.py | 80 + sources/shiboken2/tests/samplebinding/time_test.py | 139 + .../tests/samplebinding/transform_test.py | 56 + .../tests/samplebinding/typeconverters_test.py | 189 + .../tests/samplebinding/typedealloc_test.py | 75 + .../tests/samplebinding/typedtordoublefree_test.py | 54 + .../tests/samplebinding/typesystem_sample.xml | 2426 +++++++++ .../tests/samplebinding/unsafe_parent_test.py | 54 + .../tests/samplebinding/useraddedctor_test.py | 45 + .../tests/samplebinding/virtualdtor_test.py | 76 + .../tests/samplebinding/virtualmethods_test.py | 138 + .../tests/samplebinding/visibilitychange_test.py | 47 + .../tests/samplebinding/voidholder_test.py | 69 + .../shiboken2/tests/samplebinding/weakref_test.py | 65 + .../tests/samplebinding/writableclassdict_test.py | 52 + .../shiboken2/tests/shibokenmodule/module_test.py | 116 + .../shiboken2/tests/smartbinding/CMakeLists.txt | 39 + sources/shiboken2/tests/smartbinding/global.h | 29 + .../tests/smartbinding/smart-binding.txt.in | 15 + .../tests/smartbinding/smart_pointer_test.py | 147 + .../tests/smartbinding/typesystem_smart.xml | 23 + sources/shiboken2/tests/sphinxtabletest.cpp | 332 ++ sources/shiboken2/tests/sphinxtabletest.h | 54 + .../shiboken2/tests/test_generator/CMakeLists.txt | 68 + .../tests/test_generator/dummygenerator.cpp | 70 + .../tests/test_generator/dummygenerator.h | 49 + .../test_generator/dummygentest-project.txt.in | 20 + .../tests/test_generator/dummygentest.cpp | 138 + .../shiboken2/tests/test_generator/dummygentest.h | 56 + .../tests/test_generator/dummygentestconfig.h.in | 15 + sources/shiboken2/tests/test_generator/main.cpp | 39 + .../shiboken2/tests/test_generator/run_test.cmake | 11 + .../shiboken2/tests/test_generator/test_global.h | 1 + .../tests/test_generator/test_typesystem.xml | 3 + tests/CMakeLists.txt | 102 - tests/dumpcodemodel/CMakeLists.txt | 5 - tests/dumpcodemodel/main.cpp | 82 - tests/libminimal/CMakeLists.txt | 13 - tests/libminimal/libminimalmacros.h | 46 - tests/libminimal/listuser.cpp | 124 - tests/libminimal/listuser.h | 75 - tests/libminimal/minbool.h | 68 - tests/libminimal/obj.cpp | 44 - tests/libminimal/obj.h | 59 - tests/libminimal/typedef.cpp | 75 - tests/libminimal/typedef.h | 54 - tests/libminimal/val.h | 59 - tests/libother/CMakeLists.txt | 18 - tests/libother/extendsnoimplicitconversion.h | 45 - tests/libother/libothermacros.h | 46 - tests/libother/number.cpp | 59 - tests/libother/number.h | 57 - tests/libother/otherderived.cpp | 61 - tests/libother/otherderived.h | 65 - tests/libother/othermultiplederived.cpp | 50 - tests/libother/othermultiplederived.h | 46 - tests/libother/otherobjecttype.cpp | 36 - tests/libother/otherobjecttype.h | 49 - tests/libsample/CMakeLists.txt | 57 - tests/libsample/abstract.cpp | 97 - tests/libsample/abstract.h | 107 - tests/libsample/blackbox.cpp | 131 - tests/libsample/blackbox.h | 67 - tests/libsample/bucket.cpp | 86 - tests/libsample/bucket.h | 59 - tests/libsample/bytearray.cpp | 214 - tests/libsample/bytearray.h | 89 - tests/libsample/collector.cpp | 62 - tests/libsample/collector.h | 71 - tests/libsample/complex.cpp | 54 - tests/libsample/complex.h | 55 - tests/libsample/ctorconvrule.h | 45 - tests/libsample/cvlist.h | 53 - tests/libsample/derived.cpp | 119 - tests/libsample/derived.h | 92 - tests/libsample/echo.cpp | 29 - tests/libsample/echo.h | 55 - tests/libsample/expression.cpp | 137 - tests/libsample/expression.h | 64 - tests/libsample/filter.cpp | 73 - tests/libsample/filter.h | 99 - tests/libsample/functions.cpp | 214 - tests/libsample/functions.h | 93 - tests/libsample/handle.cpp | 44 - tests/libsample/handle.h | 72 - tests/libsample/implicitconv.cpp | 66 - tests/libsample/implicitconv.h | 83 - tests/libsample/injectcode.cpp | 108 - tests/libsample/injectcode.h | 65 - tests/libsample/libsamplemacros.h | 46 - tests/libsample/list.h | 106 - tests/libsample/listuser.cpp | 91 - tests/libsample/listuser.h | 74 - tests/libsample/main.cpp | 244 - tests/libsample/mapuser.cpp | 69 - tests/libsample/mapuser.h | 65 - tests/libsample/modelindex.h | 72 - tests/libsample/modifications.cpp | 151 - tests/libsample/modifications.h | 142 - tests/libsample/modified_constructor.cpp | 42 - tests/libsample/modified_constructor.h | 46 - tests/libsample/multiple_derived.cpp | 64 - tests/libsample/multiple_derived.h | 195 - tests/libsample/noimplicitconversion.h | 49 - tests/libsample/nondefaultctor.h | 75 - tests/libsample/null.h | 44 - tests/libsample/objectmodel.cpp | 42 - tests/libsample/objectmodel.h | 58 - tests/libsample/objecttype.cpp | 311 -- tests/libsample/objecttype.h | 176 - tests/libsample/objecttypebyvalue.h | 46 - tests/libsample/objecttypeholder.cpp | 52 - tests/libsample/objecttypeholder.h | 51 - tests/libsample/objecttypelayout.cpp | 68 - tests/libsample/objecttypelayout.h | 56 - tests/libsample/objecttypeoperators.cpp | 63 - tests/libsample/objecttypeoperators.h | 61 - tests/libsample/objectview.cpp | 54 - tests/libsample/objectview.h | 58 - tests/libsample/oddbool.h | 83 - tests/libsample/onlycopy.cpp | 57 - tests/libsample/onlycopy.h | 59 - tests/libsample/overload.cpp | 50 - tests/libsample/overload.h | 143 - tests/libsample/overloadsort.cpp | 30 - tests/libsample/overloadsort.h | 88 - tests/libsample/pairuser.cpp | 57 - tests/libsample/pairuser.h | 55 - tests/libsample/pen.cpp | 67 - tests/libsample/pen.h | 62 - tests/libsample/photon.cpp | 50 - tests/libsample/photon.h | 140 - tests/libsample/point.cpp | 155 - tests/libsample/point.h | 99 - tests/libsample/pointerholder.h | 45 - tests/libsample/pointf.cpp | 126 - tests/libsample/pointf.h | 88 - tests/libsample/polygon.cpp | 75 - tests/libsample/polygon.h | 66 - tests/libsample/privatector.h | 55 - tests/libsample/privatedtor.h | 60 - tests/libsample/protected.cpp | 32 - tests/libsample/protected.h | 151 - tests/libsample/rect.h | 86 - tests/libsample/reference.cpp | 78 - tests/libsample/reference.h | 81 - tests/libsample/removednamespaces.h | 68 - tests/libsample/sample.cpp | 39 - tests/libsample/sample.h | 48 - tests/libsample/samplenamespace.cpp | 128 - tests/libsample/samplenamespace.h | 162 - tests/libsample/sbkdate.cpp | 48 - tests/libsample/sbkdate.h | 50 - tests/libsample/simplefile.cpp | 108 - tests/libsample/simplefile.h | 56 - tests/libsample/size.cpp | 39 - tests/libsample/size.h | 206 - tests/libsample/sometime.cpp | 99 - tests/libsample/sometime.h | 92 - tests/libsample/str.cpp | 185 - tests/libsample/str.h | 78 - tests/libsample/strlist.cpp | 57 - tests/libsample/strlist.h | 65 - tests/libsample/templateptr.cpp | 33 - tests/libsample/templateptr.h | 43 - tests/libsample/transform.cpp | 65 - tests/libsample/transform.h | 45 - tests/libsample/valueandvirtual.h | 47 - tests/libsample/virtualmethods.cpp | 59 - tests/libsample/virtualmethods.h | 139 - tests/libsample/voidholder.h | 50 - tests/libsmart/CMakeLists.txt | 11 - tests/libsmart/libsmartmacros.h | 46 - tests/libsmart/smart.cpp | 174 - tests/libsmart/smart.h | 210 - tests/minimalbinding/CMakeLists.txt | 38 - tests/minimalbinding/global.h | 33 - tests/minimalbinding/listuser_test.py | 323 -- tests/minimalbinding/minbool_test.py | 64 - tests/minimalbinding/minimal-binding.txt.in | 15 - tests/minimalbinding/obj_test.py | 114 - tests/minimalbinding/typedef_test.py | 116 - tests/minimalbinding/typesystem_minimal.xml | 93 - tests/minimalbinding/val_test.py | 115 - tests/otherbinding/CMakeLists.txt | 48 - .../collector_external_operator_test.py | 58 - ..._for_class_without_implicit_conversions_test.py | 73 - .../extended_multiply_operator_test.py | 64 - tests/otherbinding/global.h | 35 - tests/otherbinding/module_reload_test.py | 61 - tests/otherbinding/new_ctor_operator_test.py | 56 - tests/otherbinding/objtypehashes_test.py | 53 - tests/otherbinding/other-binding.txt.in | 18 - tests/otherbinding/otherderived_test.py | 120 - tests/otherbinding/test_module_template.py | 40 - tests/otherbinding/typediscovery_test.py | 64 - tests/otherbinding/typesystem_other.xml | 15 - .../usersprimitivefromothermodule_test.py | 52 - tests/otherbinding/wrongctor_test.py | 53 - tests/py3k.py | 2 - tests/py3kcompat.py | 54 - tests/samplebinding/CMakeLists.txt | 145 - tests/samplebinding/__del___test.py | 50 - tests/samplebinding/abstract_test.py | 111 - tests/samplebinding/addedfunction_test.py | 62 - .../addedfunction_with_container_args_test.py | 51 - tests/samplebinding/argumentmodifications_test.py | 111 - tests/samplebinding/bug_554_test.py | 45 - tests/samplebinding/bug_704_test.py | 68 - tests/samplebinding/bytearray_bufferprotocol.cpp | 55 - tests/samplebinding/bytearray_test.py | 151 - tests/samplebinding/child_return_test.py | 58 - tests/samplebinding/class_fields_test.py | 168 - tests/samplebinding/collector_test.py | 81 - tests/samplebinding/complex_test.py | 84 - tests/samplebinding/conversion_operator_test.py | 55 - tests/samplebinding/copy_test.py | 86 - tests/samplebinding/ctorconvrule_test.py | 49 - tests/samplebinding/cyclic_test.py | 109 - tests/samplebinding/date_test.py | 58 - tests/samplebinding/decisor_test.py | 65 - tests/samplebinding/delete_test.py | 47 - tests/samplebinding/deprecated_test.py | 44 - tests/samplebinding/derived_test.py | 153 - tests/samplebinding/duck_punching_test.py | 176 - tests/samplebinding/echo_test.py | 52 - tests/samplebinding/enum_test.py | 168 - .../samplebinding/enumfromremovednamespace_test.py | 53 - .../samplebinding/event_loop_call_virtual_test.py | 70 - tests/samplebinding/event_loop_thread_test.py | 96 - tests/samplebinding/filter_test.py | 45 - tests/samplebinding/global.h | 90 - tests/samplebinding/handleholder_test.py | 57 - tests/samplebinding/hashabletype_test.py | 54 - tests/samplebinding/ignorederefop_test.py | 38 - tests/samplebinding/implicitconv_numerical_test.py | 151 - tests/samplebinding/implicitconv_test.py | 66 - tests/samplebinding/inheritanceandscope_test.py | 48 - tests/samplebinding/injectcode_test.py | 132 - tests/samplebinding/innerclass_test.py | 42 - tests/samplebinding/intlist_test.py | 98 - tests/samplebinding/invalid_virtual_return_test.py | 65 - tests/samplebinding/keep_reference_test.py | 81 - tests/samplebinding/list_test.py | 121 - tests/samplebinding/lock_test.py | 95 - tests/samplebinding/map_test.py | 80 - tests/samplebinding/metaclass_test.py | 61 - tests/samplebinding/mi_virtual_methods_test.py | 88 - tests/samplebinding/mixed_mi_test.py | 76 - tests/samplebinding/modelindex_test.py | 53 - tests/samplebinding/modelview_test.py | 78 - tests/samplebinding/modifications_test.py | 224 - tests/samplebinding/modified_constructor_test.py | 49 - tests/samplebinding/modifiedvirtualmethods_test.py | 248 - tests/samplebinding/multi_cpp_inheritance_test.py | 105 - tests/samplebinding/multiple_derived_test.py | 221 - tests/samplebinding/namespace_test.py | 69 - tests/samplebinding/newdivision_test.py | 42 - tests/samplebinding/nondefaultctor_test.py | 71 - tests/samplebinding/nonzero_test.py | 43 - tests/samplebinding/numericaltypedef_test.py | 56 - tests/samplebinding/numpy_test.py | 58 - tests/samplebinding/objecttype_test.py | 122 - .../objecttype_with_named_args_test.py | 72 - tests/samplebinding/objecttypebyvalue_test.py | 42 - tests/samplebinding/objecttypelayout_test.py | 302 - tests/samplebinding/objecttypeoperators_test.py | 60 - ...ecttypereferenceasvirtualmethodargument_test.py | 49 - tests/samplebinding/oddbool_test.py | 78 - .../samplebinding/oldstyleclass_as_number_test.py | 82 - tests/samplebinding/onlycopyclass_test.py | 57 - tests/samplebinding/overflow_test.py | 87 - tests/samplebinding/overload_sorting_test.py | 92 - tests/samplebinding/overload_test.py | 209 - tests/samplebinding/overloadwithdefault_test.py | 64 - .../ownership_argument_invalidation_test.py | 62 - .../ownership_delete_child_in_cpp_test.py | 54 - .../ownership_delete_child_in_python_test.py | 60 - .../samplebinding/ownership_delete_parent_test.py | 82 - .../ownership_invalidate_after_use_test.py | 110 - .../ownership_invalidate_child_test.py | 69 - .../ownership_invalidate_nonpolymorphic_test.py | 53 - .../ownership_invalidate_parent_test.py | 68 - tests/samplebinding/ownership_reparenting_test.py | 130 - tests/samplebinding/ownership_transference_test.py | 85 - tests/samplebinding/pair_test.py | 105 - tests/samplebinding/pen_test.py | 63 - tests/samplebinding/point_test.py | 109 - tests/samplebinding/pointerholder_test.py | 59 - tests/samplebinding/pointf_test.py | 69 - .../primitivereferenceargument_test.py | 49 - tests/samplebinding/privatector_test.py | 84 - tests/samplebinding/privatedtor_test.py | 99 - tests/samplebinding/protected_test.py | 357 -- tests/samplebinding/pstrlist_test.py | 50 - tests/samplebinding/pystr_test.py | 49 - tests/samplebinding/python_thread_test.py | 116 - tests/samplebinding/receive_null_cstring_test.py | 54 - tests/samplebinding/reference_test.py | 122 - tests/samplebinding/referencetopointer_test.py | 97 - tests/samplebinding/return_null_test.py | 59 - tests/samplebinding/richcompare_test.py | 46 - tests/samplebinding/sample-binding.txt.in | 15 - tests/samplebinding/sample_test.py | 78 - tests/samplebinding/simplefile_glue.cpp | 34 - tests/samplebinding/simplefile_test.py | 81 - tests/samplebinding/size_test.py | 119 - .../samplebinding/static_nonstatic_methods_test.py | 109 - tests/samplebinding/str_test.py | 115 - tests/samplebinding/strlist_test.py | 112 - .../samplebinding/templateinheritingclass_test.py | 80 - tests/samplebinding/time_test.py | 139 - tests/samplebinding/transform_test.py | 56 - tests/samplebinding/typeconverters_test.py | 189 - tests/samplebinding/typedealloc_test.py | 75 - tests/samplebinding/typedtordoublefree_test.py | 54 - tests/samplebinding/typesystem_sample.xml | 2426 --------- tests/samplebinding/unsafe_parent_test.py | 54 - tests/samplebinding/useraddedctor_test.py | 45 - tests/samplebinding/virtualdtor_test.py | 76 - tests/samplebinding/virtualmethods_test.py | 138 - tests/samplebinding/visibilitychange_test.py | 47 - tests/samplebinding/voidholder_test.py | 69 - tests/samplebinding/weakref_test.py | 65 - tests/samplebinding/writableclassdict_test.py | 52 - tests/shibokenmodule/module_test.py | 116 - tests/smartbinding/CMakeLists.txt | 39 - tests/smartbinding/global.h | 29 - tests/smartbinding/smart-binding.txt.in | 15 - tests/smartbinding/smart_pointer_test.py | 147 - tests/smartbinding/typesystem_smart.xml | 23 - tests/sphinxtabletest.cpp | 332 -- tests/sphinxtabletest.h | 54 - tests/test_generator/CMakeLists.txt | 68 - tests/test_generator/dummygenerator.cpp | 70 - tests/test_generator/dummygenerator.h | 49 - tests/test_generator/dummygentest-project.txt.in | 20 - tests/test_generator/dummygentest.cpp | 138 - tests/test_generator/dummygentest.h | 56 - tests/test_generator/dummygentestconfig.h.in | 15 - tests/test_generator/main.cpp | 39 - tests/test_generator/run_test.cmake | 11 - tests/test_generator/test_global.h | 1 - tests/test_generator/test_typesystem.xml | 3 - 1198 files changed, 91828 insertions(+), 91828 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .gitignore delete mode 100644 AUTHORS delete mode 100644 ApiExtractor/AUTHORS delete mode 100644 ApiExtractor/CMakeLists.txt delete mode 100644 ApiExtractor/COPYING delete mode 100644 ApiExtractor/abstractmetabuilder.cpp delete mode 100644 ApiExtractor/abstractmetabuilder.h delete mode 100644 ApiExtractor/abstractmetabuilder_p.h delete mode 100644 ApiExtractor/abstractmetalang.cpp delete mode 100644 ApiExtractor/abstractmetalang.h delete mode 100644 ApiExtractor/abstractmetalang_typedefs.h delete mode 100644 ApiExtractor/apiextractor.cpp delete mode 100644 ApiExtractor/apiextractor.h delete mode 100644 ApiExtractor/apiextractormacros.h delete mode 100644 ApiExtractor/clangparser/clangbuilder.cpp delete mode 100644 ApiExtractor/clangparser/clangbuilder.h delete mode 100644 ApiExtractor/clangparser/clangdebugutils.cpp delete mode 100644 ApiExtractor/clangparser/clangdebugutils.h delete mode 100644 ApiExtractor/clangparser/clangparser.cpp delete mode 100644 ApiExtractor/clangparser/clangparser.h delete mode 100644 ApiExtractor/clangparser/clangutils.cpp delete mode 100644 ApiExtractor/clangparser/clangutils.h delete mode 100644 ApiExtractor/clangparser/compilersupport.cpp delete mode 100644 ApiExtractor/clangparser/compilersupport.h delete mode 100644 ApiExtractor/cmake_uninstall.cmake delete mode 100644 ApiExtractor/dependency.h delete mode 100644 ApiExtractor/doc/CMakeLists.txt delete mode 100644 ApiExtractor/doc/_templates/index.html delete mode 100644 ApiExtractor/doc/_templates/layout.html delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/searchbox.html delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png delete mode 100644 ApiExtractor/doc/_themes/pysidedocs/theme.conf delete mode 100644 ApiExtractor/doc/conf.py.in delete mode 100644 ApiExtractor/doc/contents.rst delete mode 100644 ApiExtractor/doc/dependency-apiextractor.svg delete mode 100644 ApiExtractor/doc/overview.rst delete mode 100644 ApiExtractor/doc/ownership.rst delete mode 100644 ApiExtractor/doc/typesystem.rst delete mode 100644 ApiExtractor/doc/typesystem_arguments.rst delete mode 100644 ApiExtractor/doc/typesystem_conversionrule.rst delete mode 100644 ApiExtractor/doc/typesystem_documentation.rst delete mode 100644 ApiExtractor/doc/typesystem_manipulating_objects.rst delete mode 100644 ApiExtractor/doc/typesystem_modify_function.rst delete mode 100644 ApiExtractor/doc/typesystem_solving_compilation.rst delete mode 100644 ApiExtractor/doc/typesystem_specifying_types.rst delete mode 100644 ApiExtractor/doc/typesystem_templates.rst delete mode 100644 ApiExtractor/docparser.cpp delete mode 100644 ApiExtractor/docparser.h delete mode 100644 ApiExtractor/doxygenparser.cpp delete mode 100644 ApiExtractor/doxygenparser.h delete mode 100644 ApiExtractor/fileout.cpp delete mode 100644 ApiExtractor/fileout.h delete mode 100644 ApiExtractor/graph.cpp delete mode 100644 ApiExtractor/graph.h delete mode 100644 ApiExtractor/header_paths.h delete mode 100644 ApiExtractor/icecc.cmake delete mode 100644 ApiExtractor/include.cpp delete mode 100644 ApiExtractor/include.h delete mode 100644 ApiExtractor/merge.xsl delete mode 100644 ApiExtractor/parser/codemodel.cpp delete mode 100644 ApiExtractor/parser/codemodel.h delete mode 100644 ApiExtractor/parser/codemodel_enums.h delete mode 100644 ApiExtractor/parser/codemodel_fwd.h delete mode 100644 ApiExtractor/qtdocparser.cpp delete mode 100644 ApiExtractor/qtdocparser.h delete mode 100644 ApiExtractor/reporthandler.cpp delete mode 100644 ApiExtractor/reporthandler.h delete mode 100644 ApiExtractor/symbols.filter delete mode 100644 ApiExtractor/tests/CMakeLists.txt delete mode 100644 ApiExtractor/tests/a.xml delete mode 100644 ApiExtractor/tests/testabstractmetaclass.cpp delete mode 100644 ApiExtractor/tests/testabstractmetaclass.h delete mode 100644 ApiExtractor/tests/testabstractmetatype.cpp delete mode 100644 ApiExtractor/tests/testabstractmetatype.h delete mode 100644 ApiExtractor/tests/testaddfunction.cpp delete mode 100644 ApiExtractor/tests/testaddfunction.h delete mode 100644 ApiExtractor/tests/testarrayargument.cpp delete mode 100644 ApiExtractor/tests/testarrayargument.h delete mode 100644 ApiExtractor/tests/testcodeinjection.cpp delete mode 100644 ApiExtractor/tests/testcodeinjection.h delete mode 100644 ApiExtractor/tests/testcontainer.cpp delete mode 100644 ApiExtractor/tests/testcontainer.h delete mode 100644 ApiExtractor/tests/testconversionoperator.cpp delete mode 100644 ApiExtractor/tests/testconversionoperator.h delete mode 100644 ApiExtractor/tests/testconversionruletag.cpp delete mode 100644 ApiExtractor/tests/testconversionruletag.h delete mode 100644 ApiExtractor/tests/testctorinformation.cpp delete mode 100644 ApiExtractor/tests/testctorinformation.h delete mode 100644 ApiExtractor/tests/testdroptypeentries.cpp delete mode 100644 ApiExtractor/tests/testdroptypeentries.h delete mode 100644 ApiExtractor/tests/testdtorinformation.cpp delete mode 100644 ApiExtractor/tests/testdtorinformation.h delete mode 100644 ApiExtractor/tests/testenum.cpp delete mode 100644 ApiExtractor/tests/testenum.h delete mode 100644 ApiExtractor/tests/testextrainclude.cpp delete mode 100644 ApiExtractor/tests/testextrainclude.h delete mode 100644 ApiExtractor/tests/testfunctiontag.cpp delete mode 100644 ApiExtractor/tests/testfunctiontag.h delete mode 100644 ApiExtractor/tests/testimplicitconversions.cpp delete mode 100644 ApiExtractor/tests/testimplicitconversions.h delete mode 100644 ApiExtractor/tests/testinserttemplate.cpp delete mode 100644 ApiExtractor/tests/testinserttemplate.h delete mode 100644 ApiExtractor/tests/testmodifydocumentation.cpp delete mode 100644 ApiExtractor/tests/testmodifydocumentation.h delete mode 100644 ApiExtractor/tests/testmodifyfunction.cpp delete mode 100644 ApiExtractor/tests/testmodifyfunction.h delete mode 100644 ApiExtractor/tests/testmultipleinheritance.cpp delete mode 100644 ApiExtractor/tests/testmultipleinheritance.h delete mode 100644 ApiExtractor/tests/testnamespace.cpp delete mode 100644 ApiExtractor/tests/testnamespace.h delete mode 100644 ApiExtractor/tests/testnestedtypes.cpp delete mode 100644 ApiExtractor/tests/testnestedtypes.h delete mode 100644 ApiExtractor/tests/testnumericaltypedef.cpp delete mode 100644 ApiExtractor/tests/testnumericaltypedef.h delete mode 100644 ApiExtractor/tests/testprimitivetypetag.cpp delete mode 100644 ApiExtractor/tests/testprimitivetypetag.h delete mode 100644 ApiExtractor/tests/testrefcounttag.cpp delete mode 100644 ApiExtractor/tests/testrefcounttag.h delete mode 100644 ApiExtractor/tests/testreferencetopointer.cpp delete mode 100644 ApiExtractor/tests/testreferencetopointer.h delete mode 100644 ApiExtractor/tests/testremovefield.cpp delete mode 100644 ApiExtractor/tests/testremovefield.h delete mode 100644 ApiExtractor/tests/testremoveimplconv.cpp delete mode 100644 ApiExtractor/tests/testremoveimplconv.h delete mode 100644 ApiExtractor/tests/testremoveoperatormethod.cpp delete mode 100644 ApiExtractor/tests/testremoveoperatormethod.h delete mode 100644 ApiExtractor/tests/testresolvetype.cpp delete mode 100644 ApiExtractor/tests/testresolvetype.h delete mode 100644 ApiExtractor/tests/testreverseoperators.cpp delete mode 100644 ApiExtractor/tests/testreverseoperators.h delete mode 100644 ApiExtractor/tests/testtemplates.cpp delete mode 100644 ApiExtractor/tests/testtemplates.h delete mode 100644 ApiExtractor/tests/testtoposort.cpp delete mode 100644 ApiExtractor/tests/testtoposort.h delete mode 100644 ApiExtractor/tests/testtyperevision.cpp delete mode 100644 ApiExtractor/tests/testtyperevision.h delete mode 100644 ApiExtractor/tests/testutil.h delete mode 100644 ApiExtractor/tests/testvaluetypedefaultctortag.cpp delete mode 100644 ApiExtractor/tests/testvaluetypedefaultctortag.h delete mode 100644 ApiExtractor/tests/testvoidarg.cpp delete mode 100644 ApiExtractor/tests/testvoidarg.h delete mode 100644 ApiExtractor/tests/utf8code.txt delete mode 100644 ApiExtractor/typedatabase.cpp delete mode 100644 ApiExtractor/typedatabase.h delete mode 100644 ApiExtractor/typedatabase_typedefs.h delete mode 100644 ApiExtractor/typeparser.cpp delete mode 100644 ApiExtractor/typeparser.h delete mode 100644 ApiExtractor/typesystem.cpp delete mode 100644 ApiExtractor/typesystem.h delete mode 100644 ApiExtractor/typesystem_enums.h delete mode 100644 ApiExtractor/typesystem_p.h delete mode 100644 ApiExtractor/typesystem_typedefs.h delete mode 100644 CMakeLists.txt delete mode 100644 COPYING delete mode 100644 COPYING.libsample delete mode 100644 COPYING.libshiboken delete mode 100644 Doxyfile delete mode 100644 LICENSE.GPLv3 delete mode 100644 LICENSE.LGPLv21 delete mode 100644 LICENSE.LGPLv3 delete mode 100644 LICENSE.PREVIEW.COMMERCIAL delete mode 100644 README.md delete mode 100644 cmake_uninstall.cmake delete mode 100644 data/CMakeLists.txt delete mode 100644 data/GeneratorRunnerConfig.cmake.in delete mode 100644 data/GeneratorRunnerConfigVersion.cmake.in delete mode 100644 data/Shiboken2Config-spec.cmake.in delete mode 100644 data/Shiboken2Config.cmake.in delete mode 100644 data/Shiboken2ConfigVersion.cmake.in delete mode 120000 data/docgenerator.1 delete mode 100644 data/generatorrunner.1 delete mode 100644 data/generatorrunner.pc.in delete mode 100644 data/shiboken2.pc.in delete mode 100644 doc/CMakeLists.txt delete mode 100644 doc/_templates/index.html delete mode 100644 doc/_templates/layout.html delete mode 100644 doc/_themes/pysidedocs/searchbox.html delete mode 100644 doc/_themes/pysidedocs/static/bg_header.png delete mode 100644 doc/_themes/pysidedocs/static/bg_topo.jpg delete mode 100644 doc/_themes/pysidedocs/static/fakebar.png delete mode 100644 doc/_themes/pysidedocs/static/logo_python.jpg delete mode 100644 doc/_themes/pysidedocs/static/logo_qt.png delete mode 100644 doc/_themes/pysidedocs/static/pysidedocs.css delete mode 100644 doc/_themes/pysidedocs/static/pysidelogo.png delete mode 100644 doc/_themes/pysidedocs/static/relbar_bg.png delete mode 100644 doc/_themes/pysidedocs/theme.conf delete mode 100644 doc/codeinjectionsemantics.rst delete mode 100644 doc/commandlineoptions.rst delete mode 100644 doc/conf.py.in delete mode 100644 doc/contents.rst delete mode 100644 doc/dependency-pyqtb.svg delete mode 100644 doc/dependency-pyside.svg delete mode 100644 doc/faq.rst delete mode 100644 doc/images/.directory delete mode 100644 doc/images/bindinggen-development.png delete mode 100644 doc/images/bindinggen-development.svg delete mode 100644 doc/images/boostgen.png delete mode 100644 doc/images/boostqtarch.png delete mode 100644 doc/images/boostqtarch.svg delete mode 100644 doc/images/converter.dot delete mode 100644 doc/images/converter.png delete mode 100644 doc/images/genrunnerarch.png delete mode 100644 doc/images/genrunnerarch.svg delete mode 100644 doc/overview.rst delete mode 100644 doc/ownership.rst delete mode 100644 doc/projectfile.rst delete mode 100644 doc/sequenceprotocol.rst delete mode 100644 doc/shiboken2.1 delete mode 100644 doc/shibokenmodule.rst delete mode 100644 doc/typeconverters.rst delete mode 100644 doc/typesystemvariables.rst delete mode 100644 doc/wordsofadvice.rst delete mode 100644 generator/CMakeLists.txt delete mode 100644 generator/generator.cpp delete mode 100644 generator/generator.h delete mode 100644 generator/main.cpp delete mode 100644 generator/qtdoc/CMakeLists.txt delete mode 100644 generator/qtdoc/qtdocgenerator.cpp delete mode 100644 generator/qtdoc/qtdocgenerator.h delete mode 100644 generator/shiboken2/CMakeLists.txt delete mode 100644 generator/shiboken2/cppgenerator.cpp delete mode 100644 generator/shiboken2/cppgenerator.h delete mode 100644 generator/shiboken2/headergenerator.cpp delete mode 100644 generator/shiboken2/headergenerator.h delete mode 100644 generator/shiboken2/overloaddata.cpp delete mode 100644 generator/shiboken2/overloaddata.h delete mode 100644 generator/shiboken2/shibokengenerator.cpp delete mode 100644 generator/shiboken2/shibokengenerator.h delete mode 100644 generator/shibokenconfig.h.in delete mode 100644 generatorrunnerconfig.h.in delete mode 100644 generatorrunnermacros.h delete mode 100644 generators/shiboken/shiboken.cpp delete mode 100644 header.COMM delete mode 100644 header.LGPL-ONLY delete mode 100644 header.LGPL21 delete mode 100644 header.LGPL3 delete mode 100644 header.LGPL3-COMM delete mode 100644 icecc.cmake delete mode 100644 libshiboken/CMakeLists.txt delete mode 100644 libshiboken/autodecref.h delete mode 100644 libshiboken/basewrapper.cpp delete mode 100644 libshiboken/basewrapper.h delete mode 100644 libshiboken/basewrapper_p.h delete mode 100644 libshiboken/bindingmanager.cpp delete mode 100644 libshiboken/bindingmanager.h delete mode 100644 libshiboken/conversions.h delete mode 100644 libshiboken/debugfreehook.cpp delete mode 100644 libshiboken/debugfreehook.h delete mode 100644 libshiboken/gilstate.cpp delete mode 100644 libshiboken/gilstate.h delete mode 100644 libshiboken/helper.cpp delete mode 100644 libshiboken/helper.h delete mode 100644 libshiboken/python25compat.h delete mode 100644 libshiboken/sbkconverter.cpp delete mode 100644 libshiboken/sbkconverter.h delete mode 100644 libshiboken/sbkconverter_p.h delete mode 100644 libshiboken/sbkdbg.h delete mode 100644 libshiboken/sbkenum.cpp delete mode 100644 libshiboken/sbkenum.h delete mode 100644 libshiboken/sbkmodule.cpp delete mode 100644 libshiboken/sbkmodule.h delete mode 100644 libshiboken/sbkpython.h delete mode 100644 libshiboken/sbkstring.cpp delete mode 100644 libshiboken/sbkstring.h delete mode 100644 libshiboken/sbkversion.h.in delete mode 100644 libshiboken/shiboken.h delete mode 100644 libshiboken/shibokenbuffer.cpp delete mode 100644 libshiboken/shibokenbuffer.h delete mode 100644 libshiboken/shibokenmacros.h delete mode 100644 libshiboken/threadstatesaver.cpp delete mode 100644 libshiboken/threadstatesaver.h delete mode 100644 libshiboken/tmp-referencetopython/sbkconverter.cpp delete mode 100644 libshiboken/tmp-referencetopython/sbkconverter.h delete mode 100644 libshiboken/typeresolver.cpp delete mode 100644 libshiboken/typeresolver.h delete mode 100644 shibokenmodule/CMakeLists.txt delete mode 100644 shibokenmodule/nothing.h delete mode 100644 shibokenmodule/shibokenmodule.txt.in delete mode 100644 shibokenmodule/typesystem_shiboken.xml create mode 100644 sources/shiboken2/.gitattributes create mode 100644 sources/shiboken2/.gitignore create mode 100644 sources/shiboken2/AUTHORS create mode 100644 sources/shiboken2/ApiExtractor/AUTHORS create mode 100644 sources/shiboken2/ApiExtractor/CMakeLists.txt create mode 100644 sources/shiboken2/ApiExtractor/COPYING create mode 100644 sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp create mode 100644 sources/shiboken2/ApiExtractor/abstractmetabuilder.h create mode 100644 sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h create mode 100644 sources/shiboken2/ApiExtractor/abstractmetalang.cpp create mode 100644 sources/shiboken2/ApiExtractor/abstractmetalang.h create mode 100644 sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h create mode 100644 sources/shiboken2/ApiExtractor/apiextractor.cpp create mode 100644 sources/shiboken2/ApiExtractor/apiextractor.h create mode 100644 sources/shiboken2/ApiExtractor/apiextractormacros.h create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangparser.h create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp create mode 100644 sources/shiboken2/ApiExtractor/clangparser/clangutils.h create mode 100644 sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp create mode 100644 sources/shiboken2/ApiExtractor/clangparser/compilersupport.h create mode 100644 sources/shiboken2/ApiExtractor/cmake_uninstall.cmake create mode 100644 sources/shiboken2/ApiExtractor/dependency.h create mode 100644 sources/shiboken2/ApiExtractor/doc/CMakeLists.txt create mode 100644 sources/shiboken2/ApiExtractor/doc/_templates/index.html create mode 100644 sources/shiboken2/ApiExtractor/doc/_templates/layout.html create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/searchbox.html create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png create mode 100644 sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/theme.conf create mode 100644 sources/shiboken2/ApiExtractor/doc/conf.py.in create mode 100644 sources/shiboken2/ApiExtractor/doc/contents.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/dependency-apiextractor.svg create mode 100644 sources/shiboken2/ApiExtractor/doc/overview.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/ownership.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_arguments.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_conversionrule.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_documentation.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_manipulating_objects.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_modify_function.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_solving_compilation.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst create mode 100644 sources/shiboken2/ApiExtractor/doc/typesystem_templates.rst create mode 100644 sources/shiboken2/ApiExtractor/docparser.cpp create mode 100644 sources/shiboken2/ApiExtractor/docparser.h create mode 100644 sources/shiboken2/ApiExtractor/doxygenparser.cpp create mode 100644 sources/shiboken2/ApiExtractor/doxygenparser.h create mode 100644 sources/shiboken2/ApiExtractor/fileout.cpp create mode 100644 sources/shiboken2/ApiExtractor/fileout.h create mode 100644 sources/shiboken2/ApiExtractor/graph.cpp create mode 100644 sources/shiboken2/ApiExtractor/graph.h create mode 100644 sources/shiboken2/ApiExtractor/header_paths.h create mode 100644 sources/shiboken2/ApiExtractor/icecc.cmake create mode 100644 sources/shiboken2/ApiExtractor/include.cpp create mode 100644 sources/shiboken2/ApiExtractor/include.h create mode 100644 sources/shiboken2/ApiExtractor/merge.xsl create mode 100644 sources/shiboken2/ApiExtractor/parser/codemodel.cpp create mode 100644 sources/shiboken2/ApiExtractor/parser/codemodel.h create mode 100644 sources/shiboken2/ApiExtractor/parser/codemodel_enums.h create mode 100644 sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h create mode 100644 sources/shiboken2/ApiExtractor/qtdocparser.cpp create mode 100644 sources/shiboken2/ApiExtractor/qtdocparser.h create mode 100644 sources/shiboken2/ApiExtractor/reporthandler.cpp create mode 100644 sources/shiboken2/ApiExtractor/reporthandler.h create mode 100644 sources/shiboken2/ApiExtractor/symbols.filter create mode 100644 sources/shiboken2/ApiExtractor/tests/CMakeLists.txt create mode 100644 sources/shiboken2/ApiExtractor/tests/a.xml create mode 100644 sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testaddfunction.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testarrayargument.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testcodeinjection.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testcontainer.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testcontainer.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testconversionoperator.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testconversionruletag.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testconversionruletag.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testctorinformation.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testctorinformation.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testdroptypeentries.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testdtorinformation.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testdtorinformation.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testenum.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testenum.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testextrainclude.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testfunctiontag.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testfunctiontag.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testimplicitconversions.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testinserttemplate.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testnamespace.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testnamespace.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testnestedtypes.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testrefcounttag.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testreferencetopointer.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testreferencetopointer.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testremovefield.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testremovefield.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testremoveimplconv.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testremoveimplconv.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testresolvetype.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testresolvetype.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testreverseoperators.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testtemplates.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testtemplates.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testtoposort.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testtoposort.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testtyperevision.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testutil.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.h create mode 100644 sources/shiboken2/ApiExtractor/tests/testvoidarg.cpp create mode 100644 sources/shiboken2/ApiExtractor/tests/testvoidarg.h create mode 100644 sources/shiboken2/ApiExtractor/tests/utf8code.txt create mode 100644 sources/shiboken2/ApiExtractor/typedatabase.cpp create mode 100644 sources/shiboken2/ApiExtractor/typedatabase.h create mode 100644 sources/shiboken2/ApiExtractor/typedatabase_typedefs.h create mode 100644 sources/shiboken2/ApiExtractor/typeparser.cpp create mode 100644 sources/shiboken2/ApiExtractor/typeparser.h create mode 100644 sources/shiboken2/ApiExtractor/typesystem.cpp create mode 100644 sources/shiboken2/ApiExtractor/typesystem.h create mode 100644 sources/shiboken2/ApiExtractor/typesystem_enums.h create mode 100644 sources/shiboken2/ApiExtractor/typesystem_p.h create mode 100644 sources/shiboken2/ApiExtractor/typesystem_typedefs.h create mode 100644 sources/shiboken2/CMakeLists.txt create mode 100644 sources/shiboken2/COPYING create mode 100644 sources/shiboken2/COPYING.libsample create mode 100644 sources/shiboken2/COPYING.libshiboken create mode 100644 sources/shiboken2/Doxyfile create mode 100644 sources/shiboken2/LICENSE.GPLv3 create mode 100644 sources/shiboken2/LICENSE.LGPLv21 create mode 100644 sources/shiboken2/LICENSE.LGPLv3 create mode 100644 sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL create mode 100644 sources/shiboken2/README.md create mode 100644 sources/shiboken2/cmake_uninstall.cmake create mode 100644 sources/shiboken2/data/CMakeLists.txt create mode 100644 sources/shiboken2/data/GeneratorRunnerConfig.cmake.in create mode 100644 sources/shiboken2/data/GeneratorRunnerConfigVersion.cmake.in create mode 100644 sources/shiboken2/data/Shiboken2Config-spec.cmake.in create mode 100644 sources/shiboken2/data/Shiboken2Config.cmake.in create mode 100644 sources/shiboken2/data/Shiboken2ConfigVersion.cmake.in create mode 120000 sources/shiboken2/data/docgenerator.1 create mode 100644 sources/shiboken2/data/generatorrunner.1 create mode 100644 sources/shiboken2/data/generatorrunner.pc.in create mode 100644 sources/shiboken2/data/shiboken2.pc.in create mode 100644 sources/shiboken2/doc/CMakeLists.txt create mode 100644 sources/shiboken2/doc/_templates/index.html create mode 100644 sources/shiboken2/doc/_templates/layout.html create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/searchbox.html create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.png create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpg create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.png create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpg create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.png create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/pysidedocs.css create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.png create mode 100644 sources/shiboken2/doc/_themes/pysidedocs/theme.conf create mode 100644 sources/shiboken2/doc/codeinjectionsemantics.rst create mode 100644 sources/shiboken2/doc/commandlineoptions.rst create mode 100644 sources/shiboken2/doc/conf.py.in create mode 100644 sources/shiboken2/doc/contents.rst create mode 100644 sources/shiboken2/doc/dependency-pyqtb.svg create mode 100644 sources/shiboken2/doc/dependency-pyside.svg create mode 100644 sources/shiboken2/doc/faq.rst create mode 100644 sources/shiboken2/doc/images/.directory create mode 100644 sources/shiboken2/doc/images/bindinggen-development.png create mode 100644 sources/shiboken2/doc/images/bindinggen-development.svg create mode 100644 sources/shiboken2/doc/images/boostgen.png create mode 100644 sources/shiboken2/doc/images/boostqtarch.png create mode 100644 sources/shiboken2/doc/images/boostqtarch.svg create mode 100644 sources/shiboken2/doc/images/converter.dot create mode 100644 sources/shiboken2/doc/images/converter.png create mode 100644 sources/shiboken2/doc/images/genrunnerarch.png create mode 100644 sources/shiboken2/doc/images/genrunnerarch.svg create mode 100644 sources/shiboken2/doc/overview.rst create mode 100644 sources/shiboken2/doc/ownership.rst create mode 100644 sources/shiboken2/doc/projectfile.rst create mode 100644 sources/shiboken2/doc/sequenceprotocol.rst create mode 100644 sources/shiboken2/doc/shiboken2.1 create mode 100644 sources/shiboken2/doc/shibokenmodule.rst create mode 100644 sources/shiboken2/doc/typeconverters.rst create mode 100644 sources/shiboken2/doc/typesystemvariables.rst create mode 100644 sources/shiboken2/doc/wordsofadvice.rst create mode 100644 sources/shiboken2/generator/CMakeLists.txt create mode 100644 sources/shiboken2/generator/generator.cpp create mode 100644 sources/shiboken2/generator/generator.h create mode 100644 sources/shiboken2/generator/main.cpp create mode 100644 sources/shiboken2/generator/qtdoc/CMakeLists.txt create mode 100644 sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp create mode 100644 sources/shiboken2/generator/qtdoc/qtdocgenerator.h create mode 100644 sources/shiboken2/generator/shiboken2/CMakeLists.txt create mode 100644 sources/shiboken2/generator/shiboken2/cppgenerator.cpp create mode 100644 sources/shiboken2/generator/shiboken2/cppgenerator.h create mode 100644 sources/shiboken2/generator/shiboken2/headergenerator.cpp create mode 100644 sources/shiboken2/generator/shiboken2/headergenerator.h create mode 100644 sources/shiboken2/generator/shiboken2/overloaddata.cpp create mode 100644 sources/shiboken2/generator/shiboken2/overloaddata.h create mode 100644 sources/shiboken2/generator/shiboken2/shibokengenerator.cpp create mode 100644 sources/shiboken2/generator/shiboken2/shibokengenerator.h create mode 100644 sources/shiboken2/generator/shibokenconfig.h.in create mode 100644 sources/shiboken2/generatorrunnerconfig.h.in create mode 100644 sources/shiboken2/generatorrunnermacros.h create mode 100644 sources/shiboken2/generators/shiboken/shiboken.cpp create mode 100644 sources/shiboken2/header.COMM create mode 100644 sources/shiboken2/header.LGPL-ONLY create mode 100644 sources/shiboken2/header.LGPL21 create mode 100644 sources/shiboken2/header.LGPL3 create mode 100644 sources/shiboken2/header.LGPL3-COMM create mode 100644 sources/shiboken2/icecc.cmake create mode 100644 sources/shiboken2/libshiboken/CMakeLists.txt create mode 100644 sources/shiboken2/libshiboken/autodecref.h create mode 100644 sources/shiboken2/libshiboken/basewrapper.cpp create mode 100644 sources/shiboken2/libshiboken/basewrapper.h create mode 100644 sources/shiboken2/libshiboken/basewrapper_p.h create mode 100644 sources/shiboken2/libshiboken/bindingmanager.cpp create mode 100644 sources/shiboken2/libshiboken/bindingmanager.h create mode 100644 sources/shiboken2/libshiboken/conversions.h create mode 100644 sources/shiboken2/libshiboken/debugfreehook.cpp create mode 100644 sources/shiboken2/libshiboken/debugfreehook.h create mode 100644 sources/shiboken2/libshiboken/gilstate.cpp create mode 100644 sources/shiboken2/libshiboken/gilstate.h create mode 100644 sources/shiboken2/libshiboken/helper.cpp create mode 100644 sources/shiboken2/libshiboken/helper.h create mode 100644 sources/shiboken2/libshiboken/python25compat.h create mode 100644 sources/shiboken2/libshiboken/sbkconverter.cpp create mode 100644 sources/shiboken2/libshiboken/sbkconverter.h create mode 100644 sources/shiboken2/libshiboken/sbkconverter_p.h create mode 100644 sources/shiboken2/libshiboken/sbkdbg.h create mode 100644 sources/shiboken2/libshiboken/sbkenum.cpp create mode 100644 sources/shiboken2/libshiboken/sbkenum.h create mode 100644 sources/shiboken2/libshiboken/sbkmodule.cpp create mode 100644 sources/shiboken2/libshiboken/sbkmodule.h create mode 100644 sources/shiboken2/libshiboken/sbkpython.h create mode 100644 sources/shiboken2/libshiboken/sbkstring.cpp create mode 100644 sources/shiboken2/libshiboken/sbkstring.h create mode 100644 sources/shiboken2/libshiboken/sbkversion.h.in create mode 100644 sources/shiboken2/libshiboken/shiboken.h create mode 100644 sources/shiboken2/libshiboken/shibokenbuffer.cpp create mode 100644 sources/shiboken2/libshiboken/shibokenbuffer.h create mode 100644 sources/shiboken2/libshiboken/shibokenmacros.h create mode 100644 sources/shiboken2/libshiboken/threadstatesaver.cpp create mode 100644 sources/shiboken2/libshiboken/threadstatesaver.h create mode 100644 sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp create mode 100644 sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h create mode 100644 sources/shiboken2/libshiboken/typeresolver.cpp create mode 100644 sources/shiboken2/libshiboken/typeresolver.h create mode 100644 sources/shiboken2/shibokenmodule/CMakeLists.txt create mode 100644 sources/shiboken2/shibokenmodule/nothing.h create mode 100644 sources/shiboken2/shibokenmodule/shibokenmodule.txt.in create mode 100644 sources/shiboken2/shibokenmodule/typesystem_shiboken.xml create mode 100644 sources/shiboken2/tests/CMakeLists.txt create mode 100644 sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt create mode 100644 sources/shiboken2/tests/dumpcodemodel/main.cpp create mode 100644 sources/shiboken2/tests/libminimal/CMakeLists.txt create mode 100644 sources/shiboken2/tests/libminimal/libminimalmacros.h create mode 100644 sources/shiboken2/tests/libminimal/listuser.cpp create mode 100644 sources/shiboken2/tests/libminimal/listuser.h create mode 100644 sources/shiboken2/tests/libminimal/minbool.h create mode 100644 sources/shiboken2/tests/libminimal/obj.cpp create mode 100644 sources/shiboken2/tests/libminimal/obj.h create mode 100644 sources/shiboken2/tests/libminimal/typedef.cpp create mode 100644 sources/shiboken2/tests/libminimal/typedef.h create mode 100644 sources/shiboken2/tests/libminimal/val.h create mode 100644 sources/shiboken2/tests/libother/CMakeLists.txt create mode 100644 sources/shiboken2/tests/libother/extendsnoimplicitconversion.h create mode 100644 sources/shiboken2/tests/libother/libothermacros.h create mode 100644 sources/shiboken2/tests/libother/number.cpp create mode 100644 sources/shiboken2/tests/libother/number.h create mode 100644 sources/shiboken2/tests/libother/otherderived.cpp create mode 100644 sources/shiboken2/tests/libother/otherderived.h create mode 100644 sources/shiboken2/tests/libother/othermultiplederived.cpp create mode 100644 sources/shiboken2/tests/libother/othermultiplederived.h create mode 100644 sources/shiboken2/tests/libother/otherobjecttype.cpp create mode 100644 sources/shiboken2/tests/libother/otherobjecttype.h create mode 100644 sources/shiboken2/tests/libsample/CMakeLists.txt create mode 100644 sources/shiboken2/tests/libsample/abstract.cpp create mode 100644 sources/shiboken2/tests/libsample/abstract.h create mode 100644 sources/shiboken2/tests/libsample/blackbox.cpp create mode 100644 sources/shiboken2/tests/libsample/blackbox.h create mode 100644 sources/shiboken2/tests/libsample/bucket.cpp create mode 100644 sources/shiboken2/tests/libsample/bucket.h create mode 100644 sources/shiboken2/tests/libsample/bytearray.cpp create mode 100644 sources/shiboken2/tests/libsample/bytearray.h create mode 100644 sources/shiboken2/tests/libsample/collector.cpp create mode 100644 sources/shiboken2/tests/libsample/collector.h create mode 100644 sources/shiboken2/tests/libsample/complex.cpp create mode 100644 sources/shiboken2/tests/libsample/complex.h create mode 100644 sources/shiboken2/tests/libsample/ctorconvrule.h create mode 100644 sources/shiboken2/tests/libsample/cvlist.h create mode 100644 sources/shiboken2/tests/libsample/derived.cpp create mode 100644 sources/shiboken2/tests/libsample/derived.h create mode 100644 sources/shiboken2/tests/libsample/echo.cpp create mode 100644 sources/shiboken2/tests/libsample/echo.h create mode 100644 sources/shiboken2/tests/libsample/expression.cpp create mode 100644 sources/shiboken2/tests/libsample/expression.h create mode 100644 sources/shiboken2/tests/libsample/filter.cpp create mode 100644 sources/shiboken2/tests/libsample/filter.h create mode 100644 sources/shiboken2/tests/libsample/functions.cpp create mode 100644 sources/shiboken2/tests/libsample/functions.h create mode 100644 sources/shiboken2/tests/libsample/handle.cpp create mode 100644 sources/shiboken2/tests/libsample/handle.h create mode 100644 sources/shiboken2/tests/libsample/implicitconv.cpp create mode 100644 sources/shiboken2/tests/libsample/implicitconv.h create mode 100644 sources/shiboken2/tests/libsample/injectcode.cpp create mode 100644 sources/shiboken2/tests/libsample/injectcode.h create mode 100644 sources/shiboken2/tests/libsample/libsamplemacros.h create mode 100644 sources/shiboken2/tests/libsample/list.h create mode 100644 sources/shiboken2/tests/libsample/listuser.cpp create mode 100644 sources/shiboken2/tests/libsample/listuser.h create mode 100644 sources/shiboken2/tests/libsample/main.cpp create mode 100644 sources/shiboken2/tests/libsample/mapuser.cpp create mode 100644 sources/shiboken2/tests/libsample/mapuser.h create mode 100644 sources/shiboken2/tests/libsample/modelindex.h create mode 100644 sources/shiboken2/tests/libsample/modifications.cpp create mode 100644 sources/shiboken2/tests/libsample/modifications.h create mode 100644 sources/shiboken2/tests/libsample/modified_constructor.cpp create mode 100644 sources/shiboken2/tests/libsample/modified_constructor.h create mode 100644 sources/shiboken2/tests/libsample/multiple_derived.cpp create mode 100644 sources/shiboken2/tests/libsample/multiple_derived.h create mode 100644 sources/shiboken2/tests/libsample/noimplicitconversion.h create mode 100644 sources/shiboken2/tests/libsample/nondefaultctor.h create mode 100644 sources/shiboken2/tests/libsample/null.h create mode 100644 sources/shiboken2/tests/libsample/objectmodel.cpp create mode 100644 sources/shiboken2/tests/libsample/objectmodel.h create mode 100644 sources/shiboken2/tests/libsample/objecttype.cpp create mode 100644 sources/shiboken2/tests/libsample/objecttype.h create mode 100644 sources/shiboken2/tests/libsample/objecttypebyvalue.h create mode 100644 sources/shiboken2/tests/libsample/objecttypeholder.cpp create mode 100644 sources/shiboken2/tests/libsample/objecttypeholder.h create mode 100644 sources/shiboken2/tests/libsample/objecttypelayout.cpp create mode 100644 sources/shiboken2/tests/libsample/objecttypelayout.h create mode 100644 sources/shiboken2/tests/libsample/objecttypeoperators.cpp create mode 100644 sources/shiboken2/tests/libsample/objecttypeoperators.h create mode 100644 sources/shiboken2/tests/libsample/objectview.cpp create mode 100644 sources/shiboken2/tests/libsample/objectview.h create mode 100644 sources/shiboken2/tests/libsample/oddbool.h create mode 100644 sources/shiboken2/tests/libsample/onlycopy.cpp create mode 100644 sources/shiboken2/tests/libsample/onlycopy.h create mode 100644 sources/shiboken2/tests/libsample/overload.cpp create mode 100644 sources/shiboken2/tests/libsample/overload.h create mode 100644 sources/shiboken2/tests/libsample/overloadsort.cpp create mode 100644 sources/shiboken2/tests/libsample/overloadsort.h create mode 100644 sources/shiboken2/tests/libsample/pairuser.cpp create mode 100644 sources/shiboken2/tests/libsample/pairuser.h create mode 100644 sources/shiboken2/tests/libsample/pen.cpp create mode 100644 sources/shiboken2/tests/libsample/pen.h create mode 100644 sources/shiboken2/tests/libsample/photon.cpp create mode 100644 sources/shiboken2/tests/libsample/photon.h create mode 100644 sources/shiboken2/tests/libsample/point.cpp create mode 100644 sources/shiboken2/tests/libsample/point.h create mode 100644 sources/shiboken2/tests/libsample/pointerholder.h create mode 100644 sources/shiboken2/tests/libsample/pointf.cpp create mode 100644 sources/shiboken2/tests/libsample/pointf.h create mode 100644 sources/shiboken2/tests/libsample/polygon.cpp create mode 100644 sources/shiboken2/tests/libsample/polygon.h create mode 100644 sources/shiboken2/tests/libsample/privatector.h create mode 100644 sources/shiboken2/tests/libsample/privatedtor.h create mode 100644 sources/shiboken2/tests/libsample/protected.cpp create mode 100644 sources/shiboken2/tests/libsample/protected.h create mode 100644 sources/shiboken2/tests/libsample/rect.h create mode 100644 sources/shiboken2/tests/libsample/reference.cpp create mode 100644 sources/shiboken2/tests/libsample/reference.h create mode 100644 sources/shiboken2/tests/libsample/removednamespaces.h create mode 100644 sources/shiboken2/tests/libsample/sample.cpp create mode 100644 sources/shiboken2/tests/libsample/sample.h create mode 100644 sources/shiboken2/tests/libsample/samplenamespace.cpp create mode 100644 sources/shiboken2/tests/libsample/samplenamespace.h create mode 100644 sources/shiboken2/tests/libsample/sbkdate.cpp create mode 100644 sources/shiboken2/tests/libsample/sbkdate.h create mode 100644 sources/shiboken2/tests/libsample/simplefile.cpp create mode 100644 sources/shiboken2/tests/libsample/simplefile.h create mode 100644 sources/shiboken2/tests/libsample/size.cpp create mode 100644 sources/shiboken2/tests/libsample/size.h create mode 100644 sources/shiboken2/tests/libsample/sometime.cpp create mode 100644 sources/shiboken2/tests/libsample/sometime.h create mode 100644 sources/shiboken2/tests/libsample/str.cpp create mode 100644 sources/shiboken2/tests/libsample/str.h create mode 100644 sources/shiboken2/tests/libsample/strlist.cpp create mode 100644 sources/shiboken2/tests/libsample/strlist.h create mode 100644 sources/shiboken2/tests/libsample/templateptr.cpp create mode 100644 sources/shiboken2/tests/libsample/templateptr.h create mode 100644 sources/shiboken2/tests/libsample/transform.cpp create mode 100644 sources/shiboken2/tests/libsample/transform.h create mode 100644 sources/shiboken2/tests/libsample/valueandvirtual.h create mode 100644 sources/shiboken2/tests/libsample/virtualmethods.cpp create mode 100644 sources/shiboken2/tests/libsample/virtualmethods.h create mode 100644 sources/shiboken2/tests/libsample/voidholder.h create mode 100644 sources/shiboken2/tests/libsmart/CMakeLists.txt create mode 100644 sources/shiboken2/tests/libsmart/libsmartmacros.h create mode 100644 sources/shiboken2/tests/libsmart/smart.cpp create mode 100644 sources/shiboken2/tests/libsmart/smart.h create mode 100644 sources/shiboken2/tests/minimalbinding/CMakeLists.txt create mode 100644 sources/shiboken2/tests/minimalbinding/global.h create mode 100644 sources/shiboken2/tests/minimalbinding/listuser_test.py create mode 100644 sources/shiboken2/tests/minimalbinding/minbool_test.py create mode 100644 sources/shiboken2/tests/minimalbinding/minimal-binding.txt.in create mode 100644 sources/shiboken2/tests/minimalbinding/obj_test.py create mode 100644 sources/shiboken2/tests/minimalbinding/typedef_test.py create mode 100644 sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml create mode 100644 sources/shiboken2/tests/minimalbinding/val_test.py create mode 100644 sources/shiboken2/tests/otherbinding/CMakeLists.txt create mode 100644 sources/shiboken2/tests/otherbinding/collector_external_operator_test.py create mode 100755 sources/shiboken2/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py create mode 100755 sources/shiboken2/tests/otherbinding/extended_multiply_operator_test.py create mode 100644 sources/shiboken2/tests/otherbinding/global.h create mode 100644 sources/shiboken2/tests/otherbinding/module_reload_test.py create mode 100755 sources/shiboken2/tests/otherbinding/new_ctor_operator_test.py create mode 100644 sources/shiboken2/tests/otherbinding/objtypehashes_test.py create mode 100644 sources/shiboken2/tests/otherbinding/other-binding.txt.in create mode 100644 sources/shiboken2/tests/otherbinding/otherderived_test.py create mode 100644 sources/shiboken2/tests/otherbinding/test_module_template.py create mode 100644 sources/shiboken2/tests/otherbinding/typediscovery_test.py create mode 100644 sources/shiboken2/tests/otherbinding/typesystem_other.xml create mode 100755 sources/shiboken2/tests/otherbinding/usersprimitivefromothermodule_test.py create mode 100644 sources/shiboken2/tests/otherbinding/wrongctor_test.py create mode 100644 sources/shiboken2/tests/py3k.py create mode 100644 sources/shiboken2/tests/py3kcompat.py create mode 100644 sources/shiboken2/tests/samplebinding/CMakeLists.txt create mode 100644 sources/shiboken2/tests/samplebinding/__del___test.py create mode 100644 sources/shiboken2/tests/samplebinding/abstract_test.py create mode 100644 sources/shiboken2/tests/samplebinding/addedfunction_test.py create mode 100644 sources/shiboken2/tests/samplebinding/addedfunction_with_container_args_test.py create mode 100644 sources/shiboken2/tests/samplebinding/argumentmodifications_test.py create mode 100644 sources/shiboken2/tests/samplebinding/bug_554_test.py create mode 100644 sources/shiboken2/tests/samplebinding/bug_704_test.py create mode 100644 sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp create mode 100644 sources/shiboken2/tests/samplebinding/bytearray_test.py create mode 100644 sources/shiboken2/tests/samplebinding/child_return_test.py create mode 100644 sources/shiboken2/tests/samplebinding/class_fields_test.py create mode 100644 sources/shiboken2/tests/samplebinding/collector_test.py create mode 100644 sources/shiboken2/tests/samplebinding/complex_test.py create mode 100644 sources/shiboken2/tests/samplebinding/conversion_operator_test.py create mode 100644 sources/shiboken2/tests/samplebinding/copy_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ctorconvrule_test.py create mode 100644 sources/shiboken2/tests/samplebinding/cyclic_test.py create mode 100644 sources/shiboken2/tests/samplebinding/date_test.py create mode 100644 sources/shiboken2/tests/samplebinding/decisor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/delete_test.py create mode 100644 sources/shiboken2/tests/samplebinding/deprecated_test.py create mode 100644 sources/shiboken2/tests/samplebinding/derived_test.py create mode 100644 sources/shiboken2/tests/samplebinding/duck_punching_test.py create mode 100644 sources/shiboken2/tests/samplebinding/echo_test.py create mode 100644 sources/shiboken2/tests/samplebinding/enum_test.py create mode 100644 sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py create mode 100644 sources/shiboken2/tests/samplebinding/event_loop_call_virtual_test.py create mode 100644 sources/shiboken2/tests/samplebinding/event_loop_thread_test.py create mode 100644 sources/shiboken2/tests/samplebinding/filter_test.py create mode 100644 sources/shiboken2/tests/samplebinding/global.h create mode 100644 sources/shiboken2/tests/samplebinding/handleholder_test.py create mode 100644 sources/shiboken2/tests/samplebinding/hashabletype_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ignorederefop_test.py create mode 100644 sources/shiboken2/tests/samplebinding/implicitconv_numerical_test.py create mode 100644 sources/shiboken2/tests/samplebinding/implicitconv_test.py create mode 100755 sources/shiboken2/tests/samplebinding/inheritanceandscope_test.py create mode 100644 sources/shiboken2/tests/samplebinding/injectcode_test.py create mode 100644 sources/shiboken2/tests/samplebinding/innerclass_test.py create mode 100644 sources/shiboken2/tests/samplebinding/intlist_test.py create mode 100644 sources/shiboken2/tests/samplebinding/invalid_virtual_return_test.py create mode 100644 sources/shiboken2/tests/samplebinding/keep_reference_test.py create mode 100644 sources/shiboken2/tests/samplebinding/list_test.py create mode 100644 sources/shiboken2/tests/samplebinding/lock_test.py create mode 100644 sources/shiboken2/tests/samplebinding/map_test.py create mode 100644 sources/shiboken2/tests/samplebinding/metaclass_test.py create mode 100644 sources/shiboken2/tests/samplebinding/mi_virtual_methods_test.py create mode 100644 sources/shiboken2/tests/samplebinding/mixed_mi_test.py create mode 100644 sources/shiboken2/tests/samplebinding/modelindex_test.py create mode 100644 sources/shiboken2/tests/samplebinding/modelview_test.py create mode 100644 sources/shiboken2/tests/samplebinding/modifications_test.py create mode 100644 sources/shiboken2/tests/samplebinding/modified_constructor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/modifiedvirtualmethods_test.py create mode 100644 sources/shiboken2/tests/samplebinding/multi_cpp_inheritance_test.py create mode 100644 sources/shiboken2/tests/samplebinding/multiple_derived_test.py create mode 100644 sources/shiboken2/tests/samplebinding/namespace_test.py create mode 100644 sources/shiboken2/tests/samplebinding/newdivision_test.py create mode 100644 sources/shiboken2/tests/samplebinding/nondefaultctor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/nonzero_test.py create mode 100644 sources/shiboken2/tests/samplebinding/numericaltypedef_test.py create mode 100644 sources/shiboken2/tests/samplebinding/numpy_test.py create mode 100644 sources/shiboken2/tests/samplebinding/objecttype_test.py create mode 100755 sources/shiboken2/tests/samplebinding/objecttype_with_named_args_test.py create mode 100644 sources/shiboken2/tests/samplebinding/objecttypebyvalue_test.py create mode 100644 sources/shiboken2/tests/samplebinding/objecttypelayout_test.py create mode 100644 sources/shiboken2/tests/samplebinding/objecttypeoperators_test.py create mode 100644 sources/shiboken2/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py create mode 100644 sources/shiboken2/tests/samplebinding/oddbool_test.py create mode 100644 sources/shiboken2/tests/samplebinding/oldstyleclass_as_number_test.py create mode 100644 sources/shiboken2/tests/samplebinding/onlycopyclass_test.py create mode 100644 sources/shiboken2/tests/samplebinding/overflow_test.py create mode 100644 sources/shiboken2/tests/samplebinding/overload_sorting_test.py create mode 100644 sources/shiboken2/tests/samplebinding/overload_test.py create mode 100644 sources/shiboken2/tests/samplebinding/overloadwithdefault_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_argument_invalidation_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_delete_child_in_cpp_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_delete_child_in_python_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_delete_parent_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_invalidate_after_use_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_invalidate_child_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_invalidate_parent_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_reparenting_test.py create mode 100644 sources/shiboken2/tests/samplebinding/ownership_transference_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pair_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pen_test.py create mode 100644 sources/shiboken2/tests/samplebinding/point_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pointerholder_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pointf_test.py create mode 100644 sources/shiboken2/tests/samplebinding/primitivereferenceargument_test.py create mode 100644 sources/shiboken2/tests/samplebinding/privatector_test.py create mode 100644 sources/shiboken2/tests/samplebinding/privatedtor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/protected_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pstrlist_test.py create mode 100644 sources/shiboken2/tests/samplebinding/pystr_test.py create mode 100644 sources/shiboken2/tests/samplebinding/python_thread_test.py create mode 100644 sources/shiboken2/tests/samplebinding/receive_null_cstring_test.py create mode 100644 sources/shiboken2/tests/samplebinding/reference_test.py create mode 100644 sources/shiboken2/tests/samplebinding/referencetopointer_test.py create mode 100644 sources/shiboken2/tests/samplebinding/return_null_test.py create mode 100644 sources/shiboken2/tests/samplebinding/richcompare_test.py create mode 100644 sources/shiboken2/tests/samplebinding/sample-binding.txt.in create mode 100644 sources/shiboken2/tests/samplebinding/sample_test.py create mode 100644 sources/shiboken2/tests/samplebinding/simplefile_glue.cpp create mode 100644 sources/shiboken2/tests/samplebinding/simplefile_test.py create mode 100644 sources/shiboken2/tests/samplebinding/size_test.py create mode 100644 sources/shiboken2/tests/samplebinding/static_nonstatic_methods_test.py create mode 100644 sources/shiboken2/tests/samplebinding/str_test.py create mode 100644 sources/shiboken2/tests/samplebinding/strlist_test.py create mode 100644 sources/shiboken2/tests/samplebinding/templateinheritingclass_test.py create mode 100644 sources/shiboken2/tests/samplebinding/time_test.py create mode 100644 sources/shiboken2/tests/samplebinding/transform_test.py create mode 100644 sources/shiboken2/tests/samplebinding/typeconverters_test.py create mode 100644 sources/shiboken2/tests/samplebinding/typedealloc_test.py create mode 100644 sources/shiboken2/tests/samplebinding/typedtordoublefree_test.py create mode 100644 sources/shiboken2/tests/samplebinding/typesystem_sample.xml create mode 100644 sources/shiboken2/tests/samplebinding/unsafe_parent_test.py create mode 100644 sources/shiboken2/tests/samplebinding/useraddedctor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/virtualdtor_test.py create mode 100644 sources/shiboken2/tests/samplebinding/virtualmethods_test.py create mode 100644 sources/shiboken2/tests/samplebinding/visibilitychange_test.py create mode 100644 sources/shiboken2/tests/samplebinding/voidholder_test.py create mode 100644 sources/shiboken2/tests/samplebinding/weakref_test.py create mode 100644 sources/shiboken2/tests/samplebinding/writableclassdict_test.py create mode 100644 sources/shiboken2/tests/shibokenmodule/module_test.py create mode 100644 sources/shiboken2/tests/smartbinding/CMakeLists.txt create mode 100644 sources/shiboken2/tests/smartbinding/global.h create mode 100644 sources/shiboken2/tests/smartbinding/smart-binding.txt.in create mode 100644 sources/shiboken2/tests/smartbinding/smart_pointer_test.py create mode 100644 sources/shiboken2/tests/smartbinding/typesystem_smart.xml create mode 100644 sources/shiboken2/tests/sphinxtabletest.cpp create mode 100644 sources/shiboken2/tests/sphinxtabletest.h create mode 100644 sources/shiboken2/tests/test_generator/CMakeLists.txt create mode 100644 sources/shiboken2/tests/test_generator/dummygenerator.cpp create mode 100644 sources/shiboken2/tests/test_generator/dummygenerator.h create mode 100644 sources/shiboken2/tests/test_generator/dummygentest-project.txt.in create mode 100644 sources/shiboken2/tests/test_generator/dummygentest.cpp create mode 100644 sources/shiboken2/tests/test_generator/dummygentest.h create mode 100644 sources/shiboken2/tests/test_generator/dummygentestconfig.h.in create mode 100644 sources/shiboken2/tests/test_generator/main.cpp create mode 100644 sources/shiboken2/tests/test_generator/run_test.cmake create mode 100644 sources/shiboken2/tests/test_generator/test_global.h create mode 100644 sources/shiboken2/tests/test_generator/test_typesystem.xml delete mode 100644 tests/CMakeLists.txt delete mode 100644 tests/dumpcodemodel/CMakeLists.txt delete mode 100644 tests/dumpcodemodel/main.cpp delete mode 100644 tests/libminimal/CMakeLists.txt delete mode 100644 tests/libminimal/libminimalmacros.h delete mode 100644 tests/libminimal/listuser.cpp delete mode 100644 tests/libminimal/listuser.h delete mode 100644 tests/libminimal/minbool.h delete mode 100644 tests/libminimal/obj.cpp delete mode 100644 tests/libminimal/obj.h delete mode 100644 tests/libminimal/typedef.cpp delete mode 100644 tests/libminimal/typedef.h delete mode 100644 tests/libminimal/val.h delete mode 100644 tests/libother/CMakeLists.txt delete mode 100644 tests/libother/extendsnoimplicitconversion.h delete mode 100644 tests/libother/libothermacros.h delete mode 100644 tests/libother/number.cpp delete mode 100644 tests/libother/number.h delete mode 100644 tests/libother/otherderived.cpp delete mode 100644 tests/libother/otherderived.h delete mode 100644 tests/libother/othermultiplederived.cpp delete mode 100644 tests/libother/othermultiplederived.h delete mode 100644 tests/libother/otherobjecttype.cpp delete mode 100644 tests/libother/otherobjecttype.h delete mode 100644 tests/libsample/CMakeLists.txt delete mode 100644 tests/libsample/abstract.cpp delete mode 100644 tests/libsample/abstract.h delete mode 100644 tests/libsample/blackbox.cpp delete mode 100644 tests/libsample/blackbox.h delete mode 100644 tests/libsample/bucket.cpp delete mode 100644 tests/libsample/bucket.h delete mode 100644 tests/libsample/bytearray.cpp delete mode 100644 tests/libsample/bytearray.h delete mode 100644 tests/libsample/collector.cpp delete mode 100644 tests/libsample/collector.h delete mode 100644 tests/libsample/complex.cpp delete mode 100644 tests/libsample/complex.h delete mode 100644 tests/libsample/ctorconvrule.h delete mode 100644 tests/libsample/cvlist.h delete mode 100644 tests/libsample/derived.cpp delete mode 100644 tests/libsample/derived.h delete mode 100644 tests/libsample/echo.cpp delete mode 100644 tests/libsample/echo.h delete mode 100644 tests/libsample/expression.cpp delete mode 100644 tests/libsample/expression.h delete mode 100644 tests/libsample/filter.cpp delete mode 100644 tests/libsample/filter.h delete mode 100644 tests/libsample/functions.cpp delete mode 100644 tests/libsample/functions.h delete mode 100644 tests/libsample/handle.cpp delete mode 100644 tests/libsample/handle.h delete mode 100644 tests/libsample/implicitconv.cpp delete mode 100644 tests/libsample/implicitconv.h delete mode 100644 tests/libsample/injectcode.cpp delete mode 100644 tests/libsample/injectcode.h delete mode 100644 tests/libsample/libsamplemacros.h delete mode 100644 tests/libsample/list.h delete mode 100644 tests/libsample/listuser.cpp delete mode 100644 tests/libsample/listuser.h delete mode 100644 tests/libsample/main.cpp delete mode 100644 tests/libsample/mapuser.cpp delete mode 100644 tests/libsample/mapuser.h delete mode 100644 tests/libsample/modelindex.h delete mode 100644 tests/libsample/modifications.cpp delete mode 100644 tests/libsample/modifications.h delete mode 100644 tests/libsample/modified_constructor.cpp delete mode 100644 tests/libsample/modified_constructor.h delete mode 100644 tests/libsample/multiple_derived.cpp delete mode 100644 tests/libsample/multiple_derived.h delete mode 100644 tests/libsample/noimplicitconversion.h delete mode 100644 tests/libsample/nondefaultctor.h delete mode 100644 tests/libsample/null.h delete mode 100644 tests/libsample/objectmodel.cpp delete mode 100644 tests/libsample/objectmodel.h delete mode 100644 tests/libsample/objecttype.cpp delete mode 100644 tests/libsample/objecttype.h delete mode 100644 tests/libsample/objecttypebyvalue.h delete mode 100644 tests/libsample/objecttypeholder.cpp delete mode 100644 tests/libsample/objecttypeholder.h delete mode 100644 tests/libsample/objecttypelayout.cpp delete mode 100644 tests/libsample/objecttypelayout.h delete mode 100644 tests/libsample/objecttypeoperators.cpp delete mode 100644 tests/libsample/objecttypeoperators.h delete mode 100644 tests/libsample/objectview.cpp delete mode 100644 tests/libsample/objectview.h delete mode 100644 tests/libsample/oddbool.h delete mode 100644 tests/libsample/onlycopy.cpp delete mode 100644 tests/libsample/onlycopy.h delete mode 100644 tests/libsample/overload.cpp delete mode 100644 tests/libsample/overload.h delete mode 100644 tests/libsample/overloadsort.cpp delete mode 100644 tests/libsample/overloadsort.h delete mode 100644 tests/libsample/pairuser.cpp delete mode 100644 tests/libsample/pairuser.h delete mode 100644 tests/libsample/pen.cpp delete mode 100644 tests/libsample/pen.h delete mode 100644 tests/libsample/photon.cpp delete mode 100644 tests/libsample/photon.h delete mode 100644 tests/libsample/point.cpp delete mode 100644 tests/libsample/point.h delete mode 100644 tests/libsample/pointerholder.h delete mode 100644 tests/libsample/pointf.cpp delete mode 100644 tests/libsample/pointf.h delete mode 100644 tests/libsample/polygon.cpp delete mode 100644 tests/libsample/polygon.h delete mode 100644 tests/libsample/privatector.h delete mode 100644 tests/libsample/privatedtor.h delete mode 100644 tests/libsample/protected.cpp delete mode 100644 tests/libsample/protected.h delete mode 100644 tests/libsample/rect.h delete mode 100644 tests/libsample/reference.cpp delete mode 100644 tests/libsample/reference.h delete mode 100644 tests/libsample/removednamespaces.h delete mode 100644 tests/libsample/sample.cpp delete mode 100644 tests/libsample/sample.h delete mode 100644 tests/libsample/samplenamespace.cpp delete mode 100644 tests/libsample/samplenamespace.h delete mode 100644 tests/libsample/sbkdate.cpp delete mode 100644 tests/libsample/sbkdate.h delete mode 100644 tests/libsample/simplefile.cpp delete mode 100644 tests/libsample/simplefile.h delete mode 100644 tests/libsample/size.cpp delete mode 100644 tests/libsample/size.h delete mode 100644 tests/libsample/sometime.cpp delete mode 100644 tests/libsample/sometime.h delete mode 100644 tests/libsample/str.cpp delete mode 100644 tests/libsample/str.h delete mode 100644 tests/libsample/strlist.cpp delete mode 100644 tests/libsample/strlist.h delete mode 100644 tests/libsample/templateptr.cpp delete mode 100644 tests/libsample/templateptr.h delete mode 100644 tests/libsample/transform.cpp delete mode 100644 tests/libsample/transform.h delete mode 100644 tests/libsample/valueandvirtual.h delete mode 100644 tests/libsample/virtualmethods.cpp delete mode 100644 tests/libsample/virtualmethods.h delete mode 100644 tests/libsample/voidholder.h delete mode 100644 tests/libsmart/CMakeLists.txt delete mode 100644 tests/libsmart/libsmartmacros.h delete mode 100644 tests/libsmart/smart.cpp delete mode 100644 tests/libsmart/smart.h delete mode 100644 tests/minimalbinding/CMakeLists.txt delete mode 100644 tests/minimalbinding/global.h delete mode 100644 tests/minimalbinding/listuser_test.py delete mode 100644 tests/minimalbinding/minbool_test.py delete mode 100644 tests/minimalbinding/minimal-binding.txt.in delete mode 100644 tests/minimalbinding/obj_test.py delete mode 100644 tests/minimalbinding/typedef_test.py delete mode 100644 tests/minimalbinding/typesystem_minimal.xml delete mode 100644 tests/minimalbinding/val_test.py delete mode 100644 tests/otherbinding/CMakeLists.txt delete mode 100644 tests/otherbinding/collector_external_operator_test.py delete mode 100755 tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py delete mode 100755 tests/otherbinding/extended_multiply_operator_test.py delete mode 100644 tests/otherbinding/global.h delete mode 100644 tests/otherbinding/module_reload_test.py delete mode 100755 tests/otherbinding/new_ctor_operator_test.py delete mode 100644 tests/otherbinding/objtypehashes_test.py delete mode 100644 tests/otherbinding/other-binding.txt.in delete mode 100644 tests/otherbinding/otherderived_test.py delete mode 100644 tests/otherbinding/test_module_template.py delete mode 100644 tests/otherbinding/typediscovery_test.py delete mode 100644 tests/otherbinding/typesystem_other.xml delete mode 100755 tests/otherbinding/usersprimitivefromothermodule_test.py delete mode 100644 tests/otherbinding/wrongctor_test.py delete mode 100644 tests/py3k.py delete mode 100644 tests/py3kcompat.py delete mode 100644 tests/samplebinding/CMakeLists.txt delete mode 100644 tests/samplebinding/__del___test.py delete mode 100644 tests/samplebinding/abstract_test.py delete mode 100644 tests/samplebinding/addedfunction_test.py delete mode 100644 tests/samplebinding/addedfunction_with_container_args_test.py delete mode 100644 tests/samplebinding/argumentmodifications_test.py delete mode 100644 tests/samplebinding/bug_554_test.py delete mode 100644 tests/samplebinding/bug_704_test.py delete mode 100644 tests/samplebinding/bytearray_bufferprotocol.cpp delete mode 100644 tests/samplebinding/bytearray_test.py delete mode 100644 tests/samplebinding/child_return_test.py delete mode 100644 tests/samplebinding/class_fields_test.py delete mode 100644 tests/samplebinding/collector_test.py delete mode 100644 tests/samplebinding/complex_test.py delete mode 100644 tests/samplebinding/conversion_operator_test.py delete mode 100644 tests/samplebinding/copy_test.py delete mode 100644 tests/samplebinding/ctorconvrule_test.py delete mode 100644 tests/samplebinding/cyclic_test.py delete mode 100644 tests/samplebinding/date_test.py delete mode 100644 tests/samplebinding/decisor_test.py delete mode 100644 tests/samplebinding/delete_test.py delete mode 100644 tests/samplebinding/deprecated_test.py delete mode 100644 tests/samplebinding/derived_test.py delete mode 100644 tests/samplebinding/duck_punching_test.py delete mode 100644 tests/samplebinding/echo_test.py delete mode 100644 tests/samplebinding/enum_test.py delete mode 100644 tests/samplebinding/enumfromremovednamespace_test.py delete mode 100644 tests/samplebinding/event_loop_call_virtual_test.py delete mode 100644 tests/samplebinding/event_loop_thread_test.py delete mode 100644 tests/samplebinding/filter_test.py delete mode 100644 tests/samplebinding/global.h delete mode 100644 tests/samplebinding/handleholder_test.py delete mode 100644 tests/samplebinding/hashabletype_test.py delete mode 100644 tests/samplebinding/ignorederefop_test.py delete mode 100644 tests/samplebinding/implicitconv_numerical_test.py delete mode 100644 tests/samplebinding/implicitconv_test.py delete mode 100755 tests/samplebinding/inheritanceandscope_test.py delete mode 100644 tests/samplebinding/injectcode_test.py delete mode 100644 tests/samplebinding/innerclass_test.py delete mode 100644 tests/samplebinding/intlist_test.py delete mode 100644 tests/samplebinding/invalid_virtual_return_test.py delete mode 100644 tests/samplebinding/keep_reference_test.py delete mode 100644 tests/samplebinding/list_test.py delete mode 100644 tests/samplebinding/lock_test.py delete mode 100644 tests/samplebinding/map_test.py delete mode 100644 tests/samplebinding/metaclass_test.py delete mode 100644 tests/samplebinding/mi_virtual_methods_test.py delete mode 100644 tests/samplebinding/mixed_mi_test.py delete mode 100644 tests/samplebinding/modelindex_test.py delete mode 100644 tests/samplebinding/modelview_test.py delete mode 100644 tests/samplebinding/modifications_test.py delete mode 100644 tests/samplebinding/modified_constructor_test.py delete mode 100644 tests/samplebinding/modifiedvirtualmethods_test.py delete mode 100644 tests/samplebinding/multi_cpp_inheritance_test.py delete mode 100644 tests/samplebinding/multiple_derived_test.py delete mode 100644 tests/samplebinding/namespace_test.py delete mode 100644 tests/samplebinding/newdivision_test.py delete mode 100644 tests/samplebinding/nondefaultctor_test.py delete mode 100644 tests/samplebinding/nonzero_test.py delete mode 100644 tests/samplebinding/numericaltypedef_test.py delete mode 100644 tests/samplebinding/numpy_test.py delete mode 100644 tests/samplebinding/objecttype_test.py delete mode 100755 tests/samplebinding/objecttype_with_named_args_test.py delete mode 100644 tests/samplebinding/objecttypebyvalue_test.py delete mode 100644 tests/samplebinding/objecttypelayout_test.py delete mode 100644 tests/samplebinding/objecttypeoperators_test.py delete mode 100644 tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py delete mode 100644 tests/samplebinding/oddbool_test.py delete mode 100644 tests/samplebinding/oldstyleclass_as_number_test.py delete mode 100644 tests/samplebinding/onlycopyclass_test.py delete mode 100644 tests/samplebinding/overflow_test.py delete mode 100644 tests/samplebinding/overload_sorting_test.py delete mode 100644 tests/samplebinding/overload_test.py delete mode 100644 tests/samplebinding/overloadwithdefault_test.py delete mode 100644 tests/samplebinding/ownership_argument_invalidation_test.py delete mode 100644 tests/samplebinding/ownership_delete_child_in_cpp_test.py delete mode 100644 tests/samplebinding/ownership_delete_child_in_python_test.py delete mode 100644 tests/samplebinding/ownership_delete_parent_test.py delete mode 100644 tests/samplebinding/ownership_invalidate_after_use_test.py delete mode 100644 tests/samplebinding/ownership_invalidate_child_test.py delete mode 100644 tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py delete mode 100644 tests/samplebinding/ownership_invalidate_parent_test.py delete mode 100644 tests/samplebinding/ownership_reparenting_test.py delete mode 100644 tests/samplebinding/ownership_transference_test.py delete mode 100644 tests/samplebinding/pair_test.py delete mode 100644 tests/samplebinding/pen_test.py delete mode 100644 tests/samplebinding/point_test.py delete mode 100644 tests/samplebinding/pointerholder_test.py delete mode 100644 tests/samplebinding/pointf_test.py delete mode 100644 tests/samplebinding/primitivereferenceargument_test.py delete mode 100644 tests/samplebinding/privatector_test.py delete mode 100644 tests/samplebinding/privatedtor_test.py delete mode 100644 tests/samplebinding/protected_test.py delete mode 100644 tests/samplebinding/pstrlist_test.py delete mode 100644 tests/samplebinding/pystr_test.py delete mode 100644 tests/samplebinding/python_thread_test.py delete mode 100644 tests/samplebinding/receive_null_cstring_test.py delete mode 100644 tests/samplebinding/reference_test.py delete mode 100644 tests/samplebinding/referencetopointer_test.py delete mode 100644 tests/samplebinding/return_null_test.py delete mode 100644 tests/samplebinding/richcompare_test.py delete mode 100644 tests/samplebinding/sample-binding.txt.in delete mode 100644 tests/samplebinding/sample_test.py delete mode 100644 tests/samplebinding/simplefile_glue.cpp delete mode 100644 tests/samplebinding/simplefile_test.py delete mode 100644 tests/samplebinding/size_test.py delete mode 100644 tests/samplebinding/static_nonstatic_methods_test.py delete mode 100644 tests/samplebinding/str_test.py delete mode 100644 tests/samplebinding/strlist_test.py delete mode 100644 tests/samplebinding/templateinheritingclass_test.py delete mode 100644 tests/samplebinding/time_test.py delete mode 100644 tests/samplebinding/transform_test.py delete mode 100644 tests/samplebinding/typeconverters_test.py delete mode 100644 tests/samplebinding/typedealloc_test.py delete mode 100644 tests/samplebinding/typedtordoublefree_test.py delete mode 100644 tests/samplebinding/typesystem_sample.xml delete mode 100644 tests/samplebinding/unsafe_parent_test.py delete mode 100644 tests/samplebinding/useraddedctor_test.py delete mode 100644 tests/samplebinding/virtualdtor_test.py delete mode 100644 tests/samplebinding/virtualmethods_test.py delete mode 100644 tests/samplebinding/visibilitychange_test.py delete mode 100644 tests/samplebinding/voidholder_test.py delete mode 100644 tests/samplebinding/weakref_test.py delete mode 100644 tests/samplebinding/writableclassdict_test.py delete mode 100644 tests/shibokenmodule/module_test.py delete mode 100644 tests/smartbinding/CMakeLists.txt delete mode 100644 tests/smartbinding/global.h delete mode 100644 tests/smartbinding/smart-binding.txt.in delete mode 100644 tests/smartbinding/smart_pointer_test.py delete mode 100644 tests/smartbinding/typesystem_smart.xml delete mode 100644 tests/sphinxtabletest.cpp delete mode 100644 tests/sphinxtabletest.h delete mode 100644 tests/test_generator/CMakeLists.txt delete mode 100644 tests/test_generator/dummygenerator.cpp delete mode 100644 tests/test_generator/dummygenerator.h delete mode 100644 tests/test_generator/dummygentest-project.txt.in delete mode 100644 tests/test_generator/dummygentest.cpp delete mode 100644 tests/test_generator/dummygentest.h delete mode 100644 tests/test_generator/dummygentestconfig.h.in delete mode 100644 tests/test_generator/main.cpp delete mode 100644 tests/test_generator/run_test.cmake delete mode 100644 tests/test_generator/test_global.h delete mode 100644 tests/test_generator/test_typesystem.xml diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index adbe833c1..000000000 --- a/.gitattributes +++ /dev/null @@ -1,2 +0,0 @@ -.gitignore export-ignore -.gitattributes export-ignore diff --git a/.gitignore b/.gitignore deleted file mode 100644 index adb1e4594..000000000 --- a/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -build -.kdev4 -*.log -*.pyc -*.o -*.so -.*.swp -*.kdev4 diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 4bb16b2dd..000000000 --- a/AUTHORS +++ /dev/null @@ -1,12 +0,0 @@ -John Cummings -John Ehresman -Roman Lacko -Matthew Woehlke -Anderson Lizardo -Bruno Araujo -Hugo Parente Lima -Lauro Moura -Luciano Wolf -Marcelo Lira -Renato Araujo Oliveira Filho - diff --git a/ApiExtractor/AUTHORS b/ApiExtractor/AUTHORS deleted file mode 100644 index 6e802fb53..000000000 --- a/ApiExtractor/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -Anderson Lizardo -Bruno Araujo -Hugo Parente Lima -Lauro Moura -Luciano Wolf -Marcelo Lira -Renato Araujo Oliveira Filho - diff --git a/ApiExtractor/CMakeLists.txt b/ApiExtractor/CMakeLists.txt deleted file mode 100644 index 6cb3e0185..000000000 --- a/ApiExtractor/CMakeLists.txt +++ /dev/null @@ -1,90 +0,0 @@ -project(apiextractor) - -find_package(LibXml2 2.6.32) -find_package(LibXslt 1.1.19) - -option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE) - -if (NOT DISABLE_DOCSTRINGS) - if (NOT LIBXSLT_FOUND OR NOT LIBXML2_FOUND) - set(DISABLE_DOCSTRINGS TRUE CACHE BOOL "Disable doc strings" PARENT_SCOPE) - set(DISABLE_DOCSTRINGS TRUE) - message(WARNING "libxslt and/or libxml not found, disabling support for doc strings!") - endif() -endif() - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release) -endif() - -if(BUILD_TESTS) - set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) -endif () - -set(QT_USE_QTCORE 1) -set(QT_USE_QTXML 1) -add_definitions(-DQT_PLUGIN) -add_definitions(-DQT_SHARED) -add_definitions(-DRXX_ALLOCATOR_INIT_0) - -set(apiextractor_SRC -apiextractor.cpp -abstractmetabuilder.cpp -abstractmetalang.cpp -fileout.cpp -graph.cpp -reporthandler.cpp -typeparser.cpp -typesystem.cpp -include.cpp -typedatabase.cpp -# Clang -clangparser/compilersupport.cpp -clangparser/clangparser.cpp -clangparser/clangbuilder.cpp -clangparser/clangdebugutils.cpp -clangparser/clangutils.cpp -# Old parser -parser/codemodel.cpp -) - -set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES}) -set(APIEXTRACTOR_EXTRA_LIBRARIES ${CLANG_EXTRA_LIBRARIES}) - -if (NOT DISABLE_DOCSTRINGS) - set(apiextractor_SRC - ${apiextractor_SRC} - docparser.cpp - doxygenparser.cpp - qtdocparser.cpp - ) - set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) - set(APIEXTRACTOR_EXTRA_LIBRARIES ${APIEXTRACTOR_EXTRA_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) -endif() - -set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) - -set(CMAKE_AUTOMOC ON) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/parser - ${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp - ${APIEXTRACTOR_EXTRA_INCLUDES} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5Xml_INCLUDE_DIRS} - ) - -add_library(apiextractor STATIC ${apiextractor_SRC} ${apiextractor_RCCS_SRC}) -target_link_libraries(apiextractor - ${Qt5Xml_LIBRARIES} - ${Qt5XmlPatterns_LIBRARIES} - ${APIEXTRACTOR_EXTRA_LIBRARIES} - ) - -set_property(TARGET apiextractor PROPERTY CXX_STANDARD 11) - -if (BUILD_TESTS) - enable_testing() - add_subdirectory(tests) -endif() diff --git a/ApiExtractor/COPYING b/ApiExtractor/COPYING deleted file mode 100644 index 4ccd71466..000000000 --- a/ApiExtractor/COPYING +++ /dev/null @@ -1,342 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. - -------------------------------------------------------------------------- diff --git a/ApiExtractor/abstractmetabuilder.cpp b/ApiExtractor/abstractmetabuilder.cpp deleted file mode 100644 index 3b2ecf8e1..000000000 --- a/ApiExtractor/abstractmetabuilder.cpp +++ /dev/null @@ -1,3459 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "abstractmetabuilder_p.h" -#include "reporthandler.h" -#include "typedatabase.h" - -#include -#include - -#include "parser/codemodel.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "graph.h" -#include - -static inline QString colonColon() { return QStringLiteral("::"); } - -static QString stripTemplateArgs(const QString &name) -{ - int pos = name.indexOf(QLatin1Char('<')); - return pos < 0 ? name : name.left(pos); -} - -static QStringList parseTemplateType(const QString& name) { - int n = name.indexOf(QLatin1Char('<')); - if (n <= 0) { - // If name starts with '<' or contains an unmatched (i.e. any) '>', we - // reject it - if (n == 0 || name.count(QLatin1Char('>'))) - return QStringList(); - // Doesn't look like a template instantiation; just return the name - return QStringList() << name; - } - - // Split the type name into the template name and template arguments; the - // part before the opening '<' is the template name - // - // Example: - // "foo, D>" -> ( "foo", "A", "bar", "D" ) - QStringList result; - result << name.left(n).trimmed(); - - // Extract template arguments - int i, depth = 1; - const int l = name.length(); - for (i = n + 1; i < l; ++i) { - // Consume balanced '<'/'>' within a single argument so that we won't - // split on ',' as part of a single argument which is itself a - // multi-argument template type - if (name[i] == QLatin1Char('<')) { - ++depth; - } else if (name[i] == QLatin1Char('>')) { - if (--depth == 0) - break; - } else if (name[i] == QLatin1Char(',') && depth == 1) { - // Encountered ',' in template argument list that is not within - // another template name; add current argument to result and start - // working on the next argument - result << name.mid(n + 1, i - n - 1).trimmed(); - n = i; - } - } - if (i >= l) // arg list not closed - return QStringList(); - if (i + 1 < l) // arg list closed before end of name - return QStringList(); - - // Add final argument and return result - result << name.mid(n + 1, i - n - 1).trimmed(); - return result; -} - -AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : m_currentClass(0), - m_logDirectory(QLatin1String(".") + QDir::separator()) -{ -} - -AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate() -{ - qDeleteAll(m_globalEnums); - qDeleteAll(m_globalFunctions); - qDeleteAll(m_templates); - qDeleteAll(m_smartPointers); - qDeleteAll(m_metaClasses); -} - -AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate) -{ - d->q = this; -} - -AbstractMetaBuilder::~AbstractMetaBuilder() -{ - delete d; -} - -AbstractMetaClassList AbstractMetaBuilder::classes() const -{ - return d->m_metaClasses; -} - -AbstractMetaClassList AbstractMetaBuilder::templates() const -{ - return d->m_templates; -} - -AbstractMetaClassList AbstractMetaBuilder::smartPointers() const -{ - return d->m_smartPointers; -} - -AbstractMetaFunctionList AbstractMetaBuilder::globalFunctions() const -{ - return d->m_globalFunctions; -} - -AbstractMetaEnumList AbstractMetaBuilder::globalEnums() const -{ - return d->m_globalEnums; -} - -QSet AbstractMetaBuilder::qtMetaTypeDeclaredTypeNames() const -{ - return d->m_qmetatypeDeclaredTypenames; -} - -void AbstractMetaBuilderPrivate::checkFunctionModifications() -{ - TypeDatabase *types = TypeDatabase::instance(); - const SingleTypeEntryHash entryHash = types->entries(); - - for (SingleTypeEntryHash::const_iterator it = entryHash.cbegin(), end = entryHash.cend(); it != end; ++it) { - const TypeEntry *entry = it.value(); - if (!entry) - continue; - if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing) - continue; - - const ComplexTypeEntry* centry = static_cast(entry); - FunctionModificationList modifications = centry->functionModifications(); - - for (const FunctionModification &modification : qAsConst(modifications)) { - QString signature = modification.signature; - - QString name = signature.trimmed(); - name.truncate(name.indexOf(QLatin1Char('('))); - - AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry->qualifiedCppName()); - if (!clazz) - continue; - - const AbstractMetaFunctionList functions = clazz->functions(); - bool found = false; - QStringList possibleSignatures; - for (AbstractMetaFunction *function : functions) { - if (function->minimalSignature() == signature && function->implementingClass() == clazz) { - found = true; - break; - } - - if (function->originalName() == name) { - possibleSignatures.append(function->minimalSignature() + QLatin1String(" in ") - + function->implementingClass()->name()); - } - } - - if (!found) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("signature '%1' for function modification in '%2' not found. Possible candidates: %3") - .arg(signature, clazz->qualifiedCppName(), possibleSignatures.join(QLatin1String(", "))); - } - } - } -} - -AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem argument) -{ - AbstractMetaClass* returned = 0; - bool ok = false; - AbstractMetaType* type = translateType(argument->type(), &ok); - if (ok && type && type->typeEntry() && type->typeEntry()->isComplex()) { - const TypeEntry *entry = type->typeEntry(); - returned = AbstractMetaClass::findClass(m_metaClasses, entry->name()); - } - delete type; - return returned; -} - -AbstractMetaClass *AbstractMetaBuilder::createMetaClass() -{ - return new AbstractMetaClass(); -} - -AbstractMetaEnum *AbstractMetaBuilder::createMetaEnum() -{ - return new AbstractMetaEnum(); -} - -AbstractMetaEnumValue *AbstractMetaBuilder::createMetaEnumValue() -{ - return new AbstractMetaEnumValue(); -} - -AbstractMetaField *AbstractMetaBuilder::createMetaField() -{ - return new AbstractMetaField(); -} - -AbstractMetaFunction *AbstractMetaBuilder::createMetaFunction() -{ - return new AbstractMetaFunction(); -} - -AbstractMetaArgument *AbstractMetaBuilder::createMetaArgument() -{ - return new AbstractMetaArgument(); -} - -AbstractMetaType *AbstractMetaBuilder::createMetaType() -{ - return new AbstractMetaType(); -} - -/** - * Checks the argument of a hash function and flags the type if it is a complex type - */ -void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function_item) -{ - ArgumentList arguments = function_item->arguments(); - if (arguments.size() == 1) { - if (AbstractMetaClass *cls = argumentToClass(arguments.at(0))) - cls->setHasHashFunction(true); - } -} - -/** - * Check if a class has a debug stream operator that can be used as toString - */ - -void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem function_item) -{ - ArgumentList arguments = function_item->arguments(); - if (arguments.size() == 2) { - if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) { - ArgumentModelItem arg = arguments.at(1); - if (AbstractMetaClass *cls = argumentToClass(arg)) { - if (arg->type().indirections() < 2) - cls->setToStringCapability(true); - } - } - } -} - -void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item) -{ - if (item->accessPolicy() != CodeModel::Public) - return; - - ArgumentList arguments = item->arguments(); - AbstractMetaClass* baseoperandClass; - bool firstArgumentIsSelf = true; - bool unaryOperator = false; - - baseoperandClass = argumentToClass(arguments.at(0)); - - if (arguments.size() == 1) { - unaryOperator = true; - } else if (!baseoperandClass - || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { - baseoperandClass = argumentToClass(arguments.at(1)); - firstArgumentIsSelf = false; - } else { - bool ok; - AbstractMetaType* type = translateType(item->type(), &ok); - const TypeEntry* retType = ok ? type->typeEntry() : 0; - AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1)); - if (otherArgClass && retType - && (retType->isValue() || retType->isObject()) - && retType != baseoperandClass->typeEntry() - && retType == otherArgClass->typeEntry()) { - baseoperandClass = AbstractMetaClass::findClass(m_metaClasses, retType); - firstArgumentIsSelf = false; - } - delete type; - } - - if (baseoperandClass) { - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = baseoperandClass; - AbstractMetaFunction *metaFunction = traverseFunction(item); - if (metaFunction && !metaFunction->isInvalid()) { - // Strip away first argument, since that is the containing object - AbstractMetaArgumentList arguments = metaFunction->arguments(); - if (firstArgumentIsSelf || unaryOperator) { - AbstractMetaArgument* first = arguments.takeFirst(); - if (!unaryOperator && first->type()->indirections()) - metaFunction->setPointerOperator(true); - delete first; - metaFunction->setArguments(arguments); - } else { - // If the operator method is not unary and the first operator is - // not of the same type of its owning class we suppose that it - // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)). - // All operator overloads that operate over a class are already - // being added as member functions of that class by the API Extractor. - AbstractMetaArgument* last = arguments.takeLast(); - if (last->type()->indirections()) - metaFunction->setPointerOperator(true); - delete last; - - metaFunction->setArguments(arguments); - metaFunction->setReverseOperator(true); - } - metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); - metaFunction->setVisibility(AbstractMetaFunction::Public); - metaFunction->setOriginalAttributes(metaFunction->attributes()); - setupFunctionDefaults(metaFunction, baseoperandClass); - baseoperandClass->addFunction(metaFunction); - Q_ASSERT(!metaFunction->wasPrivate()); - } else if (metaFunction) { - delete metaFunction; - } - - m_currentClass = oldCurrentClass; - } -} - -void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item) -{ - ArgumentList arguments = item->arguments(); - if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) { - AbstractMetaClass* streamClass = argumentToClass(arguments.at(0)); - AbstractMetaClass* streamedClass = argumentToClass(arguments.at(1)); - - if (streamClass && streamedClass && (streamClass->isStream())) { - AbstractMetaClass *oldCurrentClass = m_currentClass; - m_currentClass = streamedClass; - AbstractMetaFunction *streamFunction = traverseFunction(item); - - if (streamFunction && !streamFunction->isInvalid()) { - QString name = item->name(); - streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction); - // Strip first argument, since that is the containing object - AbstractMetaArgumentList arguments = streamFunction->arguments(); - if (!streamClass->typeEntry()->generateCode()) - delete arguments.takeLast(); - else - delete arguments.takeFirst(); - - streamFunction->setArguments(arguments); - - *streamFunction += AbstractMetaAttributes::Final; - *streamFunction += AbstractMetaAttributes::Public; - streamFunction->setOriginalAttributes(streamFunction->attributes()); - -// streamFunction->setType(0); - - AbstractMetaClass *funcClass; - - if (!streamClass->typeEntry()->generateCode()) { - AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments()); - streamFunction->setArguments(reverseArgs); - streamFunction->setReverseOperator(true); - funcClass = streamedClass; - } else { - funcClass = streamClass; - } - - setupFunctionDefaults(streamFunction, funcClass); - funcClass->addFunction(streamFunction); - if (funcClass == streamClass) - funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include()); - else - funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); - - m_currentClass = oldCurrentClass; - } else if (streamFunction) { - delete streamFunction; - } - - } - } -} - -void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, - const TypeDatabase *types, - const NamespaceModelItem &scope) -{ - const ClassList &scopeClasses = scope->classes(); - for (const ClassModelItem &item : scopeClasses) { - QString qualifiedName = item->qualifiedName().join(colonColon()); - TypeEntry* entry = types->findType(qualifiedName); - if (entry) { - if (isQObject(dom, qualifiedName) && entry->isComplex()) - ((ComplexTypeEntry*) entry)->setQObject(true); - } - } - - const NamespaceList &namespaces = scope->namespaces(); - for (const NamespaceModelItem &n : namespaces) { - if (scope != n) - fixQObjectForScope(dom, types, n); - } -} - -void AbstractMetaBuilderPrivate::sortLists() -{ - for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) - cls->sortFunctions(); -} - -FileModelItem AbstractMetaBuilderPrivate::buildDom(const QByteArrayList &arguments, - unsigned clangFlags) -{ - clang::Builder builder; - FileModelItem result = clang::parse(arguments, clangFlags, builder) - ? builder.dom() : FileModelItem(); - const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); - if (const int diagnosticsCount = diagnostics.size()) { - QDebug d = qWarning(); - d.nospace(); - d.noquote(); - d << "Clang: " << diagnosticsCount << " diagnostic messages:\n"; - for (int i = 0; i < diagnosticsCount; ++i) - d << " " << diagnostics.at(i) << '\n'; - } - return result; -} - -void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) -{ - const TypeDatabase *types = TypeDatabase::instance(); - - pushScope(dom); - - // fix up QObject's in the type system.. - fixQObjectForScope(dom, types, dom); - - // Start the generation... - const ClassList &typeValues = dom->classes(); - ReportHandler::setProgressReference(typeValues); - for (const ClassModelItem &item : typeValues) { - ReportHandler::progress(QLatin1String("Generating class model...")); - AbstractMetaClass *cls = traverseClass(dom, item); - if (!cls) - continue; - - addAbstractMetaClass(cls); - } - - // We need to know all global enums - const EnumList &enums = dom->enums(); - ReportHandler::setProgressReference(enums); - for (const EnumModelItem &item : enums) { - ReportHandler::progress(QLatin1String("Generating enum model...")); - AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet()); - if (metaEnum) { - if (metaEnum->typeEntry()->generateCode()) - m_globalEnums << metaEnum; - } - } - - const QSet &namespaceTypeValues = dom->uniqueNamespaces(); - ReportHandler::setProgressReference(namespaceTypeValues); - for (NamespaceModelItem item : namespaceTypeValues) { - ReportHandler::progress(QLatin1String("Generating namespace model...")); - AbstractMetaClass *metaClass = traverseNamespace(dom, item); - if (metaClass) - m_metaClasses << metaClass; - } - - // Go through all typedefs to see if we have defined any - // specific typedefs to be used as classes. - const TypeDefList typeDefs = dom->typeDefs(); - ReportHandler::setProgressReference(typeDefs); - for (const TypeDefModelItem &typeDef : typeDefs) { - ReportHandler::progress(QLatin1String("Resolving typedefs...")); - AbstractMetaClass* cls = traverseTypeDef(dom, typeDef); - addAbstractMetaClass(cls); - } - - figureOutEnumValues(); - - for (const ClassModelItem &item : typeValues) - traverseClassMembers(item); - - for (const NamespaceModelItem &item : namespaceTypeValues) - traverseNamespaceMembers(item); - - // Global functions - const FunctionList &functions = dom->functions(); - for (const FunctionModelItem &func : functions) { - if (func->accessPolicy() != CodeModel::Public || func->name().startsWith(QLatin1String("operator"))) - continue; - - FunctionTypeEntry* funcEntry = types->findFunctionType(func->name()); - if (!funcEntry || !funcEntry->generateCode()) - continue; - - AbstractMetaFunction* metaFunc = traverseFunction(func); - if (!metaFunc) - continue; - - if (!funcEntry->hasSignature(metaFunc->minimalSignature())) { - delete metaFunc; - continue; - } - - applyFunctionModifications(metaFunc); - - setInclude(funcEntry, func->fileName()); - if (metaFunc->typeEntry()) - delete metaFunc->typeEntry(); - - metaFunc->setTypeEntry(funcEntry); - m_globalFunctions << metaFunc; - } - - ReportHandler::setProgressReference(m_metaClasses); - for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { - ReportHandler::progress(QLatin1String("Fixing class inheritance...")); - if (!cls->isInterface() && !cls->isNamespace()) - setupInheritance(cls); - } - - ReportHandler::setProgressReference(m_metaClasses); - for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { - ReportHandler::progress(QLatin1String("Detecting inconsistencies in class model...")); - cls->fixFunctions(); - - if (!cls->typeEntry()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' does not have an entry in the type system") - .arg(cls->name()); - } else { - bool couldAddDefaultCtors = !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace(); - if (couldAddDefaultCtors) { - if (!cls->hasConstructors()) - cls->addDefaultConstructor(); - if (cls->typeEntry()->isValue() && !cls->isAbstract() && !cls->hasCopyConstructor()) - cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls)); - } - } - - if (cls->isAbstract() && !cls->isInterface()) - cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper")); - } - const TypeEntryHash allEntries = types->allEntries(); - ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem...")); - for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { - for (TypeEntry *entry : it.value()) { - if (entry->isPrimitive()) - continue; - - if ((entry->isValue() || entry->isObject()) - && !entry->isString() - && !entry->isChar() - && !entry->isContainer() - && !entry->isCustom() - && !entry->isVariant() - && !AbstractMetaClass::findClass(m_metaClasses, entry->qualifiedCppName())) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(entry->qualifiedCppName()); - } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { - const FunctionTypeEntry* fte = static_cast(entry); - const QStringList &signatures = fte->signatures(); - for (const QString &signature : signatures) { - bool ok = false; - for (AbstractMetaFunction* func : qAsConst(m_globalFunctions)) { - if (signature == func->minimalSignature()) { - ok = true; - break; - } - } - if (!ok) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") - .arg(signature); - } - } - } else if (entry->isEnum()) { - const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier(); - AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); - - bool enumFound = false; - if (cls) { - enumFound = cls->findEnum(entry->targetLangName()); - } else { // Global enum - for (AbstractMetaEnum *metaEnum : qAsConst(m_enums)) { - if (metaEnum->typeEntry() == entry) { - enumFound = true; - break; - } - } - } - if (!enumFound) { - entry->setCodeGeneration(TypeEntry::GenerateNothing); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum '%1' is specified in typesystem, but not declared") - .arg(entry->qualifiedCppName()); - } - - } - } - } - - { - const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash")); - for (const FunctionModelItem &item : hashFunctions) - registerHashFunction(item); - } - - { - const FunctionList &streamOps = dom->findFunctions(QLatin1String("operator<<")); - for (const FunctionModelItem &item : streamOps) - registerToStringCapability(item); - } - - { - FunctionList binaryOperators = dom->findFunctions(QStringLiteral("operator==")); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator!="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator<="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator>="))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator<"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator+"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator/"))); - // Filter binary operators, skipping for example - // class Iterator { ... Value *operator*() ... }; - const FunctionList potentiallyBinaryOperators = - dom->findFunctions(QStringLiteral("operator*")) - + dom->findFunctions(QStringLiteral("operator&")); - for (const FunctionModelItem &item : potentiallyBinaryOperators) { - if (!item->arguments().isEmpty()) - binaryOperators.append(item); - } - binaryOperators.append(dom->findFunctions(QStringLiteral("operator-"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator&"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator|"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator^"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator~"))); - binaryOperators.append(dom->findFunctions(QStringLiteral("operator>"))); - - for (const FunctionModelItem &item : qAsConst(binaryOperators)) - traverseOperatorFunction(item); - } - - { - const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) - + dom->findFunctions(QLatin1String("operator>>")); - for (const FunctionModelItem &item : streamOperators) - traverseStreamOperator(item); - } - - figureOutDefaultEnumArguments(); - checkFunctionModifications(); - - // sort all classes topologically - m_metaClasses = classesTopologicalSorted(); - - for (AbstractMetaClass* cls : qAsConst(m_metaClasses)) { -// setupEquals(cls); -// setupComparable(cls); - setupClonable(cls); - setupExternalConversion(cls); - - // sort all inner classes topologically - if (!cls->typeEntry()->codeGeneration() || cls->innerClasses().size() < 2) - continue; - - cls->setInnerClasses(classesTopologicalSorted(cls)); - } - - dumpLog(); - - sortLists(); - - m_currentClass = 0; - - // Functions added to the module on the type system. - const AddedFunctionList &globalUserFunctions = types->globalUserFunctions(); - for (const AddedFunction &addedFunc : globalUserFunctions) { - AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); - metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); - m_globalFunctions << metaFunc; - } - - std::puts(""); -} - -bool AbstractMetaBuilder::build(const QByteArrayList &arguments, unsigned clangFlags) -{ - const FileModelItem dom = d->buildDom(arguments, clangFlags); - if (dom.isNull()) - return false; - if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken) << dom.data(); - d->traverseDom(dom); - return true; -} - -void AbstractMetaBuilder::setLogDirectory(const QString& logDir) -{ - d->m_logDirectory = logDir; - if (!d->m_logDirectory.endsWith(QDir::separator())) - d->m_logDirectory.append(QDir::separator()); -} - -void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls) -{ - if (!cls) - return; - - cls->setOriginalAttributes(cls->attributes()); - if (cls->typeEntry()->isContainer()) { - m_templates << cls; - } else if (cls->typeEntry()->isSmartPointer()) { - m_smartPointers << cls; - } else { - m_metaClasses << cls; - if (cls->typeEntry()->designatedInterface()) { - AbstractMetaClass* interface = cls->extractInterface(); - m_metaClasses << interface; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name()); - } - } -} - -AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, - const NamespaceModelItem &namespaceItem) -{ - QString namespaceName = - (!m_namespacePrefix.isEmpty() ? m_namespacePrefix + colonColon() : QString()) - + namespaceItem->name(); - NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName); - - if (TypeDatabase::instance()->isClassRejected(namespaceName)) { - m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled); - return 0; - } - - if (!type) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName); - return 0; - } - - AbstractMetaClass* metaClass = q->createMetaClass(); - metaClass->setTypeEntry(type); - - *metaClass += AbstractMetaAttributes::Public; - - m_currentClass = metaClass; - - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name()); - } - - traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); - - pushScope(namespaceItem); - m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); - - const ClassList &classes = namespaceItem->classes(); - for (const ClassModelItem &cls : classes) { - AbstractMetaClass* mjc = traverseClass(dom, cls); - if (mjc) { - metaClass->addInnerClass(mjc); - mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc); - } - } - - // Go through all typedefs to see if we have defined any - // specific typedefs to be used as classes. - const TypeDefList typeDefs = namespaceItem->typeDefs(); - for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); - if (cls) { - metaClass->addInnerClass(cls); - cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls); - } - } - - // Traverse namespaces recursively - const QSet &innerNamespaces = namespaceItem->uniqueNamespaces(); - for (const NamespaceModelItem &ni : innerNamespaces) { - AbstractMetaClass* mjc = traverseNamespace(dom, ni); - if (mjc) { - metaClass->addInnerClass(mjc); - mjc->setEnclosingClass(metaClass); - addAbstractMetaClass(mjc); - } - } - - m_currentClass = 0; - - popScope(); - m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); - - if (!type->include().isValid()) - setInclude(type, namespaceItem->fileName()); - - return metaClass; -} - -struct Operator -{ - enum Type { Complement, Plus, ShiftRight, ShiftLeft, None }; - - Operator() : type(None) {} - - int calculate(int x) - { - switch (type) { - case Complement: return ~value; - case Plus: return x + value; - case ShiftRight: return x >> value; - case ShiftLeft: return x << value; - case None: return x; - } - return x; - } - - Type type; - int value; -}; - - - -Operator findOperator(QString* s) -{ - const char *names[] = { - "~", - "+", - ">>", - "<<" - }; - - for (int i = 0; i < Operator::None; ++i) { - QString name = QLatin1String(names[i]); - QString str = *s; - int splitPoint = str.indexOf(name); - if (splitPoint > -1) { - bool ok; - QString right = str.mid(splitPoint + name.length()); - Operator op; - - op.value = right.toInt(&ok); - if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u')) - op.value = right.left(right.length() - 1).toUInt(&ok, 0); - - if (ok) { - op.type = Operator::Type(i); - if (splitPoint > 0) - *s = str.left(splitPoint).trimmed(); - else - *s = QString(); - return op; - } - } - } - return Operator(); -} - -int AbstractMetaBuilderPrivate::figureOutEnumValue(const QString &stringValue, - int oldValuevalue, - AbstractMetaEnum *metaEnum, - AbstractMetaFunction *metaFunction) -{ - if (stringValue.isEmpty()) - return oldValuevalue; - - QStringList stringValues = stringValue.split(QLatin1Char('|')); - - int returnValue = 0; - - bool matched = false; - - for (int i = 0; i < stringValues.size(); ++i) { - QString s = stringValues.at(i).trimmed(); - - bool ok; - int v; - - Operator op = findOperator(&s); - - if (s.length() > 0 && s.at(0) == QLatin1Char('0')) - v = s.toUInt(&ok, 0); - else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u')) - v = s.left(s.length() - 1).toUInt(&ok, 0); - else - v = s.toInt(&ok); - - if (ok || s.isEmpty()) { - matched = true; - } else if (m_enumValues.contains(s)) { - v = m_enumValues[s]->value(); - matched = true; - } else { - if (metaEnum) { - v = findOutValueFromString(s, matched); - if (!matched) { - QString enclosingClass = QString(metaEnum->enclosingClass() ? metaEnum->enclosingClass()->name() + colonColon() : QString()); - qCWarning(lcShiboken).noquote().nospace() - << "unhandled enum value: " << s << " in " - << enclosingClass << metaEnum->name() << " from header '" - << metaEnum->typeEntry()->include().name() << '\''; - } - } else { - qCWarning(lcShiboken) << "unhandled enum value: Unknown enum"; - } - } - - if (matched) - returnValue |= op.calculate(v); - } - - if (!matched) { - QString warn = QStringLiteral("unmatched enum %1").arg(stringValue); - - if (metaFunction) { - warn += QStringLiteral(" when parsing default value of '%1' in class '%2'") - .arg(metaFunction->name(), metaFunction->implementingClass()->name()); - } - warn += QLatin1String(" from header '") + metaEnum->typeEntry()->include().name() - + QLatin1Char('\''); - - qCWarning(lcShiboken).noquote().nospace() << warn; - returnValue = oldValuevalue; - } - - return returnValue; -} - -void AbstractMetaBuilderPrivate::figureOutEnumValuesForClass(AbstractMetaClass *metaClass, - QSet *classes) -{ - AbstractMetaClass* base = metaClass->baseClass(); - - if (base && !classes->contains(base)) - figureOutEnumValuesForClass(base, classes); - - if (classes->contains(metaClass)) - return; - - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum* e : enums) { - if (!e) { - qCWarning(lcShiboken).noquote().nospace() << "bad enum in class " << metaClass->name(); - continue; - } - AbstractMetaEnumValueList lst = e->values(); - int value = 0; - for (int i = 0; i < lst.size(); ++i) { - value = figureOutEnumValue(lst.at(i)->stringValue(), value, e); - lst.at(i)->setValue(value); - value++; - } - } - - *classes += metaClass; -} - - -void AbstractMetaBuilderPrivate::figureOutEnumValues() -{ - // Keep a set of classes that we already traversed. We use this to - // enforce that we traverse base classes prior to subclasses. - QSet classes; - for (AbstractMetaClass *c : qAsConst(m_metaClasses)) - figureOutEnumValuesForClass(c, &classes); - - for (AbstractMetaEnum* metaEnum : qAsConst(m_globalEnums)) { - AbstractMetaEnumValueList enumValues = metaEnum->values(); - int value = 0; - for (int i = 0; i < enumValues.size(); ++i) { - value = figureOutEnumValue(enumValues.at(i)->stringValue(), value, metaEnum); - enumValues.at(i)->setValue(value); - value++; - } - } -} - -void AbstractMetaBuilderPrivate::figureOutDefaultEnumArguments() -{ - for (AbstractMetaClass* metaClass : qAsConst(m_metaClasses)) { - const AbstractMetaFunctionList &functions = metaClass->functions(); - for (AbstractMetaFunction* metaFunction : functions) { - const AbstractMetaArgumentList &arguments = metaFunction->arguments(); - for (AbstractMetaArgument *arg : arguments) { - QString expr = arg->defaultValueExpression(); - if (expr.isEmpty()) - continue; - - if (!metaFunction->replacedDefaultExpression(metaFunction->implementingClass(), - arg->argumentIndex() + 1).isEmpty()) { - continue; - } - - arg->setDefaultValueExpression(expr); - } - } - } -} - - -AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem, - AbstractMetaClass *enclosing, - const QSet &enumsDeclarations) -{ - QString qualifiedName = enumItem->qualifiedName().join(colonColon()); - - TypeEntry* typeEntry = 0; - if (enumItem->accessPolicy() == CodeModel::Private) { - QStringList names = enumItem->qualifiedName(); - QString enumName = names.last(); - QString nspace; - if (names.size() > 1) - nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); - typeEntry = new EnumTypeEntry(nspace, enumName, 0); - TypeDatabase::instance()->addType(typeEntry); - } else if (!enumItem->isAnonymous()) { - typeEntry = TypeDatabase::instance()->findType(qualifiedName); - } else { - QStringList tmpQualifiedName = enumItem->qualifiedName(); - const EnumeratorList &enums = enumItem->enumerators(); - for (const EnumeratorModelItem& enumValue : enums) { - tmpQualifiedName.removeLast(); - tmpQualifiedName << enumValue->name(); - qualifiedName = tmpQualifiedName.join(colonColon()); - typeEntry = TypeDatabase::instance()->findType(qualifiedName); - if (typeEntry) - break; - } - } - - QString enumName = enumItem->name(); - - QString className; - if (m_currentClass) - className = m_currentClass->typeEntry()->qualifiedCppName(); - - QString rejectReason; - if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { - if (typeEntry) - typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled); - return 0; - } - - if (!typeEntry || !typeEntry->isEnum()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum '%1' does not have a type entry or is not an enum") - .arg(qualifiedName); - m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem); - return 0; - } - - AbstractMetaEnum *metaEnum = q->createMetaEnum(); - if (enumsDeclarations.contains(qualifiedName) - || enumsDeclarations.contains(enumName)) { - metaEnum->setHasQEnumsDeclaration(true); - } - - metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry); - switch (enumItem->accessPolicy()) { - case CodeModel::Public: - *metaEnum += AbstractMetaAttributes::Public; - break; - case CodeModel::Protected: - *metaEnum += AbstractMetaAttributes::Protected; - break; - case CodeModel::Private: - *metaEnum += AbstractMetaAttributes::Private; - typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); - break; - default: - break; - } - - if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName(); - - const EnumeratorList &enums = enumItem->enumerators(); - for (const EnumeratorModelItem &value : enums) { - - AbstractMetaEnumValue *metaEnumValue = q->createMetaEnumValue(); - metaEnumValue->setName(value->name()); - // Deciding the enum value... - - metaEnumValue->setStringValue(value->value()); - metaEnum->addEnumValue(metaEnumValue); - - if (ReportHandler::isDebug(ReportHandler::FullDebug)) { - qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = " - << metaEnumValue->value() << " = " << metaEnumValue->value(); - } - - // Add into global register... - if (enclosing) - m_enumValues[enclosing->name() + colonColon() + metaEnumValue->name()] = metaEnumValue; - else - m_enumValues[metaEnumValue->name()] = metaEnumValue; - } - - m_enums << metaEnum; - - if (!metaEnum->typeEntry()->include().isValid()) - setInclude(metaEnum->typeEntry(), enumItem->fileName()); - - metaEnum->setOriginalAttributes(metaEnum->attributes()); - - // Register all enum values on Type database - const EnumeratorList &enumerators = enumItem->enumerators(); - for (EnumeratorModelItem e : enumItem->enumerators()) { - QString name; - if (enclosing) { - name += enclosing->name(); - name += colonColon(); - } - name += e->name(); - EnumValueTypeEntry* enumValue = new EnumValueTypeEntry(name, e->value(), static_cast(typeEntry), typeEntry->version()); - TypeDatabase::instance()->addType(enumValue); - } - - return metaEnum; -} - -AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, - const TypeDefModelItem &typeDef) -{ - TypeDatabase* types = TypeDatabase::instance(); - QString className = stripTemplateArgs(typeDef->name()); - - QString fullClassName = className; - // we have an inner class - if (m_currentClass) { - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) - + colonColon() + fullClassName; - } - - // If this is the alias for a primitive type - // we store the aliased type on the alias - // TypeEntry - PrimitiveTypeEntry* ptype = types->findPrimitiveType(className); - if (ptype) { - QString typeDefName = typeDef->type().qualifiedName()[0]; - ptype->setReferencedTypeEntry(types->findPrimitiveType(typeDefName)); - return 0; - } - - - // If we haven't specified anything for the typedef, then we don't care - ComplexTypeEntry* type = types->findComplexType(fullClassName); - if (!type) - return 0; - - if (type->isObject()) - static_cast(type)->setQObject(isQObject(dom, stripTemplateArgs(typeDef->type().qualifiedName().join(colonColon())))); - - AbstractMetaClass *metaClass = q->createMetaClass(); - metaClass->setTypeDef(true); - metaClass->setTypeEntry(type); - metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon())); - *metaClass += AbstractMetaAttributes::Public; - - // Set the default include file name - if (!type->include().isValid()) - setInclude(type, typeDef->fileName()); - - fillAddedFunctions(metaClass); - - return metaClass; -} - -AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom, - const ClassModelItem &classItem) -{ - QString className = stripTemplateArgs(classItem->name()); - QString fullClassName = className; - - // we have inner an class - if (m_currentClass) { - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) - + colonColon() + fullClassName; - } - - ComplexTypeEntry* type = TypeDatabase::instance()->findComplexType(fullClassName); - AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason; - - if (fullClassName == QLatin1String("QMetaTypeId")) { - // QtScript: record which types have been declared - int lpos = classItem->name().indexOf(QLatin1Char('<')); - int rpos = classItem->name().lastIndexOf(QLatin1Char('>')); - if ((lpos != -1) && (rpos != -1)) { - QString declaredTypename = classItem->name().mid(lpos + 1, rpos - lpos - 1); - m_qmetatypeDeclaredTypenames.insert(declaredTypename); - } - } - - if (TypeDatabase::instance()->isClassRejected(fullClassName)) { - reason = AbstractMetaBuilder::GenerationDisabled; - } else if (!type) { - TypeEntry *te = TypeDatabase::instance()->findType(fullClassName); - if (te && !te->isComplex()) - reason = AbstractMetaBuilder::RedefinedToNotClass; - else - reason = AbstractMetaBuilder::NotInTypeSystem; - } else if (type->codeGeneration() == TypeEntry::GenerateNothing) { - reason = AbstractMetaBuilder::GenerationDisabled; - } - if (reason != AbstractMetaBuilder::NoReason) { - m_rejectedClasses.insert(fullClassName, reason); - return 0; - } - - if (type->isObject()) - ((ObjectTypeEntry*)type)->setQObject(isQObject(dom, fullClassName)); - - AbstractMetaClass *metaClass = q->createMetaClass(); - metaClass->setTypeEntry(type); - metaClass->setBaseClassNames(classItem->baseClasses()); - *metaClass += AbstractMetaAttributes::Public; - if (type->stream()) - metaClass->setStream(true); - - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - const QString message = type->isContainer() - ? QStringLiteral("container: '%1'").arg(fullClassName) - : QStringLiteral("class: '%1'").arg(metaClass->fullName()); - qCDebug(lcShiboken) << message; - } - - TemplateParameterList template_parameters = classItem->templateParameters(); - QVector template_args; - template_args.clear(); - for (int i = 0; i < template_parameters.size(); ++i) { - const TemplateParameterModelItem ¶m = template_parameters.at(i); - TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name(), type->version()); - param_type->setOrdinal(i); - template_args.append(param_type); - } - metaClass->setTemplateArguments(template_args); - - parseQ_Property(metaClass, classItem->propertyDeclarations()); - - traverseEnums(classItem, metaClass, classItem->enumsDeclarations()); - - // Inner classes - { - const ClassList &innerClasses = classItem->classes(); - for (const ClassModelItem &ci : innerClasses) { - AbstractMetaClass *cl = traverseClass(dom, ci); - if (cl) { - cl->setEnclosingClass(metaClass); - metaClass->addInnerClass(cl); - m_metaClasses << cl; - } - } - - } - - // Go through all typedefs to see if we have defined any - // specific typedefs to be used as classes. - const TypeDefList typeDefs = classItem->typeDefs(); - for (const TypeDefModelItem &typeDef : typeDefs) { - AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); - if (cls) { - cls->setEnclosingClass(metaClass); - addAbstractMetaClass(cls); - } - } - - - m_currentClass = oldCurrentClass; - - // Set the default include file name - if (!type->include().isValid()) - setInclude(type, classItem->fileName()); - - return metaClass; -} - -void AbstractMetaBuilderPrivate::traverseScopeMembers(ScopeModelItem item, - AbstractMetaClass *metaClass) -{ - // Classes/Namespace members - traverseFields(item, metaClass); - traverseFunctions(item, metaClass); - - // Inner classes - const ClassList &innerClasses = item->classes(); - for (const ClassModelItem& ci : innerClasses) - traverseClassMembers(ci); -} - -AbstractMetaClass* AbstractMetaBuilderPrivate::currentTraversedClass(ScopeModelItem item) -{ - QString className = stripTemplateArgs(item->name()); - QString fullClassName = className; - - // This is an inner class - if (m_currentClass) - fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName; - - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, fullClassName); - if (!metaClass) - metaClass = AbstractMetaClass::findClass(m_templates, fullClassName); - - if (!metaClass) - metaClass = AbstractMetaClass::findClass(m_smartPointers, fullClassName); - return metaClass; -} - -void AbstractMetaBuilderPrivate::traverseClassMembers(ClassModelItem item) -{ - AbstractMetaClass* metaClass = currentTraversedClass(item); - if (!metaClass) - return; - - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - - // Class members - traverseScopeMembers(item, metaClass); - - m_currentClass = oldCurrentClass; -} - -void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem item) -{ - AbstractMetaClass* metaClass = currentTraversedClass(item); - if (!metaClass) - return; - - AbstractMetaClass* oldCurrentClass = m_currentClass; - m_currentClass = metaClass; - - // Namespace members - traverseScopeMembers(item, metaClass); - - // Inner namespaces - const QSet &innerNamespaces = item->uniqueNamespaces(); - for (const NamespaceModelItem &ni : innerNamespaces) - traverseNamespaceMembers(ni); - - m_currentClass = oldCurrentClass; -} - -static inline QString fieldSignatureWithType(VariableModelItem field) -{ - return field->name() + QStringLiteral(" -> ") + field->type().toString(); -} - -static inline QString qualifiedFieldSignatureWithType(const QString &className, - VariableModelItem field) -{ - return className + colonColon() + fieldSignatureWithType(field); -} - -AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem field, - const AbstractMetaClass *cls) -{ - QString fieldName = field->name(); - QString className = m_currentClass->typeEntry()->qualifiedCppName(); - - // Ignore friend decl. - if (field->isFriend()) - return 0; - - if (field->accessPolicy() == CodeModel::Private) - return 0; - - QString rejectReason; - if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) { - m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason, - AbstractMetaBuilder::GenerationDisabled); - return 0; - } - - - AbstractMetaField *metaField = q->createMetaField(); - metaField->setName(fieldName); - metaField->setEnclosingClass(cls); - - bool ok; - TypeInfo fieldType = field->type(); - AbstractMetaType *metaType = translateType(fieldType, &ok); - - if (!metaType || !ok) { - const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") - .arg(m_currentClass->name(), fieldName, type); - delete metaField; - return 0; - } - - metaField->setType(metaType); - - AbstractMetaAttributes::Attributes attr = 0; - if (field->isStatic()) - attr |= AbstractMetaAttributes::Static; - - CodeModel::AccessPolicy policy = field->accessPolicy(); - if (policy == CodeModel::Public) - attr |= AbstractMetaAttributes::Public; - else if (policy == CodeModel::Protected) - attr |= AbstractMetaAttributes::Protected; - else - attr |= AbstractMetaAttributes::Private; - metaField->setAttributes(attr); - - return metaField; -} - -void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item, - AbstractMetaClass *metaClass) -{ - const VariableList &variables = scope_item->variables(); - for (const VariableModelItem &field : variables) { - AbstractMetaField* metaField = traverseField(field, metaClass); - - if (metaField && !metaField->isModifiedRemoved()) { - metaField->setOriginalAttributes(metaField->attributes()); - metaClass->addField(metaField); - } - } -} - -void AbstractMetaBuilderPrivate::setupFunctionDefaults(AbstractMetaFunction *metaFunction, - AbstractMetaClass *metaClass) -{ - // Set the default value of the declaring class. This may be changed - // in fixFunctions later on - metaFunction->setDeclaringClass(metaClass); - - // Some of the queries below depend on the implementing class being set - // to function properly. Such as function modifications - metaFunction->setImplementingClass(metaClass); - - if (metaFunction->name() == QLatin1String("operator_equal")) - metaClass->setHasEqualsOperator(true); - - if (!metaFunction->isFinalInTargetLang() - && metaFunction->isRemovedFrom(metaClass, TypeSystem::TargetLangCode)) { - *metaFunction += AbstractMetaAttributes::FinalInCpp; - } -} - -void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction) -{ - if (!metaFunction->isConversionOperator()) - return; - - TypeDatabase* types = TypeDatabase::instance(); - static const QRegularExpression operatorRegExp(QStringLiteral("^operator ")); - Q_ASSERT(operatorRegExp.isValid()); - QString castTo = metaFunction->name().remove(operatorRegExp).trimmed(); - - if (castTo.endsWith(QLatin1Char('&'))) - castTo.chop(1); - if (castTo.startsWith(QLatin1String("const "))) - castTo.remove(0, 6); - - TypeEntry* retType = types->findType(castTo); - if (!retType) - return; - - AbstractMetaType* metaType = q->createMetaType(); - metaType->setTypeEntry(retType); - metaFunction->replaceType(metaType); -} - -static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other) -{ - if (!type && !other) - return true; - if (!type || !other) - return false; - return type->typeEntry() == other->typeEntry() - && type->isConstant() == other->isConstant() - && type->referenceType() == other->referenceType() - && type->indirections() == other->indirections(); -} - -static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other) -{ - if (!func && !other) - return true; - if (!func || !other) - return false; - if (func->arguments().count() != other->arguments().count() - || func->isConstant() != other->isConstant() - || func->isStatic() != other->isStatic() - || !_compareAbstractMetaTypes(func->type(), other->type())) { - return false; - } - for (int i = 0; i < func->arguments().count(); ++i) { - if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type())) - return false; - } - return true; -} - -// Fix the arguments of template classes that take the class itself, for example: -// "QList(const QList &)" to "QList(const QList &)". -static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass) -{ - const QVector &templateTypes = metaClass->templateArguments(); - if (templateTypes.isEmpty()) - return false; - - const QStringList classType = metaClass->typeEntry()->qualifiedCppName().split(colonColon()); - QStringList fixedClassType = classType; - fixedClassType.last().append(QLatin1Char('<')); - for (int i = 0, count = templateTypes.size(); i < count; ++i) { - if (i) - fixedClassType.last().append(QLatin1String(", ")); - fixedClassType.last().append(templateTypes.at(i)->qualifiedCppName()); - } - fixedClassType.last().append(QLatin1String(" >")); - - bool templateTypeFixed = false; - TypeInfo functionType = function->type(); - if (functionType.qualifiedName() == classType) { - templateTypeFixed = true; - functionType.setQualifiedName(fixedClassType); - function->setType(functionType); - } - - ArgumentList arguments = function->arguments(); - for (int i = 0; i < arguments.size(); ++i) { - ArgumentModelItem arg = arguments.at(i); - TypeInfo type = arg->type(); - if (type.qualifiedName() == classType) { - type.setQualifiedName(fixedClassType); - arg->setType(type); - templateTypeFixed = true; - } - } - return templateTypeFixed; -} - -AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem) -{ - AbstractMetaFunctionList result; - const FunctionList &scopeFunctionList = scopeItem->functions(); - result.reserve(scopeFunctionList.size()); - for (const FunctionModelItem &function : scopeFunctionList) { - if (AbstractMetaFunction *metaFunction = traverseFunction(function)) - result.append(metaFunction); - } - return result; -} - -// For template classes, entries with more specific types may exist from out-of- -// line definitions. If there is a declaration which matches it after fixing -// the parameters, remove it as duplicate. For example: -// template class Vector { public: -// Vector(const Vector &rhs); -// }; -// template class -// Vector::Vector(const Vector&) {} // More specific, remove declaration. - -class DuplicatingFunctionPredicate : public std::unary_function { -public: - explicit DuplicatingFunctionPredicate(const AbstractMetaFunction *f) : m_function(f) {} - - bool operator()(const AbstractMetaFunction *rhs) const - { - return rhs != m_function && rhs->name() == m_function->name() - && _compareAbstractMetaFunctions(m_function, rhs); - } - -private: - const AbstractMetaFunction *m_function; -}; - -AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass) -{ - AbstractMetaFunctionList result; - AbstractMetaFunctionList unchangedFunctions; - - const FunctionList &scopeFunctionList = scopeItem->functions(); - result.reserve(scopeFunctionList.size()); - unchangedFunctions.reserve(scopeFunctionList.size()); - for (FunctionModelItem function : scopeFunctionList) { - // This fixes method's arguments and return types that are templates - // but the template variable wasn't declared in the C++ header. - const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass); - if (AbstractMetaFunction *metaFunction = traverseFunction(function)) { - result.append(metaFunction); - if (!templateTypeFixed) - unchangedFunctions.append(metaFunction); - } - } - - const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.begin(); - const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.end(); - for (int i = result.size() - 1; i >= 0; --i) { - AbstractMetaFunction *function = result.at(i); - if (!unchangedFunctions.contains(function) - && unchangedEnd != std::find_if(unchangedBegin, unchangedEnd, DuplicatingFunctionPredicate(function))) { - delete result.takeAt(i); - } - } - return result; -} - -void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, - AbstractMetaClass *metaClass) -{ - - const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty() - ? classFunctionList(scopeItem) - : templateClassFunctionList(scopeItem, metaClass); - - for (AbstractMetaFunction *metaFunction : functions){ - metaFunction->setOriginalAttributes(metaFunction->attributes()); - if (metaClass->isNamespace()) - *metaFunction += AbstractMetaAttributes::Static; - - QPropertySpec *read = 0; - if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) { - // Property reader must be in the form " name()" - if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry()) && (metaFunction->arguments().size() == 0)) { - *metaFunction += AbstractMetaAttributes::PropertyReader; - metaFunction->setPropertySpec(read); - } - } else if (QPropertySpec* write = metaClass->propertySpecForWrite(metaFunction->name())) { - // Property setter must be in the form "void name()" - // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem - if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) { - *metaFunction += AbstractMetaAttributes::PropertyWriter; - metaFunction->setPropertySpec(write); - } - } else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) { - // Property resetter must be in the form "void name()" - if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) { - *metaFunction += AbstractMetaAttributes::PropertyResetter; - metaFunction->setPropertySpec(reset); - } - } - - const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); - const bool isInvalidConstructor = metaFunction->isConstructor() - && ((metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction) - || metaFunction->isInvalid()); - if ((isInvalidDestructor || isInvalidConstructor) - && !metaClass->hasNonPrivateConstructor()) { - *metaClass += AbstractMetaAttributes::Final; - } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { - *metaClass -= AbstractMetaAttributes::Final; - metaClass->setHasNonPrivateConstructor(true); - } - - // Classes with virtual destructors should always have a shell class - // (since we aren't registering the destructors, we need this extra check) - if (metaFunction->isDestructor() && !metaFunction->isFinal()) - metaClass->setForceShellClass(true); - - if (!metaFunction->isDestructor() - && !metaFunction->isInvalid() - && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { - - setupFunctionDefaults(metaFunction, metaClass); - - if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("signal '%1' in class '%2' is overloaded.") - .arg(metaFunction->name(), metaClass->name()); - } - - if (metaFunction->isSignal() && !metaClass->isQObject()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("signal '%1' in non-QObject class '%2'") - .arg(metaFunction->name(), metaClass->name()); - } - - if (metaFunction->isConversionOperator()) - fixReturnTypeOfConversionOperator(metaFunction); - - metaClass->addFunction(metaFunction); - applyFunctionModifications(metaFunction); - } else if (metaFunction->isDestructor()) { - metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); - metaClass->setHasProtectedDestructor(metaFunction->isProtected()); - metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); - } - if (!metaFunction->ownerClass()) { - delete metaFunction; - metaFunction = 0; - } - } - - fillAddedFunctions(metaClass); -} - -void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass) -{ - // Add the functions added by the typesystem - const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions(); - for (const AddedFunction &addedFunc : addedFunctions) - traverseFunction(addedFunc, metaClass); -} - -void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func) -{ - const FunctionModificationList &mods = func->modifications(func->implementingClass()); - AbstractMetaFunction& funcRef = *func; - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) { - func->setOriginalName(func->name()); - func->setName(mod.renamedTo()); - } else if (mod.isAccessModifier()) { - funcRef -= AbstractMetaAttributes::Public; - funcRef -= AbstractMetaAttributes::Protected; - funcRef -= AbstractMetaAttributes::Private; - funcRef -= AbstractMetaAttributes::Friendly; - - if (mod.isPublic()) - funcRef += AbstractMetaAttributes::Public; - else if (mod.isProtected()) - funcRef += AbstractMetaAttributes::Protected; - else if (mod.isPrivate()) - funcRef += AbstractMetaAttributes::Private; - else if (mod.isFriendly()) - funcRef += AbstractMetaAttributes::Friendly; - } - - if (mod.isFinal()) - funcRef += AbstractMetaAttributes::FinalInTargetLang; - else if (mod.isNonFinal()) - funcRef -= AbstractMetaAttributes::FinalInTargetLang; - } -} - -bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) -{ - Q_ASSERT(!metaClass->isInterface()); - - if (m_setupInheritanceDone.contains(metaClass)) - return true; - - m_setupInheritanceDone.insert(metaClass); - - QStringList baseClasses = metaClass->baseClassNames(); - - // we only support our own containers and ONLY if there is only one baseclass - if (baseClasses.size() == 1 && baseClasses.first().contains(QLatin1Char('<'))) { - TypeParser::Info info; - ComplexTypeEntry* baseContainerType; - AbstractMetaClass* templ = findTemplateClass(baseClasses.first(), metaClass, &info, &baseContainerType); - if (templ) { - setupInheritance(templ); - inheritTemplate(metaClass, templ, info); - metaClass->typeEntry()->setBaseContainerType(templ->typeEntry()); - return true; - } - - if (baseContainerType) { - // Container types are not necessarily wrapped as 'real' classes, - // but there may still be classes derived from them. In such case, - // we still need to set the base container type in order to - // generate correct code for type conversion checking. - // - // Additionally, we consider this case as successfully setting up - // inheritance. - metaClass->typeEntry()->setBaseContainerType(baseContainerType); - return true; - } - - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("template baseclass '%1' of '%2' is not known") - .arg(baseClasses.first(), metaClass->name()); - return false; - } - - TypeDatabase* types = TypeDatabase::instance(); - - int primary = -1; - int primaries = 0; - for (int i = 0; i < baseClasses.size(); ++i) { - - if (types->isClassRejected(baseClasses.at(i))) - continue; - - TypeEntry* baseClassEntry = types->findType(baseClasses.at(i)); - if (!baseClassEntry) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class '%1' inherits from unknown base class '%2'") - .arg(metaClass->name(), baseClasses.at(i)); - } else if (!baseClassEntry->designatedInterface()) { // true for primary base class - primaries++; - primary = i; - } - } - - if (primary >= 0) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary)); - if (!baseClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown baseclass for '%1': '%2'") - .arg(metaClass->name(), baseClasses.at(primary)); - return false; - } - metaClass->setBaseClass(baseClass); - } - - for (int i = 0; i < baseClasses.size(); ++i) { - if (types->isClassRejected(baseClasses.at(i))) - continue; - - if (i != primary) { - AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i)); - if (!baseClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i)); - return false; - } - - setupInheritance(baseClass); - - QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name(); - AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName); - if (!iface) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName); - return false; - } - metaClass->addInterface(iface); - - const AbstractMetaClassList &interfaces = iface->interfaces(); - for (AbstractMetaClass* iface : interfaces) - metaClass->addInterface(iface); - } - } - - return true; -} - -void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem, - AbstractMetaClass *metaClass, - const QStringList &enumsDeclarations) -{ - const EnumList &enums = scopeItem->enums(); - for (const EnumModelItem &enumItem : enums) { - AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet::fromList(enumsDeclarations)); - if (metaEnum) { - metaClass->addEnum(metaEnum); - metaEnum->setEnclosingClass(metaClass); - } - } -} - -AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc) -{ - return traverseFunction(addedFunc, 0); -} - -AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc, - AbstractMetaClass *metaClass) -{ - AbstractMetaFunction *metaFunction = q->createMetaFunction(); - metaFunction->setConstant(addedFunc.isConstant()); - metaFunction->setName(addedFunc.name()); - metaFunction->setOriginalName(addedFunc.name()); - AbstractMetaClass::Attributes visibility = - addedFunc.access() == AddedFunction::Public - ? AbstractMetaAttributes::Public : AbstractMetaAttributes::Protected; - metaFunction->setVisibility(visibility); - metaFunction->setUserAdded(true); - AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None; - metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::Final | isStatic); - metaFunction->setType(translateType(addedFunc.version(), addedFunc.returnType())); - - - QVector args = addedFunc.arguments(); - AbstractMetaArgumentList metaArguments; - - for (int i = 0; i < args.count(); ++i) { - AddedFunction::TypeInfo& typeInfo = args[i]; - AbstractMetaArgument *metaArg = q->createMetaArgument(); - AbstractMetaType* type = translateType(addedFunc.version(), typeInfo); - decideUsagePattern(type); - metaArg->setType(type); - metaArg->setArgumentIndex(i); - metaArg->setDefaultValueExpression(typeInfo.defaultValue); - metaArg->setOriginalDefaultValueExpression(typeInfo.defaultValue); - metaArguments.append(metaArg); - } - - metaFunction->setArguments(metaArguments); - if (metaFunction->isOperatorOverload() && !metaFunction->isCallOperator()) { - if (metaArguments.size() > 2) { - qCWarning(lcShiboken) << "An operator overload need to have 0, 1 or 2 arguments if it's reverse."; - } else if (metaArguments.size() == 2) { - // Check if it's a reverse operator - if (metaArguments[1]->type()->typeEntry() == metaClass->typeEntry()) { - metaFunction->setReverseOperator(true); - // we need to call these two function to cache the old signature (with two args) - // we do this buggy behaviour to comply with the original apiextractor buggy behaviour. - metaFunction->signature(); - metaFunction->minimalSignature(); - metaArguments.removeLast(); - metaFunction->setArguments(metaArguments); - } else { - qCWarning(lcShiboken) << "Operator overload can have two arguments only if it's a reverse operator!"; - } - } - } - - - // Find the correct default values - for (int i = 0; i < metaArguments.size(); ++i) { - AbstractMetaArgument* metaArg = metaArguments.at(i); - - //use relace-default-expression for set default value - QString replacedExpression; - if (m_currentClass) - replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); - - if (!replacedExpression.isEmpty()) { - QString expr = replacedExpression; - if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { - metaArg->setDefaultValueExpression(expr); - metaArg->setOriginalDefaultValueExpression(expr); - - if (metaArg->type()->isEnum() || metaArg->type()->isFlags()) - m_enumDefaultArguments << QPair(metaArg, metaFunction); - } - } - } - - metaFunction->setOriginalAttributes(metaFunction->attributes()); - fixArgumentNames(metaFunction); - - if (metaClass) { - const AbstractMetaArgumentList fargs = metaFunction->arguments(); - if (metaClass->isNamespace()) - *metaFunction += AbstractMetaFunction::Static; - if (metaFunction->name() == metaClass->name()) { - metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); - if (fargs.size() == 1) { - const TypeEntry *te = fargs.first()->type()->typeEntry(); - if (te->isCustom()) - metaFunction->setExplicit(true); - if (te->name() == metaFunction->name()) - metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - } - } else { - metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); - } - - metaFunction->setDeclaringClass(metaClass); - metaFunction->setImplementingClass(metaClass); - metaClass->addFunction(metaFunction); - metaClass->setHasNonPrivateConstructor(true); - } - - return metaFunction; -} - -void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func) -{ - if (func->arguments().isEmpty()) - return; - const FunctionModificationList &mods = func->modifications(m_currentClass); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argMod : mod.argument_mods) { - if (!argMod.renamed_to.isEmpty()) { - AbstractMetaArgument* arg = func->arguments().at(argMod.index - 1); - arg->setOriginalName(arg->name()); - arg->setName(argMod.renamed_to, false); - } - } - } - - AbstractMetaArgumentList arguments = func->arguments(); - for (int i = 0, size = arguments.size(); i < size; ++i) { - if (arguments.at(i)->name().isEmpty()) - arguments[i]->setName(QLatin1String("arg__") + QString::number(i + 1), false); - } -} - -static QString functionSignature(FunctionModelItem functionItem) -{ - QStringList args; - const ArgumentList &arguments = functionItem->arguments(); - for (const ArgumentModelItem &arg : arguments) - args << arg->type().toString(); - return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')'); -} - -static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem &functionItem, - const QString &className = QString()) -{ - QString result = functionItem->type().toString() + QLatin1Char(' '); - if (!className.isEmpty()) - result += className + colonColon(); - result += functionSignature(functionItem); - return result; -} - -static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n) -{ - QString result; - QTextStream str(&result); - str << "unmatched type '" << arg->type().toString() << "' in parameter #" - << (n + 1); - if (!arg->name().isEmpty()) - str << " \"" << arg->name() << '"'; - return result; -} - -static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n) -{ - QString result; - QTextStream str(&result); - str << "'void' encountered at parameter #" << (n + 1); - if (!arg->name().isEmpty()) - str << " \"" << arg->name() << '"'; - return result; -} - -AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem) -{ - if (!functionItem->templateParameters().isEmpty()) - return nullptr; - QString functionName = functionItem->name(); - QString className; - if (m_currentClass) { - // Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT - // and overridden metaObject(), QGADGET helpers - if (functionName == QLatin1String("qt_check_for_QGADGET_macro") - || functionName.startsWith(QLatin1String("qt_meta"))) { - return nullptr; - } - className = m_currentClass->typeEntry()->qualifiedCppName(); - if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject")) - return nullptr; - } - - // 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); - return 0; - } - else if (TypeDatabase::instance()->isFunctionRejected(className, - functionSignature(functionItem), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); - return 0; - } - - Q_ASSERT(functionItem->functionType() == CodeModel::Normal - || functionItem->functionType() == CodeModel::Signal - || functionItem->functionType() == CodeModel::Slot); - - if (functionItem->isFriend()) - return 0; - - AbstractMetaFunction *metaFunction = q->createMetaFunction(); - metaFunction->setConstant(functionItem->isConstant()); - - if (ReportHandler::isDebug(ReportHandler::MediumDebug)) - qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()"; - - metaFunction->setName(functionName); - metaFunction->setOriginalName(functionItem->name()); - - if (functionItem->isAbstract()) - *metaFunction += AbstractMetaAttributes::Abstract; - - if (!metaFunction->isAbstract()) - *metaFunction += AbstractMetaAttributes::Native; - - if (!functionItem->isVirtual()) - *metaFunction += AbstractMetaAttributes::Final; - - if (functionItem->isInvokable()) - *metaFunction += AbstractMetaAttributes::Invokable; - - if (functionItem->isStatic()) { - *metaFunction += AbstractMetaAttributes::Static; - *metaFunction += AbstractMetaAttributes::Final; - } - - // Access rights - if (functionItem->accessPolicy() == CodeModel::Public) - *metaFunction += AbstractMetaAttributes::Public; - else if (functionItem->accessPolicy() == CodeModel::Private) - *metaFunction += AbstractMetaAttributes::Private; - else - *metaFunction += AbstractMetaAttributes::Protected; - - - QString strippedClassName = className; - int cc_pos = strippedClassName.lastIndexOf(colonColon()); - if (cc_pos > 0) - strippedClassName = strippedClassName.mid(cc_pos + 2); - - TypeInfo functionType = functionItem->type(); - - if (TypeDatabase::instance()->isReturnTypeRejected(className, functionType.toString(), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); - delete metaFunction; - return nullptr; - } - - if (functionName.startsWith(QLatin1Char('~'))) { - metaFunction->setFunctionType(AbstractMetaFunction::DestructorFunction); - metaFunction->setInvalid(true); - } else if (stripTemplateArgs(functionName) == strippedClassName) { - metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); - // Check for Copy/Move down below - metaFunction->setExplicit(functionItem->isExplicit()); - metaFunction->setName(m_currentClass->name()); - } else { - bool ok; - AbstractMetaType* type = translateType(functionType, &ok); - - if (!ok) { - Q_ASSERT(type == 0); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping function '%1', unmatched return type '%2'") - .arg(originalQualifiedSignatureWithReturn, - functionItem->type().toString()); - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); - metaFunction->setInvalid(true); - return metaFunction; - } - - metaFunction->setType(type); - - if (functionItem->functionType() == CodeModel::Signal) - metaFunction->setFunctionType(AbstractMetaFunction::SignalFunction); - else if (functionItem->functionType() == CodeModel::Slot) - metaFunction->setFunctionType(AbstractMetaFunction::SlotFunction); - } - - ArgumentList arguments = functionItem->arguments(); - - if (arguments.size() == 1) { - ArgumentModelItem arg = arguments.at(0); - TypeInfo type = arg->type(); - if (type.qualifiedName().first() == QLatin1String("void") && type.indirections() == 0) - arguments.pop_front(); - } - - AbstractMetaArgumentList metaArguments; - - for (int i = 0; i < arguments.size(); ++i) { - ArgumentModelItem arg = arguments.at(i); - - if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) { - m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); - delete metaFunction; - return nullptr; - } - - bool ok; - AbstractMetaType* metaType = translateType(arg->type(), &ok); - if (!ok) { - Q_ASSERT(metaType == 0); - const QString reason = msgUnmatchedParameterType(arg, i); - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("skipping function '%1', %2") - .arg(originalQualifiedSignatureWithReturn, reason); - const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn - + QLatin1String(": ") + reason; - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); - metaFunction->setInvalid(true); - return metaFunction; - } - - if (metaType == Q_NULLPTR) { - const QString reason = msgVoidParameterType(arg, i); - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("skipping function '%1': %2") - .arg(originalQualifiedSignatureWithReturn, reason); - const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn - + QLatin1String(": ") + reason; - m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); - metaFunction->setInvalid(true); - return metaFunction; - } - - AbstractMetaArgument *metaArgument = q->createMetaArgument(); - - metaArgument->setType(metaType); - metaArgument->setName(arg->name()); - metaArgument->setArgumentIndex(i); - metaArguments << metaArgument; - } - - metaFunction->setArguments(metaArguments); - - // Find the correct default values - for (int i = 0; i < arguments.size(); ++i) { - ArgumentModelItem arg = arguments.at(i); - AbstractMetaArgument* metaArg = metaArguments.at(i); - - //use relace-default-expression for set default value - QString replacedExpression; - if (m_currentClass) { - replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); - } else { - FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature()); - if (!mods.isEmpty()) { - QVector argMods = mods.first().argument_mods; - if (!argMods.isEmpty()) - replacedExpression = argMods.first().replacedDefaultExpression; - } - } - - bool hasDefaultValue = false; - if (arg->defaultValue() || !replacedExpression.isEmpty()) { - QString expr = arg->defaultValueExpression(); - expr = fixDefaultValue(arg, metaArg->type(), metaFunction, m_currentClass, i); - metaArg->setOriginalDefaultValueExpression(expr); - - if (metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { - expr.clear(); - } else if (!replacedExpression.isEmpty()) { - expr = replacedExpression; - } - metaArg->setDefaultValueExpression(expr); - - if (metaArg->type()->isEnum() || metaArg->type()->isFlags()) - m_enumDefaultArguments << QPair(metaArg, metaFunction); - - hasDefaultValue = !expr.isEmpty(); - } - - //Check for missing argument name - if (hasDefaultValue - && !metaArg->hasName() - && !metaFunction->isOperatorOverload() - && !metaFunction->isSignal() - && metaFunction->argumentName(i+1, false, m_currentClass).isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Argument %1 on function '%2::%3' has default expression but does not have name.") - .arg(i+1).arg(className, metaFunction->minimalSignature()); - } - - } - - fixArgumentNames(metaFunction); - - // Determine class special functions - if (m_currentClass && metaFunction->arguments().size() == 1) { - const AbstractMetaType *argType = metaFunction->arguments().first()->type(); - if (argType->typeEntry() == m_currentClass->typeEntry() && argType->indirections() == 0) { - if (metaFunction->isConstructor()) { - switch (argType->referenceType()) { - case NoReference: - metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - break; - case LValueReference: - if (argType->isConstant()) - metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - break; - case RValueReference: - metaFunction->setFunctionType(AbstractMetaFunction::MoveConstructorFunction); - break; - } - } else if (metaFunction->name() == QLatin1String("operator=")) { - switch (argType->referenceType()) { - case NoReference: - metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); - break; - case LValueReference: - if (argType->isConstant()) - metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); - break; - case RValueReference: - metaFunction->setFunctionType(AbstractMetaFunction::MoveAssignmentOperatorFunction); - break; - } - } - } - } - return metaFunction; -} - -AbstractMetaType *AbstractMetaBuilderPrivate::translateType(double vr, - const AddedFunction::TypeInfo &typeInfo) -{ - Q_ASSERT(!typeInfo.name.isEmpty()); - TypeDatabase* typeDb = TypeDatabase::instance(); - TypeEntry* type; - - QString typeName = typeInfo.name; - - if (typeName == QLatin1String("void")) - return 0; - - type = typeDb->findType(typeName); - - // test if the type is a template, like a container - bool isTemplate = false; - QStringList templateArgs; - if (!type && typeInfo.name.contains(QLatin1Char('<'))) { - const QStringList& parsedType = parseTemplateType(typeInfo.name); - if (parsedType.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Template type parsing failed for '%1'").arg(typeInfo.name); - } else { - templateArgs = parsedType.mid(1); - isTemplate = (type = typeDb->findContainerType(parsedType[0])); - } - } - - if (!type) { - QStringList candidates; - SingleTypeEntryHash entries = typeDb->entries(); - for (SingleTypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - // Let's try to find the type in different scopes. - if (it.key().endsWith(colonColon() + typeName)) - candidates.append(it.key()); - } - - QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName); - - if (candidates.isEmpty()) - qFatal(qPrintable(QString(msg + QLatin1String("Declare it in the type system using the proper <*-type> tag."))), NULL); - - msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"); - candidates.sort(); - for (const QString& candidate : qAsConst(candidates)) { - msg += QLatin1String(" ") + candidate + QLatin1Char('\n'); - } - qFatal(qPrintable(msg), NULL); - } - - AbstractMetaType *metaType = q->createMetaType(); - metaType->setTypeEntry(type); - metaType->setIndirections(typeInfo.indirections); - if (typeInfo.isReference) - metaType->setReferenceType(LValueReference); - metaType->setConstant(typeInfo.isConstant); - if (isTemplate) { - for (const QString& templateArg : qAsConst(templateArgs)) { - AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg)); - metaType->addInstantiation(metaArgType); - } - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - } - - return metaType; -} - -static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName) -{ - const TypeEntry* type = 0; - QStringList context = metaClass->qualifiedCppName().split(colonColon()); - while(!type && (context.size() > 0) ) { - type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName); - context.removeLast(); - } - return type; -} - -AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, - bool *ok, bool resolveType, - bool resolveScope) -{ - Q_ASSERT(ok); - *ok = true; - - // 1. Test the type info without resolving typedefs in case this is present in the - // type system - TypeInfo typei; - if (resolveType) { - bool ok; - AbstractMetaType* t = translateType(_typei, &ok, false, resolveScope); - if (t && ok) - return t; - Q_ASSERT(t == 0); - } - - if (!resolveType) { - typei = _typei; - } else { - // Go through all parts of the current scope (including global namespace) - // to resolve typedefs. The parser does not properly resolve typedefs in - // 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 = m_scopes.size() - 1; - while (i >= 0) { - typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)); - if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon())) - break; - } - - } - - if (typei.isFunctionPointer()) { - *ok = false; - return 0; - } - - QString errorMessage; - TypeParser::Info typeInfo = TypeParser::parse(typei.toString(), &errorMessage); - if (typeInfo.is_busted) { - qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString() - << "\": " << errorMessage; - *ok = false; - return 0; - } - - // 2. Handle pointers specified as arrays with unspecified size - bool arrayOfUnspecifiedSize = false; - if (typeInfo.arrays.size() > 0) { - arrayOfUnspecifiedSize = true; - for (int i = 0; i < typeInfo.arrays.size(); ++i) - arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty(); - - if (!arrayOfUnspecifiedSize) { - TypeInfo newInfo; - //newInfo.setArguments(typei.arguments()); - newInfo.setIndirections(typei.indirections()); - newInfo.setConstant(typei.isConstant()); - newInfo.setFunctionPointer(typei.isFunctionPointer()); - newInfo.setQualifiedName(typei.qualifiedName()); - newInfo.setReferenceType(typei.referenceType()); - newInfo.setVolatile(typei.isVolatile()); - - AbstractMetaType* elementType = translateType(newInfo, ok); - if (!(*ok)) - return 0; - - for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) { - QString s = typeInfo.arrays.at(i); - bool _ok; - int elems = findOutValueFromString(s, _ok); - - AbstractMetaType *arrayType = q->createMetaType(); - arrayType->setArrayElementCount(elems); - arrayType->setArrayElementType(elementType); - arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); - decideUsagePattern(arrayType); - - elementType = arrayType; - } - - return elementType; - } else { - typeInfo.indirections += typeInfo.arrays.size(); - } - } - - QStringList qualifierList = typeInfo.qualified_name; - if (qualifierList.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("horribly broken type '%1'").arg(_typei.toString()); - *ok = false; - return 0; - } - - QString qualifiedName = qualifierList.join(colonColon()); - QString name = qualifierList.takeLast(); - - // 3. Special case 'void' type - if (name == QLatin1String("void") && !typeInfo.indirections) - return 0; - - // 4. Special case QFlags (include instantiation in name) - if (qualifiedName == QLatin1String("QFlags")) - qualifiedName = typeInfo.toString(); - - const TypeEntry *type = 0; - // 5. Try to find the type - - // 5.1 - Try first using the current scope - if (m_currentClass) { - type = findTypeEntryUsingContext(m_currentClass, qualifiedName); - - // 5.1.1 - Try using the class parents' scopes - if (!type && !m_currentClass->baseClassNames().isEmpty()) { - const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass); - for (const AbstractMetaClass *cls : baseClasses) { - type = findTypeEntryUsingContext(cls, qualifiedName); - if (type) - break; - } - } - } - - // 5.2 - Try without scope - if (!type) - type = TypeDatabase::instance()->findType(qualifiedName); - - // 6. No? Try looking it up as a flags type - if (!type) - type = TypeDatabase::instance()->findFlagsType(qualifiedName); - - // 7. No? Try looking it up as a container type - if (!type) - type = TypeDatabase::instance()->findContainerType(name); - - // 8. No? Check if the current class is a template and this type is one - // of the parameters. - if (!type && m_currentClass) { - const QVector &template_args = m_currentClass->templateArguments(); - for (TypeEntry *te : template_args) { - if (te->name() == qualifiedName) - type = te; - } - } - - // 9. Try finding the type by prefixing it with the current - // context and all baseclasses of the current context - if (!type && !TypeDatabase::instance()->isClassRejected(qualifiedName) && m_currentClass && resolveScope) { - QStringList contexts; - contexts.append(m_currentClass->qualifiedCppName()); - contexts.append(currentScope()->qualifiedName().join(colonColon())); - - - TypeInfo info = typei; - bool subclassesDone = false; - while (!contexts.isEmpty() && !type) { - type = TypeDatabase::instance()->findType(contexts.at(0) + colonColon() + qualifiedName); - contexts.pop_front(); - - // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so - // enum types from there may be addressed without any scope resolution in properties. - if (!contexts.size() && !subclassesDone) { - contexts << QLatin1String("Qt"); - subclassesDone = true; - } - } - - } - - if (!type) { - *ok = false; - return 0; - } - - // Used to for diagnostics later... - m_usedTypes << type; - - // These are only implicit and should not appear in code... - Q_ASSERT(!type->isInterface()); - - AbstractMetaType *metaType = q->createMetaType(); - metaType->setTypeEntry(type); - metaType->setIndirections(typeInfo.indirections); - metaType->setReferenceType(typeInfo.referenceType); - metaType->setConstant(typeInfo.is_constant); - metaType->setOriginalTypeDescription(_typei.toString()); - - for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) { - TypeInfo info; - info.setConstant(ta.is_constant); - info.setReferenceType(ta.referenceType); - info.setIndirections(ta.indirections); - - info.setFunctionPointer(false); - info.setQualifiedName(ta.instantiationName().split(colonColon())); - - AbstractMetaType* targType = translateType(info, ok); - if (!(*ok)) { - delete metaType; - return 0; - } - - metaType->addInstantiation(targType, true); - } - - // The usage pattern *must* be decided *after* the possible template - // instantiations have been determined, or else the absence of - // such instantiations will break the caching scheme of - // AbstractMetaType::cppSignature(). - decideUsagePattern(metaType); - - return metaType; -} - - -int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok) -{ - int value = stringValue.toInt(&ok); - if (ok) - return value; - - if (stringValue == QLatin1String("true") || stringValue == QLatin1String("false")) { - ok = true; - return (stringValue == QLatin1String("true")); - } - - // 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_]*$")); - Q_ASSERT(variableNameRegExp.isValid()); - if (!variableNameRegExp.match(stringValue).hasMatch()) { - ok = true; - return 0; - } - - AbstractMetaEnumValue *enumValue = AbstractMetaClass::findEnumValue(m_metaClasses, stringValue); - if (enumValue) { - ok = true; - return enumValue->value(); - } - - for (AbstractMetaEnum *metaEnum : qAsConst(m_globalEnums)) { - const AbstractMetaEnumValueList &values = metaEnum->values(); - for (const AbstractMetaEnumValue *ev : values) { - if (ev->name() == stringValue) { - ok = true; - return ev->value(); - } - } - } - - ok = false; - return 0; -} - -void AbstractMetaBuilderPrivate::decideUsagePattern(AbstractMetaType *metaType) -{ - metaType->decideUsagePattern(); -} - -QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item, - AbstractMetaType *type, - AbstractMetaFunction *fnc, - AbstractMetaClass *implementingClass, - int /* argumentIndex */) -{ - QString functionName = fnc->name(); - QString className = implementingClass ? implementingClass->qualifiedCppName() : QString(); - - QString expr = item->defaultValueExpression(); - if (type) { - if (type->isPrimitive()) { - if (type->name() == QLatin1String("boolean")) { - if (expr != QLatin1String("false") && expr != QLatin1String("true")) { - bool ok = false; - int number = expr.toInt(&ok); - if (ok && number) - expr = QLatin1String("true"); - else - expr = QLatin1String("false"); - } - } else { - // This can be an enum or flag so I need to delay the - // translation untill all namespaces are completly - // processed. This is done in figureOutEnumValues() - } - } else if (type->isFlags() || type->isEnum()) { - bool isNumber; - expr.toInt(&isNumber); - if (!isNumber && expr.indexOf(colonColon()) < 0) { - // Add the enum/flag scope to default value, making it usable - // from other contexts beside its owner class hierarchy - static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch match = typeRegEx.match(type->minimalSignature()); - if (match.hasMatch()) - expr.prepend(match.captured(1)); - } - } else if (type->isContainer() && expr.contains(QLatin1Char('<'))) { - static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); - static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); - Q_ASSERT(defaultRegEx.isValid()); - const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); - if (typeMatch.hasMatch() && defaultMatch.hasMatch()) - expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); - } else { - // Here the default value is supposed to be a constructor, - // a class field, or a constructor receiving a class field - static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)")); - Q_ASSERT(defaultRegEx.isValid()); - const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); - QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString(); - if (defaultValueCtorName.endsWith(QLatin1Char('('))) - defaultValueCtorName.chop(1); - - // Fix the scope for constructor using the already - // resolved argument type as a reference. - // The following regular expression extracts any - // use of namespaces/scopes from the type string. - static const QRegularExpression typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$")); - Q_ASSERT(typeRegEx.isValid()); - const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); - - QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString(); - QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString(); - if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) - expr.prepend(typeNamespace); - - // Fix scope if the parameter is a field of the current class - if (implementingClass) { - const AbstractMetaFieldList &fields = implementingClass->fields(); - for (const AbstractMetaField *field : fields) { - if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field->name()) { - expr = defaultMatch.captured(1) + implementingClass->name() - + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3); - break; - } - } - } - } - } else { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("undefined type for default value '%3' of argument in function '%1', class '%2'") - .arg(functionName, className, item->defaultValueExpression()); - - expr = QString(); - } - - return expr; -} - -bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QString &qualifiedName) -{ - if (qualifiedName == QLatin1String("QObject")) - return true; - - ClassModelItem classItem = dom->findClass(qualifiedName); - - if (!classItem) { - QStringList names = qualifiedName.split(colonColon()); - NamespaceModelItem ns = dom; - for (int i = 0; i < names.size() - 1 && ns; ++i) - ns = ns->findNamespace(names.at(i)); - if (ns && names.size() >= 2) - classItem = ns->findClass(names.at(names.size() - 1)); - } - - bool isqobject = classItem && classItem->extendsClass(QLatin1String("QObject")); - - if (classItem && !isqobject) { - QStringList baseClasses = classItem->baseClasses(); - for (int i = 0; i < baseClasses.count(); ++i) { - - isqobject = isQObject(dom, baseClasses.at(i)); - if (isqobject) - break; - } - } - - return isqobject; -} - - -bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringList& qualified_name) -{ - CodeModelItem item = dom->model()->findItem(qualified_name, dom); - return item && item->kind() == _EnumModelItem::__node_kind; -} - -AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, - const AbstractMetaClass *context, - TypeParser::Info *info, - ComplexTypeEntry **baseContainerType) const -{ - TypeParser::Info localInfo; - if (!info) - info = &localInfo; - - TypeDatabase* types = TypeDatabase::instance(); - - QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon()); - 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(); - QString completeName = prefix + name; - const TypeParser::Info parsed = TypeParser::parse(completeName, &errorMessage); - if (parsed.is_busted) { - qWarning().noquote().nospace() << "Unable to parse type \"" << completeName - << "\" while looking for template \"" << name << "\": " << errorMessage; - continue; - } - *info = parsed; - QString qualifiedName = info->qualified_name.join(colonColon()); - - AbstractMetaClass* templ = 0; - for (AbstractMetaClass *c : qAsConst(m_templates)) { - if (c->typeEntry()->name() == qualifiedName) { - templ = c; - break; - } - } - - if (!templ) - templ = AbstractMetaClass::findClass(m_metaClasses, qualifiedName); - - if (templ) - return templ; - - if (baseContainerType) - *baseContainerType = types->findContainerType(qualifiedName); - } - - return 0; -} - -AbstractMetaClassList AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const -{ - AbstractMetaClassList baseClasses; - const QStringList &baseClassNames = metaClass->baseClassNames(); - for (const QString& parent : baseClassNames) { - AbstractMetaClass* cls = 0; - if (parent.contains(QLatin1Char('<'))) - cls = findTemplateClass(parent, metaClass); - else - cls = AbstractMetaClass::findClass(m_metaClasses, parent); - - if (cls) - baseClasses << cls; - } - return baseClasses; -} - -bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const -{ - if (metaClass->hasPrivateCopyConstructor()) - return true; - const AbstractMetaClassList &baseClasses = getBaseClasses(metaClass); - for (const AbstractMetaClass *cls : baseClasses) { - if (ancestorHasPrivateCopyConstructor(cls)) - return true; - } - return false; -} - -AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector &templateTypes, - const AbstractMetaType *metaType, - bool *ok) -{ - if (ok) - *ok = true; - if (!metaType || (!metaType->typeEntry()->isTemplateArgument() && !metaType->hasInstantiations())) - return metaType ? metaType->copy() : 0; - - AbstractMetaType *returned = metaType->copy(); - returned->setOriginalTemplateType(metaType->copy()); - - if (returned->typeEntry()->isTemplateArgument()) { - const TemplateArgumentEntry* tae = static_cast(returned->typeEntry()); - - // If the template is intantiated with void we special case this as rejecting the functions that use this - // parameter from the instantiation. - if (templateTypes.size() <= tae->ordinal() || templateTypes.at(tae->ordinal())->typeEntry()->name() == QLatin1String("void")) { - if (ok) - *ok = false; - return 0; - } - - AbstractMetaType* t = returned->copy(); - t->setTypeEntry(templateTypes.at(tae->ordinal())->typeEntry()); - t->setIndirections(templateTypes.at(tae->ordinal())->indirections() + t->indirections() ? 1 : 0); - decideUsagePattern(t); - - delete returned; - returned = inheritTemplateType(templateTypes, t, ok); - if (ok && !(*ok)) - return 0; - } - - if (returned->hasInstantiations()) { - AbstractMetaTypeList instantiations = returned->instantiations(); - for (int i = 0; i < instantiations.count(); ++i) { - AbstractMetaType *type = instantiations[i]; - instantiations[i] = inheritTemplateType(templateTypes, type, ok); - if (ok && !(*ok)) - return 0; - } - returned->setInstantiations(instantiations, true); - } - - return returned; -} - -bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, - const TypeParser::Info &info) -{ - QVector targs = info.template_instantiations; - QVector templateTypes; - - if (subclass->isTypeDef()) { - subclass->setHasCloneOperator(templateClass->hasCloneOperator()); - subclass->setHasEqualsOperator(templateClass->hasEqualsOperator()); - subclass->setHasHashFunction(templateClass->hasHashFunction()); - subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor()); - subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor()); - subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor()); - subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor()); - } - - for (const TypeParser::Info &i : qAsConst(targs)) { - QString typeName = i.qualified_name.join(colonColon()); - QStringList possibleNames; - possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; - possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; - if (subclass->enclosingClass()) - possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName; - possibleNames << typeName; - - TypeDatabase* typeDb = TypeDatabase::instance(); - TypeEntry* t = 0; - QString templateParamName; - for (const QString &possibleName : qAsConst(possibleNames)) { - t = typeDb->findType(possibleName); - if (t) { - QString templateParamName = possibleName; - break; - } - } - - if (t) { - AbstractMetaType *temporaryType = q->createMetaType(); - temporaryType->setTypeEntry(t); - temporaryType->setConstant(i.is_constant); - temporaryType->setReferenceType(i.referenceType); - temporaryType->setIndirections(i.indirections); - temporaryType->decideUsagePattern(); - templateTypes << temporaryType; - } else { - qCWarning(lcShiboken).noquote().nospace() - << "Ignoring template parameter " << templateParamName << " from " - << info.instantiationName() << ", because I don't know what it is."; - } - } - - AbstractMetaFunctionList funcs = subclass->functions(); - const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions(); - for (const AbstractMetaFunction *function : templateClassFunctions) { - if (function->isModifiedRemoved(TypeSystem::All)) - continue; - - AbstractMetaFunction *f = function->copy(); - f->setArguments(AbstractMetaArgumentList()); - - bool ok = true; - AbstractMetaType *ftype = function->type(); - f->replaceType(inheritTemplateType(templateTypes, ftype, &ok)); - if (!ok) { - delete f; - continue; - } - - const AbstractMetaArgumentList &arguments = function->arguments(); - for (AbstractMetaArgument *argument : arguments) { - AbstractMetaType* atype = argument->type(); - - AbstractMetaArgument *arg = argument->copy(); - arg->replaceType(inheritTemplateType(templateTypes, atype, &ok)); - if (!ok) - break; - f->addArgument(arg); - } - - if (!ok) { - delete f; - continue; - } - - // There is no base class in the target language to inherit from here, so - // the template instantiation is the class that implements the function. - f->setImplementingClass(subclass); - - // We also set it as the declaring class, since the superclass is - // supposed to disappear. This allows us to make certain function modifications - // on the inherited functions. - f->setDeclaringClass(subclass); - - - if (f->isConstructor() && subclass->isTypeDef()) { - f->setName(subclass->name()); - f->setOriginalName(subclass->name()); - } else if (f->isConstructor()) { - delete f; - continue; - } - - // if the instantiation has a function named the same as an existing - // function we have shadowing so we need to skip it. - bool found = false; - for (int i = 0; i < funcs.size(); ++i) { - if (funcs.at(i)->name() == f->name()) { - found = true; - continue; - } - } - if (found) { - delete f; - continue; - } - - ComplexTypeEntry* te = subclass->typeEntry(); - FunctionModificationList mods = function->modifications(templateClass); - for (int i = 0; i < mods.size(); ++i) { - FunctionModification mod = mods.at(i); - mod.signature = f->minimalSignature(); - - // If we ever need it... Below is the code to do - // substitution of the template instantation type inside - // injected code.. -#if 0 - if (mod.modifiers & Modification::CodeInjection) { - for (int j = 0; j < template_types.size(); ++j) { - CodeSnip &snip = mod.snips.last(); - QString code = snip.code(); - code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j), - template_types.at(j)->typeEntry()->qualifiedCppName()); - snip.codeList.clear(); - snip.addCode(code); - } - } -#endif - te->addFunctionModification(mod); - } - - subclass->addFunction(f); - } - - subclass->setTemplateBaseClass(templateClass); - subclass->setTemplateBaseClassInstantiations(templateTypes); - subclass->setInterfaces(templateClass->interfaces()); - subclass->setBaseClass(templateClass->baseClass()); - - return true; -} - -void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, - const QStringList &declarations) -{ - for (int i = 0; i < declarations.size(); ++i) { - QString p = declarations.at(i); - - QStringList l = p.split(QLatin1String(" ")); - - - QStringList qualifiedScopeName = currentScope()->qualifiedName(); - bool ok = false; - AbstractMetaType* type = 0; - QString scope; - for (int j = qualifiedScopeName.size(); j >= 0; --j) { - scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join(colonColon()) + colonColon() : QString(); - TypeInfo info; - info.setQualifiedName((scope + l.at(0)).split(colonColon())); - - type = translateType(info, &ok); - if (type && ok) - break; - } - - if (!type || !ok) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Unable to decide type of property: '%1' in class '%2'") - .arg(l.at(0), metaClass->name()); - continue; - } - - QString typeName = scope + l.at(0); - - QPropertySpec* spec = new QPropertySpec(type->typeEntry()); - spec->setName(l.at(1)); - spec->setIndex(i); - - for (int pos = 2; pos + 1 < l.size(); pos += 2) { - if (l.at(pos) == QLatin1String("READ")) - spec->setRead(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("WRITE")) - spec->setWrite(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("DESIGNABLE")) - spec->setDesignable(l.at(pos + 1)); - else if (l.at(pos) == QLatin1String("RESET")) - spec->setReset(l.at(pos + 1)); - } - - metaClass->addPropertySpec(spec); - delete type; - } -} - -static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls) -{ - AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible); - functions << cls->queryFunctions(AbstractMetaClass::Visible); - - for (AbstractMetaFunction *f : qAsConst(functions)) { - const AbstractMetaFunction::FunctionType t = f->functionType(); - if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction) - return f; - } - return 0; -} - -void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) -{ - bool result = true; - - // find copy ctor for the current class - AbstractMetaFunction* copyCtor = findCopyCtor(cls); - if (copyCtor) { // if exists a copy ctor in this class - result = copyCtor->isPublic(); - } else { // else... lets find one in the parent class - QQueue baseClasses; - if (cls->baseClass()) - baseClasses.enqueue(cls->baseClass()); - baseClasses << cls->interfaces().toList(); - - while (!baseClasses.isEmpty()) { - AbstractMetaClass* currentClass = baseClasses.dequeue(); - baseClasses << currentClass->interfaces().toList(); - if (currentClass->baseClass()) - baseClasses.enqueue(currentClass->baseClass()); - - copyCtor = findCopyCtor(currentClass); - if (copyCtor) { - result = copyCtor->isPublic(); - break; - } - } - } - cls->setHasCloneOperator(result); -} - -void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls) -{ - const AbstractMetaFunctionList &convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp); - for (AbstractMetaFunction *func : convOps) { - if (func->isModifiedRemoved()) - continue; - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type()->typeEntry()); - if (!metaClass) - continue; - metaClass->addExternalConversionOperator(func); - } - const AbstractMetaClassList &innerClasses = cls->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - setupExternalConversion(innerClass); -} - -static void writeRejectLogFile(const QString &name, - const QMap &rejects) -{ - QFile f(name); - if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("failed to write log file: '%1'") - .arg(QDir::toNativeSeparators(f.fileName())); - return; - } - - QTextStream s(&f); - - - for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { - s << QString(72, QLatin1Char('*')) << endl; - 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; - - default: - s << "unknown reason"; - break; - } - - s << endl; - - for (QMap::const_iterator it = rejects.constBegin(); - it != rejects.constEnd(); ++it) { - if (it.value() != reason) - continue; - s << " - " << it.key() << endl; - } - - s << QString(72, QLatin1Char('*')) << endl << endl; - } - -} - -void AbstractMetaBuilderPrivate::dumpLog() const -{ - writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_classes.log"), m_rejectedClasses); - writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_enums.log"), m_rejectedEnums); - writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_functions.log"), m_rejectedFunctions); - writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_fields.log"), m_rejectedFields); -} - -AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClass *cppClass, - const Dependencies &additionalDependencies) const -{ - QLinkedList unmappedResult; - QHash map; - QHash reverseMap; - - const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses; - - int i = 0; - for (AbstractMetaClass *clazz : classList) { - if (map.contains(clazz->qualifiedCppName())) - continue; - map[clazz->qualifiedCppName()] = i; - reverseMap[i] = clazz; - i++; - } - - Graph graph(map.count()); - - for (const Dependency &dep : additionalDependencies) { - const int parentIndex = map.value(dep.parent, -1); - const int childIndex = map.value(dep.child, -1); - if (parentIndex >= 0 && childIndex >= 0) { - graph.addEdge(parentIndex, childIndex); - } else { - qCWarning(lcShiboken).noquote().nospace() - << "AbstractMetaBuilder::classesTopologicalSorted(): Invalid additional dependency: " - << dep.child << " -> " << dep.parent << '.'; - } - } - - // TODO choose a better name to these regexs - static const QRegularExpression regex1(QStringLiteral("\\(.*\\)")); - Q_ASSERT(regex1.isValid()); - static const QRegularExpression regex2(QStringLiteral("::.*")); - Q_ASSERT(regex2.isValid()); - for (AbstractMetaClass *clazz : classList) { - if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName())) - graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]); - - const AbstractMetaClassList &bases = getBaseClasses(clazz); - for (AbstractMetaClass *baseClass : bases) { - // Fix polymorphic expression - if (clazz->baseClass() == baseClass) - clazz->setBaseClass(baseClass); - - if (map.contains(baseClass->qualifiedCppName())) - graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]); - } - - const AbstractMetaFunctionList &functions = clazz->functions(); - for (AbstractMetaFunction *func : functions) { - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - // check methods with default args - QString defaultExpression = arg->originalDefaultValueExpression(); - if (!defaultExpression.isEmpty()) { - if (defaultExpression == QLatin1String("0") && arg->type()->isValue()) - defaultExpression = arg->type()->name(); - - defaultExpression.remove(regex1); - defaultExpression.remove(regex2); - } - if (!defaultExpression.isEmpty()) { - QString exprClassName = clazz->qualifiedCppName() + colonColon() + defaultExpression; - if (!map.contains(exprClassName)) { - bool found = false; - for (AbstractMetaClass *baseClass : bases) { - exprClassName = baseClass->qualifiedCppName() + colonColon() + defaultExpression; - if (map.contains(exprClassName)) { - found = true; - break; - } - } - if (!found) { - if (map.contains(defaultExpression)) - exprClassName = defaultExpression; - else - exprClassName.clear(); - } - } - if (!exprClassName.isEmpty() && exprClassName != clazz->qualifiedCppName()) - graph.addEdge(map[exprClassName], map[clazz->qualifiedCppName()]); - } - } - } - } - - AbstractMetaClassList result; - unmappedResult = graph.topologicalSort(); - if (unmappedResult.isEmpty() && graph.nodeCount()) { - QTemporaryFile tempFile; - tempFile.setAutoRemove(false); - tempFile.open(); - QHash hash; - QHash::iterator it = map.begin(); - for (; it != map.end(); ++it) - hash[it.value()] = it.key(); - graph.dumpDot(hash, tempFile.fileName()); - qCWarning(lcShiboken).noquote().nospace() - << "Cyclic dependency found! Graph can be found at " - << QDir::toNativeSeparators(tempFile.fileName()); - } else { - for (int i : qAsConst(unmappedResult)) { - Q_ASSERT(reverseMap.contains(i)); - if (!reverseMap[i]->isInterface()) - result << reverseMap[i]; - } - } - - return result; -} - -AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClass *cppClass, - const Dependencies &additionalDependencies) const -{ - return d->classesTopologicalSorted(cppClass, additionalDependencies); -} - -AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractMetaArgumentList &list) -{ - AbstractMetaArgumentList ret; - - int index = list.size(); - for (AbstractMetaArgument *arg : list) { - arg->setArgumentIndex(index); - ret.prepend(arg); - index--; - } - - return ret; -} - -void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader) -{ - d->m_globalHeader = QFileInfo(globalHeader); -} - -void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const -{ - QFileInfo info(fileName); - if (m_globalHeader.fileName() != info.fileName()) - te->setInclude(Include(Include::IncludePath, info.fileName())); -} - -#ifndef QT_NO_DEBUG_STREAM -template -static void debugFormatSequence(QDebug &d, const char *key, const Container& c, - const char *separator = ", ") -{ - typedef typename Container::const_iterator ConstIt; - if (c.isEmpty()) - return; - const ConstIt begin = c.begin(); - const ConstIt end = c.end(); - d << "\n " << key << '[' << c.size() << "]=("; - for (ConstIt it = begin; it != end; ++it) { - if (it != begin) - d << separator; - d << *it; - } - d << ')'; -} - -void AbstractMetaBuilder::formatDebug(QDebug &debug) const -{ - debug << "m_globalHeader=" << d->m_globalHeader.absoluteFilePath(); - debugFormatSequence(debug, "qtMetaTypeDeclaredTypeNames", d->m_qmetatypeDeclaredTypenames); - debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n"); - debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n"); - if (const int scopeCount = d->m_scopes.size()) { - debug << "\n scopes[" << scopeCount << "]=("; - for (int i = 0; i < scopeCount; ++i) { - if (i) - debug << ", "; - _CodeModelItem::formatKind(debug, d->m_scopes.at(i)->kind()); - debug << " \"" << d->m_scopes.at(i)->name() << '"'; - } - debug << ')'; - } - debugFormatSequence(debug, "classes", d->m_metaClasses, "\n"); - debugFormatSequence(debug, "templates", d->m_templates, "\n"); -} - -QDebug operator<<(QDebug d, const AbstractMetaBuilder &ab) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaBuilder("; - ab.formatDebug(d); - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM diff --git a/ApiExtractor/abstractmetabuilder.h b/ApiExtractor/abstractmetabuilder.h deleted file mode 100644 index f7427d488..000000000 --- a/ApiExtractor/abstractmetabuilder.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ABSTRACTMETABUILDER_H -#define ABSTRACTMETABUILDER_H - -#include "abstractmetalang_typedefs.h" -#include "dependency.h" - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -class AbstractMetaBuilderPrivate; -class AbstractMetaClass; -class AbstractMetaEnumValue; - -class AbstractMetaBuilder -{ -public: - enum RejectReason { - NotInTypeSystem, - GenerationDisabled, - RedefinedToNotClass, - UnmatchedArgumentType, - UnmatchedReturnType, - ApiIncompatible, - NoReason - }; - - AbstractMetaBuilder(); - virtual ~AbstractMetaBuilder(); - - AbstractMetaClassList classes() const; - AbstractMetaClassList templates() const; - AbstractMetaClassList smartPointers() const; - AbstractMetaFunctionList globalFunctions() const; - AbstractMetaEnumList globalEnums() const; - // QtScript - QSet qtMetaTypeDeclaredTypeNames() const; - - /** - * Sorts a list of classes topologically, if an AbstractMetaClass object - * is passed the list of classes will be its inner classes, otherwise - * the list will be the module global classes. - * \return a list of classes sorted topologically - */ - AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, - const Dependencies &additionalDependencies = Dependencies()) const; - - bool build(const QByteArrayList &arguments, unsigned clangFlags = 0); - void setLogDirectory(const QString& logDir); - - /** - * AbstractMetaBuilder should know what's the global header being used, - * so any class declared under this header wont have the include file - * filled. - */ - void setGlobalHeader(const QString& globalHeader); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const; -#endif - -protected: - virtual AbstractMetaClass *createMetaClass(); - virtual AbstractMetaEnum *createMetaEnum(); - virtual AbstractMetaEnumValue *createMetaEnumValue(); - virtual AbstractMetaField *createMetaField(); - virtual AbstractMetaFunction *createMetaFunction(); - virtual AbstractMetaArgument *createMetaArgument(); - virtual AbstractMetaType *createMetaType(); - -private: - friend class AbstractMetaBuilderPrivate; - AbstractMetaBuilderPrivate *d; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaBuilder &ab); -#endif - -#endif // ABSTRACTMETBUILDER_H diff --git a/ApiExtractor/abstractmetabuilder_p.h b/ApiExtractor/abstractmetabuilder_p.h deleted file mode 100644 index 96a6fdbfd..000000000 --- a/ApiExtractor/abstractmetabuilder_p.h +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ABSTRACTMETABUILDER_P_H -#define ABSTRACTMETABUILDER_P_H - -#include "abstractmetabuilder.h" -#include "parser/codemodel_fwd.h" -#include "abstractmetalang.h" -#include "typesystem.h" -#include "typeparser.h" - -#include -#include - -class TypeDatabase; - -class AbstractMetaBuilderPrivate -{ -public: - AbstractMetaBuilderPrivate(); - ~AbstractMetaBuilderPrivate(); - - static FileModelItem buildDom(const QByteArrayList &arguments, unsigned clangFlags); - void traverseDom(const FileModelItem &dom); - - void dumpLog() const; - AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, - const Dependencies &additionalDependencies = Dependencies()) const; - ScopeModelItem popScope() { return m_scopes.takeLast(); } - - void pushScope(ScopeModelItem item) { m_scopes << item; } - - ScopeModelItem currentScope() const { return m_scopes.last(); } - - AbstractMetaClass *argumentToClass(ArgumentModelItem); - - void figureOutEnumValuesForClass(AbstractMetaClass *metaClass, QSet *classes); - int figureOutEnumValue(const QString &name, int value, AbstractMetaEnum *meta_enum, AbstractMetaFunction *metaFunction = 0); - void figureOutEnumValues(); - void figureOutDefaultEnumArguments(); - - void addAbstractMetaClass(AbstractMetaClass *cls); - AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, - const TypeDefModelItem &typeDef); - AbstractMetaClass *traverseClass(const FileModelItem &dom, - const ClassModelItem &item); - AbstractMetaClass *currentTraversedClass(ScopeModelItem item); - void traverseScopeMembers(ScopeModelItem item, AbstractMetaClass *metaClass); - void traverseClassMembers(ClassModelItem scopeItem); - void traverseNamespaceMembers(NamespaceModelItem scopeItem); - bool setupInheritance(AbstractMetaClass *metaClass); - AbstractMetaClass *traverseNamespace(const FileModelItem &dom, - const NamespaceModelItem &item); - AbstractMetaEnum *traverseEnum(EnumModelItem item, AbstractMetaClass *enclosing, - const QSet &enumsDeclarations); - void traverseEnums(ScopeModelItem item, AbstractMetaClass *parent, - const QStringList &enumsDeclarations); - AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem); - AbstractMetaFunctionList templateClassFunctionList(const ScopeModelItem &scopeItem, - AbstractMetaClass *metaClass); - void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); - void applyFunctionModifications(AbstractMetaFunction* func); - void traverseFields(ScopeModelItem item, AbstractMetaClass *parent); - void traverseStreamOperator(FunctionModelItem functionItem); - void traverseOperatorFunction(FunctionModelItem item); - AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc); - AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc, - AbstractMetaClass *metaClass); - AbstractMetaFunction *traverseFunction(FunctionModelItem function); - AbstractMetaField *traverseField(VariableModelItem field, - const AbstractMetaClass *cls); - void checkFunctionModifications(); - void registerHashFunction(FunctionModelItem functionItem); - void registerToStringCapability(FunctionModelItem functionItem); - - /** - * A conversion operator function should not have its owner class as - * its return type, but unfortunately it does. This function fixes the - * return type of operator functions of this kind making the return type - * be the same as it is supposed to generate when used in C++. - * If the returned type is a wrapped C++ class, this method also adds the - * conversion operator to the collection of external conversions of the - * said class. - * \param metaFunction conversion operator function to be fixed. - */ - void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction); - - void parseQ_Property(AbstractMetaClass *metaClass, const QStringList &declarations); - void setupEquals(AbstractMetaClass *metaClass); - void setupComparable(AbstractMetaClass *metaClass); - void setupClonable(AbstractMetaClass *cls); - void setupExternalConversion(AbstractMetaClass *cls); - void setupFunctionDefaults(AbstractMetaFunction *metaFunction, - AbstractMetaClass *metaClass); - - QString fixDefaultValue(ArgumentModelItem item, AbstractMetaType *type, - AbstractMetaFunction *fnc, AbstractMetaClass *, - int argumentIndex); - AbstractMetaType* translateType(double vr, const AddedFunction::TypeInfo &typeInfo); - AbstractMetaType *translateType(const TypeInfo &type, bool *ok, - bool resolveType = true, - bool resolveScope = true); - - int findOutValueFromString(const QString &stringValue, bool &ok); - - void decideUsagePattern(AbstractMetaType *type); - - AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, - TypeParser::Info *info = Q_NULLPTR, - ComplexTypeEntry **baseContainerType = Q_NULLPTR) const; - AbstractMetaClassList getBaseClasses(const AbstractMetaClass *metaClass) const; - bool ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const; - - bool inheritTemplate(AbstractMetaClass *subclass, - const AbstractMetaClass *templateClass, - const TypeParser::Info &info); - AbstractMetaType *inheritTemplateType(const QVector &templateTypes, - const AbstractMetaType *metaType, - bool *ok = Q_NULLPTR); - - bool isQObject(const FileModelItem &dom, const QString &qualifiedName); - bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName); - - void fixQObjectForScope(const FileModelItem &dom, const TypeDatabase *types, - const NamespaceModelItem &item); - - void sortLists(); - AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); - void setInclude(TypeEntry *te, const QString &fileName) const; - void fixArgumentNames(AbstractMetaFunction *func); - void fillAddedFunctions(AbstractMetaClass *metaClass); - - AbstractMetaBuilder *q; - AbstractMetaClassList m_metaClasses; - AbstractMetaClassList m_templates; - AbstractMetaClassList m_smartPointers; - AbstractMetaFunctionList m_globalFunctions; - AbstractMetaEnumList m_globalEnums; - - QSet m_usedTypes; - - typedef QMap RejectMap; - - RejectMap m_rejectedClasses; - RejectMap m_rejectedEnums; - RejectMap m_rejectedFunctions; - RejectMap m_rejectedFields; - - QList m_enums; - - QList > m_enumDefaultArguments; - - QHash m_enumValues; - - AbstractMetaClass *m_currentClass; - QList m_scopes; - QString m_namespacePrefix; - - QSet m_setupInheritanceDone; - - // QtScript - QSet m_qmetatypeDeclaredTypenames; - - QString m_logDirectory; - QFileInfo m_globalHeader; -}; - -#endif // ABSTRACTMETBUILDER_P_H diff --git a/ApiExtractor/abstractmetalang.cpp b/ApiExtractor/abstractmetalang.cpp deleted file mode 100644 index 4fa009fd2..000000000 --- a/ApiExtractor/abstractmetalang.cpp +++ /dev/null @@ -1,2784 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "abstractmetalang.h" -#include "reporthandler.h" -#include "typedatabase.h" -#include "typesystem.h" - -#ifndef QT_NO_DEBUG_STREAM -# include -# include -#endif - -#include -#include - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaAttributes("; - if (aa) - d << aa->attributes(); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaVariable - */ - -AbstractMetaVariable::AbstractMetaVariable(const AbstractMetaVariable &other) -{ - m_originalName = other.m_originalName; - m_name = other.m_name; - m_type = other.m_type->copy(); - m_hasName = other.m_hasName; - m_doc = other.m_doc; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaVariable *av) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaVariable("; - if (av) { - d << av->type()->name() << ' ' << av->name(); - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaType - */ - -AbstractMetaType::AbstractMetaType() - :m_typeEntry(0), - m_arrayElementCount(0), - m_arrayElementType(0), - m_originalTemplateType(0), - m_pattern(InvalidPattern), - m_constant(false), - m_cppInstantiation(true), - m_indirections(0), - m_reserved(0), - m_referenceType(NoReference) -{ -} - -AbstractMetaType::~AbstractMetaType() -{ - qDeleteAll(m_children); - m_instantiations.clear(); -} - -QString AbstractMetaType::package() const -{ - return m_typeEntry->targetLangPackage(); -} - -QString AbstractMetaType::name() const -{ - if (m_name.isNull()) - // avoid constLast to stay Qt 5.5 compatible - m_name = m_typeEntry->targetLangName().split(QLatin1String("::")).last(); - return m_name; -} - -QString AbstractMetaType::fullName() const -{ - return m_typeEntry->qualifiedTargetLangName(); -} - -AbstractMetaType *AbstractMetaType::copy() const -{ - AbstractMetaType *cpy = new AbstractMetaType; - - cpy->setTypeUsagePattern(typeUsagePattern()); - cpy->setConstant(isConstant()); - cpy->setReferenceType(referenceType()); - cpy->setIndirections(indirections()); - cpy->setInstantiations(instantiations()); - cpy->setArrayElementCount(arrayElementCount()); - cpy->setOriginalTypeDescription(originalTypeDescription()); - cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0); - - cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0); - - cpy->setTypeEntry(typeEntry()); - - return cpy; -} - -QString AbstractMetaType::cppSignature() const -{ - if (m_cachedCppSignature.isEmpty()) { - if (isConstant()) - m_cachedCppSignature += QLatin1String("const "); - - m_cachedCppSignature += typeEntry()->qualifiedCppName(); - - if (hasInstantiationInCpp()) { - AbstractMetaTypeList types = instantiations(); - m_cachedCppSignature += QLatin1Char('<'); - for (int i = 0; i < types.count(); ++i) { - if (i > 0) - m_cachedCppSignature += QLatin1String(", "); - m_cachedCppSignature += types[i]->cppSignature(); - } - m_cachedCppSignature += QLatin1String(" >"); - } - - if (indirections() || m_referenceType != NoReference) { - m_cachedCppSignature += QLatin1Char(' '); - if (indirections()) - m_cachedCppSignature += QString(indirections(), QLatin1Char('*')); - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - m_cachedCppSignature += QLatin1Char('&'); - break; - case RValueReference: - m_cachedCppSignature += QLatin1String("&&"); - break; - } - } - } - return m_cachedCppSignature; -} - -AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() const -{ - if (m_typeEntry->isTemplateArgument() || m_referenceType == RValueReference) - return InvalidPattern; - - if (m_typeEntry->isPrimitive() && (!actualIndirections() - || (isConstant() && m_referenceType == LValueReference && !indirections()))) { - return PrimitivePattern; - } - - if (m_typeEntry->isVoid()) - return NativePointerPattern; - - if (m_typeEntry->isVarargs()) - return VarargsPattern; - - if (m_typeEntry->isString() && indirections() == 0 - && (isConstant() == (m_referenceType == LValueReference) - || isConstant())) { - return StringPattern; - } - - if (m_typeEntry->isChar() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return CharPattern; - } - - if (m_typeEntry->isJObjectWrapper() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return JObjectWrapperPattern; - } - - if (m_typeEntry->isVariant() - && indirections() == 0 - && isConstant() == (m_referenceType == LValueReference)) { - return VariantPattern; - } - - if (m_typeEntry->isEnum() && actualIndirections() == 0) - return EnumPattern; - - if (m_typeEntry->isObject()) { - if (indirections() == 0 && m_referenceType == NoReference) - return ValuePattern; - return static_cast(m_typeEntry)->isQObject() - ? QObjectPattern : ObjectPattern; - } - - if (m_typeEntry->isContainer() && indirections() == 0) - return ContainerPattern; - - if (m_typeEntry->isSmartPointer() && indirections() == 0) - return SmartPointerPattern; - - if (m_typeEntry->isFlags() && indirections() == 0 - && (isConstant() == (m_referenceType == LValueReference))) - return FlagsPattern; - - if (m_typeEntry->isArray()) - return ArrayPattern; - - if (m_typeEntry->isThread()) { - Q_ASSERT(indirections() == 1); - return ThreadPattern; - } - - if (m_typeEntry->isValue()) - return indirections() == 1 ? ValuePointerPattern : ValuePattern; - - if (ReportHandler::isDebug(ReportHandler::FullDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("native pointer pattern for '%1'").arg(cppSignature()); - } - return NativePointerPattern; -} - -void AbstractMetaType::decideUsagePattern() -{ - TypeUsagePattern pattern = determineUsagePattern(); - if (m_typeEntry->isObject() && indirections() == 1 - && m_referenceType == LValueReference && isConstant()) { - // const-references to pointers can be passed as pointers - setReferenceType(NoReference); - setConstant(false); - pattern = static_cast(m_typeEntry)->isQObject() - ? QObjectPattern : ObjectPattern; - } - setTypeUsagePattern(pattern); -} - -bool AbstractMetaType::hasTemplateChildren() const -{ - QStack children; - children << m_children; - - // Recursively iterate over the children / descendants of the type, to check if any of them - // corresponds to a template argument type. - while (!children.isEmpty()) { - AbstractMetaType *child = children.pop(); - if (child->typeEntry()->isTemplateArgument()) - return true; - children << child->m_children; - } - - return false; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaType *at) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaType("; - if (at) - d << at->name(); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaArgument - */ -AbstractMetaArgument *AbstractMetaArgument::copy() const -{ - return new AbstractMetaArgument(*this); -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaArgument("; - if (aa) - d << aa->toString(); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaFunction - */ -AbstractMetaFunction::~AbstractMetaFunction() -{ - qDeleteAll(m_arguments); - delete m_type; -} - -/******************************************************************************* - * Indicates that this function has a modification that removes it - */ -bool AbstractMetaFunction::isModifiedRemoved(int types) const -{ - const FunctionModificationList &mods = modifications(implementingClass()); - for (const FunctionModification &mod : mods) { - if (!mod.isRemoveModifier()) - continue; - - if ((mod.removal & types) == types) - return true; - } - - return false; -} - -bool AbstractMetaFunction::needsCallThrough() const -{ - if (ownerClass()->isInterface()) - return false; - if (referenceCounts(implementingClass()).size() > 0) - return true; - if (argumentsHaveNativeId() || !isStatic()) - return true; - - for (const AbstractMetaArgument *arg : m_arguments) { - if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags()) - return true; - } - - if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags())) - return true; - - for (int i = -1; i <= arguments().size(); ++i) { - TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i); - if (owner != TypeSystem::InvalidOwnership) - return true; - } - - return false; -} - -bool AbstractMetaFunction::needsSuppressUncheckedWarning() const -{ - for (int i = -1; i <= arguments().size(); ++i) { - const QVector &referenceCounts = this->referenceCounts(implementingClass(), i); - for (const ReferenceCount &referenceCount : referenceCounts) { - if (referenceCount.action != ReferenceCount::Set) - return true; - } - } - return false; -} - -QString AbstractMetaFunction::marshalledName() const -{ - QString returned = QLatin1String("__qt_") + name(); - for (const AbstractMetaArgument *arg : m_arguments) { - returned += QLatin1Char('_'); - if (arg->type()->isNativePointer()) { - returned += QLatin1String("nativepointer"); - } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) { - returned += QLatin1String("int"); - } else { - QString a = arg->type()->name(); - a.replace(QLatin1String("[]"), QLatin1String("_3")); - a.replace(QLatin1Char('.'), QLatin1Char('_')); - returned += a; - } - } - return returned; -} - -bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const -{ - return compareTo(&other) & NameLessThan; -} - - -/*! - Returns a mask of CompareResult describing how this function is - compares to another function -*/ -AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const -{ - CompareResult result = 0; - - // Enclosing class... - if (ownerClass() == other->ownerClass()) - result |= EqualImplementor; - - // Attributes - if (attributes() == other->attributes()) - result |= EqualAttributes; - - // Compare types - AbstractMetaType *t = type(); - AbstractMetaType *ot = other->type(); - if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) - result |= EqualReturnType; - - // Compare names - int cmp = originalName().compare(other->originalName()); - - if (cmp < 0) - result |= NameLessThan; - else if (!cmp) - result |= EqualName; - - // compare name after modification... - cmp = modifiedName().compare(other->modifiedName()); - if (!cmp) - result |= EqualModifiedName; - - // Compare arguments... - AbstractMetaArgumentList minArguments; - AbstractMetaArgumentList maxArguments; - if (arguments().size() < other->arguments().size()) { - minArguments = arguments(); - maxArguments = other->arguments(); - } else { - minArguments = other->arguments(); - maxArguments = arguments(); - } - - int minCount = minArguments.size(); - int maxCount = maxArguments.size(); - bool same = true; - for (int i = 0; i < maxCount; ++i) { - if (i < minCount) { - const AbstractMetaArgument *min_arg = minArguments.at(i); - const AbstractMetaArgument *max_arg = maxArguments.at(i); - if (min_arg->type()->name() != max_arg->type()->name() - && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) { - same = false; - break; - } - } else { - if (maxArguments.at(i)->defaultValueExpression().isEmpty()) { - same = false; - break; - } - } - } - - if (same) - result |= minCount == maxCount ? EqualArguments : EqualDefaultValueOverload; - - return result; -} - -AbstractMetaFunction *AbstractMetaFunction::copy() const -{ - AbstractMetaFunction *cpy = new AbstractMetaFunction; - cpy->setName(name()); - cpy->setOriginalName(originalName()); - cpy->setOwnerClass(ownerClass()); - cpy->setImplementingClass(implementingClass()); - cpy->setFunctionType(functionType()); - cpy->setAttributes(attributes()); - cpy->setDeclaringClass(declaringClass()); - if (type()) - cpy->setType(type()->copy()); - cpy->setConstant(isConstant()); - cpy->setOriginalAttributes(originalAttributes()); - - for (AbstractMetaArgument *arg : m_arguments) - cpy->addArgument(arg->copy()); - - Q_ASSERT((!type() && !cpy->type()) - || (type()->instantiations() == cpy->type()->instantiations())); - - return cpy; -} - -bool AbstractMetaFunction::usesRValueReferences() const -{ - if (m_functionType == MoveConstructorFunction || m_functionType == MoveAssignmentOperatorFunction) - return true; - if (m_type && m_type->referenceType() == RValueReference) - return true; - for (const AbstractMetaArgument *a : m_arguments) { - if (a->type()->referenceType() == RValueReference) - return true; - } - return false; -} - -QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const -{ - AbstractMetaArgumentList arguments = this->arguments(); - if (arguments.size() == resolvedArguments.size()) { - QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')'); - return QStringList(TypeDatabase::normalizedSignature(signature)); - } else { - QStringList returned; - - AbstractMetaArgument *argument = arguments.at(resolvedArguments.size()); - QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::")); - for (int i = 0; i < minimalTypeSignature.size(); ++i) { - returned += introspectionCompatibleSignatures(QStringList(resolvedArguments) - << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::"))); - } - - return returned; - } -} - -QString AbstractMetaFunction::signature() const -{ - if (m_cachedSignature.isEmpty()) { - m_cachedSignature = m_originalName; - - m_cachedSignature += QLatin1Char('('); - - for (int i = 0; i < m_arguments.count(); ++i) { - AbstractMetaArgument *a = m_arguments.at(i); - AbstractMetaType *t = a->type(); - if (t) { - if (i > 0) - m_cachedSignature += QLatin1String(", "); - m_cachedSignature += t->cppSignature(); - // We need to have the argument names in the qdoc files - m_cachedSignature += QLatin1Char(' '); - m_cachedSignature += a->name(); - } else { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("No abstract meta type found for argument '%1' while" - "constructing signature for function '%2'.") - .arg(a->name(), name()); - } - } - m_cachedSignature += QLatin1Char(')'); - - if (isConstant()) - m_cachedSignature += QLatin1String(" const"); - } - return m_cachedSignature; -} - -int AbstractMetaFunction::actualMinimumArgumentCount() const -{ - AbstractMetaArgumentList arguments = this->arguments(); - - int count = 0; - for (int i = 0; i < arguments.size(); ++i && ++count) { - if (argumentRemoved(i + 1)) - --count; - else if (!arguments.at(i)->defaultValueExpression().isEmpty()) - break; - } - - return count; -} - -// Returns reference counts for argument at idx, or all arguments if idx == -2 -QVector AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const -{ - QVector returned; - - const FunctionModificationList &mods = this->modifications(cls); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argumentMod : mod.argument_mods) { - if (argumentMod.index != idx && idx != -2) - continue; - returned += argumentMod.referenceCounts; - } - } - - return returned; -} - - -ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const -{ - const FunctionModificationList &mods = this->modifications(cls); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argumentMod : mod.argument_mods) { - if (argumentMod.index != idx) - continue; - return argumentMod.owner; - } - } - return ArgumentOwner(); -} - - -QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key - && !argumentModification.replacedDefaultExpression.isEmpty()) { - return argumentModification.replacedDefaultExpression; - } - } - } - - return QString(); -} - -bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key - && argumentModification.removedDefaultExpression) { - return true; - } - } - } - - return false; -} - -bool AbstractMetaFunction::resetObjectAfterUse(int argumentIdx) const -{ - const AbstractMetaClass *cls = declaringClass(); - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == argumentIdx && argumentModification.resetAfterUse) - return true; - } - } - - return false; -} - -QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argumentIdx) const -{ - Q_ASSERT(nullPointersDisabled(mainClass, argumentIdx)); - - const AbstractMetaClass *cls = mainClass; - if (!cls) - cls = implementingClass(); - - do { - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == argumentIdx - && argumentModification.noNullPointers) { - return argumentModification.nullPointerDefaultValue; - } - } - } - cls = cls->baseClass(); - } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class - - return QString(); - -} - -bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argumentIdx) const -{ - const AbstractMetaClass *cls = mainClass; - if (!cls) - cls = implementingClass(); - - do { - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == argumentIdx - && argumentModification.noNullPointers) { - return true; - } - } - } - - cls = cls->baseClass(); - } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class - - return false; -} - -QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index != key) - continue; - - for (const CodeSnip &snip : argumentModification.conversion_rules) { - if (snip.language == language && !snip.code().isEmpty()) - return snip.code(); - } - } - } - - return QString(); -} - -QString AbstractMetaFunction::argumentReplaced(int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key && !argumentModification.replace_value.isEmpty()) - return argumentModification.replace_value; - } - } - - return QString(); -} - -// FIXME If we remove a arg. in the method at the base class, it will not reflect here. -bool AbstractMetaFunction::argumentRemoved(int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key) { - if (argumentModification.removed) - return true; - } - } - } - - return false; -} - -bool AbstractMetaFunction::isVirtualSlot() const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - if (modification.isVirtualSlot()) - return true; - } - - return false; -} - -bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const -{ - typedef QHash::const_iterator OwnershipMapIt; - - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index != key) - continue; - - for (OwnershipMapIt it = argumentModification.ownerships.cbegin(), end = argumentModification.ownerships.cend(); it != end; ++it) { - if (it.value() == TypeSystem::CppOwnership) - return true; - } - - } - } - - return false; -} - -bool AbstractMetaFunction::isDeprecated() const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - if (modification.isDeprecated()) - return true; - } - return false; -} - -bool AbstractMetaFunction::isThread() const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - if (modification.isThread()) - return true; - } - return false; -} - -bool AbstractMetaFunction::allowThread() const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - if (modification.allowThread()) - return true; - } - return false; -} - - -TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key) - return argumentModification.ownerships.value(language, TypeSystem::InvalidOwnership); - } - } - - return TypeSystem::InvalidOwnership; -} - -bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const -{ - return isRemovedFrom(cls, TypeSystem::All); -} - -bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const -{ - const FunctionModificationList &modifications = this->modifications(cls); - for (const FunctionModification &modification : modifications) { - if ((modification.removal & language) == language) - return true; - } - - return false; - -} - -QString AbstractMetaFunction::typeReplaced(int key) const -{ - const FunctionModificationList &modifications = this->modifications(declaringClass()); - for (const FunctionModification &modification : modifications) { - for (const ArgumentModification &argumentModification : modification.argument_mods) { - if (argumentModification.index == key - && !argumentModification.modified_type.isEmpty()) { - return argumentModification.modified_type; - } - } - } - - return QString(); -} - -QString AbstractMetaFunction::minimalSignature() const -{ - if (!m_cachedMinimalSignature.isEmpty()) - return m_cachedMinimalSignature; - - QString minimalSignature = originalName() + QLatin1Char('('); - AbstractMetaArgumentList arguments = this->arguments(); - - for (int i = 0; i < arguments.count(); ++i) { - AbstractMetaType *t = arguments.at(i)->type(); - if (t) { - if (i > 0) - minimalSignature += QLatin1Char(','); - minimalSignature += t->minimalSignature(); - } else { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("No abstract meta type found for argument '%1' while constructing" - " minimal signature for function '%2'.") - .arg(arguments.at(i)->name(), name()); - } - } - minimalSignature += QLatin1Char(')'); - if (isConstant()) - minimalSignature += QLatin1String("const"); - - minimalSignature = TypeDatabase::normalizedSignature(minimalSignature); - m_cachedMinimalSignature = minimalSignature; - - return minimalSignature; -} - -FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const -{ - if (!implementor) - implementor = ownerClass(); - - if (!implementor) - return TypeDatabase::instance()->functionModifications(minimalSignature()); - - FunctionModificationList mods; - while (implementor) { - mods += implementor->typeEntry()->functionModifications(minimalSignature()); - if ((implementor == implementor->baseClass()) || - (implementor == implementingClass() && (mods.size() > 0))) - break; - const AbstractMetaClassList &interfaces = implementor->interfaces(); - for (const AbstractMetaClass *interface : interfaces) - mods += this->modifications(interface); - implementor = implementor->baseClass(); - } - return mods; -} - -bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const -{ - return !modifications(implementor).isEmpty(); -} - -QString AbstractMetaFunction::argumentName(int index, - bool /* create */, - const AbstractMetaClass * /* implementor */) const -{ - return m_arguments[--index]->name(); -} - -bool AbstractMetaFunction::isCallOperator() const -{ - return m_name == QLatin1String("operator()"); -} - -bool AbstractMetaFunction::hasInjectedCode() const -{ - const FunctionModificationList &mods = modifications(ownerClass()); - for (const FunctionModification &mod : mods) { - if (mod.isCodeInjection()) - return true; - } - return false; -} - -CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const -{ - CodeSnipList result; - const FunctionModificationList &mods = modifications(ownerClass()); - for (const FunctionModification &mod : mods) { - if (mod.isCodeInjection()) { - for (const CodeSnip &snip : mod.snips) { - if ((snip.language & language) && (snip.position == position || position == TypeSystem::CodeSnipPositionAny)) - result << snip; - } - } - } - return result; -} - -bool AbstractMetaFunction::hasSignatureModifications() const -{ - const FunctionModificationList &mods = modifications(); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) - return true; - for (const ArgumentModification &argmod : mod.argument_mods) { - // since zero represents the return type and we're - // interested only in checking the function arguments, - // it will be ignored. - if (argmod.index > 0) - return true; - } - } - return false; -} - -bool AbstractMetaFunction::isConversionOperator(QString funcName) -{ - static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$")); - Q_ASSERT(opRegEx.isValid()); - return opRegEx.match(funcName).hasMatch(); -} - -bool AbstractMetaFunction::isOperatorOverload(QString funcName) -{ - if (isConversionOperator(funcName)) - return true; - - static const QRegularExpression opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?" - "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~" - "|\\[\\]|\\s+delete\\[?\\]?" - "|\\(\\)" - "|\\s+new\\[?\\]?)$")); - Q_ASSERT(opRegEx.isValid()); - return opRegEx.match(funcName).hasMatch(); -} - -bool AbstractMetaFunction::isCastOperator() const -{ - return originalName().startsWith(QLatin1String("operator ")); -} - -bool AbstractMetaFunction::isArithmeticOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - - // It's a dereference operator! - if (name == QLatin1String("operator*") && m_arguments.isEmpty()) - return false; - - return name == QLatin1String("operator+") || name == QLatin1String("operator+=") - || name == QLatin1String("operator-") || name == QLatin1String("operator-=") - || name == QLatin1String("operator*") || name == QLatin1String("operator*=") - || name == QLatin1String("operator/") || name == QLatin1String("operator/=") - || name == QLatin1String("operator%") || name == QLatin1String("operator%=") - || name == QLatin1String("operator++") || name == QLatin1String("operator--"); -} - -bool AbstractMetaFunction::isBitwiseOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<<") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator>>") || name == QLatin1String("operator>>=") - || name == QLatin1String("operator&") || name == QLatin1String("operator&=") - || name == QLatin1String("operator|") || name == QLatin1String("operator|=") - || name == QLatin1String("operator^") || name == QLatin1String("operator^=") - || name == QLatin1String("operator~"); -} - -bool AbstractMetaFunction::isComparisonOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator<") || name == QLatin1String("operator<=") - || name == QLatin1String("operator>") || name == QLatin1String("operator>=") - || name == QLatin1String("operator==") || name == QLatin1String("operator!="); -} - -bool AbstractMetaFunction::isLogicalOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator!") - || name == QLatin1String("operator&&") - || name == QLatin1String("operator||"); -} - -bool AbstractMetaFunction::isSubscriptOperator() const -{ - if (!isOperatorOverload()) - return false; - - return originalName() == QLatin1String("operator[]"); -} - -bool AbstractMetaFunction::isAssignmentOperator() const -{ - return m_functionType == AssignmentOperatorFunction - || m_functionType == MoveAssignmentOperatorFunction; -} - -bool AbstractMetaFunction::isOtherOperator() const -{ - if (!isOperatorOverload()) - return false; - - return !isArithmeticOperator() - && !isBitwiseOperator() - && !isComparisonOperator() - && !isLogicalOperator() - && !isConversionOperator() - && !isSubscriptOperator() - && !isAssignmentOperator(); -} - -int AbstractMetaFunction::arityOfOperator() const -{ - if (!isOperatorOverload() || isCallOperator()) - return -1; - - int arity = m_arguments.size(); - - // Operator overloads that are class members - // implicitly includes the instance and have - // one parameter less than their arity, - // so we increment it. - if (ownerClass() && arity < 2) - arity++; - - return arity; -} - -bool AbstractMetaFunction::isInplaceOperator() const -{ - if (!isOperatorOverload()) - return false; - - QString name = originalName(); - return name == QLatin1String("operator+=") || name == QLatin1String("operator&=") - || name == QLatin1String("operator-=") || name == QLatin1String("operator|=") - || name == QLatin1String("operator*=") || name == QLatin1String("operator^=") - || name == QLatin1String("operator/=") || name == QLatin1String("operator<<=") - || name == QLatin1String("operator%=") || name == QLatin1String("operator>>="); -} - -bool AbstractMetaFunction::isVirtual() const -{ - return !isFinal() && !isSignal() && !isStatic() && !isFinalInCpp() && !isConstructor(); -} - -QString AbstractMetaFunction::modifiedName() const -{ - if (m_cachedModifiedName.isEmpty()) { - const FunctionModificationList &mods = modifications(implementingClass()); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) { - m_cachedModifiedName = mod.renamedToName; - break; - } - } - if (m_cachedModifiedName.isEmpty()) - m_cachedModifiedName = name(); - } - return m_cachedModifiedName; -} - -QString AbstractMetaFunction::targetLangSignature(bool minimal) const -{ - QString s; - - // Attributes... - if (!minimal) { - // Return type - if (type()) - s += type()->name() + QLatin1Char(' '); - else - s += QLatin1String("void "); - } - - s += modifiedName(); - s += QLatin1Char('('); - - int j = 0; - for (int i = 0; i < m_arguments.size(); ++i) { - if (argumentRemoved(i + 1)) - continue; - if (j) { - s += QLatin1Char(','); - if (!minimal) - s += QLatin1Char(' '); - } - s += m_arguments.at(i)->type()->name(); - - if (!minimal) { - s += QLatin1Char(' '); - s += m_arguments.at(i)->name(); - } - ++j; - } - - s += QLatin1Char(')'); - - return s; -} - - -bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) -{ - return a->signature() < b->signature(); -} - -#ifndef QT_NO_DEBUG_STREAM -static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af) -{ - d << '"' << af->minimalSignature() << '"'; -} - -void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const -{ - d << m_functionType << ' ' << m_type << ' ' << m_name << '('; - for (int i = 0, count = m_arguments.size(); i < count; ++i) { - if (i) - d << ", "; - d << m_arguments.at(i); - } - d << "), signature=\"" << minimalSignature() << '"'; - if (m_constant) - d << " [const]"; - if (m_invalid) - d << " [invalid]"; - if (m_reverse) - d << " [reverse]"; - if (m_userAdded) - d << " [userAdded]"; - if (m_explicit) - d << " [explicit]"; - if (m_pointerOperator) - d << " [operator->]"; - if (m_isCallOperator) - d << " [operator()]"; - if (m_class) - d << " class: " << m_class->name(); - if (m_implementingClass) - d << " implementing class: " << m_implementingClass->name(); - if (m_declaringClass) - d << " declaring class: " << m_declaringClass->name(); -} - -QDebug operator<<(QDebug d, const AbstractMetaFunction *af) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaFunction("; - if (af) { -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) { - af->formatDebugVerbose(d); - } else { -#endif - d << "signature="; - formatMetaFunctionBrief(d, af); -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - } -#endif - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -/******************************************************************************* - * AbstractMetaClass - */ -AbstractMetaClass::~AbstractMetaClass() -{ - qDeleteAll(m_functions); - qDeleteAll(m_fields); - qDeleteAll(m_enums); - if (hasTemplateBaseClassInstantiations()) - qDeleteAll(templateBaseClassInstantiations()); -} - -/******************************************************************************* - * Returns true if this class is a subclass of the given class - */ -bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const -{ - Q_ASSERT(cls); - - const AbstractMetaClass *clazz = this; - while (clazz) { - if (clazz == cls) - return true; - - clazz = clazz->baseClass(); - } - - return false; -} - -/******************************************************************************* - * Constructs an interface based on the functions and enums in this - * class and returns it... - */ -AbstractMetaClass *AbstractMetaClass::extractInterface() -{ - Q_ASSERT(typeEntry()->designatedInterface()); - - if (!m_extractedInterface) { - AbstractMetaClass *iface = new AbstractMetaClass; - iface->setAttributes(attributes()); - iface->setBaseClass(0); - - iface->setTypeEntry(typeEntry()->designatedInterface()); - - for (AbstractMetaFunction *function : qAsConst(m_functions)) { - if (!function->isConstructor()) - iface->addFunction(function->copy()); - } - -// iface->setEnums(enums()); -// setEnums(AbstractMetaEnumList()); - - for (const AbstractMetaField *field : qAsConst(m_fields)) { - if (field->isPublic()) { - AbstractMetaField *new_field = field->copy(); - new_field->setEnclosingClass(iface); - iface->addField(new_field); - } - } - - m_extractedInterface = iface; - addInterface(iface); - } - - return m_extractedInterface; -} - -/******************************************************************************* - * Returns a list of all the functions with a given name - */ -AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const -{ - AbstractMetaFunctionList returned; - for (AbstractMetaFunction *function : m_functions) { - if (function->name() == name) - returned.append(function); - } - - return returned; -} - -/******************************************************************************* - * Returns a list of all the functions retrieved during parsing which should - * be added to the API. - */ -AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const -{ - FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; - - // Interfaces don't implement functions - if (isInterface()) - default_flags |= ClassImplements; - - // Only public functions in final classes - // default_flags |= isFinal() ? WasPublic : 0; - FunctionQueryOptions public_flags; - if (isFinal()) - public_flags |= WasPublic; - - // Constructors - AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags); - - // Final functions - returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); - - // Virtual functions - returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); - - // Static functions - returned += queryFunctions(StaticFunctions | default_flags | public_flags); - - // Empty, private functions, since they aren't caught by the other ones - returned += queryFunctions(Empty | Invisible); - - return returned; -} - -AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const -{ - const AbstractMetaFunctionList &list = functionsInShellClass(); - - AbstractMetaFunctionList returned; - for (AbstractMetaFunction *f : list) { - if (!f->isFinalInCpp() || f->isVirtualSlot()) - returned += f; - } - - return returned; -} - -AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const -{ - if (!hasCloneOperator() && !hasExternalConversionOperators()) - return AbstractMetaFunctionList(); - - AbstractMetaFunctionList returned; - const AbstractMetaFunctionList list = queryFunctions(Constructors) + externalConversionOperators(); - - // Exclude anything that uses rvalue references, be it a move - // constructor "QPolygon(QPolygon &&)" or something else like - // "QPolygon(QVector &&)". - for (AbstractMetaFunction *f : list) { - if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) - && !f->isExplicit() - && f->functionType() != AbstractMetaFunction::CopyConstructorFunction - && !f->usesRValueReferences() - && !f->isModifiedRemoved() - && (f->originalAttributes() & Public)) { - returned += f; - } - } - return returned; -} - -AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptions query) const -{ - const AbstractMetaFunctionList &list = queryFunctions(OperatorOverloads | Visible); - AbstractMetaFunctionList returned; - for (AbstractMetaFunction *f : list) { - if (((query & ArithmeticOp) && f->isArithmeticOperator()) - || ((query & BitwiseOp) && f->isBitwiseOperator()) - || ((query & ComparisonOp) && f->isComparisonOperator()) - || ((query & LogicalOp) && f->isLogicalOperator()) - || ((query & SubscriptionOp) && f->isSubscriptOperator()) - || ((query & AssignmentOp) && f->isAssignmentOperator()) - || ((query & ConversionOp) && f->isConversionOperator()) - || ((query & OtherOp) && f->isOtherOperator())) - returned += f; - } - - return returned; -} - -bool AbstractMetaClass::hasOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isOperatorOverload() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasArithmeticOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasBitwiseOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasComparisonOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasLogicalOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasSubscriptOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isSubscriptOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasAssignmentOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isAssignmentOperator() && !f->isPrivate()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasConversionOperatorOverload() const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->ownerClass() == f->implementingClass() && f->isConversionOperator() && !f->isPrivate()) - return true; - } - return false; -} - -/******************************************************************************* - * Returns a list of all functions that should be declared and implemented in - * the shell class which is generated as a wrapper on top of the actual C++ class - */ -AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const -{ - // Only functions and only protected and public functions - FunctionQueryOptions default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell; - - // All virtual functions - AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags); - - // All functions explicitly set to be implemented by the shell class - // (mainly superclass functions that are hidden by other declarations) - returned += queryFunctions(ForcedShellFunctions | default_flags); - - // All functions explicitly set to be virtual slots - returned += queryFunctions(VirtualSlots | default_flags); - - return returned; -} - -/******************************************************************************* - * Returns a list of all functions that require a public override function to - * be generated in the shell class. This includes all functions that were originally - * protected in the superclass. - */ -AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const -{ - return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang) - + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang); -} - -AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const -{ - return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) + - queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell); -} - -void AbstractMetaClass::sortFunctions() -{ - qSort(m_functions.begin(), m_functions.end(), function_sorter); -} - -void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) -{ - m_functions = functions; - - // Functions must be sorted by name before next loop - sortFunctions(); - - QString currentName; - bool hasVirtuals = false; - AbstractMetaFunctionList finalFunctions; - for (AbstractMetaFunction *f : qAsConst(m_functions)) { - f->setOwnerClass(this); - - m_hasVirtualSlots = m_hasVirtualSlots || f->isVirtualSlot(); - m_hasVirtuals = m_hasVirtuals || f->isVirtualSlot() || hasVirtualDestructor(); - m_isPolymorphic = m_isPolymorphic || m_hasVirtuals; - m_hasNonpublic = m_hasNonpublic || !f->isPublic(); - - // If we have non-virtual overloads of a virtual function, we have to implement - // all the overloads in the shell class to override the hiding rule - if (currentName == f->name()) { - hasVirtuals = hasVirtuals || !f->isFinal(); - if (f->isFinal()) - finalFunctions += f; - } else { - if (hasVirtuals && finalFunctions.size() > 0) { - for (AbstractMetaFunction *final_function : qAsConst(finalFunctions)) { - *final_function += AbstractMetaAttributes::ForceShellImplementation; - - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("hiding of function '%1' in class '%2'") - .arg(final_function->name(), name()); - } - } - - hasVirtuals = !f->isFinal(); - finalFunctions.clear(); - if (f->isFinal()) - finalFunctions += f; - currentName = f->name(); - } - } -} - -bool AbstractMetaClass::hasFieldAccessors() const -{ - for (const AbstractMetaField *field : m_fields) { - if (field->getter() || field->setter()) - return true; - } - - return false; -} - -bool AbstractMetaClass::hasDefaultToStringFunction() const -{ - const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString")); - for (const AbstractMetaFunction *f : funcs) { - if (!f->actualMinimumArgumentCount()) - return true; - } - return false; -} - -void AbstractMetaClass::addFunction(AbstractMetaFunction *function) -{ - Q_ASSERT(!function->signature().startsWith(QLatin1Char('('))); - function->setOwnerClass(this); - - if (!function->isDestructor()) - m_functions << function; - else - Q_ASSERT(false); //memory leak - - m_hasVirtualSlots |= function->isVirtualSlot(); - m_hasVirtuals |= !function->isFinal() || function->isVirtualSlot() || hasVirtualDestructor(); - m_isPolymorphic |= m_hasVirtuals; - m_hasNonpublic |= !function->isPublic(); -} - -bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const -{ - if (!other->isSignal()) - return false; - - for (const AbstractMetaFunction *f : m_functions) { - if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName) - return other->modifiedName() == f->modifiedName(); - } - - return false; -} - - -QString AbstractMetaClass::name() const -{ - return QString(m_typeEntry->targetLangName()).split(QLatin1String("::")).last(); -} - -void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) -{ - m_baseClass = baseClass; - if (baseClass) - m_isPolymorphic |= baseClass->isPolymorphic(); -} - -QString AbstractMetaClass::package() const -{ - return m_typeEntry->targetLangPackage(); -} - -bool AbstractMetaClass::isInterface() const -{ - return m_typeEntry->isInterface(); -} - -bool AbstractMetaClass::isNamespace() const -{ - return m_typeEntry->isNamespace(); -} - -bool AbstractMetaClass::isQObject() const -{ - return m_typeEntry->isQObject(); -} - -QString AbstractMetaClass::qualifiedCppName() const -{ - return m_typeEntry->qualifiedCppName(); -} - -bool AbstractMetaClass::hasFunction(const QString &str) const -{ - return findFunction(str); -} - -const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& functionName) const -{ - for (const AbstractMetaFunction *f : m_functions) { - if (f->name() == functionName) - return f; - } - return 0; -} - -bool AbstractMetaClass::hasProtectedFunctions() const -{ - for (AbstractMetaFunction *func : m_functions) { - if (func->isProtected()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasProtectedFields() const -{ - for (const AbstractMetaField *field : m_fields) { - if (field->isProtected()) - return true; - } - return false; -} - -bool AbstractMetaClass::hasProtectedMembers() const -{ - return hasProtectedFields() || hasProtectedFunctions(); -} - -bool AbstractMetaClass::generateShellClass() const -{ - return m_forceShellClass || - (!isFinal() - && (hasVirtualFunctions() - || hasProtectedFunctions() - || hasFieldAccessors())); -} - -QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const -{ - for (int i = 0; i < m_propertySpecs.size(); ++i) - if (name == m_propertySpecs.at(i)->read()) - return m_propertySpecs.at(i); - return 0; -} - -QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const -{ - for (int i = 0; i < m_propertySpecs.size(); ++i) - if (name == m_propertySpecs.at(i)->write()) - return m_propertySpecs.at(i); - return 0; -} - -QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const -{ - for (int i = 0; i < m_propertySpecs.size(); ++i) { - if (name == m_propertySpecs.at(i)->reset()) - return m_propertySpecs.at(i); - } - return 0; -} - -typedef QHash AbstractMetaClassBaseTemplateInstantiationsMap; -Q_GLOBAL_STATIC(AbstractMetaClassBaseTemplateInstantiationsMap, metaClassBaseTemplateInstantiations); - -bool AbstractMetaClass::hasTemplateBaseClassInstantiations() const -{ - if (!templateBaseClass()) - return false; - return metaClassBaseTemplateInstantiations()->contains(this); -} - -AbstractMetaTypeList AbstractMetaClass::templateBaseClassInstantiations() const -{ - if (!templateBaseClass()) - return AbstractMetaTypeList(); - return metaClassBaseTemplateInstantiations()->value(this); -} - -void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations) -{ - if (!templateBaseClass()) - return; - metaClassBaseTemplateInstantiations()->insert(this, instantiations); -} - -static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) -{ - for (const AbstractMetaFunction *f : l) { - if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar) - return true; - } - return false; -} - -AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0) -{ -} - -AbstractMetaField::~AbstractMetaField() -{ - delete m_setter; - delete m_getter; -} - -AbstractMetaField *AbstractMetaField::copy() const -{ - AbstractMetaField *returned = new AbstractMetaField; - returned->setEnclosingClass(0); - returned->setAttributes(attributes()); - returned->setName(name()); - returned->setType(type()->copy()); - returned->setOriginalAttributes(originalAttributes()); - - return returned; -} - -/******************************************************************************* - * Indicates that this field has a modification that removes it - */ -bool AbstractMetaField::isModifiedRemoved(int types) const -{ - const FieldModificationList &mods = modifications(); - for (const FieldModification &mod : mods) { - if (!mod.isRemoveModifier()) - continue; - - if ((mod.removal & types) == types) - return true; - } - - return false; -} - -static QString upCaseFirst(const QString &str) -{ - Q_ASSERT(!str.isEmpty()); - QString s = str; - s[0] = s.at(0).toUpper(); - return s; -} - -static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, - AbstractMetaAttributes::Attributes type) -{ - AbstractMetaFunction *f = new AbstractMetaFunction; - - f->setName(name); - f->setOriginalName(name); - f->setOwnerClass(g->enclosingClass()); - f->setImplementingClass(g->enclosingClass()); - f->setDeclaringClass(g->enclosingClass()); - - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native - | AbstractMetaAttributes::Final - | type; - if (g->isStatic()) - attr |= AbstractMetaAttributes::Static; - if (g->isPublic()) - attr |= AbstractMetaAttributes::Public; - else if (g->isProtected()) - attr |= AbstractMetaAttributes::Protected; - else - attr |= AbstractMetaAttributes::Private; - f->setAttributes(attr); - f->setOriginalAttributes(attr); - - const FieldModificationList &mods = g->modifications(); - for (const FieldModification &mod : mods) { - if (mod.isRenameModifier()) - f->setName(mod.renamedTo()); - if (mod.isAccessModifier()) { - if (mod.isPrivate()) - f->setVisibility(AbstractMetaAttributes::Private); - else if (mod.isProtected()) - f->setVisibility(AbstractMetaAttributes::Protected); - else if (mod.isPublic()) - f->setVisibility(AbstractMetaAttributes::Public); - else if (mod.isFriendly()) - f->setVisibility(AbstractMetaAttributes::Friendly); - } - } - return f; -} - -FieldModificationList AbstractMetaField::modifications() const -{ - const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications(); - FieldModificationList returned; - - for (const FieldModification &mod : mods) { - if (mod.name == name()) - returned += mod; - } - - return returned; -} - -const AbstractMetaFunction *AbstractMetaField::setter() const -{ - if (!m_setter) { - m_setter = createXetter(this, - QLatin1String("set") + upCaseFirst(name()), - AbstractMetaAttributes::SetterFunction); - AbstractMetaArgumentList arguments; - AbstractMetaArgument *argument = new AbstractMetaArgument; - argument->setType(type()->copy()); - argument->setName(name()); - arguments.append(argument); - m_setter->setArguments(arguments); - } - return m_setter; -} - -const AbstractMetaFunction *AbstractMetaField::getter() const -{ - if (!m_getter) { - m_getter = createXetter(this, - name(), - AbstractMetaAttributes::GetterFunction); - m_getter->setType(type()); - } - - return m_getter; -} - -#ifndef QT_NO_DEBUG_STREAM -static void formatMetaAttributes(QDebug &d, AbstractMetaAttributes::Attributes value) -{ - static const int meIndex = AbstractMetaAttributes::staticMetaObject.indexOfEnumerator("Attribute"); - Q_ASSERT(meIndex >= 0); - const QMetaEnum me = AbstractMetaAttributes::staticMetaObject.enumerator(meIndex); - d << me.valueToKeys(value); -} - -static void formatMetaField(QDebug &d, const AbstractMetaField *af) -{ - formatMetaAttributes(d, af->attributes()); - d << ' ' << af->type()->name() << " \"" << af->name() << '"'; -} - -QDebug operator<<(QDebug d, const AbstractMetaField *af) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaField("; - if (af) - formatMetaField(d, af); - else - d << '0'; - d << ')'; - return d; -} - -static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue *v) -{ - const QString &name = v->stringValue(); - if (!name.isEmpty()) - d << name << '='; - d << v->value(); -} - -QDebug operator<<(QDebug d, const AbstractMetaEnumValue *v) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaEnumValue("; - if (v) - formatMetaEnumValue(d, v); - else - d << '0'; - d << ')'; - return d; -} - -QDebug operator<<(QDebug d, const AbstractMetaEnum *ae) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaEnum("; - if (ae) { - d << ae->fullName() << '['; - const AbstractMetaEnumValueList &values = ae->values(); - for (int i = 0, count = values.size(); i < count; ++i) { - if (i) - d << ' '; - formatMetaEnumValue(d, values.at(i)); - } - d << ']'; - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -bool AbstractMetaClass::hasConstructors() const -{ - return queryFunctions(Constructors).size(); -} - -bool AbstractMetaClass::hasCopyConstructor() const -{ - const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); - for (const AbstractMetaFunction* ctor : ctors) { - if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction) - return true; - } - return false; -} - -bool AbstractMetaClass::hasPrivateCopyConstructor() const -{ - const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); - for (const AbstractMetaFunction *ctor : ctors) { - if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate()) - return true; - } - return false; -} - -void AbstractMetaClass::addDefaultConstructor() -{ - AbstractMetaFunction *f = new AbstractMetaFunction; - f->setOriginalName(name()); - f->setName(name()); - f->setOwnerClass(this); - f->setFunctionType(AbstractMetaFunction::ConstructorFunction); - f->setArguments(AbstractMetaArgumentList()); - f->setDeclaringClass(this); - - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; - attr |= AbstractMetaAttributes::Public; - attr |= AbstractMetaAttributes::Final; - f->setAttributes(attr); - f->setImplementingClass(this); - f->setOriginalAttributes(f->attributes()); - - addFunction(f); - this->setHasNonPrivateConstructor(true); -} - -void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) -{ - AbstractMetaFunction* f = new AbstractMetaFunction; - f->setOriginalName(name()); - f->setName(name()); - f->setOwnerClass(this); - f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); - f->setDeclaringClass(this); - - AbstractMetaType* argType = new AbstractMetaType; - argType->setTypeEntry(typeEntry()); - argType->setReferenceType(LValueReference); - argType->setConstant(true); - argType->setTypeUsagePattern(AbstractMetaType::ValuePattern); - - AbstractMetaArgument* arg = new AbstractMetaArgument; - arg->setType(argType); - arg->setName(name()); - f->addArgument(arg); - - AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; - attr |= AbstractMetaAttributes::Final; - if (isPrivate) - attr |= AbstractMetaAttributes::Private; - else - attr |= AbstractMetaAttributes::Public; - f->setAttributes(attr); - f->setImplementingClass(this); - f->setOriginalAttributes(f->attributes()); - - addFunction(f); -} - -bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const -{ - return functions_contains(m_functions, f); -} - -/* Goes through the list of functions and returns a list of all - functions matching all of the criteria in \a query. - */ - -AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const -{ - AbstractMetaFunctionList functions; - - for (AbstractMetaFunction *f : m_functions) { - - if ((query & VirtualSlots) && !f->isVirtualSlot()) - continue; - - if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) - continue; - - if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) - continue; - - if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) - continue; - - if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) - continue; - - if ((query & Visible) && f->isPrivate()) - continue; - - if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) - continue; - - if ((query & Invisible) && !f->isPrivate()) - continue; - - if ((query & Empty) && !f->isEmptyFunction()) - continue; - - if ((query & WasPublic) && !f->wasPublic()) - continue; - - if ((query & WasVisible) && f->wasPrivate()) - continue; - - if ((query & WasProtected) && !f->wasProtected()) - continue; - - if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) - continue; - - if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) - continue; - - if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) - continue; - - if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) - continue; - - if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) - continue; - - if ((query & Signals) && (!f->isSignal())) - continue; - - if ((query & ForcedShellFunctions) && - (!f->isForcedShellImplementation() || !f->isFinal())) { - continue; - } - - if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass())) - continue; - - if (!(query & Constructors) && f->isConstructor()) - continue; - - // Destructors are never included in the functions of a class currently - /* - if ((query & Destructors) && (!f->isDestructor() - || f->ownerClass() != f->implementingClass()) - || f->isDestructor() && (query & Destructors) == 0) { - continue; - }*/ - - if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) - continue; - - if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) - continue; - - if ((query & NonStaticFunctions) && (f->isStatic())) - continue; - - if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) - continue; - - if ((query & NormalFunctions) && (f->isSignal())) - continue; - - if ((query & AbstractFunctions) && !f->isAbstract()) - continue; - - if ((query & OperatorOverloads) && !f->isOperatorOverload()) - continue; - - functions << f; - } - - return functions; -} - -bool AbstractMetaClass::hasSignals() const -{ - return cppSignalFunctions().size() > 0; -} - - -/** - * Adds the specified interface to this class by adding all the - * functions in the interface to this class. - */ -void AbstractMetaClass::addInterface(AbstractMetaClass *interface) -{ - Q_ASSERT(!m_interfaces.contains(interface)); - m_interfaces << interface; - - m_isPolymorphic |= interface->isPolymorphic(); - - if (m_extractedInterface && m_extractedInterface != interface) - m_extractedInterface->addInterface(interface); - - -#if 0 - const AbstractMetaFunctionList &funcs = interface->functions(); - for (AbstractMetaFunction *function : funcs) - if (!hasFunction(function) && !function->isConstructor()) { - AbstractMetaFunction *cpy = function->copy(); - cpy->setImplementingClass(this); - - // Setup that this function is an interface class. - cpy->setInterfaceClass(interface); - *cpy += AbstractMetaAttributes::InterfaceFunction; - - // Copy the modifications in interface into the implementing classes. - const FunctionModificationList &mods = function->modifications(interface); - for (const FunctionModification &mod : mods) - m_typeEntry->addFunctionModification(mod); - - // It should be mostly safe to assume that when we implement an interface - // we don't "pass on" pure virtual functions to our sublcasses... -// *cpy -= AbstractMetaAttributes::Abstract; - - addFunction(cpy); - } -#endif - -} - - -void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) -{ - m_interfaces = interfaces; - for (const AbstractMetaClass *interface : interfaces) { - if (interface) - m_isPolymorphic |= interface->isPolymorphic(); - } -} - - -AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) -{ - for (AbstractMetaEnum *e : qAsConst(m_enums)) { - if (e->name() == enumName) - return e; - } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnum(enumName); - - return 0; -} - - - - -/*! Recursivly searches for the enum value named \a enumValueName in - this class and its superclasses and interfaces. Values belonging to - \a meta_enum are excluded from the search. -*/ -AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum) -{ - for (AbstractMetaEnum *e : qAsConst(m_enums)) { - if (e != meta_enum) - continue; - const AbstractMetaEnumValueList &values = e->values(); - for (AbstractMetaEnumValue *v : values) { - if (v->name() == enumValueName) - return v; - } - } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumValue(enumValueName, meta_enum); - - if (baseClass()) - return baseClass()->findEnumValue(enumValueName, meta_enum); - - return 0; -} - - -/*! - * Searches through all of this class' enums for a value matching the - * name \a enumValueName. The name is excluding the class/namespace - * prefix. The function recursivly searches interfaces and baseclasses - * of this class. - */ -AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName) -{ - for (AbstractMetaEnum *e : qAsConst(m_enums)) { - const AbstractMetaEnumValueList &values = e->values(); - for (AbstractMetaEnumValue *v : values) { - if (v->name() == enumValueName) - return e; - } - } - - if (typeEntry()->designatedInterface()) - return extractInterface()->findEnumForValue(enumValueName); - - if (baseClass()) - return baseClass()->findEnumForValue(enumValueName); - - return 0; -} - - -static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) -{ - if (!type) - return; - - Q_ASSERT(metaClass); - const TypeEntry *entry = (type ? type->typeEntry() : 0); - if (entry && entry->isComplex()) { - const ComplexTypeEntry *centry = static_cast(entry); - ComplexTypeEntry *class_entry = metaClass->typeEntry(); - if (class_entry && centry->include().isValid()) - class_entry->addExtraInclude(centry->include()); - } - - if (type->hasInstantiations()) { - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) - addExtraIncludeForType(metaClass, instantiation); - } -} - -static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, const AbstractMetaFunction *meta_function) -{ - Q_ASSERT(metaClass); - Q_ASSERT(meta_function); - addExtraIncludeForType(metaClass, meta_function->type()); - - const AbstractMetaArgumentList &arguments = meta_function->arguments(); - for (AbstractMetaArgument *argument : arguments) - addExtraIncludeForType(metaClass, argument->type()); -} - -void AbstractMetaClass::fixFunctions() -{ - if (m_functionsFixed) - return; - else - m_functionsFixed = true; - - AbstractMetaClass *superClass = baseClass(); - AbstractMetaFunctionList funcs = functions(); - - if (superClass) - superClass->fixFunctions(); - int iface_idx = 0; - while (superClass || iface_idx < interfaces().size()) { - // 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. - AbstractMetaFunctionList superFuncs; - if (superClass) { - // 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 -= AbstractMetaAttributes::FinalInTargetLang; - } - superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); - AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - } else { - superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); - AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); - superFuncs += virtuals; - } - - QSet funcsToAdd; - for (int sfi = 0; sfi < superFuncs.size(); ++sfi) { - AbstractMetaFunction *sf = superFuncs.at(sfi); - - if (sf->isRemovedFromAllLanguages(sf->implementingClass())) - continue; - - // skip functions added in base classes - if (sf->isUserAdded() && sf->declaringClass() != this) - continue; - - // 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 = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction()); - for (int fi = 0; fi < funcs.size(); ++fi) { - AbstractMetaFunction *f = funcs.at(fi); - if (f->isRemovedFromAllLanguages(f->implementingClass())) - continue; - - - const AbstractMetaFunction::CompareResult cmp = f->compareTo(sf); - - if (cmp & AbstractMetaFunction::EqualModifiedName) { - add = false; - if (cmp & AbstractMetaFunction::EqualArguments) { - // Same function, propegate virtual... - if (!(cmp & AbstractMetaFunction::EqualAttributes)) { - if (!f->isEmptyFunction()) { - if (!sf->isFinalInCpp() && f->isFinalInCpp()) { - *f -= AbstractMetaAttributes::FinalInCpp; - } - if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { - *f -= AbstractMetaAttributes::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 - } - } - - if (f->visibility() != sf->visibility()) { - QString warn = QStringLiteral("visibility of function '%1' modified in class '%2'") - .arg(f->name(), name()); - qCWarning(lcShiboken).noquote().nospace() << warn; -#if 0 - // If new visibility is private, we can't - // do anything. If it isn't, then we - // prefer the parent class's visibility - // setting for the function. - if (!f->isPrivate() && !sf->isPrivate()) - f->setVisibility(sf->visibility()); -#endif - // 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()) { - f->setFunctionType(AbstractMetaFunction::EmptyFunction); - *f += AbstractMetaAttributes::FinalInTargetLang; - *f += AbstractMetaAttributes::FinalInCpp; - } - } - - // 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; - } else if (mod.isPrivate()) { - isBaseImplPrivate = true; - break; - } - } - - if (!hasNonFinalModifier && !isBaseImplPrivate) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Shadowing: %1::%2 and %3::%4") - .arg(sf->implementingClass()->name(), sf->signature(), - f->implementingClass()->name(), f->signature()); - } - } - } - - } - - if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { - AbstractMetaArgumentList arguments; - if (f->arguments().size() < sf->arguments().size()) - arguments = sf->arguments(); - else - arguments = f->arguments(); - //TODO: fix this - //for (int i=0; isetDefaultValueExpression("<#>" + QString()); - } - - - // Otherwise we have function shadowing and we can - // skip the thing... - } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) { - // In the case of function shadowing where the function name has been altered to - // avoid conflict, we don't copy in the original. - add = false; - } - } - - if (add) - funcsToAdd << sf; - } - - for (AbstractMetaFunction *f : qAsConst(funcsToAdd)) - funcs << f->copy(); - - if (superClass) - superClass = superClass->baseClass(); - else - iface_idx++; - } - - bool hasPrivateConstructors = false; - bool hasPublicConstructors = false; - for (AbstractMetaFunction *func : qAsConst(funcs)) { - const FunctionModificationList &mods = func->modifications(this); - for (const FunctionModification &mod : mods) { - if (mod.isRenameModifier()) { - func->setName(mod.renamedTo()); - } - } - - // Make sure class is abstract if one of the functions is - if (func->isAbstract()) { - (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::Final; - } - - if (func->isConstructor()) { - if (func->isPrivate()) - hasPrivateConstructors = true; - else - hasPublicConstructors = true; - } - - - - // Make sure that we include files for all classes that are in use - - if (!func->isRemovedFrom(this, TypeSystem::ShellCode)) - addExtraIncludesForFunction(this, func); - } - - if (hasPrivateConstructors && !hasPublicConstructors) { - (*this) += AbstractMetaAttributes::Abstract; - (*this) -= AbstractMetaAttributes::Final; - } - - for (AbstractMetaFunction *f1 : qAsConst(funcs)) { - for (AbstractMetaFunction *f2 : qAsConst(funcs)) { - if (f1 != f2) { - const AbstractMetaFunction::CompareResult cmp = f1->compareTo(f2); - if ((cmp & AbstractMetaFunction::EqualName) - && !f1->isFinalInCpp() - && f2->isFinalInCpp()) { - *f2 += AbstractMetaAttributes::FinalOverload; - } - } - } - } - - setFunctions(funcs); -} - - -QString AbstractMetaType::minimalSignature() const -{ - QString minimalSignature; - if (isConstant()) - minimalSignature += QLatin1String("const "); - minimalSignature += typeEntry()->qualifiedCppName(); - if (hasInstantiations()) { - AbstractMetaTypeList instantiations = this->instantiations(); - minimalSignature += QLatin1String("< "); - for (int i = 0; i < instantiations.size(); ++i) { - if (i > 0) - minimalSignature += QLatin1Char(','); - minimalSignature += instantiations[i]->minimalSignature(); - } - minimalSignature += QLatin1String(" >"); - } - - for (int j = 0; j < indirections(); ++j) - minimalSignature += QLatin1Char('*'); - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - minimalSignature += QLatin1Char('&'); - break; - case RValueReference: - minimalSignature += QLatin1String("&&"); - break; - } - - return minimalSignature; -} - -bool AbstractMetaType::hasNativeId() const -{ - return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased(); -} - -bool AbstractMetaType::isTargetLangEnum() const -{ - return isEnum() && !static_cast(typeEntry())->forceInteger(); -} - -bool AbstractMetaType::isTargetLangFlags() const -{ - return isFlags() && !static_cast(typeEntry())->forceInteger(); -} - - -/******************************************************************************* - * Other stuff... - */ - - -AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &classes, - const EnumTypeEntry *entry) -{ - Q_ASSERT(entry->isEnum()); - - QString qualifiedName = entry->qualifiedCppName(); - int pos = qualifiedName.lastIndexOf(QLatin1String("::")); - - QString enumName; - QString className; - - if (pos > 0) { - enumName = qualifiedName.mid(pos + 2); - className = qualifiedName.mid(0, pos); - } else { - enumName = qualifiedName; - className = TypeDatabase::globalNamespaceClassName(entry); - } - - AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, className); - if (!metaClass) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("AbstractMeta::findEnum(), unknown class '%1' in '%2'") - .arg(className, entry->qualifiedCppName()); - return 0; - } - - return metaClass->findEnum(enumName); -} - -AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, - const QString &name) -{ - QStringList lst = name.split(QLatin1String("::")); - - if (lst.size() > 1) { - QString prefixName = lst.at(0); - QString enumName = lst.at(1); - - AbstractMetaClass* cl = findClass(classes, prefixName); - if (cl) - return cl->findEnumValue(enumName, 0); - } - - for (AbstractMetaClass *metaClass : classes) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum *metaEnum : enums) { - AbstractMetaEnumValue* enumValue = metaClass->findEnumValue(name, metaEnum); - if (enumValue) - return enumValue; - } - } - - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("no matching enum '%1'").arg(name); - return 0; -} - -/*! - * Searches the list after a class that mathces \a name; either as - * C++, Target language base name or complete Target language package.class name. - */ - -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const QString &name) -{ - if (name.isEmpty()) - return 0; - - for (AbstractMetaClass *c : classes) { - if (c->qualifiedCppName() == name) - return c; - } - - for (AbstractMetaClass *c : classes) { - if (c->fullName() == name) - return c; - } - - for (AbstractMetaClass *c : classes) { - if (c->name() == name) - return c; - } - - return 0; -} - -AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, - const TypeEntry* typeEntry) -{ - for (AbstractMetaClass* c : classes) { - if (c->typeEntry() == typeEntry) - return c; - } - return 0; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaClass *ac) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "AbstractMetaClass("; - if (ac) { - d << '"' << ac->fullName() << '"'; - if (ac->m_baseClass) - d << ", inherits \"" << ac->m_baseClass->name() << '"'; - const AbstractMetaEnumList &enums = ac->enums(); - if (!enums.isEmpty()) - d << ", enums[" << enums.size() << "]=" << enums; - const AbstractMetaFunctionList &functions = ac->functions(); - if (!functions.isEmpty()) { - const int count = functions.size(); - d << ", functions=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - if (d.verbosity() > 2) - d << functions.at(i); - else -#endif - formatMetaFunctionBrief(d, functions.at(i)); - } - d << ')'; - } - const AbstractMetaFieldList &fields = ac->fields(); - if (!fields.isEmpty()) { - const int count = fields.size(); - d << ", fields=[" << count << "]("; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - formatMetaField(d, fields.at(i)); - } - d << ')'; - } - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -QString AbstractMetaEnum::name() const -{ - return m_typeEntry->targetLangName(); -} - -QString AbstractMetaEnum::qualifier() const -{ - return m_typeEntry->targetLangQualifier(); -} - -QString AbstractMetaEnum::package() const -{ - return m_typeEntry->targetLangPackage(); -} - -bool AbstractMetaEnum::isAnonymous() const -{ - return m_typeEntry->isAnonymous(); -} diff --git a/ApiExtractor/abstractmetalang.h b/ApiExtractor/abstractmetalang.h deleted file mode 100644 index 4d6d5fb1f..000000000 --- a/ApiExtractor/abstractmetalang.h +++ /dev/null @@ -1,1976 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ABSTRACTMETALANG_H -#define ABSTRACTMETALANG_H - -#include "abstractmetalang_typedefs.h" -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" - -#include "parser/codemodel_enums.h" - -#include -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) - -class AbstractMeta; -class AbstractMetaClass; -class AbstractMetaField; -class AbstractMetaFunction; -class AbstractMetaType; -class AbstractMetaVariable; -class AbstractMetaArgument; -class AbstractMetaEnumValue; -class AbstractMetaEnum; -class QPropertySpec; - -class CodeSnip; -class ComplexTypeEntry; -class EnumTypeEntry; -class FlagsTypeEntry; -class FunctionTypeEntry; -class TypeEntry; - -struct ArgumentOwner; -struct FieldModification; -struct FunctionModification; -struct ReferenceCount; - -class Documentation -{ -public: - enum Format { - Native, - Target - }; - - Documentation() - : m_format(Documentation::Native) {} - - Documentation(const QString& value, Format fmt = Documentation::Native) - : m_data(value), m_format(fmt) {} - - QString value() const - { - return m_data; - } - - void setValue(const QString& value, Format fmt = Documentation::Native) - { - m_data = value; m_format = fmt; - } - - Documentation::Format format() const - { - return m_format; - } - -private: - QString m_data; - Format m_format; - -}; - -class AbstractMetaAttributes -{ - Q_GADGET -public: - AbstractMetaAttributes() : m_attributes(0), m_originalAttributes(0) {}; - - enum Attribute { - None = 0x00000000, - - Private = 0x00000001, - Protected = 0x00000002, - Public = 0x00000004, - Friendly = 0x00000008, - Visibility = 0x0000000f, - - Native = 0x00000010, - Abstract = 0x00000020, - Static = 0x00000040, - - FinalInTargetLang = 0x00000080, - FinalInCpp = 0x00000100, - ForceShellImplementation = 0x00000200, - - GetterFunction = 0x00000400, - SetterFunction = 0x00000800, - - FinalOverload = 0x00001000, - InterfaceFunction = 0x00002000, - - PropertyReader = 0x00004000, - PropertyWriter = 0x00008000, - PropertyResetter = 0x00010000, - - Fake = 0x00020000, - - Invokable = 0x00040000, - - Final = FinalInTargetLang | FinalInCpp - }; - Q_DECLARE_FLAGS(Attributes, Attribute) - Q_FLAG(Attribute) - - Attributes attributes() const - { - return m_attributes; - } - - void setAttributes(Attributes attributes) - { - m_attributes = attributes; - } - - Attributes originalAttributes() const - { - return m_originalAttributes; - } - - void setOriginalAttributes(Attributes attributes) - { - m_originalAttributes = attributes; - } - - Attributes visibility() const - { - return m_attributes & Visibility; - } - - void setVisibility(Attributes visi) - { - m_attributes = (m_attributes & ~Visibility) | visi; - } - - void operator+=(Attribute attribute) - { - m_attributes |= attribute; - } - - void operator-=(Attribute attribute) - { - m_attributes &= ~attribute; - } - - bool isNative() const - { - return m_attributes & Native; - } - - bool isFinal() const - { - return (m_attributes & Final) == Final; - } - - bool isFinalInTargetLang() const - { - return m_attributes & FinalInTargetLang; - } - - bool isFinalInCpp() const - { - return m_attributes & FinalInCpp; - } - - bool isAbstract() const - { - return m_attributes & Abstract; - } - - bool isStatic() const - { - return m_attributes & Static; - } - - bool isForcedShellImplementation() const - { - return m_attributes & ForceShellImplementation; - } - - bool isInterfaceFunction() const - { - return m_attributes & InterfaceFunction; - } - - bool isFinalOverload() const - { - return m_attributes & FinalOverload; - } - - bool isInvokable() const - { - return m_attributes & Invokable; - } - - bool isPropertyReader() const - { - return m_attributes & PropertyReader; - } - - bool isPropertyWriter() const - { - return m_attributes & PropertyWriter; - } - - bool isPropertyResetter() const - { - return m_attributes & PropertyResetter; - } - - bool isPrivate() const - { - return m_attributes & Private; - } - - bool isProtected() const - { - return m_attributes & Protected; - } - - bool isPublic() const - { - return m_attributes & Public; - } - - bool isFriendly() const - { - return m_attributes & Friendly; - } - - bool wasPrivate() const - { - return m_originalAttributes & Private; - } - - bool wasProtected() const - { - return m_originalAttributes & Protected; - } - - bool wasPublic() const - { - return m_originalAttributes & Public; - } - - bool wasFriendly() const - { - return m_originalAttributes & Friendly; - } - - void setDocumentation(const Documentation& doc) - { - m_doc = doc; - } - - Documentation documentation() const - { - return m_doc; - } - -private: - Attributes m_attributes; - Attributes m_originalAttributes; - Documentation m_doc; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaAttributes::Attributes) - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa); -#endif - -class AbstractMetaType -{ - Q_GADGET -public: - - enum TypeUsagePattern { - InvalidPattern, - PrimitivePattern, - FlagsPattern, - EnumPattern, - ValuePattern, - StringPattern, - CharPattern, - ObjectPattern, - QObjectPattern, - ValuePointerPattern, - NativePointerPattern, - ContainerPattern, - SmartPointerPattern, - VariantPattern, - VarargsPattern, - JObjectWrapperPattern, - ArrayPattern, - ThreadPattern - }; - Q_ENUM(TypeUsagePattern) - - AbstractMetaType(); - ~AbstractMetaType(); - - QString package() const; - QString name() const; - QString fullName() const; - - void setTypeUsagePattern(TypeUsagePattern pattern) - { - m_pattern = pattern; - } - TypeUsagePattern typeUsagePattern() const - { - return m_pattern; - } - - // true when use pattern is container - bool hasInstantiations() const - { - return !m_instantiations.isEmpty(); - } - - void addInstantiation(AbstractMetaType* inst, bool owner = false) - { - if (owner) - m_children << inst; - m_instantiations << inst; - } - - void setInstantiations(const AbstractMetaTypeList &insts, bool owner = false) - { - m_instantiations = insts; - if (owner) { - m_children.clear(); - m_children = insts; - } - } - - AbstractMetaTypeList instantiations() const - { - return m_instantiations; - } - - void setInstantiationInCpp(bool incpp) - { - m_cppInstantiation = incpp; - } - bool hasInstantiationInCpp() const - { - return hasInstantiations() && m_cppInstantiation; - } - - QString minimalSignature() const; - - // true when the type is a QtJambiObject subclass - bool hasNativeId() const; - - // returns true if the typs is used as a non complex primitive, no & or *'s - bool isPrimitive() const - { - return m_pattern == PrimitivePattern; - } - - // returns true if the type is used as an enum - bool isEnum() const - { - return m_pattern == EnumPattern; - } - - // returns true if the type is used as a QObject * - bool isQObject() const - { - return m_pattern == QObjectPattern; - } - - // returns true if the type is used as an object, e.g. Xxx * - bool isObject() const - { - return m_pattern == ObjectPattern; - } - - // returns true if the type is used as an array, e.g. Xxx[42] - bool isArray() const - { - return m_pattern == ArrayPattern; - } - - // returns true if the type is used as a value type (X or const X &) - bool isValue() const - { - return m_pattern == ValuePattern; - } - - bool isValuePointer() const - { - return m_pattern == ValuePointerPattern; - } - - // returns true for more complex types... - bool isNativePointer() const - { - return m_pattern == NativePointerPattern; - } - - // returns true if the type was originally a QString or const QString & or equivalent for QLatin1String - bool isTargetLangString() const - { - return m_pattern == StringPattern; - } - - // returns true if the type was originally a QChar or const QChar & - bool isTargetLangChar() const - { - return m_pattern == CharPattern; - } - - // return true if the type was originally a QVariant or const QVariant & - bool isVariant() const - { - return m_pattern == VariantPattern; - } - - // return true if the type was originally a varargs - bool isVarargs() const - { - return m_pattern == VarargsPattern; - } - - // return true if the type was originally a JObjectWrapper or const JObjectWrapper & - bool isJObjectWrapper() const - { - return m_pattern == JObjectWrapperPattern; - } - - // returns true if the type was used as a container - bool isContainer() const - { - return m_pattern == ContainerPattern; - } - - // returns true if the type was used as a smart pointer - bool isSmartPointer() const { return m_pattern == SmartPointerPattern; } - - // returns true if the type was used as a flag - bool isFlags() const - { - return m_pattern == FlagsPattern; - } - - // returns true if the type was used as a thread - bool isThread() const - { - return m_pattern == ThreadPattern; - } - - bool isConstant() const - { - return m_constant; - } - void setConstant(bool constant) - { - m_constant = constant; - } - - ReferenceType referenceType() const { return m_referenceType; } - void setReferenceType(ReferenceType ref) { m_referenceType = ref; } - - /** - * Says if the type is to be implemented using target language - * equivalent of C++ enums, i.e. not plain ints. - * /return true if the type is to be implemented using target - * language enums - */ - bool isTargetLangEnum() const; - bool isIntegerEnum() const - { - return isEnum() && !isTargetLangEnum(); - } - - /** - * Says if the type is to be implemented using target language - * equivalent of Qt's QFlags, i.e. not plain ints. - * /return true if the type is to be implemented using target - * language QFlags - */ - bool isTargetLangFlags() const; - bool isIntegerFlags() const - { - return isFlags() && !isTargetLangFlags(); - } - - int actualIndirections() const - { - return m_indirections + (m_referenceType == LValueReference ? 1 : 0); - } - int indirections() const - { - return m_indirections; - } - void setIndirections(int indirections) - { - m_indirections = indirections; - } - - void setArrayElementCount(int n) - { - m_arrayElementCount = n; - } - int arrayElementCount() const - { - return m_arrayElementCount; - } - - const AbstractMetaType *arrayElementType() const - { - return m_arrayElementType; - } - void setArrayElementType(const AbstractMetaType *t) - { - m_arrayElementType = t; - } - - QString cppSignature() const; - - AbstractMetaType *copy() const; - - const TypeEntry *typeEntry() const - { - return m_typeEntry; - } - void setTypeEntry(const TypeEntry *type) - { - m_typeEntry = type; - } - - void setOriginalTypeDescription(const QString &otd) - { - m_originalTypeDescription = otd; - } - QString originalTypeDescription() const - { - return m_originalTypeDescription; - } - - void setOriginalTemplateType(const AbstractMetaType *type) - { - m_originalTemplateType = type; - } - const AbstractMetaType *originalTemplateType() const - { - return m_originalTemplateType; - } - - AbstractMetaType *getSmartPointerInnerType() const - { - Q_ASSERT(isSmartPointer()); - AbstractMetaTypeList instantiations = this->instantiations(); - Q_ASSERT(!instantiations.isEmpty()); - AbstractMetaType *innerType = instantiations.at(0); - return innerType; - } - - QString getSmartPointerInnerTypeName() const - { - Q_ASSERT(isSmartPointer()); - AbstractMetaType *innerType = getSmartPointerInnerType(); - Q_ASSERT(innerType); - return innerType->name(); - } - - /// Decides and sets the proper usage patter for the current meta type. - void decideUsagePattern(); - - bool hasTemplateChildren() const; - -private: - TypeUsagePattern determineUsagePattern() const; - - const TypeEntry *m_typeEntry; - AbstractMetaTypeList m_instantiations; - QString m_package; - mutable QString m_name; - mutable QString m_cachedCppSignature; - QString m_originalTypeDescription; - - int m_arrayElementCount; - const AbstractMetaType *m_arrayElementType; - const AbstractMetaType *m_originalTemplateType; - - TypeUsagePattern m_pattern; - uint m_constant : 1; - uint m_cppInstantiation : 1; - int m_indirections : 4; - uint m_reserved : 26; // unused - ReferenceType m_referenceType; - AbstractMetaTypeList m_children; - - Q_DISABLE_COPY(AbstractMetaType); -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaType *at); -#endif - -class AbstractMetaVariable -{ -public: - AbstractMetaVariable() : m_type(0), m_hasName(false) {} - AbstractMetaVariable(const AbstractMetaVariable &other); - - virtual ~AbstractMetaVariable() - { - delete m_type; - } - - AbstractMetaType *type() const - { - return m_type; - } - void setType(AbstractMetaType *type) - { - Q_ASSERT(m_type == 0); - m_type = type; - } - void replaceType(AbstractMetaType *type) - { - if (m_type) - delete m_type; - m_type = type; - } - - QString name() const - { - return m_name; - } - void setName(const QString &name, bool realName = true) - { - m_name = name; - m_hasName = realName; - } - bool hasName() const - { - return m_hasName; - } - QString originalName() const - { - return m_originalName; - } - void setOriginalName(const QString& name) - { - m_originalName = name; - } - void setDocumentation(const Documentation& doc) - { - m_doc = doc; - } - Documentation documentation() const - { - return m_doc; - } - -private: - QString m_originalName; - QString m_name; - AbstractMetaType *m_type; - bool m_hasName; - - Documentation m_doc; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaVariable *av); -#endif - -class AbstractMetaArgument : public AbstractMetaVariable -{ -public: - AbstractMetaArgument() : m_argumentIndex(0) {}; - - QString defaultValueExpression() const - { - return m_expression; - } - void setDefaultValueExpression(const QString &expr) - { - m_expression = expr; - } - - QString originalDefaultValueExpression() const - { - return m_originalExpression; - } - void setOriginalDefaultValueExpression(const QString &expr) - { - m_originalExpression = expr; - } - - QString toString() const - { - return type()->name() + QLatin1Char(' ') + AbstractMetaVariable::name() + - (m_expression.isEmpty() ? QString() : QLatin1String(" = ") + m_expression); - } - - int argumentIndex() const - { - return m_argumentIndex; - } - void setArgumentIndex(int argIndex) - { - m_argumentIndex = argIndex; - } - - AbstractMetaArgument *copy() const; -private: - QString m_expression; - QString m_originalExpression; - int m_argumentIndex; - - friend class AbstractMetaClass; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaArgument *aa); -#endif - -class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes -{ -public: - AbstractMetaField(); - ~AbstractMetaField(); - - const AbstractMetaClass *enclosingClass() const - { - return m_class; - } - void setEnclosingClass(const AbstractMetaClass *cls) - { - m_class = cls; - } - - const AbstractMetaFunction *getter() const; - const AbstractMetaFunction *setter() const; - - FieldModificationList modifications() const; - - bool isModifiedRemoved(int types = TypeSystem::All) const; - - using AbstractMetaVariable::setDocumentation; - using AbstractMetaVariable::documentation; - - AbstractMetaField *copy() const; - -private: - mutable AbstractMetaFunction *m_getter; - mutable AbstractMetaFunction *m_setter; - const AbstractMetaClass *m_class; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaField *af); -#endif - -class AbstractMetaFunction : public AbstractMetaAttributes -{ - Q_GADGET -public: - enum FunctionType { - ConstructorFunction, - CopyConstructorFunction, - MoveConstructorFunction, - AssignmentOperatorFunction, - MoveAssignmentOperatorFunction, - DestructorFunction, - NormalFunction, - SignalFunction, - EmptyFunction, - SlotFunction, - GlobalScopeFunction - }; - Q_ENUM(FunctionType) - - enum CompareResultFlag { - EqualName = 0x00000001, - EqualArguments = 0x00000002, - EqualAttributes = 0x00000004, - EqualImplementor = 0x00000008, - EqualReturnType = 0x00000010, - EqualDefaultValueOverload = 0x00000020, - EqualModifiedName = 0x00000040, - - NameLessThan = 0x00001000, - - PrettySimilar = EqualName | EqualArguments, - Equal = 0x0000001f, - NotEqual = 0x00001000 - }; - Q_DECLARE_FLAGS(CompareResult, CompareResultFlag) - Q_FLAG(CompareResultFlag) - - AbstractMetaFunction() - : m_typeEntry(0), - m_functionType(NormalFunction), - m_type(0), - m_class(0), - m_implementingClass(0), - m_declaringClass(0), - m_propertySpec(0), - m_constant(false), - m_invalid(false), - m_reverse(false), - m_userAdded(false), - m_explicit(false), - m_pointerOperator(false), - m_isCallOperator(false) - { - } - - ~AbstractMetaFunction(); - - QString name() const - { - return m_name; - } - - void setName(const QString &name) - { - m_name = name; - } - - QString originalName() const - { - return m_originalName.isEmpty() ? name() : m_originalName; - } - - void setOriginalName(const QString &name) - { - m_originalName = name; - } - - void setReverseOperator(bool reverse) - { - m_reverse = reverse; - } - - bool isReverseOperator() const - { - return m_reverse; - } - - /** - * Returns true if this is a operator and the "self" operand is a pointer. - * e.g. class Foo {}; operator+(SomeEnum, Foo*); - */ - bool isPointerOperator() const - { - return m_pointerOperator; - } - - void setPointerOperator(bool value) - { - m_pointerOperator = value; - } - - void setExplicit(bool isExplicit) - { - m_explicit = isExplicit; - } - /** - * Says if the function (a constructor) was declared as explicit in C++. - * \return true if the function was declared as explicit in C++ - */ - bool isExplicit() const - { - return m_explicit; - } - - static bool isConversionOperator(QString funcName); - bool isConversionOperator() const - { - return isConversionOperator(originalName()); - } - - static bool isOperatorOverload(QString funcName); - bool isOperatorOverload() const - { - return isOperatorOverload(originalName()); - } - bool isCastOperator() const; - - bool isArithmeticOperator() const; - bool isBitwiseOperator() const; - bool isComparisonOperator() const; - bool isLogicalOperator() const; - bool isSubscriptOperator() const; - bool isAssignmentOperator() const; // Assignment or move assignment - bool isOtherOperator() const; - - /** - * Informs the arity of the operator or -1 if the function is not - * an operator overload. - * /return the arity of the operator or -1 - */ - int arityOfOperator() const; - bool isUnaryOperator() const { return arityOfOperator() == 1; } - bool isBinaryOperator() const { return arityOfOperator() == 2; } - bool isInplaceOperator() const; - - // TODO: ths function *should* know if it is virtual - // instead of asking to your implementing class. - bool isVirtual() const; - bool isThread() const; - bool allowThread() const; - QString modifiedName() const; - - QString minimalSignature() const; - QStringList possibleIntrospectionCompatibleSignatures() const; - - QString marshalledName() const; - - // true if one or more of the arguments are of QtJambiObject subclasses - bool argumentsHaveNativeId() const - { - for (const AbstractMetaArgument *arg : m_arguments) { - if (arg->type()->hasNativeId()) - return true; - } - - return false; - } - - bool isModifiedRemoved(int types = TypeSystem::All) const; - - AbstractMetaType *type() const - { - return m_type; - } - void setType(AbstractMetaType *type) - { - Q_ASSERT(m_type == 0); - m_type = type; - } - - void replaceType(AbstractMetaType *type) - { - if (m_type) - delete m_type; - m_type = type; - } - - // The class that has this function as a member. - const AbstractMetaClass *ownerClass() const - { - return m_class; - } - void setOwnerClass(const AbstractMetaClass *cls) - { - m_class = cls; - } - - // The first class in a hierarchy that declares the function - const AbstractMetaClass *declaringClass() const - { - return m_declaringClass; - } - void setDeclaringClass(const AbstractMetaClass *cls) - { - m_declaringClass = cls; - } - - // The class that actually implements this function - const AbstractMetaClass *implementingClass() const - { - return m_implementingClass; - } - void setImplementingClass(const AbstractMetaClass *cls) - { - m_implementingClass = cls; - } - - bool needsCallThrough() const; - - AbstractMetaArgumentList arguments() const - { - return m_arguments; - } - void setArguments(const AbstractMetaArgumentList &arguments) - { - m_arguments = arguments; - } - void addArgument(AbstractMetaArgument *argument) - { - m_arguments << argument; - } - int actualMinimumArgumentCount() const; - - void setInvalid(bool on) - { - m_invalid = on; - } - bool isInvalid() const - { - return m_invalid; - } - bool isDeprecated() const; - bool isDestructor() const - { - return functionType() == DestructorFunction; - } - bool isConstructor() const - { - return m_functionType == ConstructorFunction || m_functionType == CopyConstructorFunction - || m_functionType == MoveConstructorFunction; - } - bool isNormal() const - { - return functionType() == NormalFunction || isSlot() || isInGlobalScope(); - } - bool isInGlobalScope() const - { - return functionType() == GlobalScopeFunction; - } - bool isSignal() const - { - return functionType() == SignalFunction; - } - bool isSlot() const - { - return functionType() == SlotFunction; - } - bool isEmptyFunction() const - { - return functionType() == EmptyFunction; - } - FunctionType functionType() const - { - return m_functionType; - } - void setFunctionType(FunctionType type) - { - m_functionType = type; - } - - bool usesRValueReferences() const; - QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const; - QString signature() const; - QString targetLangSignature(bool minimal = false) const; - bool shouldReturnThisObject() const - { - return QLatin1String("this") == argumentReplaced(0); - } - bool shouldIgnoreReturnValue() const - { - return QLatin1String("void") == argumentReplaced(0); - } - - bool isConstant() const - { - return m_constant; - } - void setConstant(bool constant) - { - m_constant = constant; - } - - /// Returns true if the AbstractMetaFunction was added by the user via the type system description. - bool isUserAdded() const - { - return m_userAdded; - } - void setUserAdded(bool userAdded) - { - m_userAdded = userAdded; - } - - QString toString() const - { - return m_name; - } - - CompareResult compareTo(const AbstractMetaFunction *other) const; - - bool operator <(const AbstractMetaFunction &a) const; - - AbstractMetaFunction *copy() const; - - QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const; - bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const; - QString conversionRule(TypeSystem::Language language, int idx) const; - QVector referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; - ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const; - - bool nullPointersDisabled(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; - QString nullPointerDefaultValue(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; - - bool resetObjectAfterUse(int argument_idx) const; - - // Returns whether garbage collection is disabled for the argument in any context - bool disabledGarbageCollection(const AbstractMetaClass *cls, int key) const; - - // Returns the ownership rules for the given argument in the given context - TypeSystem::Ownership ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int idx) const; - - bool isVirtualSlot() const; - - QString typeReplaced(int argument_index) const; - bool isRemovedFromAllLanguages(const AbstractMetaClass *) const; - bool isRemovedFrom(const AbstractMetaClass *, TypeSystem::Language language) const; - bool argumentRemoved(int) const; - - QString argumentReplaced(int key) const; - bool needsSuppressUncheckedWarning() const; - - bool hasModifications(const AbstractMetaClass *implementor) const; - /** - * Verifies if any modification to the function is an inject code. - * \return true if there is inject code modifications to the function. - */ - bool hasInjectedCode() const; - /** - * Returns a list of code snips for this function. - * The code snips can be filtered by position and language. - * \return list of code snips - */ - CodeSnipList injectedCodeSnips(TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, - TypeSystem::Language language = TypeSystem::All) const; - - /** - * Verifies if any modification to the function alters/removes its - * arguments types or default values. - * \return true if there is some modification to function signature - */ - bool hasSignatureModifications() const; - FunctionModificationList modifications(const AbstractMetaClass* implementor = 0) const; - - /** - * 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 = 0) const; - - void setPropertySpec(QPropertySpec *spec) - { - m_propertySpec = spec; - } - - QPropertySpec *propertySpec() const - { - return m_propertySpec; - } - - FunctionTypeEntry* typeEntry() const - { - return m_typeEntry; - } - - void setTypeEntry(FunctionTypeEntry* typeEntry) - { - m_typeEntry = typeEntry; - } - - bool isCallOperator() const; - -#ifndef QT_NO_DEBUG_STREAM - void formatDebugVerbose(QDebug &d) const; -#endif - -private: - QString m_name; - QString m_originalName; - mutable QString m_cachedMinimalSignature; - mutable QString m_cachedSignature; - mutable QString m_cachedModifiedName; - - FunctionTypeEntry* m_typeEntry; - FunctionType m_functionType; - AbstractMetaType *m_type; - const AbstractMetaClass *m_class; - const AbstractMetaClass *m_implementingClass; - const AbstractMetaClass *m_declaringClass; - QPropertySpec *m_propertySpec; - AbstractMetaArgumentList m_arguments; - uint m_constant : 1; - uint m_invalid : 1; - uint m_reverse : 1; - uint m_userAdded : 1; - uint m_explicit : 1; - uint m_pointerOperator : 1; - uint m_isCallOperator : 1; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::CompareResult) - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaFunction *af); -#endif - -class AbstractMetaEnumValue -{ -public: - AbstractMetaEnumValue() - : m_valueSet(false), m_value(0) - { - } - - int value() const - { - return m_value; - } - - void setValue(int value) - { - m_valueSet = true; - m_value = value; - } - - QString stringValue() const - { - return m_stringValue; - } - - void setStringValue(const QString &v) - { - m_stringValue = v; - } - - QString name() const - { - return m_name; - } - - void setName(const QString &name) - { - m_name = name; - } - - bool isValueSet() const - { - return m_valueSet; - } - - void setDocumentation(const Documentation& doc) - { - m_doc = doc; - } - - Documentation documentation() const - { - return m_doc; - } - -private: - QString m_name; - QString m_stringValue; - - bool m_valueSet; - int m_value; - - Documentation m_doc; -}; - -class AbstractMetaEnum : public AbstractMetaAttributes -{ -public: - AbstractMetaEnum() : m_typeEntry(0), m_class(0), m_hasQenumsDeclaration(false) {} - ~AbstractMetaEnum() - { - qDeleteAll(m_enumValues); - } - - AbstractMetaEnumValueList values() const - { - return m_enumValues; - } - - void addEnumValue(AbstractMetaEnumValue *enumValue) - { - m_enumValues << enumValue; - } - - QString name() const; - - QString qualifier() const; - - QString package() const; - - QString fullName() const - { - return package() + QLatin1Char('.') + qualifier() + QLatin1Char('.') + name(); - } - - // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class? - void setHasQEnumsDeclaration(bool on) - { - m_hasQenumsDeclaration = on; - } - - bool hasQEnumsDeclaration() const - { - return m_hasQenumsDeclaration; - } - - EnumTypeEntry *typeEntry() const - { - return m_typeEntry; - } - - void setTypeEntry(EnumTypeEntry *entry) - { - m_typeEntry = entry; - } - - AbstractMetaClass *enclosingClass() const - { - return m_class; - } - - void setEnclosingClass(AbstractMetaClass *c) - { - m_class = c; - } - - bool isAnonymous() const; - -private: - AbstractMetaEnumValueList m_enumValues; - EnumTypeEntry *m_typeEntry; - AbstractMetaClass *m_class; - - uint m_hasQenumsDeclaration : 1; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AbstractMetaEnum *ae); -#endif - -class AbstractMetaClass : public AbstractMetaAttributes -{ - Q_GADGET -public: - enum FunctionQueryOption { - Constructors = 0x0000001, // Only constructors - //Destructors = 0x0000002, // Only destructors. Not included in class. - VirtualFunctions = 0x0000004, // Only virtual functions (virtual in both TargetLang and C++) - FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang - FinalInCppFunctions = 0x0000010, // Only functions that are non-virtual in C++ - ClassImplements = 0x0000020, // Only functions implemented by the current class - Inconsistent = 0x0000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++) - StaticFunctions = 0x0000080, // Only static functions - Signals = 0x0000100, // Only signals - NormalFunctions = 0x0000200, // Only functions that aren't signals - Visible = 0x0000400, // Only public and protected functions - ForcedShellFunctions = 0x0000800, // Only functions that are overridden to be implemented in the shell class - WasPublic = 0x0001000, // Only functions that were originally public - WasProtected = 0x0002000, // Only functions that were originally protected - 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++ - NonEmptyFunctions = 0x0040000, // Only functions with target language API implementations - VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang - AbstractFunctions = 0x0100000, // Only abstract functions - WasVisible = 0x0200000, // Only functions that were public or protected in the original code - NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang - NotRemovedFromShell = 0x0800000, // Only functions that have not been removed from the shell class - VirtualSlots = 0x1000000, // Only functions that are set as virtual slots in the type system - OperatorOverloads = 0x2000000 // Only functions that are operator overloads - }; - Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption) - Q_FLAG(FunctionQueryOption) - - enum OperatorQueryOption { - ArithmeticOp = 0x01, // Arithmetic: +, -, *, /, %, +=, -=, *=, /=, %=, ++, --, unary+, unary- - BitwiseOp = 0x02, // Bitwise: <<, <<=, >>, >>=, ~, &, &=, |, |=, ^, ^= - ComparisonOp = 0x04, // Comparison: <, <=, >, >=, !=, == - LogicalOp = 0x08, // Logical: !, &&, || - ConversionOp = 0x10, // Conversion: operator [const] TYPE() - SubscriptionOp = 0x20, // Subscription: [] - AssignmentOp = 0x40, // Assignment: = - OtherOp = 0x80, // The remaining operators: call(), etc - AllOperators = ArithmeticOp | BitwiseOp | ComparisonOp - | LogicalOp | ConversionOp | SubscriptionOp - | AssignmentOp | OtherOp - }; - Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption) - Q_FLAG(OperatorQueryOption) - - AbstractMetaClass() - : m_hasVirtuals(false), - m_isPolymorphic(false), - m_hasNonpublic(false), - m_hasVirtualSlots(false), - m_hasNonPrivateConstructor(false), - m_functionsFixed(false), - m_hasPrivateDestructor(false), - m_hasProtectedDestructor(false), - m_hasVirtualDestructor(false), - m_forceShellClass(false), - m_hasHashFunction(false), - m_hasEqualsOperator(false), - m_hasCloneOperator(false), - m_isTypeDef(false), - m_hasToStringCapability(false), - m_enclosingClass(0), - m_baseClass(0), - m_templateBaseClass(0), - m_extractedInterface(0), - m_typeEntry(0), - m_stream(false) - { - } - - virtual ~AbstractMetaClass(); - - AbstractMetaClass *extractInterface(); - void fixFunctions(); - - AbstractMetaFunctionList functions() const - { - return m_functions; - } - - void setFunctions(const AbstractMetaFunctionList &functions); - void addFunction(AbstractMetaFunction *function); - bool hasFunction(const AbstractMetaFunction *f) const; - bool hasFunction(const QString &str) const; - const AbstractMetaFunction* findFunction(const QString& functionName) const; - bool hasSignal(const AbstractMetaFunction *f) const; - - bool hasConstructors() const; - bool hasCopyConstructor() const; - bool hasPrivateCopyConstructor() const; - - void addDefaultConstructor(); - void addDefaultCopyConstructor(bool isPrivate = false); - - bool hasNonPrivateConstructor() const - { - return m_hasNonPrivateConstructor; - } - - void setHasNonPrivateConstructor(bool value) - { - m_hasNonPrivateConstructor = value; - } - - bool hasPrivateDestructor() const - { - return m_hasPrivateDestructor; - } - - void setHasPrivateDestructor(bool value) - { - m_hasPrivateDestructor = value; - } - - bool hasProtectedDestructor() const - { - return m_hasProtectedDestructor; - } - - void setHasProtectedDestructor(bool value) - { - m_hasProtectedDestructor = value; - } - - bool hasVirtualDestructor() const - { - return m_hasVirtualDestructor; - } - - void setHasVirtualDestructor(bool value) - { - m_hasVirtualDestructor = value; - } - - AbstractMetaFunctionList queryFunctionsByName(const QString &name) const; - AbstractMetaFunctionList queryFunctions(FunctionQueryOptions query) const; - AbstractMetaFunctionList functionsInTargetLang() const; - AbstractMetaFunctionList functionsInShellClass() const; - inline AbstractMetaFunctionList cppSignalFunctions() const; - AbstractMetaFunctionList publicOverrideFunctions() const; - AbstractMetaFunctionList virtualOverrideFunctions() const; - AbstractMetaFunctionList virtualFunctions() const; - AbstractMetaFunctionList implicitConversions() const; - - /** - * Retrieves all class' operator overloads that meet - * query criteria defined with the OperatorQueryOption - * enum. - * /param query composition of OperatorQueryOption enum values - * /return list of operator overload methods that meet the - * query criteria - */ - AbstractMetaFunctionList operatorOverloads(OperatorQueryOptions query = AllOperators) const; - - bool hasOperatorOverload() const; - bool hasArithmeticOperatorOverload() const; - bool hasBitwiseOperatorOverload() const; - bool hasComparisonOperatorOverload() const; - bool hasLogicalOperatorOverload() const; - bool hasSubscriptOperatorOverload() const; - bool hasAssignmentOperatorOverload() const; - bool hasConversionOperatorOverload() const; - - AbstractMetaFieldList fields() const - { - return m_fields; - } - - void setFields(const AbstractMetaFieldList &fields) - { - m_fields = fields; - } - - void addField(AbstractMetaField *field) - { - m_fields << field; - } - - AbstractMetaEnumList enums() const - { - return m_enums; - } - void setEnums(const AbstractMetaEnumList &enums) - { - m_enums = enums; - } - - void addEnum(AbstractMetaEnum *e) - { - m_enums << e; - } - - AbstractMetaEnum *findEnum(const QString &enumName); - AbstractMetaEnum *findEnumForValue(const QString &enumName); - AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum); - - AbstractMetaClassList interfaces() const - { - return m_interfaces; - } - void addInterface(AbstractMetaClass *interface); - void setInterfaces(const AbstractMetaClassList &interface); - - QString fullName() const - { - return package() + QLatin1Char('.') + name(); - } - - /** - * Retrieves the class name without any namespace/scope information. - * /return the class name without scope information - */ - QString name() const; - - QString baseClassName() const - { - return m_baseClass ? m_baseClass->name() : QString(); - } - - AbstractMetaClass *baseClass() const - { - return m_baseClass; - } - - void setBaseClass(AbstractMetaClass *base_class); - - const AbstractMetaClass *enclosingClass() const - { - return m_enclosingClass; - } - - void setEnclosingClass(AbstractMetaClass *cl) - { - m_enclosingClass = cl; - } - - const AbstractMetaClassList& innerClasses() const - { - return m_innerClasses; - } - - void addInnerClass(AbstractMetaClass* cl) - { - m_innerClasses << cl; - } - - void setInnerClasses(AbstractMetaClassList innerClasses) - { - m_innerClasses = innerClasses; - } - - QString package() const; - - bool isInterface() const; - - bool isNamespace() const; - - bool isQObject() const; - - bool isQtNamespace() const - { - return isNamespace() && name() == QLatin1String("Qt"); - } - - QString qualifiedCppName() const; - - bool hasSignals() const; - bool inheritsFrom(const AbstractMetaClass *other) const; - - void setForceShellClass(bool on) - { - m_forceShellClass = on; - } - - bool generateShellClass() const; - - bool hasVirtualSlots() const - { - return m_hasVirtualSlots; - } - - /** - * Says if a class has any virtual functions of its own. - * \return true if the class implements any virtual methods - */ - bool hasVirtualFunctions() const - { - return !isFinal() && m_hasVirtuals; - } - /** - * Says if the class that declares or inherits a virtual function. - * \return true if the class implements or inherits any virtual methods - */ - bool isPolymorphic() const - { - return m_isPolymorphic; - } - - /** - * Tells if this class has one or more functions that are protected. - * \return true if the class has protected functions. - */ - bool hasProtectedFunctions() const; - - /** - * Tells if this class has one or more fields (member variables) that are protected. - * \return true if the class has protected fields. - */ - bool hasProtectedFields() const; - - /** - * Tells if this class has one or more members (functions or fields) that are protected. - * \return true if the class has protected members. - */ - bool hasProtectedMembers() const; - - - QVector templateArguments() const - { - return m_templateArgs; - } - - void setTemplateArguments(const QVector &args) - { - m_templateArgs = args; - } - - bool hasFieldAccessors() const; - - // only valid during metabuilder's run - QStringList baseClassNames() const - { - return m_baseClassNames; - } - - void setBaseClassNames(const QStringList &names) - { - m_baseClassNames = names; - } - - const ComplexTypeEntry *typeEntry() const - { - return m_typeEntry; - } - - ComplexTypeEntry *typeEntry() - { - return m_typeEntry; - } - - void setTypeEntry(ComplexTypeEntry *type) - { - m_typeEntry = type; - } - - void setHasHashFunction(bool on) - { - m_hasHashFunction = on; - } - - bool hasHashFunction() const - { - return m_hasHashFunction; - } - virtual bool hasDefaultToStringFunction() const; - - void setHasEqualsOperator(bool on) - { - m_hasEqualsOperator = on; - } - - bool hasEqualsOperator() const - { - return m_hasEqualsOperator; - } - - void setHasCloneOperator(bool on) - { - m_hasCloneOperator = on; - } - - bool hasCloneOperator() const - { - return m_hasCloneOperator; - } - - void addPropertySpec(QPropertySpec *spec) - { - m_propertySpecs << spec; - } - - QVector propertySpecs() const - { - return m_propertySpecs; - } - - QPropertySpec *propertySpecForRead(const QString &name) const; - QPropertySpec *propertySpecForWrite(const QString &name) const; - QPropertySpec *propertySpecForReset(const QString &name) const; - - /// Returns a list of conversion operators for this class. The conversion operators are defined in other classes of the same module. - AbstractMetaFunctionList externalConversionOperators() const - { - return m_externalConversionOperators; - } - /// Adds a converter operator for this class. - void addExternalConversionOperator(AbstractMetaFunction* conversionOp) - { - if (!m_externalConversionOperators.contains(conversionOp)) - m_externalConversionOperators.append(conversionOp); - } - /// Returns true if this class has any converter operators defined elsewhere. - bool hasExternalConversionOperators() const - { - return !m_externalConversionOperators.isEmpty(); - } - - void sortFunctions(); - - const AbstractMetaClass *templateBaseClass() const - { - return m_templateBaseClass; - } - - void setTemplateBaseClass(const AbstractMetaClass *cls) - { - m_templateBaseClass = cls; - } - - bool hasTemplateBaseClassInstantiations() const; - AbstractMetaTypeList templateBaseClassInstantiations() const; - void setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations); - - void setTypeDef(bool typeDef) { m_isTypeDef = typeDef; } - bool isTypeDef() const { return m_isTypeDef; } - - void setStream(bool stream) - { - m_stream = stream; - } - - bool isStream() const - { - return m_stream; - } - - void setToStringCapability(bool value) - { - m_hasToStringCapability = value; - } - - bool hasToStringCapability() const - { - return m_hasToStringCapability; - } - - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, - const QString &name); - static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, - const TypeEntry* typeEntry); - static AbstractMetaEnumValue *findEnumValue(const AbstractMetaClassList &classes, - const QString &string); - static AbstractMetaEnum *findEnum(const AbstractMetaClassList &classes, - const EnumTypeEntry *entry); - -private: -#ifndef QT_NO_DEBUG_STREAM - friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); -#endif - uint m_hasVirtuals : 1; - uint m_isPolymorphic : 1; - uint m_hasNonpublic : 1; - uint m_hasVirtualSlots : 1; - uint m_hasNonPrivateConstructor : 1; - uint m_functionsFixed : 1; - uint m_hasPrivateDestructor : 1; - uint m_hasProtectedDestructor : 1; - uint m_hasVirtualDestructor : 1; - uint m_forceShellClass : 1; - uint m_hasHashFunction : 1; - uint m_hasEqualsOperator : 1; - uint m_hasCloneOperator : 1; - uint m_isTypeDef : 1; - uint m_hasToStringCapability : 1; - - const AbstractMetaClass *m_enclosingClass; - AbstractMetaClass *m_baseClass; - const AbstractMetaClass *m_templateBaseClass; - AbstractMetaFunctionList m_functions; - AbstractMetaFieldList m_fields; - AbstractMetaEnumList m_enums; - AbstractMetaClassList m_interfaces; - AbstractMetaClass *m_extractedInterface; - QVector m_propertySpecs; - AbstractMetaClassList m_innerClasses; - - AbstractMetaFunctionList m_externalConversionOperators; - - QStringList m_baseClassNames; - QVector m_templateArgs; - ComplexTypeEntry *m_typeEntry; -// FunctionModelItem m_qDebugStreamFunction; - - bool m_stream; -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::FunctionQueryOptions) -Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::OperatorQueryOptions) - -class QPropertySpec -{ -public: - QPropertySpec(const TypeEntry *type) - : m_type(type), - m_index(-1) - {} - - const TypeEntry *type() const - { - return m_type; - } - - QString name() const - { - return m_name; - } - - void setName(const QString &name) - { - m_name = name; - } - - QString read() const - { - return m_read; - } - - void setRead(const QString &read) - { - m_read = read; - } - - QString write() const - { - return m_write; - } - - void setWrite(const QString &write) - { - m_write = write; - } - - QString designable() const - { - return m_designable; - } - - void setDesignable(const QString &designable) - { - m_designable = designable; - } - - QString reset() const - { - return m_reset; - } - - void setReset(const QString &reset) - { - m_reset = reset; - } - - int index() const - { - return m_index; - } - - void setIndex(int index) - { - m_index = index; - } - -private: - QString m_name; - QString m_read; - QString m_write; - QString m_designable; - QString m_reset; - const TypeEntry *m_type; - int m_index; -}; - -inline AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const -{ - return queryFunctions(Signals - | Visible - | NotRemovedFromTargetLang); -} - -#endif // ABSTRACTMETALANG_H diff --git a/ApiExtractor/abstractmetalang_typedefs.h b/ApiExtractor/abstractmetalang_typedefs.h deleted file mode 100644 index da8369895..000000000 --- a/ApiExtractor/abstractmetalang_typedefs.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ABSTRACTMETALANG_TYPEDEFS_H -#define ABSTRACTMETALANG_TYPEDEFS_H - -#include - -class AbstractMetaClass; -class AbstractMetaField; -class AbstractMetaArgument; -class AbstractMetaEnum; -class AbstractMetaEnumValue; -class AbstractMetaFunction; -class AbstractMetaType; - -typedef QVector AbstractMetaArgumentList; -typedef QVector AbstractMetaClassList; -typedef QVector AbstractMetaEnumList; -typedef QVector AbstractMetaEnumValueList; -typedef QVector AbstractMetaFieldList; -typedef QVector AbstractMetaFunctionList; -typedef QVector AbstractMetaTypeList; - -#endif // ABSTRACTMETALANG_TYPEDEFS_H diff --git a/ApiExtractor/apiextractor.cpp b/ApiExtractor/apiextractor.cpp deleted file mode 100644 index abb7c08b9..000000000 --- a/ApiExtractor/apiextractor.cpp +++ /dev/null @@ -1,317 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "apiextractor.h" -#include "abstractmetalang.h" - -#include -#include -#include -#include -#include -#include - -#include "reporthandler.h" -#include "typesystem.h" -#include "fileout.h" -#include "abstractmetabuilder.h" -#include "typedatabase.h" -#include "typesystem.h" - -static bool appendFile(const QString& sourceFileName, QFile& targetFile) -{ - QFile sourceFile(sourceFileName); - if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - std::cerr << "Cannot open " << qPrintable(QDir::toNativeSeparators(sourceFileName)) - << ": " << qPrintable(sourceFile.errorString()) << '\n'; - return false; - } - targetFile.write(sourceFile.readAll()); - return true; -} - -ApiExtractor::ApiExtractor() : m_builder(0) -{ - // Environment TYPESYSTEMPATH - QString envTypesystemPaths = QFile::decodeName(getenv("TYPESYSTEMPATH")); - if (!envTypesystemPaths.isEmpty()) - TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths); -} - -ApiExtractor::~ApiExtractor() -{ - delete m_builder; -} - -void ApiExtractor::addTypesystemSearchPath (const QString& path) -{ - TypeDatabase::instance()->addTypesystemPath(path); -} - -void ApiExtractor::addTypesystemSearchPath(const QStringList& paths) -{ - for (const QString &path : paths) - addTypesystemSearchPath(path); -} - -void ApiExtractor::addIncludePath(const HeaderPath& path) -{ - m_includePaths << path; -} - -void ApiExtractor::addIncludePath(const HeaderPaths& paths) -{ - m_includePaths << paths; -} - -void ApiExtractor::setLogDirectory(const QString& logDir) -{ - m_logDirectory = logDir; -} - -void ApiExtractor::setCppFileName(const QString& cppFileName) -{ - m_cppFileName = cppFileName; -} - -void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) -{ - m_typeSystemFileName = typeSystemFileName; -} - -void ApiExtractor::setDebugLevel(ReportHandler::DebugLevel debugLevel) -{ - ReportHandler::setDebugLevel(debugLevel); -} - -void ApiExtractor::setSuppressWarnings ( bool value ) -{ - TypeDatabase::instance()->setSuppressWarnings(value); -} - -void ApiExtractor::setSilent ( bool value ) -{ - ReportHandler::setSilent(value); -} - -bool ApiExtractor::setApiVersion(const QString& package, const QString &version) -{ - return TypeDatabase::instance()->setApiVersion(package, version); -} - -void ApiExtractor::setDropTypeEntries(QString dropEntries) -{ - dropEntries.remove(QLatin1Char(' ')); - QStringList entries = dropEntries.split(QLatin1Char(';')); - TypeDatabase::instance()->setDropTypeEntries(entries); -} - -AbstractMetaEnumList ApiExtractor::globalEnums() const -{ - Q_ASSERT(m_builder); - return m_builder->globalEnums(); -} - -AbstractMetaFunctionList ApiExtractor::globalFunctions() const -{ - Q_ASSERT(m_builder); - return m_builder->globalFunctions(); -} - -AbstractMetaClassList ApiExtractor::classes() const -{ - Q_ASSERT(m_builder); - return m_builder->classes(); -} - -AbstractMetaClassList ApiExtractor::smartPointers() const -{ - Q_ASSERT(m_builder); - return m_builder->smartPointers(); -} - -AbstractMetaClassList ApiExtractor::classesTopologicalSorted(const Dependencies &additionalDependencies) const -{ - Q_ASSERT(m_builder); - return m_builder->classesTopologicalSorted(Q_NULLPTR, additionalDependencies); -} - -PrimitiveTypeEntryList ApiExtractor::primitiveTypes() const -{ - return TypeDatabase::instance()->primitiveTypes(); -} - -ContainerTypeEntryList ApiExtractor::containerTypes() const -{ - return TypeDatabase::instance()->containerTypes(); -} - -QSet ApiExtractor::qtMetaTypeDeclaredTypeNames() const -{ - Q_ASSERT(m_builder); - return m_builder->qtMetaTypeDeclaredTypeNames(); -} - -static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) -{ - const AbstractMetaEnum* result = 0; - for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->typeEntry() == typeEntry) { - result = metaEnum; - break; - } - } - if (result) - break; - result = findEnumOnClasses(metaClass->innerClasses(), typeEntry); - } - return result; -} - -const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const -{ - if (!typeEntry) - return 0; - const AbstractMetaEnumList &globalEnums = m_builder->globalEnums(); - for (AbstractMetaEnum* metaEnum : globalEnums) { - if (metaEnum->typeEntry() == typeEntry) - return metaEnum; - } - return findEnumOnClasses(m_builder->classes(), typeEntry); -} - -const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const -{ - if (!typeEntry) - return 0; - if (typeEntry->isFlags()) - return findAbstractMetaEnum(reinterpret_cast(typeEntry)); - if (typeEntry->isEnum()) - return findAbstractMetaEnum(reinterpret_cast(typeEntry)); - return 0; -} - -const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const -{ - if (!typeEntry) - return 0; - return findAbstractMetaEnum(typeEntry->originator()); -} - -const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const AbstractMetaType* metaType) const -{ - if (!metaType) - return 0; - return findAbstractMetaEnum(metaType->typeEntry()); -} - -int ApiExtractor::classCount() const -{ - Q_ASSERT(m_builder); - return m_builder->classes().count(); -} - -bool ApiExtractor::run() -{ - if (m_builder) - return false; - - if (m_typeSystemFileName.isEmpty()) { - std::cerr << "You must specify a Type System file." << std::endl; - return false; - } else if (!TypeDatabase::instance()->parseFile(m_typeSystemFileName)) { - std::cerr << "Cannot parse file: " << qPrintable(m_typeSystemFileName); - return false; - } - - const QString pattern = QDir::tempPath() + QLatin1Char('/') + - QFileInfo(m_cppFileName).baseName() + QStringLiteral("_XXXXXX.hpp"); - QTemporaryFile ppFile(pattern); - bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); - // make sure that a tempfile can be written - if (!ppFile.open()) { - std::cerr << "could not create tempfile " << qPrintable(pattern) - << ": " << qPrintable(ppFile.errorString()) << '\n'; - return false; - } - - if (!appendFile(m_cppFileName, ppFile)) - return false; - const QString preprocessedCppFileName = ppFile.fileName(); - ppFile.close(); - m_builder = new AbstractMetaBuilder; - m_builder->setLogDirectory(m_logDirectory); - m_builder->setGlobalHeader(m_cppFileName); - QByteArrayList arguments; - arguments.reserve(m_includePaths.size() + 1); - for (const HeaderPath &headerPath : qAsConst(m_includePaths)) - arguments.append(HeaderPath::includeOption(headerPath)); - arguments.append(QFile::encodeName(preprocessedCppFileName)); - qCDebug(lcShiboken) << __FUNCTION__ << arguments; - const bool result = m_builder->build(arguments); - if (!result) - autoRemove = false; - if (!autoRemove) { - ppFile.setAutoRemove(false); - std::cerr << "Keeping temporary file: " << qPrintable(QDir::toNativeSeparators(preprocessedCppFileName)) << '\n'; - } - return result; -} - -#ifndef QT_NO_DEBUG_STREAM -template -static void debugFormatSequence(QDebug &d, const char *key, const Container& c) -{ - typedef typename Container::const_iterator ConstIt; - if (c.isEmpty()) - return; - const ConstIt begin = c.begin(); - const ConstIt end = c.end(); - d << "\n " << key << '[' << c.size() << "]=("; - for (ConstIt it = begin; it != end; ++it) { - if (it != begin) - d << ", "; - d << *it; - } - d << ')'; -} - -QDebug operator<<(QDebug d, const ApiExtractor &ae) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "ApiExtractor(typeSystem=\"" << ae.typeSystem() << "\", cppFileName=\"" - << ae.cppFileName() << ", "; - ae.m_builder->formatDebug(d); - d << ')'; - return d; -} -#endif // QT_NO_DEBUG_STREAM diff --git a/ApiExtractor/apiextractor.h b/ApiExtractor/apiextractor.h deleted file mode 100644 index ac90f5b2f..000000000 --- a/ApiExtractor/apiextractor.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef APIEXTRACTOR_H -#define APIEXTRACTOR_H - -#include "reporthandler.h" -#include "dependency.h" -#include "abstractmetalang_typedefs.h" -#include "apiextractormacros.h" -#include "header_paths.h" -#include "typedatabase_typedefs.h" -#include "typesystem_typedefs.h" -#include - -class AbstractMetaBuilder; -class AbstractMetaClass; -class AbstractMetaEnum; -class AbstractMetaFunction; -class AbstractMetaType; -class ContainerTypeEntry; -class EnumTypeEntry; -class FlagsTypeEntry; -class PrimitiveTypeEntry; -class TypeEntry; - -QT_BEGIN_NAMESPACE -class QDebug; -class QIODevice; -QT_END_NAMESPACE - -class ApiExtractor -{ -public: - ApiExtractor(); - ~ApiExtractor(); - - void setTypeSystem(const QString& typeSystemFileName); - QString typeSystem() const { return m_typeSystemFileName; } - void setCppFileName(const QString& cppFileName); - QString cppFileName() const { return m_cppFileName; } - void setDebugLevel(ReportHandler::DebugLevel debugLevel); - void setSuppressWarnings(bool value); - void setSilent(bool value); - void addTypesystemSearchPath(const QString& path); - void addTypesystemSearchPath(const QStringList& paths); - void addIncludePath(const HeaderPath& path); - void addIncludePath(const HeaderPaths& paths); - HeaderPaths includePaths() const { return m_includePaths; } - void setLogDirectory(const QString& logDir); - bool setApiVersion(const QString& package, const QString& version); - void setDropTypeEntries(QString dropEntries); - - AbstractMetaEnumList globalEnums() const; - AbstractMetaFunctionList globalFunctions() const; - AbstractMetaClassList classes() const; - AbstractMetaClassList smartPointers() const; - AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const; - PrimitiveTypeEntryList primitiveTypes() const; - ContainerTypeEntryList containerTypes() const; - QSet qtMetaTypeDeclaredTypeNames() const; - - const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const; - const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const; - const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const; - const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const; - - int classCount() const; - - bool run(); -private: - QString m_typeSystemFileName; - QString m_cppFileName; - HeaderPaths m_includePaths; - AbstractMetaBuilder* m_builder; - QString m_logDirectory; - - // disable copy - ApiExtractor(const ApiExtractor&); - ApiExtractor& operator=(const ApiExtractor&); -#ifndef QT_NO_DEBUG_STREAM - friend QDebug operator<<(QDebug d, const ApiExtractor &ae); -#endif -}; - -#endif // APIEXTRACTOR_H diff --git a/ApiExtractor/apiextractormacros.h b/ApiExtractor/apiextractormacros.h deleted file mode 100644 index 41a710773..000000000 --- a/ApiExtractor/apiextractormacros.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef APIEXTRACTORMACROS_H -#define APIEXTRACTORMACROS_H - - -// APIEXTRACTOR_API is used for the public API symbols. -#if defined _WIN32 - #define APIEXTRACTOR_DEPRECATED(func) __declspec(deprecated) func -#elif __GNUC__ >= 4 - #define APIEXTRACTOR_DEPRECATED(func) func __attribute__ ((deprecated)) -#else - #define APIEXTRACTOR_DEPRECATED(func) func -#endif -#endif diff --git a/ApiExtractor/clangparser/clangbuilder.cpp b/ApiExtractor/clangparser/clangbuilder.cpp deleted file mode 100644 index dc0c59dd5..000000000 --- a/ApiExtractor/clangparser/clangbuilder.cpp +++ /dev/null @@ -1,770 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "clangbuilder.h" -#include "compilersupport.h" -#include "clangutils.h" - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#if QT_VERSION < 0x050800 -# define Q_FALLTHROUGH() (void)0 -#endif - -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 - || c.kind == CXCursor_ClassTemplate - || c.kind == CXCursor_ClassTemplatePartialSpecialization; -} - -static inline bool withinClassDeclaration(const CXCursor &cursor) -{ - return isClassCursor(clang_getCursorLexicalParent(cursor)); -} - -static QString fixTypeName(QString t) -{ - // Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**" - int pos = t.size() - 1; - for (; pos >= 0 && (t.at(pos) == QLatin1Char('&') || t.at(pos) == QLatin1Char('*')); --pos) {} - if (pos > 0 && t.at(pos) == QLatin1Char(' ')) - t.remove(pos, 1); - return t; -} - -// Insert template parameter to class name: "Foo<>" -> "Foo" -> "Foo" -// This needs to be done immediately when template parameters are encountered since -// the class name "Foo" is the scope for nested items. -static bool insertTemplateParameterIntoClassName(const QString &parmName, QString *name) -{ - if (Q_UNLIKELY(!name->endsWith(QLatin1Char('>')))) - return false; - const bool needsComma = name->at(name->size() - 2) != QLatin1Char('<'); - const int insertionPos = name->size() - 1; - name->insert(insertionPos, parmName); - if (needsComma) - name->insert(insertionPos, QLatin1Char(',')); - return true; -} - -static inline bool insertTemplateParameterIntoClassName(const QString &parmName, - const ClassModelItem &item) -{ - QString name = item->name(); - const bool result = insertTemplateParameterIntoClassName(parmName, &name); - item->setName(name); - return result; -} - -static inline CodeModel::AccessPolicy accessPolicy(CX_CXXAccessSpecifier access) -{ - CodeModel::AccessPolicy result = CodeModel::Public; - switch (access) { - case CX_CXXProtected: - result = CodeModel::Protected; - break; - case CX_CXXPrivate: - result = CodeModel::Private; - break; - default: - break; - } - return result; -} - -static void setFileName(const CXCursor &cursor, _CodeModelItem *item) -{ - const SourceRange range = getCursorRange(cursor); - if (!range.first.file.isEmpty()) { // Has been observed to be 0 for invalid locations - item->setFileName(QDir::cleanPath(range.first.file)); - item->setStartPosition(int(range.first.line), int(range.first.column)); - item->setEndPosition(int(range.second.line), int(range.second.column)); - } -} - -class BuilderPrivate { -public: - typedef QHash CursorClassHash; - typedef QHash CursorTypedefHash; - - explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel) - { - m_scopeStack.push(NamespaceModelItem(new _FileModelItem(m_model))); - } - - // Determine scope from top item. Note that the scope list does not necessarily - // match the scope stack in case of forward-declared inner classes whose definition - // appears in the translation unit while the scope is the outer class. - void updateScope() - { - if (m_scopeStack.size() <= 1) - m_scope.clear(); - else - m_scope = m_scopeStack.back()->scope() << m_scopeStack.back()->name(); - } - - void pushScope(const ScopeModelItem &i) - { - m_scopeStack.push(i); - updateScope(); - } - - void popScope() - { - m_scopeStack.pop(); - updateScope(); - } - - bool addClass(const CXCursor &cursor, CodeModel::ClassType t); - FunctionModelItem createFunction(const CXCursor &cursor, - CodeModel::FunctionType t = CodeModel::Normal) const; - FunctionModelItem createMemberFunction(const CXCursor &cursor, - CodeModel::FunctionType t = CodeModel::Normal) const; - void qualifyConstructor(const CXCursor &cursor); - TypeInfo createTypeInfo(const CXType &type) const; - TypeInfo createTypeInfo(const CXCursor &cursor) const - { return createTypeInfo(clang_getCursorType(cursor)); } - - TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const; - TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const; - void addField(const CXCursor &cursor); - - QString cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const; - void addBaseClass(const CXCursor &cursor); - - template - void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer &item) const; - - BaseVisitor *m_baseVisitor; - CodeModel *m_model; - - QStack m_scopeStack; - QStringList m_scope; - // Store all classes by cursor so that base classes can be found and inner - // classes can be correctly parented in case of forward-declared inner classes - // (QMetaObject::Connection) - CursorClassHash m_cursorClassHash; - CursorTypedefHash m_cursorTypedefHash; - - ClassModelItem m_currentClass; - EnumModelItem m_currentEnum; - FunctionModelItem m_currentFunction; - ArgumentModelItem m_currentArgument; - VariableModelItem m_currentField; - - int m_anonymousEnumCount = 0; - CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; -}; - -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()); - 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: - // class QMetaObject { class Connection; } - // class QMetaObject::Connection {} - const CXCursor semPar = clang_getCursorSemanticParent(cursor); - if (isClassCursor(semPar)) { - const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(semPar); - if (it == m_cursorClassHash.constEnd()) { - const QString message = QStringLiteral("Unable to find parent of inner class ") + className; - const Diagnostic d(message, cursor, CXDiagnostic_Error); - qWarning() << d; - m_baseVisitor->appendDiagnostic(d); - return false; - } - const ClassModelItem &containingClass = it.value(); - containingClass->addClass(m_currentClass); - m_currentClass->setScope(containingClass->scope() << containingClass->name()); - } else { - m_currentClass->setScope(m_scope); - m_scopeStack.back()->addClass(m_currentClass); - } - pushScope(m_currentClass); - m_cursorClassHash.insert(cursor, m_currentClass); - return true; -} - -FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, - CodeModel::FunctionType t) const -{ - QString name = getCursorSpelling(cursor); - // Apply type fixes to "operator X &" -> "operator X&" - if (name.startsWith(QLatin1String("operator "))) - name = fixTypeName(name); - FunctionModelItem result(new _FunctionModelItem(m_model, name)); - setFileName(cursor, result.data()); - result->setType(createTypeInfo(clang_getCursorResultType(cursor))); - result->setFunctionType(t); - result->setScope(m_scope); - result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); - return result; -} - -FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor, - CodeModel::FunctionType t) const -{ - FunctionModelItem result = createFunction(cursor, t); - 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->setFunctionType(m_currentFunctionType); - return result; -} - -// For CXCursor_Constructor, on endToken(). -void BuilderPrivate::qualifyConstructor(const CXCursor &cursor) -{ - // Clang does not tell us whether a constructor is explicit, preventing it - // from being used for implicit conversions. Try to guess whether a - // constructor is explicit in the C++99 sense (1 parameter) by checking for - // isConvertingConstructor() == 0. Fixme: The notion of "isConvertingConstructor" - // should be used in the code model instead of "explicit" - if (clang_CXXConstructor_isDefaultConstructor(cursor) == 0 - && m_currentFunction->arguments().size() == 1 - && clang_CXXConstructor_isCopyConstructor(cursor) == 0 - && clang_CXXConstructor_isMoveConstructor(cursor) == 0) { - m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0); - } -} - -TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const -{ - return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor))); -} - -TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const -{ - TemplateParameterModelItem result = createTemplateParameter(cursor); - result->setType(createTypeInfo(cursor)); - return result; -} - -// CXCursor_VarDecl, CXCursor_FieldDecl cursors -void BuilderPrivate::addField(const CXCursor &cursor) -{ - VariableModelItem field(new _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); - m_currentField = field; - m_scopeStack.back()->addVariable(field); -} - -// Array helpers: Parse "a[2][4]" into a list of dimensions - -struct ArrayDimensionResult -{ - QVector dimensions; - int position; -}; - -static ArrayDimensionResult arrayDimensions(const QString &typeName) -{ - ArrayDimensionResult result; - result.position = typeName.indexOf(QLatin1Char('[')); - for (int openingPos = result.position; openingPos != -1; ) { - const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1); - if (closingPos == -1) - break; - result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1)); - openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1); - } - return result; -} - -// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none -static QStringList parseArrayArgs(const CXType &type, QString *typeName) -{ - const ArrayDimensionResult dimensions = arrayDimensions(*typeName); - Q_ASSERT(!dimensions.dimensions.isEmpty()); - - QStringList result; - // get first dimension from clang, preferably. - // "a[]" is seen as pointer by Clang, set special indicator "" - const long long size = clang_getArraySize(type); - result.append(size >= 0 ? QString::number(size) : QString()); - // Parse out remaining dimensions - for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i) - result.append(dimensions.dimensions.at(i).toString()); - typeName->truncate(dimensions.position); - return result; -} - -TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const -{ - if (type.kind == CXType_Pointer) { // Check for function pointers, first. - const CXType pointeeType = clang_getPointeeType(type); - const int argCount = clang_getNumArgTypes(pointeeType); - if (argCount >= 0) { - TypeInfo result = createTypeInfo(clang_getResultType(pointeeType)); - result.setFunctionPointer(true); - for (int a = 0; a < argCount; ++a) - result.addArgument(createTypeInfo(clang_getArgType(pointeeType, unsigned(a)))); - return result; - } - } - - TypeInfo typeInfo; - QString typeName = fixTypeName(getTypeName(type)); - - int indirections = 0; - // "int **" - for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections) - typeName.chop(1); - typeInfo.setIndirections(indirections); - // "int &&" - if (typeName.endsWith(QLatin1String("&&"))) { - typeName.chop(2); - typeInfo.setReferenceType(RValueReference); - } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &" - typeName.chop(1); - typeInfo.setReferenceType(LValueReference); - } - - // "int [3], int[]" - if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray - || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) { - typeInfo.setArrayElements(parseArrayArgs(type, &typeName)); - } - - bool isConstant = clang_isConstQualifiedType(type) != 0; - // A "char *const" parameter, is considered to be const-qualified by Clang, but - // not in the TypeInfo sense (corresponds to "char *" and not "const char *"). - if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) { - typeName.chop(5); - typeName = typeName.trimmed(); - isConstant = false; - } - // Clang has been observed to return false for "const int .." - if (!isConstant && typeName.startsWith(QLatin1String("const "))) { - typeName.remove(0, 6); - isConstant = true; - } - typeInfo.setConstant(isConstant); - - // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *" - if (typeName.startsWith(QLatin1String("volatile "))) { - typeName.remove(0, 9); - typeInfo.setVolatile(true); - } - - typeName = typeName.trimmed(); - - typeInfo.setQualifiedName(typeName.split(colonColon())); - // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types? - return typeInfo; -} - -// extract an expression from the cursor via source -// CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2) -QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const -{ - BaseVisitor::CodeSnippet snippet = bv->getCodeSnippet(cursor); - const char *equalSign = std::find(snippet.first, snippet.second, '='); - if (equalSign == snippet.second) - return QString(); - ++equalSign; - return QString::fromLocal8Bit(equalSign, int(snippet.second - equalSign)).trimmed(); -} - -// Add a base class to the current class from CXCursor_CXXBaseSpecifier -void BuilderPrivate::addBaseClass(const CXCursor &cursor) -{ - const CXType inheritedType = clang_getCursorType(cursor); // Note spelling has "struct baseClass", - QString baseClassName = getTypeName(inheritedType); // use type. - const CXCursor declCursor = clang_getTypeDeclaration(inheritedType); - const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor); - if (it == m_cursorClassHash.constEnd()) { - // Set unqualified name. This happens in cases like "class X : public std::list<...>" - // "template class Foo : public T" and standard types like true_type, false_type. - m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); - return; - } - // Completely qualify the class name by looking it up and taking its scope - // plus the actual baseClass stripped off any scopes. Consider: - // namespace std { - // template class vector {}; - // namespace n { - // class Foo : public vector {}; - // } - // } - // should have "std::vector" as base class (whereas the type of the base class is - // "std::vector"). - const QStringList &baseScope = it.value()->scope(); - if (!baseScope.isEmpty()) { - const int lastSep = baseClassName.lastIndexOf(colonColon()); - if (lastSep >= 0) - baseClassName.remove(0, lastSep + colonColon().size()); - baseClassName.prepend(colonColon()); - baseClassName.prepend(baseScope.join(colonColon())); - } - m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); -} - -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 ConversionFlags; -// class QTextCodec { -// enum ConversionFlag {}; -// typedef QFlags ConversionFlags; -// struct ConverterState { -// explicit ConverterState(ConversionFlags); -// ^^ qualify to QTextCodec::ConversionFlags -// ConversionFlags m_flags; -// ^^ ditto - -template // ArgumentModelItem, VariableModelItem -void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer &item) const -{ - typedef typename CursorTypedefHash::const_iterator ConstIt; - - TypeInfo type = item->type(); - if (type.qualifiedName().size() == 1) { // item's type is unqualified. - const ConstIt 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); - } - } -} - -Builder::Builder() -{ - d = new BuilderPrivate(this); -} - -Builder::~Builder() -{ - delete d; -} - -bool Builder::visitLocation(const CXSourceLocation &location) const -{ - return !clang_Location_isInSystemHeader(location); -} - -FileModelItem Builder::dom() const -{ - Q_ASSERT(!d->m_scopeStack.isEmpty()); - return qSharedPointerDynamicCast<_FileModelItem>(d->m_scopeStack.constFirst()); -} - -static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope) -{ - return getCursorKindName(cursor.kind) + QLatin1Char(' ') - + getCursorSpelling(cursor) + QLatin1String(" encountered outside ") - + QLatin1String(expectedScope) + QLatin1Char('.'); -} - -static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) -{ - CodeModel::ClassType result = CodeModel::Class; - if (kind == CXCursor_UnionDecl) - result = CodeModel::Union; - else if (kind == CXCursor_StructDecl) - result = CodeModel::Struct; - return result; -} - -BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) -{ - switch (cursor.kind) { - case CXCursor_CXXAccessSpecifier: - d->m_currentFunctionType = CodeModel::Normal; - break; - case CXCursor_AnnotateAttr: { - const QString annotation = getCursorSpelling(cursor); - if (annotation == QLatin1String("qt_slot")) - d->m_currentFunctionType = CodeModel::Slot; - else if (annotation == QLatin1String("qt_signal")) - d->m_currentFunctionType = CodeModel::Signal; - else - d->m_currentFunctionType = CodeModel::Normal; - } - break; - case CXCursor_CXXBaseSpecifier: - if (d->m_currentClass.isNull()) { - const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error); - qWarning() << d; - appendDiagnostic(d); - return Error; - } - d->addBaseClass(cursor); - break; - case CXCursor_ClassDecl: - case CXCursor_UnionDecl: - case CXCursor_StructDecl: - if (clang_isCursorDefinition(cursor) == 0) - return Skip; - if (!d->addClass(cursor, codeModelClassTypeFromCursor(cursor.kind))) - return Error; - break; - case CXCursor_ClassTemplate: - case CXCursor_ClassTemplatePartialSpecialization: - if (clang_isCursorDefinition(cursor) == 0) - return Skip; - d->addClass(cursor, CodeModel::Class); - d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); - d->m_scope.back() += templateBrackets(); - break; - case CXCursor_EnumDecl: { - QString name = getCursorSpelling(cursor); - const bool anonymous = name.isEmpty(); - if (anonymous) - name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); - d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); - setFileName(cursor, d->m_currentEnum.data()); - d->m_currentEnum->setScope(d->m_scope); - d->m_currentEnum->setAnonymous(anonymous); - if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) - d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); - d->m_scopeStack.back()->addEnum(d->m_currentEnum); - } - break; - case CXCursor_EnumConstantDecl: { - const QString name = getCursorSpelling(cursor); - if (d->m_currentEnum.isNull()) { - const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error); - qWarning() << d; - appendDiagnostic(d); - return Error; - } - EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); - enumConstant->setValue(d->cursorValueExpression(this, cursor)); - d->m_currentEnum->addEnumerator(enumConstant); - } - break; - case CXCursor_VarDecl: - // static class members are seen as CXCursor_VarDecl - if (!d->m_currentClass.isNull() && isClassCursor(clang_getCursorSemanticParent(cursor))) { - d->addField(cursor); - d->m_currentField->setStatic(true); - } - break; - case CXCursor_FieldDecl: - d->addField(cursor); - break; -#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 37 // Clang 4.0 - case CXCursor_FriendDecl: - return Skip; -#endif - case CXCursor_Constructor: - case CXCursor_Destructor: // Note: Also use clang_CXXConstructor_is..Constructor? - case CXCursor_CXXMethod: - case CXCursor_ConversionFunction: - // Skip inline member functions outside class, only go by declarations inside class - if (!withinClassDeclaration(cursor)) - return Skip; - d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal); - d->m_scopeStack.back()->addFunction(d->m_currentFunction); - break; - // Not fully supported, currently, seen as normal function - // Note: May appear inside class (member template) or outside (free template). - case CXCursor_FunctionTemplate: { - const CXCursor semParent = clang_getCursorSemanticParent(cursor); - if (isClassCursor(semParent)) { - if (semParent == clang_getCursorLexicalParent(cursor)) { - d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal); - d->m_scopeStack.back()->addFunction(d->m_currentFunction); - break; - } else { - return Skip; // inline member functions outside class - } - } - } - Q_FALLTHROUGH(); // fall through to free template function. - case CXCursor_FunctionDecl: - d->m_currentFunction = d->createFunction(cursor); - d->m_scopeStack.back()->addFunction(d->m_currentFunction); - break; - case CXCursor_Namespace: { - const QString name = getCursorSpelling(cursor); - const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); - if (parentNamespaceItem.isNull()) { - const QString message = msgOutOfOrder(cursor, "namespace") - + QLatin1String(" (current scope: ") + d->m_scopeStack.back()->name() + QLatin1Char(')'); - const Diagnostic d(message, cursor, CXDiagnostic_Error); - qWarning() << d; - appendDiagnostic(d); - return Error; - } - // If possible, continue existing namespace (as otherwise, all headers - // where a namespace is continued show up in the type database). - NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name); - if (namespaceItem.isNull()) { - namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); - setFileName(cursor, namespaceItem.data()); - namespaceItem->setScope(d->m_scope); - parentNamespaceItem->addNamespace(namespaceItem); - } - d->pushScope(namespaceItem); - } - break; - 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()) { - const QString name = getCursorSpelling(cursor); - d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name)); - d->m_currentArgument->setType(d->createTypeInfo(cursor)); - d->m_currentFunction->addArgument(d->m_currentArgument); - QString defaultValueExpression = d->cursorValueExpression(this, cursor); - if (!defaultValueExpression.isEmpty()) { - d->m_currentArgument->setDefaultValueExpression(defaultValueExpression); - d->m_currentArgument->setDefaultValue(true); - } - } else { - return Skip; - } - break; - case CXCursor_TemplateTypeParameter: - case CXCursor_NonTypeTemplateParameter: { - const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter - ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor); - // Apply to function/member template? - if (!d->m_currentFunction.isNull()) { - d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); - } else if (!d->m_currentClass.isNull()) { // 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 Diagnostic d(message, cursor, CXDiagnostic_Error); - qWarning() << d; - appendDiagnostic(d); - return Error; - } - d->m_currentClass->setTemplateParameters(d->m_currentClass->templateParameters() << tItem); - } - } - break; - case CXCursor_TypeAliasDecl: - case CXCursor_TypeAliasTemplateDecl: // May contain nested CXCursor_TemplateTypeParameter - return Skip; - case CXCursor_TypedefDecl: { - const QString name = getCursorSpelling(cursor); - TypeDefModelItem item(new _TypeDefModelItem(d->m_model, name)); - setFileName(cursor, item.data()); - item->setType(d->createTypeInfo(clang_getTypedefDeclUnderlyingType(cursor))); - item->setScope(d->m_scope); - d->m_scopeStack.back()->addTypeDef(item); - d->m_cursorTypedefHash.insert(cursor, item); - } - 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); - } - break; - default: - break; - } - return BaseVisitor::Recurse; -} - -bool Builder::endToken(const CXCursor &cursor) -{ - switch (cursor.kind) { - case CXCursor_UnionDecl: - case CXCursor_ClassDecl: - case CXCursor_StructDecl: - case CXCursor_ClassTemplate: - case CXCursor_ClassTemplatePartialSpecialization: - d->popScope(); - // Continue in outer class after leaving inner class? - if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back())) - d->m_currentClass = lastClass; - else - d->m_currentClass.clear(); - d->m_currentFunctionType = CodeModel::Normal; - break; - case CXCursor_EnumDecl: - d->m_currentEnum.clear(); - break; - case CXCursor_VarDecl: - case CXCursor_FieldDecl: - d->m_currentField.clear(); - break; - case CXCursor_Constructor: - d->qualifyConstructor(cursor); - d->m_currentFunction.clear(); - break; - case CXCursor_Destructor: - case CXCursor_CXXMethod: - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - d->m_currentFunction.clear(); - break; - case CXCursor_Namespace: - d->popScope(); - break; - case CXCursor_ParmDecl: - d->m_currentArgument.clear(); - break; - default: - break; - } - return true; -} - -} // namespace clang diff --git a/ApiExtractor/clangparser/clangbuilder.h b/ApiExtractor/clangparser/clangbuilder.h deleted file mode 100644 index c97b7d2b7..000000000 --- a/ApiExtractor/clangparser/clangbuilder.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CLANGBUILDER_H -#define CLANGBUILDER_H - -#include "clangparser.h" - -#include - -namespace clang { - -class BuilderPrivate; - -class Builder : public BaseVisitor { -public: - Builder(); - ~Builder(); - - bool visitLocation(const CXSourceLocation &location) const override; - - StartTokenResult startToken(const CXCursor &cursor) override; - bool endToken(const CXCursor &cursor) override; - - FileModelItem dom() const; - -private: - BuilderPrivate *d; -}; - -} // namespace clang - -#endif // CLANGBUILDER_H diff --git a/ApiExtractor/clangparser/clangdebugutils.cpp b/ApiExtractor/clangparser/clangdebugutils.cpp deleted file mode 100644 index 8d0fd098a..000000000 --- a/ApiExtractor/clangparser/clangdebugutils.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "clangdebugutils.h" -#include "clangutils.h" - -#include -#include - -#include - -#ifndef QT_NO_DEBUG_STREAM - -#ifdef Q_OS_WIN -const char pathSep = '\\'; -#else -const char pathSep = '/'; -#endif - -static const char *baseName(const char *fileName) -{ - const char *b = strrchr(fileName, pathSep); - return b ? b + 1 : fileName; -} - -QDebug operator<<(QDebug s, const CXString &cs) -{ - s << clang_getCString(cs); - return s; -} - -QDebug operator<<(QDebug s, CXCursorKind cursorKind) // Enum -{ - const CXString kindName = clang_getCursorKindSpelling(cursorKind); - s << kindName; - clang_disposeString(kindName); - return s; -} - -static const char *accessSpecsStrings[] -{ - // CX_CXXInvalidAccessSpecifier, CX_CXXPublic, CX_CXXProtected, CX_CXXPrivate - "invalid", "public", "protected", "private" -}; - -QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac) -{ - s << accessSpecsStrings[ac]; - return s; -} - -QDebug operator<<(QDebug s, const CXType &t) -{ - CXString typeSpelling = clang_getTypeSpelling(t); - s << typeSpelling; - clang_disposeString(typeSpelling); - return s; -} - -QDebug operator<<(QDebug s, const CXCursor &cursor) -{ - QDebugStateSaver saver(s); - s.nospace(); - s.noquote(); - const CXCursorKind kind = clang_getCursorKind(cursor); - s << kind; - if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) - return s; - const CXType type = clang_getCursorType(cursor); - switch (kind) { - case CXCursor_CXXAccessSpecifier: - s << ' ' << clang_getCXXAccessSpecifier(cursor); - break; - case CXCursor_CXXBaseSpecifier: - s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; - break; - case CXCursor_CXXMethod: - case CXCursor_FunctionDecl: - case CXCursor_ConversionFunction: - s << ", result type=\"" << clang_getCursorResultType(cursor) << '"'; - break; - case CXCursor_TypedefDecl: - s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"'; - break; - default: - break; - } - - if (type.kind != CXType_Invalid) - s << ", type=\"" << type << '"'; - if (clang_Cursor_hasAttrs(cursor)) - s << ", [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; -} - -QDebug operator<<(QDebug s, const CXSourceLocation &location) -{ - QDebugStateSaver saver(s); - s.nospace(); - CXFile file; // void * - unsigned line; - unsigned column; - unsigned offset; - clang_getExpansionLocation(location, &file, &line, &column, &offset); - const CXString cxFileName = clang_getFileName(file); - // Has been observed to be 0 for invalid locations - if (const char *cFileName = clang_getCString(cxFileName)) - s << baseName(cFileName) << ':'; - s << line << ':' << column; - clang_disposeString(cxFileName); - return s; -} - -#endif // !QT_NO_DEBUG_STREAM diff --git a/ApiExtractor/clangparser/clangdebugutils.h b/ApiExtractor/clangparser/clangdebugutils.h deleted file mode 100644 index 323efdd2a..000000000 --- a/ApiExtractor/clangparser/clangdebugutils.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CLANGDEBUGUTILS_H -#define CLANGDEBUGUTILS_H - -#include - -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) -QT_FORWARD_DECLARE_CLASS(QString) - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug s, const CXString &cs); -QDebug operator<<(QDebug s, CXCursorKind cursorKind); -QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac); -QDebug operator<<(QDebug s, const CXType &t); -QDebug operator<<(QDebug s, const CXCursor &cursor); -QDebug operator<<(QDebug s, const CXSourceLocation &location); -#endif // !QT_NO_DEBUG_STREAM - -#endif // CLANGDEBUGUTILS_H diff --git a/ApiExtractor/clangparser/clangparser.cpp b/ApiExtractor/clangparser/clangparser.cpp deleted file mode 100644 index eb3be115c..000000000 --- a/ApiExtractor/clangparser/clangparser.cpp +++ /dev/null @@ -1,266 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "clangparser.h" -#include "clangutils.h" -#include "clangdebugutils.h" -#include "compilersupport.h" - -#include -#include -#include -#include -#include -#include - -namespace clang { - -SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor) -{ - Snippet result(nullptr, nullptr); - const SourceRange range = getCursorRange(cursor); - if (range.first.file.isEmpty() || range.second.file != range.first.file) - return result; - FileBufferCache::Iterator it = m_fileBufferCache.find(range.first.file); - if (it == m_fileBufferCache.end()) { - QFile file(range.first.file); - if (!file.open(QIODevice::ReadOnly)) { - qWarning().noquote().nospace() - << "Can't open " << QDir::toNativeSeparators(range.first.file) - << ": " << file.errorString(); - return result; - } - it = m_fileBufferCache.insert(range.first.file, file.readAll()); - } - - const unsigned pos = range.first.offset; - const unsigned end = range.second.offset; - const QByteArray &contents = it.value(); - if (end >= unsigned(contents.size())) { - qWarning().noquote().nospace() << "Range end " << end << " is above size of " - << range.first.file << " (" << contents.size() << ')'; - return result; - } - result.first = contents.constData() + pos; - result.second = contents.constData() + end; - return result; -} - -BaseVisitor::BaseVisitor() = default; -BaseVisitor::~BaseVisitor() = default; - -bool BaseVisitor::visitLocation(const CXSourceLocation &location) const -{ - return clang_Location_isFromMainFile(location) != 0; -} - -BaseVisitor::StartTokenResult BaseVisitor::cbHandleStartToken(const CXCursor &cursor) -{ - switch (cursor.kind) { - default: - break; - } - - return startToken(cursor); -} - -bool BaseVisitor::cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult) -{ - const bool result = startResult != Recurse || endToken(cursor); - switch (cursor.kind) { - default: - break; - } - - return result; -} - -BaseVisitor::CodeSnippet BaseVisitor::getCodeSnippet(const CXCursor &cursor) -{ - CodeSnippet result = m_fileCache.getCodeSnippet(cursor); - if (result.first == nullptr) - appendDiagnostic(Diagnostic(QStringLiteral("Unable to retrieve code snippet."), cursor, CXDiagnostic_Error)); - return result; -} - -QString BaseVisitor::getCodeSnippetString(const CXCursor &cursor) -{ - CodeSnippet result = m_fileCache.getCodeSnippet(cursor); - return result.first != nullptr - ? QString::fromUtf8(result.first, int(result.second - result.first)) - : QString(); -} - -static CXChildVisitResult - visitorCallback(CXCursor cursor, CXCursor /* parent */, CXClientData clientData) -{ - BaseVisitor *bv = reinterpret_cast(clientData); - - const CXSourceLocation location = clang_getCursorLocation(cursor); - if (!bv->visitLocation(location)) - return CXChildVisit_Continue; - - const BaseVisitor::StartTokenResult startResult = bv->cbHandleStartToken(cursor); - switch (startResult) { - case clang::BaseVisitor::Error: - return CXChildVisit_Break; - case clang::BaseVisitor::Skip: - break; - case clang::BaseVisitor::Recurse: - clang_visitChildren(cursor, visitorCallback, clientData); - break; - } - - if (!bv->cbHandleEndToken(cursor, startResult)) - return CXChildVisit_Break; - - return CXChildVisit_Continue; -} - -BaseVisitor::Diagnostics BaseVisitor::diagnostics() const -{ - return m_diagnostics; -} - -void BaseVisitor::setDiagnostics(const Diagnostics &d) -{ - m_diagnostics = d; -} - -void BaseVisitor::appendDiagnostic(const Diagnostic &d) -{ - m_diagnostics.append(d); -} - -static inline const char **byteArrayListToFlatArgV(const QByteArrayList &bl) -{ - const char **result = new const char *[bl.size() + 1]; - result[bl.size()] = nullptr; - std::transform(bl.cbegin(), bl.cend(), result, - [] (const QByteArray &a) { return a.constData(); }); - return result; -} - -static QByteArray msgCreateTranslationUnit(const QByteArrayList clangArgs, unsigned flags) -{ - QByteArray result = "clang_parseTranslationUnit2(0x"; - result += QByteArray::number(flags, 16); - const int count = clangArgs.size(); - result += ", cmd[" + QByteArray::number(count) + "]="; - for (int i = 0; i < count; ++i) { - const QByteArray &arg = clangArgs.at(i); - if (i) - result += ' '; - const bool quote = arg.contains(' ') || arg.contains('('); - if (quote) - result += '"'; - result += arg; - if (quote) - result += '"'; - } - result += ')'; - return result; -} - -static CXTranslationUnit createTranslationUnit(CXIndex index, - const QByteArrayList &args, - unsigned flags = 0) -{ - // courtesy qdoc - const unsigned defaultFlags = CXTranslationUnit_SkipFunctionBodies - | CXTranslationUnit_Incomplete; - - static const QByteArrayList defaultArgs = { - "-std=c++14", // ! otherwise, t.h is parsed as "C" - "-fPIC", - "-fno-exceptions", // Workaround for clang bug http://reviews.llvm.org/D17988 -#ifdef Q_OS_MACOS - "-Wno-expansion-to-defined", // Workaround for warnings in Darwin stdlib, see - // https://github.com/darlinghq/darling/issues/204 -#endif - "-Wno-constant-logical-operand" - }; - - const QByteArrayList clangArgs = emulatedCompilerOptions() + defaultArgs + args; - QScopedArrayPointer argv(byteArrayListToFlatArgV(clangArgs)); - qDebug().noquote().nospace() << msgCreateTranslationUnit(clangArgs, flags); - - CXTranslationUnit tu; - CXErrorCode err = clang_parseTranslationUnit2(index, nullptr, argv.data(), - clangArgs.size(), nullptr, 0, - defaultFlags | flags, &tu); - if (err || !tu) { - qWarning().noquote().nospace() << "Could not parse " - << clangArgs.constLast().constData() << ", error code: " << err; - return nullptr; - } - return tu; -} - -/* clangFlags are flags to clang_parseTranslationUnit2() such as - * CXTranslationUnit_KeepGoing (from CINDEX_VERSION_MAJOR/CINDEX_VERSION_MINOR 0.35) - */ - -bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &bv) -{ - CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */, - 1 /* displayDiagnostics */); - if (!index) { - qWarning() << "clang_createIndex() failed!"; - return false; - } - - CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, clangFlags); - if (!translationUnit) - return false; - - CXCursor rootCursor = clang_getTranslationUnitCursor(translationUnit); - - clang_visitChildren(rootCursor, visitorCallback, reinterpret_cast(&bv)); - - QVector diagnostics = getDiagnostics(translationUnit); - diagnostics.append(bv.diagnostics()); - bv.setDiagnostics(diagnostics); - - const bool ok = maxSeverity(diagnostics) < CXDiagnostic_Error; - if (!ok) { - QDebug debug = qWarning(); - debug.noquote(); - debug.nospace(); - debug << "Errors in " - << QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n"; - for (const Diagnostic &diagnostic : diagnostics) - debug << diagnostic << '\n'; - } - - clang_disposeTranslationUnit(translationUnit); - clang_disposeIndex(index); - return ok; -} - -} // namespace clang diff --git a/ApiExtractor/clangparser/clangparser.h b/ApiExtractor/clangparser/clangparser.h deleted file mode 100644 index ef1424f17..000000000 --- a/ApiExtractor/clangparser/clangparser.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CLANGPARSER_H -#define CLANGPARSER_H - -#include - -#include -#include -#include -#include -#include - -namespace clang { - -struct Diagnostic; - -class SourceFileCache { -public: - typedef QPair Snippet; - - Snippet getCodeSnippet(const CXCursor &cursor); - -private: - typedef QHash FileBufferCache; - - FileBufferCache m_fileBufferCache; -}; - -class BaseVisitor { - Q_DISABLE_COPY(BaseVisitor) -public: - typedef QVector Diagnostics; - typedef SourceFileCache::Snippet CodeSnippet; - - enum StartTokenResult { Error, Skip, Recurse }; - - BaseVisitor(); - virtual ~BaseVisitor(); - - // Whether location should be visited. - // defaults to clang_Location_isFromMainFile() - virtual bool visitLocation(const CXSourceLocation &location) const; - - virtual StartTokenResult startToken(const CXCursor &cursor) = 0; - virtual bool endToken(const CXCursor &cursor) = 0; - - StartTokenResult cbHandleStartToken(const CXCursor &cursor); - bool cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult); - - CodeSnippet getCodeSnippet(const CXCursor &cursor); - QString getCodeSnippetString(const CXCursor &cursor); - - Diagnostics diagnostics() const; - void setDiagnostics(const Diagnostics &d); - void appendDiagnostic(const Diagnostic &d); - -private: - SourceFileCache m_fileCache; - Diagnostics m_diagnostics; -}; - -bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &ctx); - -} // namespace clang - -#endif // !CLANGPARSER_H diff --git a/ApiExtractor/clangparser/clangutils.cpp b/ApiExtractor/clangparser/clangutils.cpp deleted file mode 100644 index fdc8d3312..000000000 --- a/ApiExtractor/clangparser/clangutils.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "clangutils.h" - -#include -#include -#include -#include - -bool operator==(const CXCursor &c1, const CXCursor &c2) -{ - return c1.kind == c2.kind - && c1.xdata == c2.xdata - && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); -} - -uint qHash(const CXCursor &c, uint seed) -{ - return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) - ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; -} - -namespace clang { - -SourceLocation getExpansionLocation(const CXSourceLocation &location) -{ - SourceLocation result; - CXFile file; // void * - clang_getExpansionLocation(location, &file, &result.line, &result.column, &result.offset); - const CXString cxFileName = clang_getFileName(file); - // Has been observed to be 0 for invalid locations - if (const char *cFileName = clang_getCString(cxFileName)) - result.file = QString::fromUtf8(cFileName); - clang_disposeString(cxFileName); - return result; -} - -SourceLocation getCursorLocation(const CXCursor &cursor) -{ - const CXSourceRange extent = clang_getCursorExtent(cursor); - return getExpansionLocation(clang_getRangeStart(extent)); -} - -CXString getFileNameFromLocation(const CXSourceLocation &location) -{ - CXFile file; - unsigned line; - unsigned column; - unsigned offset; - clang_getExpansionLocation(location, &file, &line, &column, &offset); - return clang_getFileName(file); -} - -SourceRange getCursorRange(const CXCursor &cursor) -{ - const CXSourceRange extent = clang_getCursorExtent(cursor); - return qMakePair(getExpansionLocation(clang_getRangeStart(extent)), - getExpansionLocation(clang_getRangeEnd(extent))); -} - -QString getCursorKindName(CXCursorKind cursorKind) -{ - CXString kindName = clang_getCursorKindSpelling(cursorKind); - const QString result = QString::fromUtf8(clang_getCString(kindName)); - clang_disposeString(kindName); - return result; -} - -QString getCursorSpelling(const CXCursor &cursor) -{ - CXString cursorSpelling = clang_getCursorSpelling(cursor); - const QString result = QString::fromUtf8(clang_getCString(cursorSpelling)); - clang_disposeString(cursorSpelling); - return result; -} - -QString getCursorDisplayName(const CXCursor &cursor) -{ - CXString displayName = clang_getCursorDisplayName(cursor); - const QString result = QString::fromUtf8(clang_getCString(displayName)); - clang_disposeString(displayName); - return result; -} - -QString getTypeName(const CXType &type) -{ - CXString typeSpelling = clang_getTypeSpelling(type); - const QString result = QString::fromUtf8(clang_getCString(typeSpelling)); - clang_disposeString(typeSpelling); - return result; -} - -Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s) - : message(m), location(getCursorLocation(c)), source(Other), severity(s) -{ -} - -Diagnostic Diagnostic::fromCXDiagnostic(CXDiagnostic cd) -{ - Diagnostic result; - result.source = Clang; - CXString spelling = clang_getDiagnosticSpelling(cd); - result.message = QString::fromUtf8(clang_getCString(spelling)); - clang_disposeString(spelling); - result.severity = clang_getDiagnosticSeverity(cd); - result.location = getExpansionLocation(clang_getDiagnosticLocation(cd)); - - CXDiagnosticSet childDiagnostics = clang_getChildDiagnostics(cd); - if (const unsigned childCount = clang_getNumDiagnosticsInSet(childDiagnostics)) { - result.childMessages.reserve(int(childCount)); - const unsigned format = clang_defaultDiagnosticDisplayOptions(); - for (unsigned i = 0; i < childCount; ++i) { - CXDiagnostic childDiagnostic = clang_getDiagnosticInSet(childDiagnostics, i); - CXString cdm = clang_formatDiagnostic(childDiagnostic, format); - result.childMessages.append(QString::fromUtf8(clang_getCString(cdm))); - clang_disposeString(cdm); - clang_disposeDiagnostic(childDiagnostic); - } - } - - return result; -} - -QVector getDiagnostics(CXTranslationUnit tu) -{ - QVector result; - const unsigned count = clang_getNumDiagnostics(tu); - result.reserve(int(count)); - for (unsigned i = 0; i < count; ++i) { - const CXDiagnostic d = clang_getDiagnostic(tu, i); - result.append(Diagnostic::fromCXDiagnostic(d)); - clang_disposeDiagnostic(d); - } - return result; -} - -CXDiagnosticSeverity maxSeverity(const QVector &ds) -{ - CXDiagnosticSeverity result = CXDiagnostic_Ignored; - for (const Diagnostic d : ds) { - if (d.severity > result) - result = d.severity; - } - return result; -} - -#ifndef QT_NO_DEBUG_STREAM - -QDebug operator<<(QDebug s, const SourceLocation &l) -{ - QDebugStateSaver saver(s); - s.nospace(); - s.noquote(); - s << QDir::toNativeSeparators(l.file) << ':' << l.line; - if (l.column) - s << ':' << l.column; - return s; -} - -// Roughly follow g++ format: -// file.cpp:214:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] -QDebug operator<<(QDebug s, const Diagnostic &d) -{ - QDebugStateSaver saver(s); - s.nospace(); - s.noquote(); - s << d.location << ": "; - switch (d.severity) { - case CXDiagnostic_Ignored: - s << "ignored"; - break; - case CXDiagnostic_Note: - s << "note"; - break; - case CXDiagnostic_Warning: - s << "warning"; - break; - case CXDiagnostic_Error: - s << "error"; - break; - case CXDiagnostic_Fatal: - s << "fatal"; - break; - } - s << ": " << d.message; - - if (d.source != Diagnostic::Clang) - s << " [other]"; - - if (const int childMessagesCount = d.childMessages.size()) { - s << '\n'; - for (int i = 0; i < childMessagesCount; ++i) - s << " " << d.childMessages.at(i) << '\n'; - } - - return s; -} - -#endif // QT_NO_DEBUG_STREAM - -} // namespace clang diff --git a/ApiExtractor/clangparser/clangutils.h b/ApiExtractor/clangparser/clangutils.h deleted file mode 100644 index 3437f51eb..000000000 --- a/ApiExtractor/clangparser/clangutils.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CLANGUTILS_H -#define CLANGUTILS_H - -#include -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) - -bool operator==(const CXCursor &c1, const CXCursor &c2); -uint qHash(const CXCursor &c, uint seed = 0); - -namespace clang { - -QString getCursorKindName(CXCursorKind cursorKind); -QString getCursorSpelling(const CXCursor &cursor); -QString getCursorDisplayName(const CXCursor &cursor); -QString getTypeName(const CXType &type); -inline QString getCursorTypeName(const CXCursor &cursor) - { return getTypeName(clang_getCursorType(cursor)); } -inline QString getCursorResultTypeName(const CXCursor &cursor) - { return getTypeName(clang_getCursorResultType(cursor)); } - -inline bool isCursorValid(const CXCursor &c) -{ - return c.kind < CXCursor_FirstInvalid || c.kind > CXCursor_LastInvalid; -} - -struct SourceLocation -{ - int compare(const SourceLocation &rhs) const; - - QString file; - unsigned line = 0; - unsigned column = 0; - unsigned offset = 0; -}; - -SourceLocation getExpansionLocation(const CXSourceLocation &location); - -typedef QPair SourceRange; - -SourceLocation getCursorLocation(const CXCursor &cursor); -CXString getFileNameFromLocation(const CXSourceLocation &location); -SourceRange getCursorRange(const CXCursor &cursor); - -struct Diagnostic { - enum Source { Clang, Other }; - - Diagnostic() : source(Clang) {} - // Clang - static Diagnostic fromCXDiagnostic(CXDiagnostic cd); - // Other - explicit Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s = CXDiagnostic_Warning); - - QString message; - QStringList childMessages; - SourceLocation location; - Source source; - CXDiagnosticSeverity severity; -}; - -QVector getDiagnostics(CXTranslationUnit tu); -CXDiagnosticSeverity maxSeverity(const QVector &ds); - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug, const SourceLocation &); -QDebug operator<<(QDebug, const Diagnostic &); -#endif // QT_NO_DEBUG_STREAM -} // namespace clang - -#endif // CLANGUTILS_H diff --git a/ApiExtractor/clangparser/compilersupport.cpp b/ApiExtractor/clangparser/compilersupport.cpp deleted file mode 100644 index df82f9080..000000000 --- a/ApiExtractor/clangparser/compilersupport.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "compilersupport.h" -#include "header_paths.h" - -#include -#include -#include - -#include -#include -#include - -namespace clang { - -static bool runProcess(const QString &program, const QStringList &arguments, - QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr) -{ - QProcess process; - process.start(program, arguments, QProcess::ReadWrite); - if (!process.waitForStarted()) { - qWarning().noquote().nospace() << "Unable to start " - << process.program() << ": " << process.errorString(); - return false; - } - process.closeWriteChannel(); - const bool finished = process.waitForFinished(); - const QByteArray stdErr = process.readAllStandardError(); - if (stdErrIn) - *stdErrIn = stdErr; - if (stdOutIn) - *stdOutIn = process.readAllStandardOutput(); - - if (!finished) { - qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr; - process.kill(); - return false; - } - - if (process.exitStatus() != QProcess::NormalExit) { - qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr; - return false; - } - - if (process.exitCode() != 0) { - qWarning().noquote().nospace() << process.program() << " exited " - << process.exitCode() << ": " << stdErr; - return false; - } - - return true; -} - -#if defined(Q_CC_GNU) - -static QByteArray frameworkPath() { return QByteArrayLiteral(" (framework directory)"); } - -// Determine g++'s internal include paths from the output of -// g++ -E -x c++ - -v search starts here: -// /usr/local/include -// /System/Library/Frameworks (framework directory) -// End of search list. -static HeaderPaths gppInternalIncludePaths(const QString &compiler) -{ - HeaderPaths result; - QStringList arguments; - arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++") - << QStringLiteral("-") << QStringLiteral("-v"); - QByteArray stdOut; - QByteArray stdErr; - if (!runProcess(compiler, arguments, &stdOut, &stdErr)) - return result; - const QByteArrayList stdErrLines = stdErr.split('\n'); - bool isIncludeDir = false; - for (const QByteArray &line : stdErrLines) { - if (isIncludeDir) { - if (line.startsWith(QByteArrayLiteral("End of search list"))) { - isIncludeDir = false; - } else { - HeaderPath headerPath(line.trimmed()); - if (headerPath.path.endsWith(frameworkPath())) { - headerPath.m_isFramework = true; - headerPath.path.truncate(headerPath.path.size() - frameworkPath().size()); - } - result.append(headerPath); - } - } else if (line.startsWith(QByteArrayLiteral("#include <...> search starts here"))) { - isIncludeDir = true; - } - } - return result; -} -#endif // Q_CC_MSVC - -// For MSVC, we set the MS compatibility version and let Clang figure out its own -// options and include paths. -// For the others, we pass "-nostdinc" since libclang tries to add it's own system -// include paths, which together with the clang compiler paths causes some clash -// which causes std types not being found and construct -I/-F options from the -// include paths of the host compiler. - -static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); } - -// Returns clang options needed for emulating the host compiler -QByteArrayList emulatedCompilerOptions() -{ - QByteArrayList result; -#if defined(Q_CC_MSVC) - const HeaderPaths headerPaths; - result.append(QByteArrayLiteral("-fms-compatibility-version=19")); -#elif defined(Q_CC_CLANG) - const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("clang++")); - result.append(noStandardIncludeOption()); -#elif defined(Q_CC_GNU) - const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("g++")); - result.append(noStandardIncludeOption()); -#else - const HeaderPaths headerPaths; -#endif - std::transform(headerPaths.cbegin(), headerPaths.cend(), - std::back_inserter(result), [](const HeaderPath &p) { - return HeaderPath::includeOption(p, true); - }); - return result; -} - -} // namespace clang diff --git a/ApiExtractor/clangparser/compilersupport.h b/ApiExtractor/clangparser/compilersupport.h deleted file mode 100644 index f556da551..000000000 --- a/ApiExtractor/clangparser/compilersupport.h +++ /dev/null @@ -1,40 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COMPILERSUPPORT_H -#define COMPILERSUPPORT_H - -#include - -namespace clang { - -QByteArrayList emulatedCompilerOptions(); - -} // namespace clang - -#endif // COMPILERSUPPORT_H diff --git a/ApiExtractor/cmake_uninstall.cmake b/ApiExtractor/cmake_uninstall.cmake deleted file mode 100644 index df95fb9d8..000000000 --- a/ApiExtractor/cmake_uninstall.cmake +++ /dev/null @@ -1,21 +0,0 @@ -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") - -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) diff --git a/ApiExtractor/dependency.h b/ApiExtractor/dependency.h deleted file mode 100644 index 17fbffcce..000000000 --- a/ApiExtractor/dependency.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DEPENDENCY_H -#define DEPENDENCY_H - -#include -#include - -// Dependencies for topologically sorting classes -struct Dependency { - QString parent; - QString child; -}; - -typedef QVector Dependencies; - -#endif // DEPENDENCY_H diff --git a/ApiExtractor/doc/CMakeLists.txt b/ApiExtractor/doc/CMakeLists.txt deleted file mode 100644 index d78844dc8..000000000 --- a/ApiExtractor/doc/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ - -find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") - -if (SPHINX) - message("-- sphinx-build - found") - configure_file(conf.py.in conf.py @ONLY) - add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) -else() - message("-- sphinx-build - not found! doc target disabled") -endif() \ No newline at end of file diff --git a/ApiExtractor/doc/_templates/index.html b/ApiExtractor/doc/_templates/index.html deleted file mode 100644 index 4aa14ede5..000000000 --- a/ApiExtractor/doc/_templates/index.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "layout.html" %} -{% set title = 'Overview' %} -{% block body %} -
-

API Extractor {{ version }}

- -

API Extractor is a tool that eases the development of bindings of Qt-based libraries for high - level languages by automating most of the process. - -

API Extractor is based on the - QtScriptGenerator project.

- -

Documentation

- - - -
- - - - -
-
-{% endblock %} diff --git a/ApiExtractor/doc/_templates/layout.html b/ApiExtractor/doc/_templates/layout.html deleted file mode 100644 index 9dc53722d..000000000 --- a/ApiExtractor/doc/_templates/layout.html +++ /dev/null @@ -1,41 +0,0 @@ -{% extends "!layout.html" %} - -# Invert sidebars -{%- block sidebar1 %}{{ sidebar() }}{%- endblock %} -{%- block sidebar2 %}{%- endblock %} - -{%- block header %} -
-
-
- - -
-
-{%- endblock -%} - -{%- block footer %} - -
-{%- endblock %} - -# No top relbar. -{%- block relbar1 %}{%- endblock %} - -# No bottom relbar. -{%- block relbar2 %}{%- endblock %} diff --git a/ApiExtractor/doc/_themes/pysidedocs/searchbox.html b/ApiExtractor/doc/_themes/pysidedocs/searchbox.html deleted file mode 100644 index 55a972156..000000000 --- a/ApiExtractor/doc/_themes/pysidedocs/searchbox.html +++ /dev/null @@ -1,12 +0,0 @@ -{%- if pagename != "search" %} - - -{%- endif %} diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png b/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png deleted file mode 100644 index 843e7e2c5..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg b/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg deleted file mode 100644 index 4229ae8db..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png b/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png deleted file mode 100644 index b45830e00..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg b/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg deleted file mode 100644 index 2a1fbe7a1..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png b/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png deleted file mode 100644 index 51e868d6e..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg b/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg deleted file mode 100644 index cd474efba..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png b/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png deleted file mode 100644 index 37800f454..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css b/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css deleted file mode 100644 index fd81f4379..000000000 --- a/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css +++ /dev/null @@ -1,409 +0,0 @@ -* { - font: 100% Verdana, Arial, Helvetica, sans-serif; - font-size:12px; -} - -html { - height: 100%; -} - -body { - margin: 0; - padding: 0; - text-align: center; - background-color: #EBEBEB; - height: 100%; - color: #333; -} - -strong { - font-weight:bold; -} - -.document { - padding-bottom: 90px; -} - -#container { - position: relative; - min-height: 100%; - background-image: url(fakebar.png); - background-repeat: repeat-y; - background-color: white; -} - -.footer { - position: absolute; - bottom: 0px; - margin-top: 50px; - text-align:center; - background-color: white; - border-top: 2px solid #e0e0e0; - white-space: nowrap; - height: 90px; - width: 100%; -} - -.footer img { - margin-left: 8px; - margin-right: 8px; -} - -.sphinxsidebar { - float: left; - width: 250px; - padding: 0px 10px 0px 10px; - text-align: left; -} - -.sphinxsidebar ul { - padding: 0px; - margin: 0px; - list-style-position: inside; -} - -.sphinxsidebar > ul { - padding: 0px; - margin: 0px; -} - -.sphinxsidebar ul li { - margin-left: 10px; - padding: 0px; -} - -.sphinxsidebar h3, .sphinxsidebar h3 a { - font-weight: bold; - color: #333; -} - -.documentwrapper { - margin-left: 270px; - text-align: left; - background-color: #ffffff; - border-left: 1px solid #989898; - font-size:18px; - padding: 10px 50px 15px 50px; - height: 100%; -} - -h1 { - font-size:18px; - padding-left: 50px; - padding-bottom: 15px; - padding-top: 15px; - border-bottom: 1px solid #c2c2c2; - text-transform:uppercase; - margin-right: -100px; - position: relative; - left: -50px; - top: -10px; -} - -h2 { - font-size:12px; - font-weight:bold; - border-left-width: 1px; - border-right-width: 1px; - border-top-width: 1px; - border-bottom-width: 2px; - border-style: solid; - border-left-color: #b1b1b1; - border-right-color: #b1b1b1; - border-top-color: #b1b1b1; - border-bottom-color: #009491; - background-color: #e0e0e0; - padding:5px; - margin-top: 20px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - -khtml-border-radius:5px; -} - -h3, h4 { - font-weight: bolder; -} - -pre { - border-top: 1px solid #e0e0e0; - border-bottom: 1px solid #e0e0e0; - background-color: #fafafa; - padding: 5px; - font: 100% monospace; - overflow: auto; -} - -pre * { - font: 100% monospace; -} - -.headerlink { - font-size: 100%; - color: inherit; - float: right; - visibility: Hidden; -} - -h1 .headerlink { - padding-right: 50px; -} - -h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink { - visibility: Visible; -} - -a, a:visited { - color: #009491; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -div.note { - border: 1px solid #e3e3e3; -} - -table.docutils { - margin-left: auto; - margin-right: auto; - margin-bottom: 10px; - border: none; -} - -table.docutils td { - border: none; -} - -table.docutils th { - border: none; - font-weight: bold; - vertical-align: top; -} - -h2 em { - float: right; - font-size: 10px; - position: relative; - top: -20px; -} - -/* Table of pymaemo components */ - -#development table.docutils td { - border-bottom: 1px solid #EBEBEB; -} - -#development th { - background-color: #EBEBEB; - color: #FC7E00; - padding: 5px; -} - -#development th:first-child { - -moz-border-radius: 20px 0px 0px 0px; - -webkit-border-radius: 20px 0px 0px 0px; - -khtml-border-radius: 20px 0px 0px 0px; - padding-left: 10px; -} -#development th:last-child { - -moz-border-radius: 0px 20px 0px 0px; - -webkit-border-radius: 0px 20px 0px 0px; - -khtml-border-radius: 0px 20px 0px 0px; - padding-right: 10px; - width: 100px; -} - -hr { - border: none; - border-bottom: 1px dashed #EBEBEB; - width: 70% -} - -.oldnews { - text-align: right; -} - -/******************* TOPO *****************************/ -.header { - background-image: url(bg_topo.jpg); - background-repeat: repeat-x; - height: 147px; -} - -.header_container { - background-image: url(bg_header.png); - background-repeat: no-repeat; - background-position: 100px 0px; -} - -.logo { - text-align: left; - margin-bottom: 10px; -} - -#searchbox { - border-top: 1px solid #989898; - padding-top: 10px; - margin-left: -10px; - margin-right: -10px; - padding-left: 10px; - padding-right: 10px; -} - -#search_button { - border: 1px solid #3A393A; - background-color: #3A393A; - color: white; - cursor: pointer; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -khtml-border-radius: 5px; - -} - -form { - margin: 0px; - padding: 0px; -} - -/* search field */ -form #q { - width: 136px; -/* height: 22px; */ - border: none; - margin: 0px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -khtml-border-radius: 5px; - margin-top: 2px; - padding: 4px; - line-height: 22px -} - -#search-results h2 { - display: none; -} - -#search-results h2 { - display: none; -} - -#search-results ul.search { - margin: 0px; - padding: 0px; -} - -ul.search div.context { - padding-left: 40px; -} - -#installation td { - text-align: center; - font-weight: bold; -} - -em { - color: inherit; - font-style:italic; -} - -/******** REL bar *********/ - -.related { - display: inline; -} - -.related ul { - padding: 0px 0px 0px 10px; - margin: 0px; - text-align: left; - background-image: url(relbar_bg.png); -} - -.related li { - display: inline; - color: white; - font-weight: bold; -} - -.related li a { - color: inherit; - line-height: 35px; - font-weight: bold; - vertical-align: middle; -} - -.related li.right { - float: right; - margin-right: 5px; -} - -.related h3 { - display: none; -} - -.align-center { - text-align: center; -} - -.contentstable { - width: 100%; -} - -.contentstable td { - padding-left: 30px; - vertical-align: top; -} - -p.biglink a { - font-size: 20px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -img { - border: 0px; -} - -.figure .caption { - font-style:italic; -} - -table.footnote { - margin: 0px; -} diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png b/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png deleted file mode 100644 index 076c1057c..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png b/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png deleted file mode 100644 index 4036733a7..000000000 Binary files a/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png and /dev/null differ diff --git a/ApiExtractor/doc/_themes/pysidedocs/theme.conf b/ApiExtractor/doc/_themes/pysidedocs/theme.conf deleted file mode 100644 index e0a652a5d..000000000 --- a/ApiExtractor/doc/_themes/pysidedocs/theme.conf +++ /dev/null @@ -1,7 +0,0 @@ -[theme] -inherit = default -stylesheet = pysidedocs.css -pygments_style = none - -[options] -nosidebar = false diff --git a/ApiExtractor/doc/conf.py.in b/ApiExtractor/doc/conf.py.in deleted file mode 100644 index 70750c899..000000000 --- a/ApiExtractor/doc/conf.py.in +++ /dev/null @@ -1,163 +0,0 @@ -# -*- coding: utf-8 -*- -# -# ApiExtractor 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. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, 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('.')) - -# -- 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.refcounting', 'sphinx.ext.coverage'] - -rst_epilog = """ -.. |project| replace:: API Extractor -""" - -# 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' - -# The encoding of source files. -source_encoding = 'utf-8' - -# The master toctree document. -#master_doc = 'contents' - -# General information about the project. -project = u'API Extractor' -copyright = u'2009-2010, Nokia Corporation' - -# 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 = '@apiextractor_MAJOR_VERSION@.@apiextractor_MINOR_VERSION@' -# The full version, including alpha/beta/rc tags. -release = '@apiextractor_VERSION@' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'pysidedocs' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = { -#} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# 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 = None - -# 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 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = { '' : ''} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -html_additional_pages = { 'index' : 'index.html'} - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - -html_add_permalinks = True; - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - diff --git a/ApiExtractor/doc/contents.rst b/ApiExtractor/doc/contents.rst deleted file mode 100644 index 83a4889fe..000000000 --- a/ApiExtractor/doc/contents.rst +++ /dev/null @@ -1,9 +0,0 @@ -Table of contents -***************** -.. toctree:: - :numbered: - :maxdepth: 3 - - overview.rst - ownership.rst - typesystem.rst diff --git a/ApiExtractor/doc/dependency-apiextractor.svg b/ApiExtractor/doc/dependency-apiextractor.svg deleted file mode 100644 index 6bec8b5a8..000000000 --- a/ApiExtractor/doc/dependency-apiextractor.svg +++ /dev/null @@ -1,360 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - Boost - Qt Software - INdT/Nokia - - - - - - - - Qt 4.5 - 4.5 - headers and libraries - compile-time and run-time - GNU General Public License v3 /GNU Lesser General Public Licence v2.1 - - - - libapiextractor - 0.2 - headers and libraries - compile-time and run-time - LGPL version 2.1 - - - - boost::graph - 1.38.0 - headers and libraries - compile-time and run-time - Boost Software License 1.0 - - - diff --git a/ApiExtractor/doc/overview.rst b/ApiExtractor/doc/overview.rst deleted file mode 100644 index 471e2439b..000000000 --- a/ApiExtractor/doc/overview.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _gen-overview: - -********************** -API Extractor Overview -********************** - -The **API Extractor** library is used by the binding generator to parse headers -of a given library and merge this data with information provided by -typesystem (XML) files, resulting in a representation of how the API should be -exported to the chosen target language. The generation of source code for the -bindings is performed by specific generators using the API Extractor library. - -The API Extractor is based on QtScriptGenerator_ codebase. - -.. _QtScriptGenerator: http://labs.trolltech.com/page/Projects/QtScript/Generator diff --git a/ApiExtractor/doc/ownership.rst b/ApiExtractor/doc/ownership.rst deleted file mode 100644 index 760967da6..000000000 --- a/ApiExtractor/doc/ownership.rst +++ /dev/null @@ -1,85 +0,0 @@ -Ownership Management -******************** - -Among the various types of instances interactions, sometimes an object -may be *owned* by another object, so that the owner is responsible for -destroying the owned object, like in Qt's object system [#]_. -This kind of relationship has a big role on interfacing with the target language, like -with Python's reference counting. - - -Ownership transfers -------------------- - -From C++ to target -^^^^^^^^^^^^^^^^^^ - - When an object that is currently owned by C++ has its ownership transfered - 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 - - - - - - -From target to C++ -^^^^^^^^^^^^^^^^^^ - - In the opposite direction,when an object ownership is transfered 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. - - .. code-block:: xml - - - - - - -Parent-child relationship -------------------------- - -One special type of relationship is the parent-child. When an object is called -the parent of another object (the child), the former is in charge of deleting its -child when deleted and the target language can trust that the child will be alive -as long as the parent is, unless some other method can take the C++ ownership away from the parent. - -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 - - - - - -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 -of the first argument using the `parent` tag. To remove ownership, just use "remove" in the action attribute. **Removing -parentship also transfers the ownership back to python.** - -Invalidation after use ----------------------- - -Sometimes an object is created as a virtual method call argument and destroyed after the -call returned. In this case, you should use the ``invalidate-after-use`` attribute in the -``modify-argument`` tag to mark the wrapper as invalid right after the virtual method returns. - - .. code-block:: xml - - - -In this example the second argument will be invalidated after this method call. - -.. [#] See *Object Trees and Object Ownership* http://doc.trolltech.com/4.5/objecttrees.html diff --git a/ApiExtractor/doc/typesystem.rst b/ApiExtractor/doc/typesystem.rst deleted file mode 100644 index 69dda43a0..000000000 --- a/ApiExtractor/doc/typesystem.rst +++ /dev/null @@ -1,29 +0,0 @@ -The API Extractor Type System -***************************** - -The typesystem is used by a binding generator or any other software using the APIExtractor library -to map a C++ library API onto a higher level language. - -The typesystem specification is a handwritten XML document listing the types -that will be available in the generated target language API; types that are not -declared in the specification will be ignored along with everything depending on -them. In addition, it is possible to manipulate and modify types and functions. -It is even possible to use the typesystem specification to inject arbitrary -code into the source files, such as an extra member function. - -Below there is a complete reference guide to the various nodes (XML tags) of the typesystem. -For usage examples, take a look at the typesystem files used to generate PySide. These files -can be found in the PySide/ directory of the PySide package. - -.. toctree:: - - typesystem_specifying_types - typesystem_manipulating_objects - typesystem_modify_function - typesystem_arguments - typesystem_solving_compilation - typesystem_templates - typesystem_conversionrule - typesystem_documentation - - diff --git a/ApiExtractor/doc/typesystem_arguments.rst b/ApiExtractor/doc/typesystem_arguments.rst deleted file mode 100644 index 16e0678d3..000000000 --- a/ApiExtractor/doc/typesystem_arguments.rst +++ /dev/null @@ -1,192 +0,0 @@ -.. _modifying-arguments: - -Modifying Arguments -------------------- - -.. _conversion-rule: - -conversion-rule -^^^^^^^^^^^^^^^ - - The conversion-rule node allows you to write customized code to convert - the given argument between the target language and C++, and it is a child of the modify-argument node. - - .. code-block:: xml - - - - // the code - - - - This node is typically used in combination with the replace-type and - 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: - - .. code-block:: xml - - - bool %out = (bool) %in; - - - .. 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 `. - -remove-argument -^^^^^^^^^^^^^^^ - - The remove-argument node removes the given argument from the function's - signature, and it is a child of the modify-argument node. - - .. code-block:: xml - - - - - -rename to -^^^^^^^^^ - - The 'rename to' node is used to rename a argument and use this new name in the generated code. - - .. code-block:: xml - - - - - - -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 modify-argument node. - - .. code-block:: xml - - - - - -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 - modify-argument node. - - .. code-block:: xml - - - - - - -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 - modify-argument node. - - .. code-block:: xml - - - - - - 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 -^^^^^^^^^^^^^^^^ - - The define-ownership tag indicates that the function changes the ownership - rules of the argument object. The ``class`` attribute specifies the class of - function where to inject the ownership altering code. 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 - - - - - - -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. 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 - - - - - - - The variable-name attribute specifies the name used for the variable that - holds the reference(s). - - -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. - - .. code-block:: xml - - - - -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. - - .. code-block:: xml - - - - - - 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/ApiExtractor/doc/typesystem_conversionrule.rst b/ApiExtractor/doc/typesystem_conversionrule.rst deleted file mode 100644 index c62d5bbf6..000000000 --- a/ApiExtractor/doc/typesystem_conversionrule.rst +++ /dev/null @@ -1,113 +0,0 @@ -.. _conversion-rule-tag: - -Conversion Rule Tag -------------------- - -.. _conversion-rule: - -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. - - .. code-block:: xml - - - - - // Code to convert a native value to a target language object. - - - - // Code to convert target language type object of type TARGETTYPEA - // to the C++ native type represented by the value/primitive/container-type. - - - // Code to convert target language type object of type TARGETTYPEB - // to the C++ native type represented by the value/primitive/container-type. - - - - - - 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. - - -.. _native-to-target: - -native-to-target -^^^^^^^^^^^^^^^^ - - The **native-to-target** tag tells how to convert a native C++ value to its - target language equivalent. 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. - ``insert-template`` tags may be used to insert commonly repeating code. - - .. code-block:: xml - - - - // Code to convert a native value to a target language object. - - - - 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"**) 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"**). - - -.. _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. 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 - - - \ - // List of target to native conversions meant to replace or expand - // the already existing implicit conversions. - - - - -.. _add-conversion: - -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. - - .. code-block:: xml - - - - // Code to convert target language type object of type TARGETTYPE_A - // to the C++ native type represented by the value/primitive/container-type. - - - - 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. - diff --git a/ApiExtractor/doc/typesystem_documentation.rst b/ApiExtractor/doc/typesystem_documentation.rst deleted file mode 100644 index 43f72a1ba..000000000 --- a/ApiExtractor/doc/typesystem_documentation.rst +++ /dev/null @@ -1,43 +0,0 @@ -Manipulating Documentation --------------------------- - -inject-documentation -^^^^^^^^^^^^^^^^^^^^ - - The inject-documentation node inserts the documentation into the generated - documentation. This node is a child of the object-type, value-type and - modify-function nodes. - - .. code-block:: xml - - - - // the documentation - - - - The **mode** attribute default value is *replace*. - - 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. - - At the moment the only supported backend is Sphinx. - -modify-documentation -^^^^^^^^^^^^^^^^^^^^ - - The modify-documentation node allows you to change the auto-generated - documentation. API Extractor transforms XML's from qdoc3 (the Qt documentation - tool) into .rst files to be processed later using Sphinx. So you can modify - the XML before the transformation occur. - - .. code-block:: xml - - - - - - The **xpath** attribute is the XPath to the node that you want to modify. diff --git a/ApiExtractor/doc/typesystem_manipulating_objects.rst b/ApiExtractor/doc/typesystem_manipulating_objects.rst deleted file mode 100644 index 2838c95e1..000000000 --- a/ApiExtractor/doc/typesystem_manipulating_objects.rst +++ /dev/null @@ -1,132 +0,0 @@ -.. _manipulating-object-and-value-types: - -Manipulating Object and Value Types ------------------------------------ - -.. _inject-code: - -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. - - .. code-block:: xml - - - - // the code - - - - The ``class`` attribute specifies which module of the generated code that - will be affected by the code injection. The ``class`` attribute accepts the - following values: - - * native: The c++ code - * target: The binding code - * target-declaration: The code will be injected into the generated header - file containing the c++ wrapper class definition. - - 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. - - The ``since`` attribute specify the API version where this code was injected. - -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. - - .. code-block:: xml - - - - - - 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* attribute, which can mark the field - to be discarded on generation; it has the same purpose of the deprecated tag - :ref:`remove`. - -.. _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 an :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 - - - - - - The ``signature`` attribute is a normalized C++ signature, excluding return - values but including potential const declarations. - - The ``since`` attribute specify the API version when this function was modified. - - The ``remove``, ``access`` and ``rename`` attributes are *optional* attributes - for added convenience; they serve the same purpose as the deprecated tags :ref:`remove`, :ref:`access` and :ref:`rename`. - -.. _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 suposed to be a method, or :ref:`namespace` and :ref:`typesystem` if - the function is suposed to be a function inside a namespace or a global function. - - 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 - - - - - - The ``return-type`` attribute defaults to *void*, the ``access`` to *public* and the ``static`` one to *no*. - - The ``since`` attribute specify the API version when this function was added. - -.. _conversion-rule-on-types: - -conversion-rule -^^^^^^^^^^^^^^^ - - The conversion-rule node allows you to write customized code to convert the given argument between the target - language and C++, and is a child of the :ref:`value-type`, :ref:`object-type`, :ref:`primitive-type` and - :ref:`container-type` nodes. - - The code pointed by the file attribute is very tied to the generator using APIExtractor, so it don't follow any - rules, but the generator rules.. - - .. code-block:: xml - - - - - - The ``since`` attribute specify the API version when this conversion rule became valid. - - .. note:: You can also use the conversion-rule node to specify :ref:`how the conversion of a single function argument should be done in a function `. - diff --git a/ApiExtractor/doc/typesystem_modify_function.rst b/ApiExtractor/doc/typesystem_modify_function.rst deleted file mode 100644 index 071cea4f5..000000000 --- a/ApiExtractor/doc/typesystem_modify_function.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _modifying-functions: - -Modifying Functions -------------------- - -.. _modify-argument: - -modify-argument -^^^^^^^^^^^^^^^ - - The modify-argument node specifies which of the given function's arguments the - modification affects, and is a child of the modify-function node. Use the - remove-argument, replace-default-expression, remove-default-expression, - replace-type, reference-count and define-ownership nodes to specify the details - of the modification. - - .. code-block:: xml - - - - // modifications - - - - 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. - -.. _remove: - -remove -^^^^^^ - - The remove node removes the given method from the generated target language - API, and it is a child of the modify-function node. - - .. code-block:: xml - - - - - - .. warning:: This tag is deprecated, use the ``remove`` attribute from :ref:`modify-function` tag instead. - -.. _access: - -access -^^^^^^ - - The access node changes the access privileges of the given function in the - generated target language API, and it is a child of the modify-function node. - - .. code-block:: xml - - - - - - .. warning:: This tag is deprecated, use the ``access`` attribute from :ref:`modify-function` tag instead. - -.. _rename: - -rename -^^^^^^ - - The rename node changes the name of the given function in the generated target - language API, and it is a child of the modify-function node. - - .. code-block:: xml - - - - - - The ``to`` attribute is the new name of the function. - - .. warning:: This tag is deprecated, use the ``rename`` attribute from :ref:`modify-function` tag instead. diff --git a/ApiExtractor/doc/typesystem_solving_compilation.rst b/ApiExtractor/doc/typesystem_solving_compilation.rst deleted file mode 100644 index 81d14a187..000000000 --- a/ApiExtractor/doc/typesystem_solving_compilation.rst +++ /dev/null @@ -1,70 +0,0 @@ -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 typesystem node. - - .. code-block:: xml - - - - - - 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 -^^^^^^^^^^^^^^ - - The extra-includes node contains declarations of additional include files, - and it can be a child of the interface-type, namespace-type, value-type and - object-type 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 witin the extra-include node: - - .. code-block:: xml - - - - - - - - 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 "...". - - -include -^^^^^^^ - - The include node specifies the name and location of a file that must be - included, and it is a child of the interface-type, namespace-type, value-type, - object-type or extra-includes nodes - - 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 - - - - - - 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/ApiExtractor/doc/typesystem_specifying_types.rst b/ApiExtractor/doc/typesystem_specifying_types.rst deleted file mode 100644 index 0d24a6d52..000000000 --- a/ApiExtractor/doc/typesystem_specifying_types.rst +++ /dev/null @@ -1,371 +0,0 @@ -Specifying Types ----------------- - -.. _typesystem: - -typesystem -^^^^^^^^^^ - - This is the root node containing all the type system information. It can - have a number of attributes, described below. - - .. code-block:: xml - - - - - 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". - -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 typesystem node. - - .. code-block:: xml - - - - - - 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. - - -rejection -^^^^^^^^^ - - The rejection node rejects the given class, or the specified function or - field, and it is a child of the typesystem node. - - .. code-block:: xml - - - - - - 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 \*. - -.. _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 typesystem node. Note that most - primitives are already specified in the QtCore typesystem. - - .. code-block:: xml - - - - - - The **name** attribute is the name of the primitive in C++, the optional, - **target-name** attribute is the name of the primitive type in the target - language. If the later two attributes are not specified their default value - will be the same as the **name** attribute. - - The *optional* **since** value is used to specify the API version of this type. - - 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* **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* **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*. - - -.. _namespace: - -namespace-type -^^^^^^^^^^^^^^ - - The namespace-type node maps the given C++ namespace to the target language, - and it is a child of the typesystem node. Note that within namespaces, the - generator only supports enums (i.e., no functions or classes). - - .. code-block:: xml - - - - - - The **name** attribute is the name of the namespace, e.g., "Qt". - - The *optional* **generate** attribute is used to inform if you need to prepend - the given namespace into each generated class. Its default value is **yes**. - - 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 **revision** attribute can be used to specify a revision for each type, easing the - production of ABI compatible bindings. - -enum-type -^^^^^^^^^ - - The enum-type node maps the given enum from C++ to the target language, - and it is a child of the typesystem node. Use the reject-enum-value to - reject values. - - .. code-block:: xml - - - - - - 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 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 **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 -^^^^^^^^^^^^^^^^^ - - The reject-enum-value node rejects the enum value specified by the **name** - attribute, and it is a child of the enum-type node. - - .. code-block:: xml - - - - - - 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. - - .. code-block:: xml - - - - - - 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* 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 *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 **revision** attribute can be used to specify a revision for each type, easing the - production of ABI compatible bindings. - -.. _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. - - .. code-block:: xml - - - - - - 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* 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. - -interface-type -^^^^^^^^^^^^^^ - - The interface-type node indicates that the given class is replaced by an - interface pattern when mapping from C++ to the target language. Using the - interface-type node implicitly makes the given type an :ref:`object-type`. - - .. code-block:: xml - - - - - - The **name** attribute is the fully qualified C++ class name. The *optional* - **package** attribute can be used to override the package of the type system. - If there is no C++ base class, the *optional* **default-superclass** attribute - can be used to specify a superclass in the generated target language API, for - the given class. - - The *optional* **since** value is used to specify the API version of this interface. - - The **revision** attribute can be used to specify a revision for each type, easing the - production of ABI compatible bindings. - -.. _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**. - - .. code-block:: xml - - - - - - 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: *list*, *string-list*, *linked-list*, *vector*, *stack*, - *queue*, *set*, *map*, *multi-map*, *hash*, *multi-hash* or *pair*. - - The *optional* **since** value is used to specify the API version of this container. - - -.. _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. - - .. code-block:: xml - - - - - - The **name** attribute is the name of the custom type, e.g., "PyObject". - - -.. _function: - -function -^^^^^^^^ - - The function node indicates that the given C++ global function is mapped onto - the target language. - - .. code-block:: xml - - - - - - This tag has some limitations, it doesn't support function modifications, besides you - can't add a function overload using :ref:`add-function` tag to an existent function. - These limitation will be addressed in future versions of ApiExtractor. - - The function tag has two *optional* attributes: **since**, whose value is used to specify - the API version of this function, and **rename**, to modify the function name. - diff --git a/ApiExtractor/doc/typesystem_templates.rst b/ApiExtractor/doc/typesystem_templates.rst deleted file mode 100644 index 31b155c5a..000000000 --- a/ApiExtractor/doc/typesystem_templates.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _using-code-templates: - -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 typesystem - node. - - .. code-block:: xml - - - - - - Use the insert-template node to insert the template code (identified by the - template's ``name`` attribute) into the generated code base. - - -insert-template -^^^^^^^^^^^^^^^ - - The insert-template node includes the code template identified by the name - attribute, and it can be a child of the inject-code, conversion-rule, template, - custom-constructor and custom-destructor nodes. - - .. code-block:: xml - - - - - - 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 insert-template node. - - .. code-block:: xml - - - - - - This node will replace the attribute ``from`` with the value pointed by - ``to``. - diff --git a/ApiExtractor/docparser.cpp b/ApiExtractor/docparser.cpp deleted file mode 100644 index bae438f18..000000000 --- a/ApiExtractor/docparser.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include "docparser.h" -#include "abstractmetalang.h" -#include "typesystem.h" -#include -#include -#include - -#include -#include -#include - -DocParser::DocParser() -{ - xmlSubstituteEntitiesDefault(1); -} - -DocParser::~DocParser() -{ -} - -QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query, - const DocModificationList& mods) const -{ - QString doc = execXQuery(xquery, query); - return applyDocModifications(mods, doc); -} - -QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const -{ - QString escapedQuery(query); - // XQuery can't have invalid XML characters - escapedQuery.replace(QLatin1Char('&'), QLatin1String("&")); - escapedQuery.replace(QLatin1Char('<'), QLatin1String("<")); - xquery.setQuery(escapedQuery); - if (!xquery.isValid()) { - qWarning() << "Bad XQuery: " << escapedQuery; - return QString(); - } - - QString result; - xquery.evaluateTo(&result); - return result; -} - -namespace -{ - -struct XslResources -{ - xmlDocPtr xmlDoc; - xsltStylesheetPtr xslt; - xmlDocPtr xslResult; - - XslResources() : xmlDoc(0), xslt(0), xslResult(0) {} - - ~XslResources() - { - if (xslt) - xsltFreeStylesheet(xslt); - - if (xslResult) - xmlFreeDoc(xslResult); - - if (xmlDoc) - xmlFreeDoc(xmlDoc); - - xsltCleanupGlobals(); - xmlCleanupParser(); - } -}; - -} // namespace - -QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) const -{ - if (mods.isEmpty()) - return xml; - - bool hasXPathBasedModification = false; - for (const DocModification &mod : mods) { - if (mod.mode() == TypeSystem::DocModificationXPathReplace) { - hasXPathBasedModification = true; - break; - } - } - - if (!hasXPathBasedModification) - return xml; - - QString xsl = QLatin1String("\n" - "\n" - "\n" - " \n" - "\n" - "\n" - "\n" - " \n" - " \n" - "\n" - "\n" - ); - for (const DocModification &mod : mods) { - if (mod.mode() == TypeSystem::DocModificationXPathReplace) { - QString xpath = mod.xpath(); - xpath.replace(QLatin1Char('"'), QLatin1String(""")); - xsl += QLatin1String("") - + mod.code() + QLatin1String("\n"); - } - } - xsl += QLatin1String(""); - - XslResources res; - // Read XML data - QByteArray xmlData = xml.toUtf8(); - res.xmlDoc = xmlParseMemory(xmlData.constData(), xmlData.size()); - if (!res.xmlDoc) - return xml; - - // Read XSL data as a XML file - QByteArray xslData = xsl.toUtf8(); - // xsltFreeStylesheet will delete this pointer - xmlDocPtr xslDoc = xmlParseMemory(xslData.constData(), xslData.size()); - if (!xslDoc) - return xml; - - // Parse XSL data - res.xslt = xsltParseStylesheetDoc(xslDoc); - if (!res.xslt) - return xml; - - // Apply XSL - res.xslResult = xsltApplyStylesheet(res.xslt, res.xmlDoc, 0); - xmlChar* buffer = 0; - int bufferSize; - QString result; - if (!xsltSaveResultToString(&buffer, &bufferSize, res.xslResult, res.xslt)) { - result = QString::fromUtf8(reinterpret_cast(buffer), bufferSize); - std::free(buffer); - } else { - result = xml; - } - - Q_ASSERT(result != xml); - return result; -} - diff --git a/ApiExtractor/docparser.h b/ApiExtractor/docparser.h deleted file mode 100644 index 5573f6851..000000000 --- a/ApiExtractor/docparser.h +++ /dev/null @@ -1,127 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef DOCPARSER_H -#define DOCPARSER_H - -#include "typesystem_typedefs.h" - -#include - -QT_BEGIN_NAMESPACE -class QDomDocument; -class QDomNode; -class QXmlQuery; -QT_END_NAMESPACE - -class AbstractMetaClass; -class DocModification; -class Documentation; - -class DocParser -{ -public: - DocParser(); - virtual ~DocParser(); - virtual void fillDocumentation(AbstractMetaClass* metaClass) = 0; - - /** - * Process and retrieves documentation concerning the entire - * module or library. - * \return object containing module/library documentation information - */ - virtual Documentation retrieveModuleDocumentation() = 0; - - void setDocumentationDataDirectory(const QString& dir) - { - m_docDataDir = dir; - } - - /** - * Informs the location of the XML data generated by the tool - * (e.g.: DoxyGen, qdoc) used to extract the library's documentation - * comment. - * \return the path for the directory containing the XML data created - * from the library's documentation beign parsed. - */ - QString documentationDataDirectory() const - { - return m_docDataDir; - } - - void setLibrarySourceDirectory(const QString& dir) - { - m_libSourceDir = dir; - } - /** - * Informs the location of the library being parsed. The library - * source code is parsed for the documentation comments. - * \return the path for the directory containing the source code of - * the library beign parsed. - */ - QString librarySourceDirectory() const - { - return m_libSourceDir; - } - - void setPackageName(const QString& packageName) - { - m_packageName = packageName; - } - /** - * Retrieves the name of the package (or module or library) being parsed. - * \return the name of the package (module/library) being parsed - */ - QString packageName() const - { - return m_packageName; - } - - /** - * Process and retrieves documentation concerning the entire - * module or library. - * \param name module name - * \return object containing module/library documentation information - * \todo Merge with retrieveModuleDocumentation() on next ABI change. - */ - virtual Documentation retrieveModuleDocumentation(const QString& name) = 0; - -protected: - QString getDocumentation(QXmlQuery& xquery, const QString& query, - const DocModificationList& mods) const; - -private: - QString m_packageName; - QString m_docDataDir; - QString m_libSourceDir; - - QString execXQuery(QXmlQuery& xquery, const QString& query) const; - QString applyDocModifications(const DocModificationList& mods, const QString& xml) const; -}; - -#endif // DOCPARSER_H - diff --git a/ApiExtractor/doxygenparser.cpp b/ApiExtractor/doxygenparser.cpp deleted file mode 100644 index 6b90fe6fc..000000000 --- a/ApiExtractor/doxygenparser.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "doxygenparser.h" -#include "abstractmetalang.h" -#include "reporthandler.h" -#include "typesystem.h" - -#include -#include -#include - -namespace -{ - -QString getSectionKindAttr(const AbstractMetaFunction* func) -{ - if (func->isSignal()) { - return QLatin1String("signal"); - } else { - QString kind = func->isPublic() ? QLatin1String("public") : QLatin1String("protected"); - if (func->isStatic()) - kind += QLatin1String("-static"); - else if (func->isSlot()) - kind += QLatin1String("-slot"); - return kind; - } -} - -} - -Documentation DoxygenParser::retrieveModuleDocumentation() -{ - return retrieveModuleDocumentation(packageName()); -} - -void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) -{ - if (!metaClass) - return; - - QString doxyFileSuffix; - if (metaClass->enclosingClass()) { - doxyFileSuffix += metaClass->enclosingClass()->name(); - doxyFileSuffix += QLatin1String("_1_1"); // FIXME: Check why _1_1!! - } - doxyFileSuffix += metaClass->name(); - doxyFileSuffix += QLatin1String(".xml"); - - const char* prefixes[] = { "class", "struct", "namespace" }; - const int numPrefixes = sizeof(prefixes) / sizeof(const char*); - bool isProperty = false; - - QString doxyFilePath; - for (int i = 0; i < numPrefixes; ++i) { - doxyFilePath = documentationDataDirectory() + QLatin1Char('/') - + QLatin1String(prefixes[i]) + doxyFileSuffix; - if (QFile::exists(doxyFilePath)) - break; - doxyFilePath.clear(); - } - - if (doxyFilePath.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find doxygen file for class " << metaClass->name() << ", tried: " - << QDir::toNativeSeparators(documentationDataDirectory()) - << "/{struct|class|namespace}"<< doxyFileSuffix; - return; - } - QXmlQuery xquery; - xquery.setFocus(QUrl(doxyFilePath)); - - // Get class documentation - QString classDoc = getDocumentation(xquery, QLatin1String("/doxygen/compounddef/detaileddescription"), - metaClass->typeEntry()->docModifications()); - if (classDoc.isEmpty()) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find documentation for class \"" << metaClass->name() << "\"."; - } - metaClass->setDocumentation(classDoc); - - //Functions Documentation - const AbstractMetaFunctionList &funcs = metaClass->functionsInTargetLang(); - for (AbstractMetaFunction *func : funcs) { - if (!func || func->isPrivate()) - continue; - - QString query = QLatin1String("/doxygen/compounddef/sectiondef"); - // properties - if (func->isPropertyReader() || func->isPropertyWriter() - || func->isPropertyResetter()) { - query += QLatin1String("[@kind=\"property\"]/memberdef/name[text()=\"") - + func->propertySpec()->name() + QLatin1String("\"]"); - isProperty = true; - } else { // normal methods - QString kind = getSectionKindAttr(func); - query += QLatin1String("[@kind=\"") + kind - + QLatin1String("-func\"]/memberdef/name[text()=\"") - + func->originalName() + QLatin1String("\"]"); - - if (func->arguments().isEmpty()) { - QString args = func->isConstant() ? QLatin1String("() const ") : QLatin1String("()"); - query += QLatin1String("/../argsstring[text()=\"") + args + QLatin1String("\"]"); - } else { - int i = 1; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - if (!arg->type()->isPrimitive()) { - query += QLatin1String("/../param[") + QString::number(i) - + QLatin1String("]/type/ref[text()=\"") - + arg->type()->name() + QLatin1String("\"]/../.."); - } else { - query += QLatin1String("/../param[") + QString::number(i) - + QLatin1String("]/type[text()=\"") - + arg->type()->name() + QLatin1String("\"]/.."); - } - ++i; - } - } - } - if (!isProperty) { - query += QLatin1String("/../detaileddescription"); - } else { - query = QLatin1Char('(') + query; - query += QLatin1String("/../detaileddescription)[1]"); - } - QString doc = getDocumentation(xquery, query, DocModificationList()); - func->setDocumentation(doc); - isProperty = false; - } - - //Fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (AbstractMetaField *field : fields) { - if (field->isPrivate()) - return; - - QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef/name[text()=\"") - + field->name() + QLatin1String("\"]/../detaileddescription"); - QString doc = getDocumentation(xquery, query, DocModificationList()); - field->setDocumentation(doc); - } - - //Enums - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum *meta_enum : enums) { - QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef[@kind=\"enum\"]/name[text()=\"") - + meta_enum->name() + QLatin1String("\"]/.."); - QString doc = getDocumentation(xquery, query, DocModificationList()); - meta_enum->setDocumentation(doc); - } - -} - -Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ - - QString sourceFile = documentationDataDirectory() + QLatin1String("/indexpage.xml"); - - if (!QFile::exists(sourceFile)) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find doxygen XML file for module " << name << ", tried: " - << QDir::toNativeSeparators(sourceFile); - return Documentation(); - } - - QXmlQuery xquery; - xquery.setFocus(QUrl(sourceFile)); - - // Module documentation - QString query = QLatin1String("/doxygen/compounddef/detaileddescription"); - return Documentation(getDocumentation(xquery, query, DocModificationList())); -} - diff --git a/ApiExtractor/doxygenparser.h b/ApiExtractor/doxygenparser.h deleted file mode 100644 index 3f9ca5142..000000000 --- a/ApiExtractor/doxygenparser.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DOXYGENPARSER_H -#define DOXYGENPARSER_H - -#include "docparser.h" - -class DoxygenParser : public DocParser -{ -public: - DoxygenParser() {} - void fillDocumentation(AbstractMetaClass *metaClass) override; - Documentation retrieveModuleDocumentation() override; - Documentation retrieveModuleDocumentation(const QString& name) override; -}; - -#endif // DOXYGENPARSER_H diff --git a/ApiExtractor/fileout.cpp b/ApiExtractor/fileout.cpp deleted file mode 100644 index c97347fe1..000000000 --- a/ApiExtractor/fileout.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "fileout.h" -#include "reporthandler.h" - -#include -#include -#include - -#include - -bool FileOut::dummy = false; -bool FileOut::diff = false; - -#ifdef Q_OS_LINUX -const char* colorDelete = "\033[31m"; -const char* colorAdd = "\033[32m"; -const char* colorInfo = "\033[36m"; -const char* colorReset = "\033[0m"; -#else -const char* colorDelete = ""; -const char* colorAdd = ""; -const char* colorInfo = ""; -const char* colorReset = ""; -#endif - -FileOut::FileOut(QString n): - name(n), - stream(&tmp), - isDone(false) -{} - -static int* lcsLength(QList a, QList b) -{ - const int height = a.size() + 1; - const int width = b.size() + 1; - - int *res = new int[width * height]; - - for (int row = 0; row < height; row++) - res[width * row] = 0; - - for (int col = 0; col < width; col++) - res[col] = 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; - else - res[width * row + col] = qMax(res[width * row + col-1], - res[width * (row-1) + col]); - } - } - return res; -} - -enum Type { - Add, - Delete, - Unchanged -}; - -struct Unit -{ - Unit(Type type, int pos) : - type(type), - start(pos), - end(pos) {} - - Type type; - int start; - int end; - - void print(QList a, QList b) - { - if (type == Unchanged) { - if ((end - start) > 9) { - for (int i = start; i <= start + 2; i++) - std::printf(" %s\n", a[i].data()); - std::printf("%s=\n= %d more lines\n=%s\n", colorInfo, end - start - 6, colorReset); - for (int i = end - 2; i <= end; i++) - std::printf(" %s\n", a[i].data()); - } else { - for (int i = start; i <= end; i++) - std::printf(" %s\n", a[i].data()); - } - } else if (type == Add) { - std::printf("%s", colorAdd); - for (int i = start; i <= end; i++) - std::printf("+ %s\n", b[i].data()); - std::printf("%s", colorReset); - } else if (type == Delete) { - std::printf("%s", colorDelete); - for (int i = start; i <= end; i++) - std::printf("- %s\n", a[i].data()); - std::printf("%s", colorReset); - } - } -}; - -static QList *unitAppend(QList *res, Type type, int pos) -{ - if (!res) { - res = new QList; - res->append(new Unit(type, pos)); - return res; - } - - Unit *last = res->last(); - if (last->type == type) - last->end = pos; - else - res->append(new Unit(type, pos)); - - return res; -} - -static QList *diffHelper(int *lcs, QList a, QList b, int row, int col) -{ - if (row > 0 && col > 0 && (a[row-1] == b[col-1])) { - return unitAppend(diffHelper(lcs, a, b, row - 1, col - 1), Unchanged, row - 1); - } else { - int width = b.size() + 1; - if ((col > 0) - && (row == 0 || lcs[width * row + col-1] >= lcs[width *(row-1) + col])) { - return unitAppend(diffHelper(lcs, a, b, row, col - 1), Add, col - 1); - } else if ((row > 0) - && (col == 0 || lcs[width * row + col-1] < lcs[width *(row-1) + col])) { - return unitAppend(diffHelper(lcs, a, b, row - 1, col), Delete, row - 1); - } - } - delete lcs; - return 0; -} - -static void diff(QList a, QList b) -{ - QList *res = diffHelper(lcsLength(a, b), a, b, a.size(), b.size()); - for (int i = 0; i < res->size(); i++) { - Unit *unit = res->at(i); - unit->print(a, b); - delete(unit); - } - delete(res); -} - - -FileOut::State FileOut::done() -{ - Q_ASSERT(!isDone); - if (name.isEmpty()) - return Failure; - - isDone = true; - bool fileEqual = false; - QFile fileRead(name); - QFileInfo info(fileRead); - stream.flush(); - QByteArray original; - if (info.exists() && (diff || (info.size() == tmp.size()))) { - if (!fileRead.open(QIODevice::ReadOnly)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("failed to open file '%1' for reading") - .arg(QDir::toNativeSeparators(fileRead.fileName())); - return Failure; - } - - original = fileRead.readAll(); - fileRead.close(); - fileEqual = (original == tmp); - } - - if (fileEqual) - return Unchanged; - - if (!FileOut::dummy) { - QDir dir(info.absolutePath()); - if (!dir.mkpath(dir.absolutePath())) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unable to create directory '%1'") - .arg(QDir::toNativeSeparators(dir.absolutePath())); - return Failure; - } - - QFile fileWrite(name); - if (!fileWrite.open(QIODevice::WriteOnly)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("failed to open file '%1' for writing") - .arg(QDir::toNativeSeparators(fileWrite.fileName())); - return Failure; - } - QTextCodec *codec = QTextCodec::codecForName("UTF-8"); - stream.setCodec(codec); - stream.setDevice(&fileWrite); - stream << tmp; - } - if (diff) { - std::printf("%sFile: %s%s\n", colorInfo, qPrintable(name), colorReset); - ::diff(original.split('\n'), tmp.split('\n')); - std::printf("\n"); - } - - return Success; -} diff --git a/ApiExtractor/fileout.h b/ApiExtractor/fileout.h deleted file mode 100644 index 14ce3a251..000000000 --- a/ApiExtractor/fileout.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FILEOUT_H -#define FILEOUT_H - -#include -#include - -class FileOut : public QObject -{ -private: - QByteArray tmp; - QString name; - -public: - enum State { Failure, Unchanged, Success }; - - FileOut(QString name); - ~FileOut() - { - if (!isDone) - done(); - } - - State done(); - - QTextStream stream; - - static bool dummy; - static bool diff; - -private: - bool isDone; -}; - -#endif // FILEOUT_H diff --git a/ApiExtractor/graph.cpp b/ApiExtractor/graph.cpp deleted file mode 100644 index e6ee660dc..000000000 --- a/ApiExtractor/graph.cpp +++ /dev/null @@ -1,135 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "graph.h" -#include -#include -#include -#include -#include -#include -#include -#include - -struct Graph::GraphPrivate -{ - enum Color { WHITE, GRAY, BLACK }; - typedef QVector > Edges; - typedef QSet::const_iterator EdgeIterator; - - Edges edges; - - GraphPrivate(int numNodes) : edges(numNodes) - { - } - - void dfsVisit(int node, QLinkedList& result, QVector& colors) const - { - colors[node] = GRAY; - EdgeIterator it = edges[node].begin(); - for (; it != edges[node].end(); ++it) { - if (colors[*it] == WHITE) - dfsVisit(*it, result, colors); - else if (colors[*it] == GRAY) // This is not a DAG! - return; - } - colors[node] = BLACK; - result.push_front(node); - } -}; - -Graph::Graph(int numNodes) : m_d(new GraphPrivate(numNodes)) -{ -} - -Graph::~Graph() -{ - delete m_d; -} - -int Graph::nodeCount() const -{ - return m_d->edges.size(); -} - -QLinkedList Graph::topologicalSort() const -{ - int nodeCount = Graph::nodeCount(); - QLinkedList result; - QVector colors(nodeCount, GraphPrivate::WHITE); - - for (int i = 0; i < nodeCount; ++i) { - if (colors[i] == GraphPrivate::WHITE) - m_d->dfsVisit(i, result, colors); - } - - // Not a DAG! - if (result.size() != nodeCount) - return QLinkedList(); - return result; -} - -bool Graph::containsEdge(int from, int to) -{ - return m_d->edges[from].contains(to); -} - -void Graph::addEdge(int from, int to) -{ - Q_ASSERT(to < (int)m_d->edges.size()); - m_d->edges[from].insert(to); -} - -void Graph::removeEdge(int from, int to) -{ - m_d->edges[from].remove(to); -} - -void Graph::dump() const -{ - for (int i = 0; i < m_d->edges.size(); ++i) { - std::cout << i << " -> "; - std::copy(m_d->edges[i].begin(), m_d->edges[i].end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - } -} - -void Graph::dumpDot(const QHash< int, QString >& nodeNames, const QString& fileName) const -{ - QFile output(fileName); - if (!output.open(QIODevice::WriteOnly)) - return; - QTextStream s(&output); - s << "digraph D {\n"; - for (int i = 0; i < m_d->edges.size(); ++i) { - GraphPrivate::EdgeIterator it = m_d->edges[i].begin(); - for (;it != m_d->edges[i].end(); ++it) - s << '"' << nodeNames[i] << "\" -> \"" << nodeNames[*it] << "\"\n"; - } - s << "}\n"; -} diff --git a/ApiExtractor/graph.h b/ApiExtractor/graph.h deleted file mode 100644 index 78b931320..000000000 --- a/ApiExtractor/graph.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef GRAPH_H -#define GRAPH_H - -#include -#include -#include - -/// A graph that can have their nodes topologically sorted. -class Graph -{ -public: - /// Create a new graph with \p numNodes nodes. - Graph(int numNodes); - ~Graph(); - - /// Returns the numbed of nodes in this graph. - int nodeCount() const; - /// Returns true if the graph contains the edge from -> to - bool containsEdge(int from, int to); - /// Adds an edge to this graph. - void addEdge(int from, int to); - /// Removes an edge out of this graph. - void removeEdge(int from, int to); - /// Print this graph to stdout. - void dump() const; - /** - * Dumps a dot graph to a file named \p filename. - * \param nodeNames map used to translate node ids to human readable text. - * \param fileName file name where the output should be written. - */ - void dumpDot(const QHash& nodeNames, const QString& fileName) const; - - /** - * Topologically sort this graph. - * \return A collection with all nodes topologically sorted or an empty collection if a ciclic dependency was found. - */ - QLinkedList topologicalSort() const; -private: - - struct GraphPrivate; - GraphPrivate* m_d; -}; - -#endif diff --git a/ApiExtractor/header_paths.h b/ApiExtractor/header_paths.h deleted file mode 100644 index 3bc26efe0..000000000 --- a/ApiExtractor/header_paths.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HEADER_PATHS_H -#define HEADER_PATHS_H - -#include -#include -#include - -class HeaderPath { -public: - explicit HeaderPath(const QByteArray &p = QByteArray()) : path(p), m_isFramework(false) {} - explicit HeaderPath(const QString &s = QString(), bool isFramework = false) : - path(s.toLatin1()), m_isFramework(isFramework) {} - - QByteArray path; - bool m_isFramework; // macOS framework path - - static QByteArray includeOption(const HeaderPath &p, bool systemInclude = false) - { - QByteArray option; - - if (p.m_isFramework) - option = QByteArrayLiteral("-F"); - else if (systemInclude) - option = QByteArrayLiteral("-isystem"); - else - option = QByteArrayLiteral("-I"); - - return option + p.path; - } -}; - -typedef QList HeaderPaths; - -#endif // HEADER_PATHS_H diff --git a/ApiExtractor/icecc.cmake b/ApiExtractor/icecc.cmake deleted file mode 100644 index b2bf071aa..000000000 --- a/ApiExtractor/icecc.cmake +++ /dev/null @@ -1,11 +0,0 @@ -include (CMakeForceCompiler) -option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") -if (ENABLE_ICECC) - find_program(ICECC icecc) - if (ICECC) - message(STATUS "icecc found! Distributed compilation for all!! huhuhu.") - cmake_force_cxx_compiler(${ICECC} icecc) - else(ICECC) - message(FATAL_ERROR "icecc NOT found! re-run cmake without -DENABLE_ICECC") - endif(ICECC) -endif(ENABLE_ICECC) diff --git a/ApiExtractor/include.cpp b/ApiExtractor/include.cpp deleted file mode 100644 index deae2d2ac..000000000 --- a/ApiExtractor/include.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "include.h" -#include -#include -#include -#include - -QString Include::toString() const -{ - if (m_type == IncludePath) - return QLatin1String("#include <") + m_name + QLatin1Char('>'); - else if (m_type == LocalPath) - return QLatin1String("#include \"") + m_name + QLatin1Char('"'); - else - return QLatin1String("import ") + m_name + QLatin1Char(';'); -} - -uint qHash(const Include& inc) -{ - return qHash(inc.m_name); -} - -QTextStream& operator<<(QTextStream& out, const Include& include) -{ - if (include.isValid()) - out << include.toString() << endl; - return out; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const Include &i) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "Include("; - if (i.isValid()) - d << "type=" << i.type() << ", file=\"" << QDir::toNativeSeparators(i.name()) << '"'; - else - d << "invalid"; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM diff --git a/ApiExtractor/include.h b/ApiExtractor/include.h deleted file mode 100644 index dc4965e1a..000000000 --- a/ApiExtractor/include.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef INCLUDE_H -#define INCLUDE_H - -#include -#include - -QT_BEGIN_NAMESPACE -class QTextStream; -QT_END_NAMESPACE - -class Include -{ -public: - enum IncludeType { - IncludePath, - LocalPath, - TargetLangImport - }; - - Include() : m_type(IncludePath) {} - Include(IncludeType t, const QString &nam) : m_type(t), m_name(nam) {}; - - bool isValid() const - { - return !m_name.isEmpty(); - } - - IncludeType type() const - { - return m_type; - } - - QString name() const - { - return m_name; - } - - QString toString() const; - - bool operator<(const Include& other) const - { - return m_name < other.m_name; - } - - bool operator==(const Include& other) const - { - return m_type == other.m_type && m_name == other.m_name; - } - - friend uint qHash(const Include&); - private: - IncludeType m_type; - QString m_name; -}; - -uint qHash(const Include& inc); -QTextStream& operator<<(QTextStream& out, const Include& include); -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const Include &i); -#endif - -typedef QVector IncludeList; - -#endif diff --git a/ApiExtractor/merge.xsl b/ApiExtractor/merge.xsl deleted file mode 100644 index d0b7eafa5..000000000 --- a/ApiExtractor/merge.xsl +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ApiExtractor/parser/codemodel.cpp b/ApiExtractor/parser/codemodel.cpp deleted file mode 100644 index 667e27344..000000000 --- a/ApiExtractor/parser/codemodel.cpp +++ /dev/null @@ -1,1207 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "codemodel.h" -#include -#include -#include -#include -#include - -// Predicate to find an item by name in a list of QSharedPointer -template class ModelItemNamePredicate : public std::unary_function > -{ -public: - explicit ModelItemNamePredicate(const QString &name) : m_name(name) {} - bool operator()(const QSharedPointer &item) const { return item->name() == m_name; } - -private: - const QString m_name; -}; - -template -static QSharedPointer findModelItem(const QVector > &list, const QString &name) -{ - typedef typename QVector >::const_iterator It; - const It it = std::find_if(list.begin(), list.end(), ModelItemNamePredicate(name)); - return it != list.end() ? *it : QSharedPointer(); -} - -// --------------------------------------------------------------------------- - -CodeModel::CodeModel() : m_globalNamespace(new _NamespaceModelItem(this)) -{ -} - -CodeModel::~CodeModel() -{ -} - -NamespaceModelItem CodeModel::globalNamespace() const -{ - return m_globalNamespace; -} - -void CodeModel::addFile(FileModelItem item) -{ - m_files.append(item); -} - -FileModelItem CodeModel::findFile(const QString &name) const -{ - return findModelItem(m_files, name); -} - -CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, CodeModelItem scope) const -{ - for (int i = 0; i < qualifiedName.size(); ++i) { - // ### Extend to look for members etc too. - const QString &name = qualifiedName.at(i); - - if (NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { - if (NamespaceModelItem tmp_ns = ns->findNamespace(name)) { - scope = tmp_ns; - continue; - } - } - - if (ScopeModelItem ss = qSharedPointerDynamicCast<_ScopeModelItem>(scope)) { - if (ClassModelItem cs = ss->findClass(name)) { - scope = cs; - } else if (EnumModelItem es = ss->findEnum(name)) { - if (i == qualifiedName.size() - 1) - return es; - } else if (TypeDefModelItem tp = ss->findTypeDef(name)) { - if (i == qualifiedName.size() - 1) - return tp; - } else { - // If we don't find the name in the scope chain we - // need to return an empty item to indicate failure... - return CodeModelItem(); - } - } - } - - return scope; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const CodeModel *m) -{ - QDebugStateSaver s(d); - d.noquote(); - d.nospace(); - d << "CodeModel("; - if (m) { - const NamespaceModelItem globalNamespaceP = m->globalNamespace(); - if (globalNamespaceP.data()) - globalNamespaceP->formatDebug(d); - } else { - d << '0'; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) -{ - TypeInfo __result = __lhs; - - __result.setConstant(__result.isConstant() || __rhs.isConstant()); - __result.setVolatile(__result.isVolatile() || __rhs.isVolatile()); - if (__rhs.referenceType() > __result.referenceType()) - __result.setReferenceType(__rhs.referenceType()); - __result.setIndirections(__result.indirections() + __rhs.indirections()); - __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); - - return __result; -} - -TypeInfo TypeInfo::resolveType(TypeInfo const &__type, CodeModelItem __scope) -{ - CodeModel *__model = __scope->model(); - Q_ASSERT(__model != 0); - - return TypeInfo::resolveType(__model->findItem(__type.qualifiedName(), __scope), __type, __scope); -} - -TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, CodeModelItem __scope) -{ - // Copy the type and replace with the proper qualified name. This - // only makes sence to do if we're actually getting a resolved - // type with a namespace. We only get this if the returned type - // has more than 2 entries in the qualified name... This test - // could be improved by returning if the type was found or not. - TypeInfo otherType(__type); - if (__item && __item->qualifiedName().size() > 1) { - otherType.setQualifiedName(__item->qualifiedName()); - } - - if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_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()) { - std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__ - << "() on " << qPrintable(__type.qualifiedName().join(QLatin1String("::"))) - << std::endl; - return otherType; - } - return resolveType(nextItem, combined, __scope); - } - - return otherType; -} - -QString TypeInfo::toString() const -{ - QString tmp; - - tmp += m_qualifiedName.join(QLatin1String("::")); - if (isConstant()) - tmp += QLatin1String(" const"); - - if (isVolatile()) - tmp += QLatin1String(" volatile"); - - if (indirections()) - tmp += QString(indirections(), QLatin1Char('*')); - - switch (referenceType()) { - case NoReference: - break; - case LValueReference: - tmp += QLatin1Char('&'); - break; - case RValueReference: - tmp += QLatin1String("&&"); - break; - } - - if (isFunctionPointer()) { - tmp += QLatin1String(" (*)("); - for (int i = 0; i < m_arguments.count(); ++i) { - if (i != 0) - tmp += QLatin1String(", "); - - tmp += m_arguments.at(i).toString(); - } - tmp += QLatin1Char(')'); - } - - for (const QString &elt : m_arrayElements) { - tmp += QLatin1Char('['); - tmp += elt; - tmp += QLatin1Char(']'); - } - - return tmp; -} - -bool TypeInfo::operator==(const TypeInfo &other) const -{ - if (arrayElements().count() != other.arrayElements().count()) - return false; - -#if defined (RXX_CHECK_ARRAY_ELEMENTS) // ### it'll break - for (int i = 0; i < arrayElements().count(); ++i) { - QString elt1 = arrayElements().at(i).trimmed(); - QString elt2 = other.arrayElements().at(i).trimmed(); - - if (elt1 != elt2) - return false; - } -#endif - - return flags == other.flags - && m_qualifiedName == other.m_qualifiedName - && (!m_functionPointer || m_arguments == other.m_arguments); -} - -#ifndef QT_NO_DEBUG_STREAM -template -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 &d) const -{ - d << '"'; - formatSequence(d, m_qualifiedName.begin(), m_qualifiedName.end(), "\", \""); - d << '"'; - if (m_constant) - d << ", [const]"; - if (m_volatile) - d << ", [volatile]"; - if (m_indirections) - d << ", indirections=" << m_indirections; - switch (m_referenceType) { - case NoReference: - break; - case LValueReference: - d << ", [ref]"; - break; - case RValueReference: - d << ", [rvalref]"; - break; - } - if (m_functionPointer) { - d << ", function ptr("; - formatSequence(d, m_arguments.begin(), m_arguments.end()); - d << ')'; - } - if (!m_arrayElements.isEmpty()) { - d << ", array[" << m_arrayElements.size() << "]["; - formatSequence(d, m_arrayElements.begin(), m_arrayElements.end()); - d << ']'; - } -} - -QDebug operator<<(QDebug d, const TypeInfo &t) -{ - QDebugStateSaver s(d); -#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) - const int verbosity = d.verbosity(); -#else - const int verbosity = 0; -#endif - d.noquote(); - d.nospace(); - d << "TypeInfo("; - if (verbosity > 2) - t.formatDebug(d); - else - d << t.toString(); - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -_CodeModelItem::_CodeModelItem(CodeModel *model, int kind) - : m_model(model), - m_kind(kind), - m_startLine(0), - m_startColumn(0), - m_endLine(0), - m_endColumn(0) -{ -} - -_CodeModelItem::_CodeModelItem(CodeModel *model, const QString &name, int kind) - : m_model(model), - m_kind(kind), - m_startLine(0), - m_startColumn(0), - m_endLine(0), - m_endColumn(0), - m_name(name) -{ -} - -_CodeModelItem::~_CodeModelItem() -{ -} - -int _CodeModelItem::kind() const -{ - return m_kind; -} - -QStringList _CodeModelItem::qualifiedName() const -{ - QStringList q = scope(); - - if (!name().isEmpty()) - q += name(); - - return q; -} - -QString _CodeModelItem::name() const -{ - return m_name; -} - -void _CodeModelItem::setName(const QString &name) -{ - m_name = name; -} - -QStringList _CodeModelItem::scope() const -{ - return m_scope; -} - -void _CodeModelItem::setScope(const QStringList &scope) -{ - m_scope = scope; -} - -QString _CodeModelItem::fileName() const -{ - return m_fileName; -} - -void _CodeModelItem::setFileName(const QString &fileName) -{ - m_fileName = fileName; -} - -FileModelItem _CodeModelItem::file() const -{ - return model()->findFile(fileName()); -} - -void _CodeModelItem::getStartPosition(int *line, int *column) -{ - *line = m_startLine; - *column = m_startColumn; -} - -void _CodeModelItem::setStartPosition(int line, int column) -{ - m_startLine = line; - m_startColumn = column; -} - -void _CodeModelItem::getEndPosition(int *line, int *column) -{ - *line = m_endLine; - *column = m_endColumn; -} - -void _CodeModelItem::setEndPosition(int line, int column) -{ - m_endLine = line; - m_endColumn = column; -} - -#ifndef QT_NO_DEBUG_STREAM -template -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->data(); - } -} - -void _CodeModelItem::formatKind(QDebug &d, int k) -{ - switch (k) { - case Kind_Argument: - d << "ArgumentModelItem"; - break; - case Kind_Class: - d << "ClassModelItem"; - break; - case Kind_Enum: - d << "EnumModelItem"; - break; - case Kind_Enumerator: - d << "EnumeratorModelItem"; - break; - case Kind_File: - d << "FileModelItem"; - break; - case Kind_Function: - d << "FunctionModelItem"; - break; - case Kind_Member: - d << "MemberModelItem"; - break; - case Kind_Namespace: - d << "NamespaceModelItem"; - break; - case Kind_Variable: - d << "VariableModelItem"; - break; - case Kind_Scope: - d << "ScopeModelItem"; - break; - case Kind_TemplateParameter: - d << "TemplateParameter"; - break; - case Kind_TypeDef: - d << "TypeDefModelItem"; - break; - default: - d << "CodeModelItem"; - break; - } -} - -void _CodeModelItem::formatDebug(QDebug &d) const -{ - d << "(\"" << name() << '"'; - if (!m_scope.isEmpty()) { - d << ", scope="; - formatSequence(d, m_scope.cbegin(), m_scope.cend(), "::"); - } - if (!m_fileName.isEmpty()) { - d << ", file=\"" << QDir::toNativeSeparators(m_fileName); - if (m_startLine > 0) - d << ':' << m_startLine; - d << '"'; - } -} - -QDebug operator<<(QDebug d, const _CodeModelItem *t) -{ - QDebugStateSaver s(d); - d.noquote(); - d.nospace(); - if (!t) { - d << "CodeModelItem(0)"; - return d; - } - _CodeModelItem::formatKind(d, t->kind()); - t->formatDebug(d); - switch (t->kind()) { - case _CodeModelItem::Kind_Class: - d << " /* class " << t->name() << " */"; - break; - case _CodeModelItem::Kind_Namespace: - d << " /* namespace " << t->name() << " */"; - break; - } - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -_ClassModelItem::~_ClassModelItem() -{ -} - -QStringList _ClassModelItem::baseClasses() const -{ - return m_baseClasses; -} - -void _ClassModelItem::setBaseClasses(const QStringList &baseClasses) -{ - m_baseClasses = baseClasses; -} - -TemplateParameterList _ClassModelItem::templateParameters() const -{ - return m_templateParameters; -} - -void _ClassModelItem::setTemplateParameters(const TemplateParameterList &templateParameters) -{ - m_templateParameters = templateParameters; -} - -void _ClassModelItem::addBaseClass(const QString &baseClass) -{ - m_baseClasses.append(baseClass); -} - -bool _ClassModelItem::extendsClass(const QString &name) const -{ - return m_baseClasses.contains(name); -} - -void _ClassModelItem::setClassType(CodeModel::ClassType type) -{ - m_classType = type; -} - -CodeModel::ClassType _ClassModelItem::classType() const -{ - return m_classType; -} - -void _ClassModelItem::addPropertyDeclaration(const QString &propertyDeclaration) -{ - m_propertyDeclarations << propertyDeclaration; -} - -#ifndef QT_NO_DEBUG_STREAM -template -static void formatModelItemList(QDebug &d, const char *prefix, const List &l, - const char *separator = ", ") -{ - if (const int size = l.size()) { - d << prefix << '[' << size << "]("; - for (int i = 0; i < size; ++i) { - if (i) - d << separator; - l.at(i)->formatDebug(d); - } - d << ')'; - } -} - -void _ClassModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - if (!m_baseClasses.isEmpty()) - d << ", inherits=" << m_baseClasses; - formatModelItemList(d, ", templateParameters=", m_templateParameters); - formatScopeItemsDebug(d); -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item) -{ - for (const FunctionModelItem &fun : qAsConst(m_functions)) { - if (fun->name() == item->name() && fun->isSimilar(item)) - return fun; - - } - return FunctionModelItem(); -} - -_ScopeModelItem::~_ScopeModelItem() -{ -} - -void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration) -{ - m_enumsDeclarations << enumsDeclaration; -} - -void _ScopeModelItem::addClass(ClassModelItem item) -{ - m_classes.append(item); -} - -void _ScopeModelItem::addFunction(FunctionModelItem item) -{ - m_functions.append(item); -} - -void _ScopeModelItem::addVariable(VariableModelItem item) -{ - m_variables.append(item); -} - -void _ScopeModelItem::addTypeDef(TypeDefModelItem item) -{ - m_typeDefs.append(item); -} - -void _ScopeModelItem::addEnum(EnumModelItem item) -{ - m_enums.append(item); -} - -#ifndef QT_NO_DEBUG_STREAM -template -static void formatScopeHash(QDebug &d, const char *prefix, const Hash &h, - const char *separator = ", ", - bool trailingNewLine = false) -{ - typedef typename Hash::ConstIterator HashIterator; - if (!h.isEmpty()) { - d << prefix << '[' << h.size() << "]("; - const HashIterator begin = h.begin(); - const HashIterator end = h.end(); - for (HashIterator it = begin; it != end; ++it) { // Omit the names as they are repeated - if (it != begin) - d << separator; - d << it.value().data(); - } - d << ')'; - if (trailingNewLine) - d << '\n'; - } -} - -template -static void formatScopeList(QDebug &d, const char *prefix, const List &l, - const char *separator = ", ", - bool trailingNewLine = false) -{ - if (!l.isEmpty()) { - d << prefix << '[' << l.size() << "]("; - formatPtrSequence(d, l.begin(), l.end(), separator); - d << ')'; - if (trailingNewLine) - d << '\n'; - } -} - -void _ScopeModelItem::formatScopeItemsDebug(QDebug &d) const -{ - formatScopeList(d, ", classes=", m_classes, "\n", true); - formatScopeList(d, ", enums=", m_enums, "\n", true); - formatScopeList(d, ", aliases=", m_typeDefs, "\n", true); - formatScopeList(d, ", functions=", m_functions, "\n", true); - formatScopeList(d, ", variables=", m_variables); -} - -void _ScopeModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - formatScopeItemsDebug(d); -} -#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" (as seen for methods -// from within the class "Vector"). -class ClassNamePredicate : public std::unary_function -{ -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()) == QLatin1Char('<'); - } - -private: - const QString m_name; -}; -} // namespace - -ClassModelItem _ScopeModelItem::findClass(const QString &name) const -{ - // A fully qualified template is matched by name only - const ClassList::const_iterator it = name.contains(QLatin1Char('<')) - ? std::find_if(m_classes.begin(), m_classes.end(), ModelItemNamePredicate<_ClassModelItem>(name)) - : std::find_if(m_classes.begin(), m_classes.end(), ClassNamePredicate(name)); - return it != m_classes.end() ? *it : ClassModelItem(); -} - -VariableModelItem _ScopeModelItem::findVariable(const QString &name) const -{ - return findModelItem(m_variables, name); -} - -TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const -{ - return findModelItem(m_typeDefs, name); -} - -EnumModelItem _ScopeModelItem::findEnum(const QString &name) const -{ - return findModelItem(m_enums, name); -} - -FunctionList _ScopeModelItem::findFunctions(const QString &name) const -{ - FunctionList result; - for (const FunctionModelItem &func : m_functions) { - if (func->name() == name) - result.append(func); - } - return result; -} - -// --------------------------------------------------------------------------- -_NamespaceModelItem::~_NamespaceModelItem() -{ -} - -QSet _NamespaceModelItem::uniqueNamespaces() const -{ - QSet result; - for (const NamespaceModelItem &n : m_namespaces) - result.insert(n); - return result; -} - -void _NamespaceModelItem::addNamespace(NamespaceModelItem item) -{ - m_namespaces.append(item); -} - -NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const -{ - return findModelItem(m_namespaces, name); -} - -_FileModelItem::~_FileModelItem() -{ -} - -#ifndef QT_NO_DEBUG_STREAM -void _NamespaceModelItem::formatDebug(QDebug &d) const -{ - _ScopeModelItem::formatDebug(d); - formatScopeList(d, ", namespaces=", m_namespaces); -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -_ArgumentModelItem::~_ArgumentModelItem() -{ -} - -TypeInfo _ArgumentModelItem::type() const -{ - return m_type; -} - -void _ArgumentModelItem::setType(const TypeInfo &type) -{ - m_type = type; -} - -bool _ArgumentModelItem::defaultValue() const -{ - return m_defaultValue; -} - -void _ArgumentModelItem::setDefaultValue(bool defaultValue) -{ - m_defaultValue = defaultValue; -} - -#ifndef QT_NO_DEBUG_STREAM -void _ArgumentModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - d << ", type=" << m_type; - if (m_defaultValue) - d << ", defaultValue=\"" << m_defaultValueExpression << '"'; -} -#endif // !QT_NO_DEBUG_STREAM -// --------------------------------------------------------------------------- -_FunctionModelItem::~_FunctionModelItem() -{ -} - -bool _FunctionModelItem::isSimilar(FunctionModelItem other) const -{ - if (name() != other->name()) - return false; - - if (isConstant() != other->isConstant()) - return false; - - if (isVariadics() != other->isVariadics()) - return false; - - if (arguments().count() != other->arguments().count()) - return false; - - // ### check the template parameters - - for (int i = 0; i < arguments().count(); ++i) { - ArgumentModelItem arg1 = arguments().at(i); - ArgumentModelItem arg2 = other->arguments().at(i); - - if (arg1->type() != arg2->type()) - return false; - } - - return true; -} - -ArgumentList _FunctionModelItem::arguments() const -{ - return m_arguments; -} - -void _FunctionModelItem::addArgument(ArgumentModelItem item) -{ - m_arguments.append(item); -} - -CodeModel::FunctionType _FunctionModelItem::functionType() const -{ - return m_functionType; -} - -void _FunctionModelItem::setFunctionType(CodeModel::FunctionType functionType) -{ - m_functionType = functionType; -} - -bool _FunctionModelItem::isVariadics() const -{ - return m_isVariadics; -} - -void _FunctionModelItem::setVariadics(bool isVariadics) -{ - m_isVariadics = isVariadics; -} - -bool _FunctionModelItem::isVirtual() const -{ - return m_isVirtual; -} - -void _FunctionModelItem::setVirtual(bool isVirtual) -{ - m_isVirtual = isVirtual; -} - -bool _FunctionModelItem::isInline() const -{ - return m_isInline; -} - -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::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; -} - -#ifndef QT_NO_DEBUG_STREAM -void _FunctionModelItem::formatDebug(QDebug &d) const -{ - _MemberModelItem::formatDebug(d); - d << ", type=" << m_functionType; - if (m_isInline) - d << " [inline]"; - if (m_isAbstract) - d << " [abstract]"; - if (m_isExplicit) - d << " [explicit]"; - if (m_isInvokable) - d << " [invokable]"; - formatModelItemList(d, ", arguments=", m_arguments); - if (m_isVariadics) - d << ",..."; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -TypeInfo _TypeDefModelItem::type() const -{ - return m_type; -} - -void _TypeDefModelItem::setType(const TypeInfo &type) -{ - m_type = type; -} - -#ifndef QT_NO_DEBUG_STREAM -void _TypeDefModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - d << ", type=" << m_type; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -CodeModel::AccessPolicy _EnumModelItem::accessPolicy() const -{ - return m_accessPolicy; -} - -_EnumModelItem::~_EnumModelItem() -{ -} - -void _EnumModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy) -{ - m_accessPolicy = accessPolicy; -} - -EnumeratorList _EnumModelItem::enumerators() const -{ - return m_enumerators; -} - -void _EnumModelItem::addEnumerator(EnumeratorModelItem item) -{ - m_enumerators.append(item); -} - -bool _EnumModelItem::isAnonymous() const -{ - return m_anonymous; -} - -void _EnumModelItem::setAnonymous(bool anonymous) -{ - m_anonymous = anonymous; -} - -#ifndef QT_NO_DEBUG_STREAM -void _EnumModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - if (m_anonymous) - d << " (anonymous)"; - formatModelItemList(d, ", enumerators=", m_enumerators); -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -_EnumeratorModelItem::~_EnumeratorModelItem() -{ -} - -QString _EnumeratorModelItem::value() const -{ - return m_value; -} - -void _EnumeratorModelItem::setValue(const QString &value) -{ - m_value = value; -} - -#ifndef QT_NO_DEBUG_STREAM -void _EnumeratorModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - if (!m_value.isEmpty()) - d << ", value=\"" << m_value << '"'; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -_TemplateParameterModelItem::~_TemplateParameterModelItem() -{ -} - -TypeInfo _TemplateParameterModelItem::type() const -{ - return m_type; -} - -void _TemplateParameterModelItem::setType(const TypeInfo &type) -{ - m_type = type; -} - -bool _TemplateParameterModelItem::defaultValue() const -{ - return m_defaultValue; -} - -void _TemplateParameterModelItem::setDefaultValue(bool defaultValue) -{ - m_defaultValue = defaultValue; -} - -#ifndef QT_NO_DEBUG_STREAM -void _TemplateParameterModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - d << ", type=" << m_type; - if (m_defaultValue) - d << " [defaultValue]"; -} -#endif // !QT_NO_DEBUG_STREAM - -// --------------------------------------------------------------------------- -TypeInfo _MemberModelItem::type() const -{ - return m_type; -} - -void _MemberModelItem::setType(const TypeInfo &type) -{ - m_type = type; -} - -CodeModel::AccessPolicy _MemberModelItem::accessPolicy() const -{ - return m_accessPolicy; -} - -_MemberModelItem::~_MemberModelItem() -{ -} - -void _MemberModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy) -{ - m_accessPolicy = accessPolicy; -} - -bool _MemberModelItem::isStatic() const -{ - return m_isStatic; -} - -void _MemberModelItem::setStatic(bool isStatic) -{ - m_isStatic = isStatic; -} - -bool _MemberModelItem::isConstant() const -{ - return m_isConstant; -} - -void _MemberModelItem::setConstant(bool isConstant) -{ - m_isConstant = isConstant; -} - -bool _MemberModelItem::isVolatile() const -{ - return m_isVolatile; -} - -void _MemberModelItem::setVolatile(bool isVolatile) -{ - m_isVolatile = isVolatile; -} - -bool _MemberModelItem::isAuto() const -{ - return m_isAuto; -} - -void _MemberModelItem::setAuto(bool isAuto) -{ - m_isAuto = isAuto; -} - -bool _MemberModelItem::isFriend() const -{ - return m_isFriend; -} - -void _MemberModelItem::setFriend(bool isFriend) -{ - m_isFriend = isFriend; -} - -bool _MemberModelItem::isRegister() const -{ - return m_isRegister; -} - -void _MemberModelItem::setRegister(bool isRegister) -{ - m_isRegister = isRegister; -} - -bool _MemberModelItem::isExtern() const -{ - return m_isExtern; -} - -void _MemberModelItem::setExtern(bool isExtern) -{ - m_isExtern = isExtern; -} - -bool _MemberModelItem::isMutable() const -{ - return m_isMutable; -} - -void _MemberModelItem::setMutable(bool isMutable) -{ - m_isMutable = isMutable; -} - -#ifndef QT_NO_DEBUG_STREAM -void _MemberModelItem::formatDebug(QDebug &d) const -{ - _CodeModelItem::formatDebug(d); - switch (m_accessPolicy) { - case CodeModel::Public: - d << ", public"; - break; - case CodeModel::Protected: - d << ", protected"; - break; - case CodeModel::Private: - d << ", private"; - break; - } - d << ", type="; - if (m_isConstant) - d << "const "; - if (m_isVolatile) - d << "volatile "; - if (m_isStatic) - d << "static "; - if (m_isAuto) - d << "auto "; - if (m_isFriend) - d << "friend "; - if (m_isRegister) - d << "register "; - if (m_isExtern) - d << "extern "; - if (m_isMutable) - d << "mutable "; - d << m_type; - formatScopeList(d, ", templateParameters", m_templateParameters); -} -#endif // !QT_NO_DEBUG_STREAM - -// kate: space-indent on; indent-width 2; replace-tabs on; - diff --git a/ApiExtractor/parser/codemodel.h b/ApiExtractor/parser/codemodel.h deleted file mode 100644 index ea16e6912..000000000 --- a/ApiExtractor/parser/codemodel.h +++ /dev/null @@ -1,687 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef CODEMODEL_H -#define CODEMODEL_H - -#include "codemodel_fwd.h" -#include "codemodel_enums.h" - -#include -#include -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) - -#define DECLARE_MODEL_NODE(k) \ - enum { __node_kind = Kind_##k }; - -class CodeModel -{ -public: - enum AccessPolicy { - Public, - Protected, - Private - }; - - enum FunctionType { - Normal, - Signal, - Slot - }; - - enum ClassType { - Class, - Struct, - Union - }; - -public: - CodeModel(); - virtual ~CodeModel(); - - FileList files() const { return m_files; } - NamespaceModelItem globalNamespace() const; - - void addFile(FileModelItem item); - FileModelItem findFile(const QString &name) const; - - CodeModelItem findItem(const QStringList &qualifiedName, CodeModelItem scope) const; - -private: - FileList m_files; - NamespaceModelItem m_globalNamespace; - -private: - CodeModel(const CodeModel &other); - void operator = (const CodeModel &other); -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const CodeModel *m); -#endif - -class TypeInfo -{ -public: - TypeInfo() : flags(0), m_referenceType(NoReference) {} - - QStringList qualifiedName() const - { - return m_qualifiedName; - } - - void setQualifiedName(const QStringList &qualified_name) - { - m_qualifiedName = qualified_name; - } - - bool isConstant() const - { - return m_constant; - } - - void setConstant(bool is) - { - m_constant = is; - } - - bool isVolatile() const - { - return m_volatile; - } - - void setVolatile(bool is) - { - m_volatile = is; - } - - ReferenceType referenceType() const { return m_referenceType; } - void setReferenceType(ReferenceType r) { m_referenceType = r; } - - int indirections() const - { - return m_indirections; - } - - void setIndirections(int indirections) - { - m_indirections = indirections; - } - - bool isFunctionPointer() const - { - return m_functionPointer; - } - void setFunctionPointer(bool is) - { - m_functionPointer = is; - } - - QStringList arrayElements() const - { - return m_arrayElements; - } - void setArrayElements(const QStringList &arrayElements) - { - m_arrayElements = arrayElements; - } - - QVector arguments() const { return m_arguments; } - - void setArguments(const QVector &arguments); - - void addArgument(const TypeInfo &arg) - { - m_arguments.append(arg); - } - - bool operator==(const TypeInfo &other) const; - - bool operator!=(const TypeInfo &other) const - { - return !(*this == other); - } - - // ### arrays and templates?? - - QString toString() const; - - static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs); - static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const; -#endif - -private: - static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope); - - QStringList m_qualifiedName; - QStringList m_arrayElements; - QVector m_arguments; - - union { - uint flags; - - struct { - uint m_constant: 1; - uint m_volatile: 1; - uint m_functionPointer: 1; - uint m_indirections: 6; - uint m_padding: 23; - }; - }; - - ReferenceType m_referenceType; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeInfo &t); -#endif - -class _CodeModelItem -{ - Q_DISABLE_COPY(_CodeModelItem) -public: - enum Kind { - /* These are bit-flags resembling inheritance */ - Kind_Scope = 0x1, - Kind_Namespace = 0x2 | Kind_Scope, - Kind_Member = 0x4, - Kind_Function = 0x8 | Kind_Member, - KindMask = 0xf, - - /* These are for classes that are not inherited from */ - FirstKind = 0x8, - Kind_Argument = 1 << FirstKind, - Kind_Class = 2 << FirstKind | Kind_Scope, - Kind_Enum = 3 << FirstKind, - Kind_Enumerator = 4 << FirstKind, - Kind_File = 5 << FirstKind | Kind_Namespace, - Kind_TemplateParameter = 7 << FirstKind, - Kind_TypeDef = 8 << FirstKind, - Kind_Variable = 9 << FirstKind | Kind_Member - }; - -public: - virtual ~_CodeModelItem(); - - int kind() const; - - QStringList qualifiedName() const; - - QString name() const; - void setName(const QString &name); - - QStringList scope() const; - void setScope(const QStringList &scope); - - QString fileName() const; - void setFileName(const QString &fileName); - - FileModelItem file() const; - - void getStartPosition(int *line, int *column); - void setStartPosition(int line, int column); - - void getEndPosition(int *line, int *column); - void setEndPosition(int line, int column); - - inline CodeModel *model() const { return m_model; } - -#ifndef QT_NO_DEBUG_STREAM - static void formatKind(QDebug &d, int k); - virtual void formatDebug(QDebug &d) const; -#endif - -protected: - explicit _CodeModelItem(CodeModel *model, int kind); - explicit _CodeModelItem(CodeModel *model, const QString &name, int kind); - -private: - CodeModel *m_model; - int m_kind; - int m_startLine; - int m_startColumn; - int m_endLine; - int m_endColumn; - QString m_name; - QString m_fileName; - QStringList m_scope; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const _CodeModelItem *t); -#endif - -class _ScopeModelItem: public _CodeModelItem -{ -public: - DECLARE_MODEL_NODE(Scope) - - ~_ScopeModelItem(); - - ClassList classes() const { return m_classes; } - EnumList enums() const { return m_enums; } - inline FunctionList functions() const { return m_functions; } - TypeDefList typeDefs() const { return m_typeDefs; } - VariableList variables() const { return m_variables; } - - void addClass(ClassModelItem item); - void addEnum(EnumModelItem item); - void addFunction(FunctionModelItem item); - void addTypeDef(TypeDefModelItem item); - void addVariable(VariableModelItem item); - - ClassModelItem findClass(const QString &name) const; - EnumModelItem findEnum(const QString &name) const; - FunctionList findFunctions(const QString &name) const; - TypeDefModelItem findTypeDef(const QString &name) const; - VariableModelItem findVariable(const QString &name) const; - - void addEnumsDeclaration(const QString &enumsDeclaration); - QStringList enumsDeclarations() const { return m_enumsDeclarations; } - - FunctionModelItem declaredFunction(FunctionModelItem item); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#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) {} - -#ifndef QT_NO_DEBUG_STREAM - void formatScopeItemsDebug(QDebug &d) const; -#endif - -private: - ClassList m_classes; - EnumList m_enums; - TypeDefList m_typeDefs; - VariableList m_variables; - FunctionList m_functions; - -private: - QStringList m_enumsDeclarations; -}; - -class _ClassModelItem: public _ScopeModelItem -{ -public: - DECLARE_MODEL_NODE(Class) - - 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) {} - ~_ClassModelItem(); - - QStringList baseClasses() const; - - void setBaseClasses(const QStringList &baseClasses); - void addBaseClass(const QString &baseClass); - - TemplateParameterList templateParameters() const; - void setTemplateParameters(const TemplateParameterList &templateParameters); - - bool extendsClass(const QString &name) const; - - void setClassType(CodeModel::ClassType type); - CodeModel::ClassType classType() const; - - void addPropertyDeclaration(const QString &propertyDeclaration); - QStringList propertyDeclarations() const { return m_propertyDeclarations; } - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - QStringList m_baseClasses; - TemplateParameterList m_templateParameters; - CodeModel::ClassType m_classType; - - QStringList m_propertyDeclarations; -}; - -class _NamespaceModelItem: public _ScopeModelItem -{ -public: - 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) {} - ~_NamespaceModelItem(); - - NamespaceList namespaces() const { return m_namespaces; } - QSet uniqueNamespaces() const; - - void addNamespace(NamespaceModelItem item); - - NamespaceModelItem findNamespace(const QString &name) const; - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - NamespaceList m_namespaces; -}; - -class _FileModelItem: public _NamespaceModelItem -{ -public: - 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) {} - ~_FileModelItem(); -}; - -class _ArgumentModelItem: public _CodeModelItem -{ -public: - 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) {} - ~_ArgumentModelItem(); - - TypeInfo type() const; - void setType(const TypeInfo &type); - - bool defaultValue() const; - void setDefaultValue(bool defaultValue); - - QString defaultValueExpression() const { return m_defaultValueExpression; } - void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; } - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - TypeInfo m_type; - QString m_defaultValueExpression; - bool m_defaultValue; -}; - -class _MemberModelItem: public _CodeModelItem -{ -public: - DECLARE_MODEL_NODE(Member) - - explicit _MemberModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_accessPolicy(CodeModel::Public), m_flags(0) {} - explicit _MemberModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_accessPolicy(CodeModel::Public), m_flags(0) {} - ~_MemberModelItem(); - - bool isConstant() const; - void setConstant(bool isConstant); - - bool isVolatile() const; - void setVolatile(bool isVolatile); - - bool isStatic() const; - void setStatic(bool isStatic); - - bool isAuto() const; - void setAuto(bool isAuto); - - bool isFriend() const; - void setFriend(bool isFriend); - - bool isRegister() const; - void setRegister(bool isRegister); - - bool isExtern() const; - void setExtern(bool isExtern); - - bool isMutable() const; - void setMutable(bool isMutable); - - CodeModel::AccessPolicy accessPolicy() const; - void setAccessPolicy(CodeModel::AccessPolicy accessPolicy); - - TemplateParameterList templateParameters() const { return m_templateParameters; } - void setTemplateParameters(const TemplateParameterList &templateParameters) { m_templateParameters = templateParameters; } - - TypeInfo type() const; - void setType(const TypeInfo &type); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - TemplateParameterList m_templateParameters; - TypeInfo m_type; - CodeModel::AccessPolicy m_accessPolicy; - union { - struct { - uint m_isConstant: 1; - uint m_isVolatile: 1; - uint m_isStatic: 1; - uint m_isAuto: 1; - uint m_isFriend: 1; - uint m_isRegister: 1; - uint m_isExtern: 1; - uint m_isMutable: 1; - }; - uint m_flags; - }; - -}; - -class _FunctionModelItem: public _MemberModelItem -{ -public: - 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) {} - ~_FunctionModelItem(); - - ArgumentList arguments() const; - - void addArgument(ArgumentModelItem item); - - CodeModel::FunctionType functionType() const; - void setFunctionType(CodeModel::FunctionType functionType); - - bool isVirtual() const; - void setVirtual(bool isVirtual); - - bool isInline() const; - void setInline(bool isInline); - - bool isExplicit() const; - void setExplicit(bool isExplicit); - - bool isInvokable() const; // Qt - void setInvokable(bool isInvokable); // Qt - - bool isAbstract() const; - void setAbstract(bool isAbstract); - - bool isVariadics() const; - void setVariadics(bool isVariadics); - - bool isSimilar(FunctionModelItem other) const; - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - ArgumentList m_arguments; - CodeModel::FunctionType m_functionType; - union { - struct { - uint m_isVirtual: 1; - uint m_isInline: 1; - uint m_isAbstract: 1; - uint m_isExplicit: 1; - uint m_isVariadics: 1; - uint m_isInvokable : 1; // Qt - }; - uint m_flags; - }; -}; - -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) {} -}; - -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) {} - - TypeInfo type() const; - void setType(const TypeInfo &type); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - TypeInfo m_type; -}; - -class _EnumModelItem: public _CodeModelItem -{ -public: - DECLARE_MODEL_NODE(Enum) - - explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} - explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} - ~_EnumModelItem(); - - CodeModel::AccessPolicy accessPolicy() const; - void setAccessPolicy(CodeModel::AccessPolicy accessPolicy); - - EnumeratorList enumerators() const; - void addEnumerator(EnumeratorModelItem item); - bool isAnonymous() const; - void setAnonymous(bool anonymous); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - CodeModel::AccessPolicy m_accessPolicy; - EnumeratorList m_enumerators; - bool m_anonymous; -}; - -class _EnumeratorModelItem: public _CodeModelItem -{ -public: - 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) {} - ~_EnumeratorModelItem(); - - QString value() const; - void setValue(const QString &value); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - QString m_value; -}; - -class _TemplateParameterModelItem: public _CodeModelItem -{ -public: - 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) {} - ~_TemplateParameterModelItem(); - - TypeInfo type() const; - void setType(const TypeInfo &type); - - bool defaultValue() const; - void setDefaultValue(bool defaultValue); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const override; -#endif - -private: - TypeInfo m_type; - bool m_defaultValue; -}; - -#endif // CODEMODEL_H - -// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/ApiExtractor/parser/codemodel_enums.h b/ApiExtractor/parser/codemodel_enums.h deleted file mode 100644 index aa8b051d8..000000000 --- a/ApiExtractor/parser/codemodel_enums.h +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CODEMODEL_ENUMS_H -#define CODEMODEL_ENUMS_H - -enum ReferenceType { - NoReference, - LValueReference, - RValueReference -}; - -#endif // CODEMODEL_ENUMS_H diff --git a/ApiExtractor/parser/codemodel_fwd.h b/ApiExtractor/parser/codemodel_fwd.h deleted file mode 100644 index d5a9f2850..000000000 --- a/ApiExtractor/parser/codemodel_fwd.h +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2002-2005 Roberto Raggi -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef CODEMODEL_FWD_H -#define CODEMODEL_FWD_H - -#include -#include - -// forward declarations -class CodeModel; -class _ArgumentModelItem; -class _ClassModelItem; -class _CodeModelItem; -class _EnumModelItem; -class _EnumeratorModelItem; -class _FileModelItem; -class _FunctionModelItem; -class _NamespaceModelItem; -class _ScopeModelItem; -class _TemplateParameterModelItem; -class _TypeDefModelItem; -class _VariableModelItem; -class _MemberModelItem; -class TypeInfo; - -typedef QSharedPointer<_ArgumentModelItem> ArgumentModelItem; -typedef QSharedPointer<_ClassModelItem> ClassModelItem; -typedef QSharedPointer<_CodeModelItem> CodeModelItem; -typedef QSharedPointer<_EnumModelItem> EnumModelItem; -typedef QSharedPointer<_EnumeratorModelItem> EnumeratorModelItem; -typedef QSharedPointer<_FileModelItem> FileModelItem; -typedef QSharedPointer<_FunctionModelItem> FunctionModelItem; -typedef QSharedPointer<_NamespaceModelItem> NamespaceModelItem; -typedef QSharedPointer<_ScopeModelItem> ScopeModelItem; -typedef QSharedPointer<_TemplateParameterModelItem> TemplateParameterModelItem; -typedef QSharedPointer<_TypeDefModelItem> TypeDefModelItem; -typedef QSharedPointer<_VariableModelItem> VariableModelItem; -typedef QSharedPointer<_MemberModelItem> MemberModelItem; - -typedef QVector ArgumentList; -typedef QVector ClassList; -typedef QVector ItemList; -typedef QVector EnumList; -typedef QVector EnumeratorList; -typedef QVector FileList; -typedef QVector FunctionList; -typedef QVector NamespaceList; -typedef QVector ScopeList; -typedef QVector TemplateParameterList; -typedef QVector TypeDefList; -typedef QVector VariableList; -typedef QVector MemberList; - -#endif // CODEMODEL_FWD_H diff --git a/ApiExtractor/qtdocparser.cpp b/ApiExtractor/qtdocparser.cpp deleted file mode 100644 index 00e2384f0..000000000 --- a/ApiExtractor/qtdocparser.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtdocparser.h" -#include "abstractmetalang.h" -#include "reporthandler.h" -#include "typesystem.h" - -#include -#include -#include -#include - -Documentation QtDocParser::retrieveModuleDocumentation() -{ - return retrieveModuleDocumentation(packageName()); -} - -void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) -{ - if (!metaClass) - return; - - QString scope = metaClass->name(); - const AbstractMetaClass* context = metaClass->enclosingClass(); - while(context) { - if (context->enclosingClass() == 0) - break; - context = context->enclosingClass(); - } - - QString filename = metaClass->qualifiedCppName().toLower(); - filename.replace(QLatin1String("::"), QLatin1String("-")); - QString sourceFile = documentationDataDirectory() + QLatin1Char('/') - + filename + QLatin1String(".xml"); - if (metaClass->enclosingClass()) - sourceFile.replace(QLatin1String("::"), QLatin1String("-")); - - if (!QFile::exists(sourceFile)) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find qdoc3 file for class " << metaClass->name() << ", tried: " - << QDir::toNativeSeparators(sourceFile); - return; - } - - QXmlQuery xquery; - xquery.setFocus(QUrl(sourceFile)); - - QString className = metaClass->name(); - - // Class/Namespace documentation - QString type = metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class"); - QString query = QLatin1String("/WebXML/document/") + type + QLatin1String("[@name=\"") - + className + QLatin1String("\"]/description"); - - 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); - } - - Documentation doc(getDocumentation(xquery, query, classModifs)); - metaClass->setDocumentation(doc); - - - //Functions Documentation - const AbstractMetaFunctionList &funcs = metaClass->functionsInTargetLang(); - for (AbstractMetaFunction *func : funcs) { - if (!func || func->isPrivate()) - continue; - - QString query = QLatin1String("/WebXML/document/") + type - + QLatin1String("[@name=\"") + className + QLatin1String("\"]"); - // properties - if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) { - query += QLatin1String("/property[@name=\"") + func->propertySpec()->name() - + QLatin1String("\"]"); - } else { // normal methods - QString isConst = func->isConstant() ? QLatin1String("true") : QLatin1String("false"); - query += QLatin1String("/function[@name=\"") + func->originalName() - + QLatin1String("\" and count(parameter)=") - + QString::number(func->arguments().count()) - + QLatin1String(" and @const=\"") + isConst + QLatin1String("\"]"); - - const AbstractMetaArgumentList &arguments = func->arguments(); - for (int i = 0, size = arguments.size(); i < size; ++i) { - const AbstractMetaArgument *arg = arguments.at(i); - QString type = arg->type()->name(); - - if (arg->type()->isConstant()) - type.prepend(QLatin1String("const ")); - - if (arg->type()->referenceType() == LValueReference) { - type += QLatin1String(" &"); - } else if (arg->type()->referenceType() == RValueReference) { - type += QLatin1String(" &&"); - } else if (arg->type()->indirections()) { - type += QLatin1Char(' '); - for (int j = 0, max = arg->type()->indirections(); j < max; ++j) - type += QLatin1Char('*'); - } - query += QLatin1String("/parameter[") + QString::number(i + 1) - + QLatin1String("][@left=\"") + type + QLatin1String("\"]/.."); - } - } - query += QLatin1String("/description"); - DocModificationList funcModifs; - for (const DocModification &funcModif : qAsConst(signedModifs)) { - if (funcModif.signature() == func->minimalSignature()) - funcModifs.append(funcModif); - } - doc.setValue(getDocumentation(xquery, query, funcModifs)); - func->setDocumentation(doc); - } -#if 0 - // Fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (AbstractMetaField *field : fields) { - if (field->isPrivate()) - return; - - QString query = "/doxygen/compounddef/sectiondef/memberdef/name[text()=\"" + field->name() + "\"]/.."; - Documentation doc = getDocumentation(DocModificationList(), xquery, query); - field->setDocumentation(doc); - } -#endif - // Enums - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum *meta_enum : enums) { - QString query = QLatin1String("/WebXML/document/") + type - + QLatin1String("[@name=\"") - + className + QLatin1String("\"]/enum[@name=\"") - + meta_enum->name() + QLatin1String("\"]/description"); - doc.setValue(getDocumentation(xquery, query, DocModificationList())); - meta_enum->setDocumentation(doc); - } -} - -Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) -{ - // TODO: This method of acquiring the module name supposes that the target language uses - // dots as module separators in package names. Improve this. - QString moduleName = name; - moduleName.remove(0, name.lastIndexOf(QLatin1Char('.')) + 1); - QString sourceFile = documentationDataDirectory() + QLatin1Char('/') - + moduleName.toLower() + QLatin1String(".xml"); - - if (!QFile::exists(sourceFile)) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't find qdoc3 file for module " << name << ", tried: " - << QDir::toNativeSeparators(sourceFile); - return Documentation(); - } - - QXmlQuery xquery; - xquery.setFocus(QUrl(sourceFile)); - - // Module documentation - QString query = QLatin1String("/WebXML/document/page[@name=\"") + moduleName + QLatin1String("\"]/description"); - return Documentation(getDocumentation(xquery, query, DocModificationList())); -} diff --git a/ApiExtractor/qtdocparser.h b/ApiExtractor/qtdocparser.h deleted file mode 100644 index f6bd479cd..000000000 --- a/ApiExtractor/qtdocparser.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QTDOCPARSER_H -#define QTDOCPARSER_H - -#include "docparser.h" - -class QtDocParser : public DocParser -{ -public: - QtDocParser() {} - void fillDocumentation(AbstractMetaClass* metaClass) override; - Documentation retrieveModuleDocumentation() override; - Documentation retrieveModuleDocumentation(const QString& name) override; -}; - -#endif // QTDOCPARSER_H - diff --git a/ApiExtractor/reporthandler.cpp b/ApiExtractor/reporthandler.cpp deleted file mode 100644 index 8abea42c6..000000000 --- a/ApiExtractor/reporthandler.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "reporthandler.h" -#include "typesystem.h" -#include "typedatabase.h" -#include -#include -#include -#include - -#if _WINDOWS || NOCOLOR - #define COLOR_END "" - #define COLOR_WHITE "" - #define COLOR_YELLOW "" - #define COLOR_GREEN "" -#else - #define COLOR_END "\033[0m" - #define COLOR_WHITE "\033[1;37m" - #define COLOR_YELLOW "\033[1;33m" - #define COLOR_GREEN "\033[0;32m" -#endif - -static bool m_silent = false; -static int m_warningCount = 0; -static int m_suppressedCount = 0; -static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug; -static QSet m_reportedWarnings; -static QString m_progressBuffer; -static int m_step_size = 0; -static int m_step = -1; -static int m_step_warning = 0; - -Q_LOGGING_CATEGORY(lcShiboken, "qt.shiboken") - -static void printProgress() -{ - std::printf("%s", m_progressBuffer.toUtf8().data()); - std::fflush(stdout); - m_progressBuffer.clear(); -} - -void ReportHandler::install() -{ - qInstallMessageHandler(ReportHandler::messageOutput); -} - -ReportHandler::DebugLevel ReportHandler::debugLevel() -{ - return m_debugLevel; -} - -void ReportHandler::setDebugLevel(ReportHandler::DebugLevel level) -{ - m_debugLevel = level; -} - -int ReportHandler::suppressedCount() -{ - return m_suppressedCount; -} - -int ReportHandler::warningCount() -{ - return m_warningCount; -} - -void ReportHandler::setProgressReference(int max) -{ - m_step_size = max; - m_step = -1; -} - -bool ReportHandler::isSilent() -{ - return m_silent; -} - -void ReportHandler::setSilent(bool silent) -{ - m_silent = silent; -} - -void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &text) -{ - if (type == QtWarningMsg) { - if (m_silent || m_reportedWarnings.contains(text)) - return; - const TypeDatabase *db = TypeDatabase::instance(); - if (db && db->isSuppressedWarning(text)) { - ++m_suppressedCount; - return; - } - ++m_warningCount; - ++m_step_warning; - m_reportedWarnings.insert(text); - } - fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, text))); -} - -void ReportHandler::progress(const QString& str, ...) -{ - if (m_silent) - return; - - if (m_step == -1) { - QTextStream buf(&m_progressBuffer); - buf.setFieldWidth(45); - buf.setFieldAlignment(QTextStream::AlignLeft); - buf << str; - printProgress(); - m_step = 0; - } - m_step++; - if (m_step >= m_step_size) { - if (m_step_warning == 0) { - m_progressBuffer = QLatin1String("[" COLOR_GREEN "OK" COLOR_END "]\n"); - } else { - m_progressBuffer = QLatin1String("[" COLOR_YELLOW "WARNING" COLOR_END "]\n"); - } - printProgress(); - m_step_warning = 0; - } -} diff --git a/ApiExtractor/reporthandler.h b/ApiExtractor/reporthandler.h deleted file mode 100644 index 6896d6e86..000000000 --- a/ApiExtractor/reporthandler.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef REPORTHANDLER_H -#define REPORTHANDLER_H - -#include -#include - -Q_DECLARE_LOGGING_CATEGORY(lcShiboken) - -class ReportHandler -{ -public: - enum DebugLevel { NoDebug, SparseDebug, MediumDebug, FullDebug }; - - static void install(); - - static DebugLevel debugLevel(); - static void setDebugLevel(DebugLevel level); - - static int warningCount(); - - static int suppressedCount(); - - template - static void setProgressReference(T collection) - { - setProgressReference(collection.count()); - } - - static void setProgressReference(int max); - - static void progress(const QString &str, ...); - - static bool isDebug(DebugLevel level) - { return debugLevel() >= level; } - - static bool isSilent(); - static void setSilent(bool silent); - -private: - static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); -}; - -#endif // REPORTHANDLER_H diff --git a/ApiExtractor/symbols.filter b/ApiExtractor/symbols.filter deleted file mode 100644 index af6c744dd..000000000 --- a/ApiExtractor/symbols.filter +++ /dev/null @@ -1,7 +0,0 @@ -{ -local: -_ZSt*; -_ZNSt*; -_ZNSs*; -_ZNKSt*; -}; diff --git a/ApiExtractor/tests/CMakeLists.txt b/ApiExtractor/tests/CMakeLists.txt deleted file mode 100644 index 860a37d9d..000000000 --- a/ApiExtractor/tests/CMakeLists.txt +++ /dev/null @@ -1,74 +0,0 @@ -find_package(Qt5Core) -find_package(Qt5Gui) -find_package(Qt5Test) -find_package(Qt5Xml) -find_package(Qt5XmlPatterns) - -macro(declare_test testname) - # gone: qt4_automoc("${testname}.cpp") - if (EXISTS "${testname}.h") - add_executable(${testname} "${testname}.h ${testname}.cpp") - else () - add_executable(${testname} "${testname}.cpp") - endif () - include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${apiextractor_SOURCE_DIR} - ${Qt5Test_INCLUDE_DIRS} - ) - link_directories(${APIEXTRACTOR_EXTRA_LINK_DIRECTORIES}) - target_link_libraries(${testname} - ${Qt5XmlPatterns_LIBRARIES} - ${Qt5Test_LIBRARIES} - ${Qt5Core_LIBRARIES} - ${Qt5Gui_LIBRARIES} - apiextractor) - add_test(${testname} ${testname}) - if (INSTALL_TESTS) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname} - DESTINATION share/apiextractor${apiextractor_SUFFIX}/tests) - endif() -endmacro(declare_test testname) - -declare_test(testabstractmetaclass) -declare_test(testabstractmetatype) -declare_test(testaddfunction) -declare_test(testarrayargument) -declare_test(testcodeinjection) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/utf8code.txt" - "${CMAKE_CURRENT_BINARY_DIR}/utf8code.txt" COPYONLY) -declare_test(testcontainer) -declare_test(testconversionoperator) -declare_test(testconversionruletag) -declare_test(testctorinformation) -declare_test(testdroptypeentries) -declare_test(testdtorinformation) -declare_test(testenum) -declare_test(testextrainclude) -declare_test(testfunctiontag) -declare_test(testimplicitconversions) -declare_test(testinserttemplate) -declare_test(testmodifyfunction) -declare_test(testmultipleinheritance) -declare_test(testnamespace) -declare_test(testnestedtypes) -declare_test(testnumericaltypedef) -declare_test(testprimitivetypetag) -declare_test(testrefcounttag) -declare_test(testreferencetopointer) -declare_test(testremovefield) -declare_test(testremoveimplconv) -declare_test(testremoveoperatormethod) -declare_test(testresolvetype) -declare_test(testreverseoperators) -declare_test(testtemplates) -declare_test(testtoposort) -declare_test(testvaluetypedefaultctortag) -declare_test(testvoidarg) -declare_test(testtyperevision) -if (NOT DISABLE_DOCSTRINGS) - declare_test(testmodifydocumentation) - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/a.xml" - "${CMAKE_CURRENT_BINARY_DIR}/a.xml" COPYONLY) -endif() - diff --git a/ApiExtractor/tests/a.xml b/ApiExtractor/tests/a.xml deleted file mode 100644 index 1c6d62a17..000000000 --- a/ApiExtractor/tests/a.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - oi - Paragraph number 1 - Paragraph number 2 - Paragraph number 3 - - - - diff --git a/ApiExtractor/tests/testabstractmetaclass.cpp b/ApiExtractor/tests/testabstractmetaclass.cpp deleted file mode 100644 index 423b8d9ff..000000000 --- a/ApiExtractor/tests/testabstractmetaclass.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testabstractmetaclass.h" -#include "abstractmetabuilder.h" -#include -#include "testutil.h" -#include -#include - -void TestAbstractMetaClass::testClassName() -{ - const char* cppCode ="class ClassName {};"; - const char* xmlCode = ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - QCOMPARE(classes[0]->name(), QLatin1String("ClassName")); -} - -void TestAbstractMetaClass::testClassNameUnderNamespace() -{ - const char* cppCode ="namespace Namespace { class ClassName {}; }\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); // 1 namespace + 1 class - if (classes.first()->name() != QLatin1String("ClassName")) - qSwap(classes[0], classes[1]); - - QCOMPARE(classes[0]->name(), QLatin1String("ClassName")); - QCOMPARE(classes[0]->qualifiedCppName(), QLatin1String("Namespace::ClassName")); - QCOMPARE(classes[1]->name(), QLatin1String("Namespace")); - QVERIFY(classes[1]->isNamespace()); - - // Check ctors info - QVERIFY(classes[0]->hasConstructors()); - QCOMPARE(classes[0]->functions().size(), 2); // default ctor + copy ctor - - AbstractMetaFunctionList ctors = classes[0]->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - if (ctors.first()->minimalSignature() != QLatin1String("ClassName()")) - qSwap(ctors[0], ctors[1]); - - QCOMPARE(ctors[0]->arguments().size(), 0); - QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("ClassName()")); - QCOMPARE(ctors[1]->arguments().size(), 1); - QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("ClassName(Namespace::ClassName)")); - - QVERIFY(!classes[0]->hasPrivateDestructor()); - QVERIFY(classes[0]->hasCloneOperator()); // implicit default copy ctor - QVERIFY(!classes[0]->hasHashFunction()); - - // This method is buggy and nobody wants to fix it or needs it fixed :-/ - // QVERIFY(classes[0]->hasNonPrivateConstructor()); -} - -void TestAbstractMetaClass::testVirtualMethods() -{ - const char* cppCode ="\ - class A {\n\ - public:\n\ - virtual int pureVirtual() const = 0;\n\ - };\n\ - class B : public A {};\n\ - class C : public B {\n\ - public:\n\ - int pureVirtual() const { return 0; }\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - AbstractMetaClass* a = AbstractMetaClass::findClass(classes, QLatin1String("A")); - AbstractMetaClass* b = AbstractMetaClass::findClass(classes, QLatin1String("B")); - AbstractMetaClass* c = AbstractMetaClass::findClass(classes, QLatin1String("C")); - - AbstractMetaClass* no_class = 0; - - QCOMPARE(a->baseClass(), no_class); - QCOMPARE(b->baseClass(), a); - QCOMPARE(c->baseClass(), b); - - QCOMPARE(a->functions().size(), 2); // default ctor + the pure virtual method - QCOMPARE(b->functions().size(), 2); - QCOMPARE(c->functions().size(), 2); - - // implementing class, ownclass, declaringclass - AbstractMetaFunction* ctorA = a->queryFunctions(AbstractMetaClass::Constructors).first(); - AbstractMetaFunction* ctorB = b->queryFunctions(AbstractMetaClass::Constructors).first(); - AbstractMetaFunction* ctorC = c->queryFunctions(AbstractMetaClass::Constructors).first(); - QVERIFY(ctorA->isConstructor()); - QVERIFY(!ctorA->isVirtual()); - QVERIFY(ctorB->isConstructor()); - QVERIFY(!ctorB->isVirtual()); - QVERIFY(ctorC->isConstructor()); - QVERIFY(!ctorC->isVirtual()); - QCOMPARE(ctorA->implementingClass(), a); - QCOMPARE(ctorA->ownerClass(), a); - QCOMPARE(ctorA->declaringClass(), a); - - QCOMPARE(a->virtualFunctions().size(), 1); // Add a pureVirtualMethods method !? - QCOMPARE(b->virtualFunctions().size(), 1); - QCOMPARE(c->virtualFunctions().size(), 1); - - AbstractMetaFunction* funcA = a->virtualFunctions().first(); - AbstractMetaFunction* funcB = b->virtualFunctions().first(); - AbstractMetaFunction* funcC = c->virtualFunctions().first(); - - QCOMPARE(funcA->ownerClass(), a); - QCOMPARE(funcB->ownerClass(), b); - QCOMPARE(funcC->ownerClass(), c); - - QCOMPARE(funcA->declaringClass(), a); - QCOMPARE(funcB->declaringClass(), a); - QCOMPARE(funcC->declaringClass(), a); - - // The next two tests could return null, because it makes more sense. - // But we have too many code written relying on this behaviour where - // implementingClass is equals to declaringClass on pure virtual functions - QCOMPARE(funcA->implementingClass(), a); - QCOMPARE(funcB->implementingClass(), a); - QCOMPARE(funcC->implementingClass(), c); -} - -void TestAbstractMetaClass::testDefaultValues() -{ - const char* cppCode ="\ - struct A {\n\ - class B {};\n\ - void method(B b = B());\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->queryFunctionsByName(QLatin1String("method")).count(), 1); - AbstractMetaFunction* method = classA->queryFunctionsByName(QLatin1String("method")).first(); - AbstractMetaArgument* arg = method->arguments().first(); - QCOMPARE(arg->defaultValueExpression(), arg->originalDefaultValueExpression()); -} - -void TestAbstractMetaClass::testModifiedDefaultValues() -{ - const char* cppCode ="\ - struct A {\n\ - class B {};\n\ - void method(B b = B());\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->queryFunctionsByName(QLatin1String("method")).count(), 1); - AbstractMetaFunction* method = classA->queryFunctionsByName(QLatin1String("method")).first(); - AbstractMetaArgument* arg = method->arguments().first(); - QCOMPARE(arg->defaultValueExpression(), QLatin1String("Hello")); - QCOMPARE(arg->originalDefaultValueExpression(), QLatin1String("A::B()")); -} - -void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne() -{ - const char* cppCode ="\ - struct A {\n\ - class B {};\n\ - virtual void method();\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QVERIFY(classA->isPolymorphic()); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("A::B")); - QVERIFY(classB); - QVERIFY(!classB->isPolymorphic()); -} - -void TestAbstractMetaClass::testForwardDeclaredInnerClass() -{ - const char cppCode[] ="\ - class A {\n\ - class B;\n\ - };\n\ - class A::B {\n\ - public:\n\ - void foo();\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("A::B")); - QVERIFY(classB); - const AbstractMetaFunction *fooF = classB->findFunction(QLatin1String("foo")); - QVERIFY(fooF); -} - -void TestAbstractMetaClass::testSpecialFunctions() -{ - const char cppCode[] ="\ - struct A {\n\ - A();\n\ - A(const A&);\n\ - A &operator=(const A&);\n\ - };\n\ - struct B {\n\ - B();\n\ - B(const B &);\n\ - B &operator=(B);\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); - QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); - AbstractMetaFunctionList assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); - QCOMPARE(assigmentOps.size(), 1); - QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); - - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - ctors = classB->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); - QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); - assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); - QCOMPARE(assigmentOps.size(), 1); - QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); -} - -void TestAbstractMetaClass::testClassDefaultConstructors() -{ - const char* cppCode ="\ - struct A {};\n\ - \n\ - struct B {\n\ - B();\n\ - private: \n\ - B(const B&);\n\ - };\n\ - \n\ - struct C {\n\ - C(const C&);\n\ - };\n\ - \n\ - struct D {\n\ - private: \n\ - D(const D&);\n\ - };\n\ - \n\ - struct E {\n\ - private: \n\ - ~E();\n\ - };\n\ - \n\ - struct F {\n\ - F(int, int);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 6); - - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().size(), 2); - - AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - if (ctors.first()->minimalSignature() != QLatin1String("A()")) - qSwap(ctors[0], ctors[1]); - - QCOMPARE(ctors[0]->arguments().size(), 0); - QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); - QCOMPARE(ctors[1]->arguments().size(), 1); - QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("A(A)")); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QCOMPARE(classB->functions().size(), 2); - QCOMPARE(classB->functions().first()->minimalSignature(), QLatin1String("B()")); - - AbstractMetaClass* classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); - QVERIFY(classC); - QCOMPARE(classC->functions().size(), 1); - QCOMPARE(classC->functions().first()->minimalSignature(), QLatin1String("C(C)")); - - AbstractMetaClass* classD = AbstractMetaClass::findClass(classes, QLatin1String("D")); - QVERIFY(classD); - QCOMPARE(classD->functions().size(), 1); - QCOMPARE(classD->functions().first()->minimalSignature(), QLatin1String("D(D)")); - QVERIFY(classD->functions().first()->isPrivate()); - - AbstractMetaClass* classE = AbstractMetaClass::findClass(classes, QLatin1String("E")); - QVERIFY(classE); - QVERIFY(classE->hasPrivateDestructor()); - QCOMPARE(classE->functions().size(), 0); - - AbstractMetaClass* classF = AbstractMetaClass::findClass(classes, QLatin1String("F")); - QVERIFY(classF); - - ctors = classF->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - if (ctors.first()->minimalSignature() != QLatin1String("F(int,int)")) - qSwap(ctors[0], ctors[1]); - - QCOMPARE(ctors[0]->arguments().size(), 2); - QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("F(int,int)")); - QCOMPARE(ctors[1]->arguments().size(), 1); - QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("F(F)")); -} - -void TestAbstractMetaClass::testClassInheritedDefaultConstructors() -{ - const char* cppCode ="\ - struct A {\n\ - A();\n\ - private: \n\ - A(const A&);\n\ - };\n\ - struct B : public A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 2); - if (ctors.first()->minimalSignature() != QLatin1String("A()")) - qSwap(ctors[0], ctors[1]); - - QCOMPARE(ctors[0]->arguments().size(), 0); - QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); - QCOMPARE(ctors[1]->arguments().size(), 1); - QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("A(A)")); - QVERIFY(ctors[1]->isPrivate()); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - - ctors = classB->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 1); - QCOMPARE(ctors.first()->arguments().size(), 0); - QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("B()")); -} - -void TestAbstractMetaClass::testAbstractClassDefaultConstructors() -{ - const char* cppCode ="\ - struct A {\n\ - virtual void method() = 0;\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 1); - QCOMPARE(ctors.first()->arguments().size(), 0); - QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("A()")); -} - -void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors() -{ - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); - QCOMPARE(ctors.size(), 1); - QCOMPARE(ctors.first()->arguments().size(), 0); - QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("A()")); -} - -void TestAbstractMetaClass::testIsPolymorphic() -{ - const char* cppCode = "\ - class A\n\ - {\n\ - public:\n\ - A();\n\ - inline bool abc() const {}\n\ - };\n\ - \n\ - class B : public A\n\ - {\n\ - public:\n\ - B();\n\ - inline bool abc() const {}\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - AbstractMetaClass* b = AbstractMetaClass::findClass(classes, QLatin1String("A")); - - QVERIFY(!b->isPolymorphic()); - AbstractMetaClass* a = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(!a->isPolymorphic()); -} - -QTEST_APPLESS_MAIN(TestAbstractMetaClass) diff --git a/ApiExtractor/tests/testabstractmetaclass.h b/ApiExtractor/tests/testabstractmetaclass.h deleted file mode 100644 index 811bf5a10..000000000 --- a/ApiExtractor/tests/testabstractmetaclass.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTABSTRACTMETACLASS_H -#define TESTABSTRACTMETACLASS_H - -#include - -class AbstractMetaBuilder; - -class TestAbstractMetaClass : public QObject -{ - Q_OBJECT -private slots: - void testClassName(); - void testClassNameUnderNamespace(); - void testVirtualMethods(); - void testDefaultValues(); - void testModifiedDefaultValues(); - void testInnerClassOfAPolymorphicOne(); - void testForwardDeclaredInnerClass(); - void testSpecialFunctions(); - void testClassDefaultConstructors(); - void testClassInheritedDefaultConstructors(); - void testAbstractClassDefaultConstructors(); - void testObjectTypesMustNotHaveCopyConstructors(); - void testIsPolymorphic(); -}; - -#endif // TESTABSTRACTMETACLASS_H diff --git a/ApiExtractor/tests/testabstractmetatype.cpp b/ApiExtractor/tests/testabstractmetatype.cpp deleted file mode 100644 index 1d52c1e41..000000000 --- a/ApiExtractor/tests/testabstractmetatype.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testabstractmetatype.h" -#include -#include "testutil.h" -#include -#include - -void TestAbstractMetaType::testConstCharPtrType() -{ - const char* cppCode ="const char* justAtest();\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - QCOMPARE(builder->globalFunctions().size(), 1); - AbstractMetaFunction* func = builder->globalFunctions().first(); - AbstractMetaType* rtype = func->type(); - // Test properties of const char* - QVERIFY(rtype); - QCOMPARE(rtype->package(), QLatin1String("Foo")); - QCOMPARE(rtype->name(), QLatin1String("char")); - QVERIFY(rtype->isConstant()); - QVERIFY(!rtype->isArray()); - QVERIFY(!rtype->isContainer()); - QVERIFY(!rtype->isObject()); - QVERIFY(!rtype->isPrimitive()); // const char* differs from char, so it's not considered a primitive type by apiextractor - QVERIFY(rtype->isNativePointer()); - QVERIFY(!rtype->isQObject()); - QCOMPARE(rtype->referenceType(), NoReference); - QVERIFY(!rtype->isValue()); - QVERIFY(!rtype->isValuePointer()); -} - -void TestAbstractMetaType::testApiVersionSupported() -{ - const char* cppCode ="class foo {}; class foo2 {};\n\ - void justAtest(); void justAtest3();\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "1.0")); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 2); - - - AbstractMetaFunctionList functions = builder->globalFunctions(); - QCOMPARE(functions.size(), 2); -} - - -void TestAbstractMetaType::testApiVersionNotSupported() -{ - const char* cppCode ="class object {};\n"; - const char* xmlCode = "\n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 1); -} - -void TestAbstractMetaType::testCharType() -{ - const char* cppCode ="char justAtest(); class A {};\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 1); - QCOMPARE(classes.first()->package(), QLatin1String("Foo")); - - AbstractMetaFunctionList functions = builder->globalFunctions(); - QCOMPARE(functions.size(), 1); - AbstractMetaFunction* func = functions.first(); - AbstractMetaType* rtype = func->type(); - // Test properties of const char* - QVERIFY(rtype); - QCOMPARE(rtype->package(), QLatin1String("Foo")); - QCOMPARE(rtype->name(), QLatin1String("char")); - QVERIFY(!rtype->isConstant()); - QVERIFY(!rtype->isArray()); - QVERIFY(!rtype->isContainer()); - QVERIFY(!rtype->isObject()); - QVERIFY(rtype->isPrimitive()); - QVERIFY(!rtype->isNativePointer()); - QVERIFY(!rtype->isQObject()); - QCOMPARE(rtype->referenceType(), NoReference); - QVERIFY(!rtype->isValue()); - QVERIFY(!rtype->isValuePointer()); -} - -void TestAbstractMetaType::testTypedef() -{ - const char* cppCode ="\ - struct A {\n\ - void someMethod();\n\ - };\n\ - typedef A B;\n\ - typedef B C;\n"; - const char* xmlCode = "\n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 1); - const AbstractMetaClass *c = AbstractMetaClass::findClass(classes, QLatin1String("C")); - QVERIFY(c); - QVERIFY(c->isTypeDef()); -} - -void TestAbstractMetaType::testTypedefWithTemplates() -{ - const char* cppCode ="\ - template\n\ - class A {};\n\ - \n\ - class B {};\n\ - typedef A C;\n\ - \n\ - void func(C c);\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 1); - AbstractMetaFunctionList functions = builder->globalFunctions(); - QCOMPARE(functions.count(), 1); - AbstractMetaFunction* function = functions.first(); - AbstractMetaArgumentList args = function->arguments(); - QCOMPARE(args.count(), 1); - AbstractMetaArgument* arg = args.first(); - AbstractMetaType* metaType = arg->type(); - QCOMPARE(metaType->cppSignature(), QLatin1String("A")); -} - - -void TestAbstractMetaType::testObjectTypeUsedAsValue() -{ - const char* cppCode ="\ - class A {\n\ - void method(A);\n\ - };\n"; - const char* xmlCode = "\n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.size(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - AbstractMetaFunctionList overloads = classA->queryFunctionsByName(QLatin1String("method")); - QCOMPARE(overloads.count(), 1); - AbstractMetaFunction* method = overloads.first(); - QVERIFY(method); - AbstractMetaArgumentList args = method->arguments(); - QCOMPARE(args.count(), 1); - AbstractMetaArgument* arg = args.first(); - AbstractMetaType* metaType = arg->type(); - QCOMPARE(metaType->cppSignature(), QLatin1String("A")); - QVERIFY(metaType->isValue()); - QVERIFY(metaType->typeEntry()->isObject()); -} - -QTEST_APPLESS_MAIN(TestAbstractMetaType) diff --git a/ApiExtractor/tests/testabstractmetatype.h b/ApiExtractor/tests/testabstractmetatype.h deleted file mode 100644 index a806d36e3..000000000 --- a/ApiExtractor/tests/testabstractmetatype.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTABSTRACTMETATYPE_H -#define TESTABSTRACTMETATYPE_H - -#include - -class TestAbstractMetaType : public QObject -{ - Q_OBJECT -private slots: - void testConstCharPtrType(); - void testCharType(); - void testTypedef(); - void testTypedefWithTemplates(); - void testApiVersionSupported(); - void testApiVersionNotSupported(); - void testObjectTypeUsedAsValue(); -}; - -#endif diff --git a/ApiExtractor/tests/testaddfunction.cpp b/ApiExtractor/tests/testaddfunction.cpp deleted file mode 100644 index bcc5238bc..000000000 --- a/ApiExtractor/tests/testaddfunction.cpp +++ /dev/null @@ -1,453 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testaddfunction.h" -#include -#include "testutil.h" -#include -#include - -void TestAddFunction::testParsingFuncNameAndConstness() -{ - // generic test... - const char sig1[] = "func(type1, const type2, const type3* const)"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 3); - AddedFunction::TypeInfo retval = f1.returnType(); - QCOMPARE(retval.name, QLatin1String("void")); - QCOMPARE(retval.indirections, 0); - QCOMPARE(retval.isConstant, false); - QCOMPARE(retval.isReference, false); - - // test with a ugly template as argument and other ugly stuff - const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc * > * *, const type3* const ) const "; - AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc * > * *"), 0); - QCOMPARE(f2.name(), QLatin1String("_fu__nc_")); - QVector< AddedFunction::TypeInfo > args = f2.arguments(); - QCOMPARE(args.count(), 4); - retval = f2.returnType(); - QCOMPARE(retval.name, QLatin1String("Abc * >")); - QCOMPARE(retval.indirections, 2); - QCOMPARE(retval.isConstant, true); - QCOMPARE(retval.isReference, false); - retval = args[2]; - QCOMPARE(retval.name, QLatin1String("Abc * >")); - QCOMPARE(retval.indirections, 2); - QCOMPARE(retval.isConstant, true); - QCOMPARE(retval.isReference, false); - - // function with no args. - const char sig3[] = "func()"; - AddedFunction f3(QLatin1String(sig3), QLatin1String("void"), 0); - QCOMPARE(f3.name(), QLatin1String("func")); - QCOMPARE(f3.arguments().count(), 0); -} - -void TestAddFunction::testAddFunction() -{ - const char cppCode[] = "struct B {}; struct A { void a(int); };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().count(), 4); // default ctor, default copy ctor, func a() and the added function - - AbstractMetaFunction* addedFunc = classA->functions().last(); - QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Protected); - QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); - QVERIFY(addedFunc->isUserAdded()); - QCOMPARE(addedFunc->ownerClass(), classA); - QCOMPARE(addedFunc->implementingClass(), classA); - QCOMPARE(addedFunc->declaringClass(), classA); - QVERIFY(!addedFunc->isVirtual()); - QVERIFY(!addedFunc->isSignal()); - QVERIFY(!addedFunc->isSlot()); - QVERIFY(!addedFunc->isStatic()); - - AbstractMetaType* returnType = addedFunc->type(); - QCOMPARE(returnType->typeEntry(), typeDb->findPrimitiveType(QLatin1String("int"))); - AbstractMetaArgumentList args = addedFunc->arguments(); - QCOMPARE(args.count(), 3); - QCOMPARE(args[0]->type()->typeEntry(), returnType->typeEntry()); - QCOMPARE(args[1]->defaultValueExpression(), QLatin1String("4.6")); - QCOMPARE(args[2]->type()->typeEntry(), typeDb->findType(QLatin1String("B"))); -} - -void TestAddFunction::testAddFunctionConstructor() -{ - const char cppCode[] = "struct A { A() {} };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().count(), 3); // default and added ctors - AbstractMetaFunction* addedFunc = classA->functions().last(); - QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); - QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::ConstructorFunction); - QCOMPARE(addedFunc->arguments().size(), 1); - QVERIFY(addedFunc->isUserAdded()); - QVERIFY(!addedFunc->type()); -} - -void TestAddFunction::testAddFunctionTagDefaultValues() -{ - const char cppCode[] = "struct A {};\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().count(), 3); // default ctor, default copy ctor and the added function - AbstractMetaFunction* addedFunc = classA->functions().last(); - QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); - QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); - QVERIFY(addedFunc->isUserAdded()); - QVERIFY(!addedFunc->type()); -} - -void TestAddFunction::testAddFunctionCodeSnippets() -{ - const char cppCode[] = "struct A {};\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - Hi!, I am the code.\n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - AbstractMetaFunction* addedFunc = classA->functions().last(); - QVERIFY(addedFunc->hasInjectedCode()); -} - -void TestAddFunction::testAddFunctionWithoutParenteses() -{ - const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 0); - QCOMPARE(f1.isConstant(), false); - - const char cppCode[] = "struct A {};\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - Hi!, I am the code.\n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); - QVERIFY(addedFunc); - QVERIFY(addedFunc->hasInjectedCode()); - QCOMPARE(addedFunc->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode).count(), 1); -} - -void TestAddFunction::testAddFunctionWithDefaultArgs() -{ - const char sig1[] = "func"; - AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 0); - QCOMPARE(f1.isConstant(), false); - - const char cppCode[] = "struct A { };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); - QVERIFY(addedFunc); - AbstractMetaArgument *arg = addedFunc->arguments()[1]; - QCOMPARE(arg->defaultValueExpression(), QLatin1String("2")); -} - -void TestAddFunction::testAddFunctionAtModuleLevel() -{ - const char cppCode[] = "struct A { };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - - TypeDatabase* typeDb = TypeDatabase::instance(); - - AddedFunctionList addedFuncs = typeDb->findGlobalUserFunctions(QLatin1String("func")); - - QCOMPARE(addedFuncs.size(), 1); - - FunctionModificationList mods = typeDb->functionModifications(QLatin1String("func(int,int)")); - - QCOMPARE(mods.size(), 1); - QVERIFY(mods.first().isCodeInjection()); - CodeSnip snip = mods.first().snips.first(); - QCOMPARE(snip.code(), QLatin1String("custom_code();")); -} - -void TestAddFunction::testAddFunctionWithVarargs() -{ - const char sig1[] = "func(int,char,...)"; - AddedFunction f1( QLatin1String(sig1), QLatin1String("void"), 0); - - QCOMPARE(f1.name(), QLatin1String("func")); - QCOMPARE(f1.arguments().count(), 3); - QVERIFY(!f1.isConstant()); - - const char cppCode[] = "struct A {};\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); - QVERIFY(addedFunc); - const AbstractMetaArgument* arg = addedFunc->arguments().last(); - QVERIFY(arg->type()->isVarargs()); - QVERIFY(arg->type()->typeEntry()->isVarargs()); -} - -void TestAddFunction::testAddStaticFunction() -{ - const char cppCode[] = "struct A { };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); - QVERIFY(addedFunc); - QVERIFY(addedFunc->isStatic()); -} - -void TestAddFunction::testAddGlobalFunction() -{ - const char cppCode[] = "struct A { };struct B {};\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 2); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(builder->classes(), QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->findFunction(QLatin1String("globalFunc"))); - QVERIFY(!classB->findFunction(QLatin1String("globalFunc2"))); - QVERIFY(!globalFuncs[0]->injectedCodeSnips().isEmpty()); - QVERIFY(!globalFuncs[1]->injectedCodeSnips().isEmpty()); -} - -void TestAddFunction::testAddFunctionWithApiVersion() -{ - const char cppCode[] = ""; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); -} - -void TestAddFunction::testModifyAddedFunction() -{ - const char cppCode[] = "class Foo { };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("Foo")); - const AbstractMetaFunction* method = foo->findFunction(QLatin1String("method")); - QCOMPARE(method->arguments().size(), 2); - AbstractMetaArgument* arg = method->arguments().at(1); - QCOMPARE(arg->defaultValueExpression(), QLatin1String("0")); - QCOMPARE(arg->name(), QLatin1String("varName")); - QCOMPARE(method->argumentName(2), QLatin1String("varName")); -} - -void TestAddFunction::testAddFunctionOnTypedef() -{ - const char cppCode[] = "template class Foo { }; typedef Foo FooInt;\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - custom_code();\n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("FooInt")); - QVERIFY(foo); - QVERIFY(foo->hasNonPrivateConstructor()); - const AbstractMetaFunctionList &lst = foo->queryFunctions(AbstractMetaClass::Constructors); - for (const AbstractMetaFunction *f : lst) - QVERIFY(f->signature().startsWith(f->name())); - QCOMPARE(lst.size(), 2); - const AbstractMetaFunction* method = foo->findFunction(QLatin1String("method")); - QVERIFY(method); -} - -void TestAddFunction::testAddFunctionWithTemplateArg() -{ - const char cppCode[] = "template class Foo { };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - QCOMPARE(builder->globalFunctions().size(), 1); - AbstractMetaFunction* func = builder->globalFunctions().first(); - AbstractMetaArgument* arg = func->arguments().first(); - QCOMPARE(arg->type()->instantiations().count(), 1); -} - -QTEST_APPLESS_MAIN(TestAddFunction) - diff --git a/ApiExtractor/tests/testaddfunction.h b/ApiExtractor/tests/testaddfunction.h deleted file mode 100644 index 16a4ede09..000000000 --- a/ApiExtractor/tests/testaddfunction.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTADDFUNCTION_H -#define TESTADDFUNCTION_H -#include - -class TestAddFunction : public QObject -{ - Q_OBJECT -private slots: - void testParsingFuncNameAndConstness(); - void testAddFunction(); - void testAddFunctionConstructor(); - void testAddFunctionTagDefaultValues(); - void testAddFunctionCodeSnippets(); - void testAddFunctionWithoutParenteses(); - void testAddFunctionWithDefaultArgs(); - void testAddFunctionAtModuleLevel(); - void testAddFunctionWithVarargs(); - void testAddStaticFunction(); - void testAddGlobalFunction(); - void testAddFunctionWithApiVersion(); - void testModifyAddedFunction(); - void testAddFunctionOnTypedef(); - void testAddFunctionWithTemplateArg(); -}; - -#endif diff --git a/ApiExtractor/tests/testarrayargument.cpp b/ApiExtractor/tests/testarrayargument.cpp deleted file mode 100644 index 4d46d44bc..000000000 --- a/ApiExtractor/tests/testarrayargument.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testarrayargument.h" -#include -#include "testutil.h" -#include -#include - -void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() -{ - const char* cppCode ="\ - struct A {\n\ - enum SomeEnum { Value0, Value1, NValues };\n\ - void method(double[3]);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - - const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); - QVERIFY(arg->type()->isArray()); - QCOMPARE(arg->type()->arrayElementCount(), 3); - QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); -} - -void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() -{ - const char* cppCode ="\ - struct A {\n\ - enum SomeEnum { Value0, Value1, NValues };\n\ - void method(double[NValues]);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaEnum* someEnum = classA->findEnum(QLatin1String("SomeEnum")); - QVERIFY(someEnum); - AbstractMetaEnumValue* nvalues = classA->findEnumValue(QLatin1String("NValues"), someEnum); - QVERIFY(nvalues); - - const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); - QVERIFY(arg->type()->isArray()); - QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); - QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); -}; - -void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum() -{ - const char* cppCode ="\ - enum SomeEnum { Value0, Value1, NValues };\n\ - struct A {\n\ - void method(double[NValues]);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaEnum* someEnum = builder->globalEnums().first(); - QVERIFY(someEnum); - AbstractMetaEnumValue* nvalues = 0; - const AbstractMetaEnumValueList &values = someEnum->values(); - for (AbstractMetaEnumValue *enumValue : values) { - if (enumValue->name() == QLatin1String("NValues")) { - nvalues = enumValue; - break; - } - } - QVERIFY(nvalues); - - const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); - QVERIFY(arg->type()->isArray()); - QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); - QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); -}; - -QTEST_APPLESS_MAIN(TestArrayArgument) diff --git a/ApiExtractor/tests/testarrayargument.h b/ApiExtractor/tests/testarrayargument.h deleted file mode 100644 index b50232ef4..000000000 --- a/ApiExtractor/tests/testarrayargument.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTARRAYARGUMENT_H -#define TESTARRAYARGUMENT_H -#include - -class TestArrayArgument : public QObject -{ - Q_OBJECT -private slots: - void testArrayArgumentWithSizeDefinedByInteger(); - void testArrayArgumentWithSizeDefinedByEnumValue(); - void testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum(); -}; - -#endif diff --git a/ApiExtractor/tests/testcodeinjection.cpp b/ApiExtractor/tests/testcodeinjection.cpp deleted file mode 100644 index ad245633e..000000000 --- a/ApiExtractor/tests/testcodeinjection.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testcodeinjection.h" -#include -#include -#include -#include "testutil.h" -#include -#include - -void TestCodeInjections::testReadFileUtf8() -{ - const char* cppCode ="struct A {};\n"; - int argc = 0; - char *argv[] = {NULL}; - QCoreApplication app(argc, argv); - QString filePath = QDir::currentPath(); - QString xmlCode = QLatin1String("\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"); - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().constData())); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); - QString code = classA->typeEntry()->codeSnips().first().code(); - QString utf8Data = QString::fromUtf8("\xC3\xA1\xC3\xA9\xC3\xAD\xC3\xB3\xC3\xBA"); - QVERIFY(code.indexOf(utf8Data) != -1); - code = classA->typeEntry()->conversionRule(); - QVERIFY(code.indexOf(utf8Data) != -1); -} - -void TestCodeInjections::testInjectWithValidApiVersion() -{ - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - test Inject code\n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "1.0")); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); -} - -void TestCodeInjections::testInjectWithInvalidApiVersion() -{ - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - test Inject code\n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->typeEntry()->codeSnips().count(), 0); -} - - - -QTEST_APPLESS_MAIN(TestCodeInjections) diff --git a/ApiExtractor/tests/testcodeinjection.h b/ApiExtractor/tests/testcodeinjection.h deleted file mode 100644 index 56c1c7cba..000000000 --- a/ApiExtractor/tests/testcodeinjection.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTCODEINJECTIONS_H -#define TESTCODEINJECTIONS_H - -#include - -class AbstractMetaBuilder; - -class TestCodeInjections : public QObject -{ - Q_OBJECT -private slots: - void testReadFileUtf8(); - void testInjectWithValidApiVersion(); - void testInjectWithInvalidApiVersion(); -}; - -#endif diff --git a/ApiExtractor/tests/testcontainer.cpp b/ApiExtractor/tests/testcontainer.cpp deleted file mode 100644 index 1c79a5a7a..000000000 --- a/ApiExtractor/tests/testcontainer.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testcontainer.h" -#include -#include "testutil.h" -#include -#include - -void TestContainer::testContainerType() -{ - const char* cppCode ="\ - namespace std {\n\ - template\n\ - class list {\n\ - T get(int x) { return 0; }\n\ - };\n\ - }\n\ - class A : public std::list {\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - //search for class A - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QVERIFY(classA->typeEntry()->baseContainerType()); - QCOMPARE(reinterpret_cast(classA->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::ListContainer); -} - -void TestContainer::testListOfValueType() -{ - const char* cppCode ="\ - namespace std {\n\ - template\n\ - class list {\n\ - T get(int x) { return 0; }\n\ - };\n\ - }\n\ - class ValueType {};\n\ - class A : public std::list {\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->templateBaseClassInstantiations().count(), 1); - const AbstractMetaType* templateInstanceType = classA->templateBaseClassInstantiations().first(); - QVERIFY(templateInstanceType); - - QCOMPARE(templateInstanceType->indirections(), 0); - QVERIFY(!templateInstanceType->typeEntry()->isObject()); - QVERIFY(templateInstanceType->typeEntry()->isValue()); - QCOMPARE(templateInstanceType->referenceType(), NoReference); - QVERIFY(!templateInstanceType->isObject()); - QVERIFY(!templateInstanceType->isValuePointer()); - QVERIFY(templateInstanceType->isValue()); -} - -QTEST_APPLESS_MAIN(TestContainer) - diff --git a/ApiExtractor/tests/testcontainer.h b/ApiExtractor/tests/testcontainer.h deleted file mode 100644 index f154ea212..000000000 --- a/ApiExtractor/tests/testcontainer.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTCONTAINER_H -#define TESTCONTAINER_H -#include - -class TestContainer : public QObject -{ - Q_OBJECT -private slots: - void testContainerType(); - void testListOfValueType(); -}; - -#endif diff --git a/ApiExtractor/tests/testconversionoperator.cpp b/ApiExtractor/tests/testconversionoperator.cpp deleted file mode 100644 index 86f571328..000000000 --- a/ApiExtractor/tests/testconversionoperator.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testconversionoperator.h" -#include -#include "testutil.h" -#include -#include - -void TestConversionOperator::testConversionOperator() -{ - const char cppCode[] = "\ - struct A {\n\ - };\n\ - struct B {\n\ - operator A() const;\n\ - };\n\ - struct C {\n\ - operator A() const;\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); - QVERIFY(classA); - QVERIFY(classB); - QVERIFY(classC); - QCOMPARE(classA->functions().count(), 2); - QCOMPARE(classB->functions().count(), 3); - QCOMPARE(classC->functions().count(), 3); - QCOMPARE(classA->externalConversionOperators().count(), 2); - - AbstractMetaFunction* convOp = 0; - for (AbstractMetaFunction *func : classB->functions()) { - if (func->isConversionOperator()) { - convOp = func; - break; - } - } - QVERIFY(convOp); - QVERIFY(classA->externalConversionOperators().contains(convOp)); -} - -void TestConversionOperator::testConversionOperatorOfDiscardedClass() -{ - const char cppCode[] = "\ - struct A {\n\ - };\n\ - struct B {\n\ - operator A() const;\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->externalConversionOperators().count(), 0); -} - -void TestConversionOperator::testRemovedConversionOperator() -{ - const char cppCode[] = "\ - struct A {\n\ - };\n\ - struct B {\n\ - operator A() const;\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classA); - QVERIFY(classB); - QCOMPARE(classA->functions().count(), 2); - QCOMPARE(classB->functions().count(), 3); - QCOMPARE(classA->externalConversionOperators().count(), 0); - QCOMPARE(classA->implicitConversions().count(), 0); -} - -void TestConversionOperator::testConversionOperatorReturningReference() -{ - const char cppCode[] = "\ - struct A {};\n\ - struct B {\n\ - operator A&() const;\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classA); - QVERIFY(classB); - QCOMPARE(classA->functions().count(), 2); - QCOMPARE(classB->functions().count(), 3); - QCOMPARE(classA->externalConversionOperators().count(), 1); - QCOMPARE(classA->externalConversionOperators().first()->type()->cppSignature(), QLatin1String("A")); - QCOMPARE(classA->externalConversionOperators().first()->ownerClass()->name(), QLatin1String("B")); - QCOMPARE(classA->implicitConversions().count(), 1); - QCOMPARE(classA->implicitConversions().first()->type()->cppSignature(), QLatin1String("A")); - QCOMPARE(classA->implicitConversions().first()->ownerClass()->name(), QLatin1String("B")); -} - -void TestConversionOperator::testConversionOperatorReturningConstReference() -{ - const char cppCode[] = "\ - struct A {};\n\ - struct B {\n\ - operator const A&() const;\n\ - };\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classA); - QVERIFY(classB); - QCOMPARE(classA->functions().count(), 2); - QCOMPARE(classB->functions().count(), 3); - QCOMPARE(classA->externalConversionOperators().count(), 1); - QCOMPARE(classA->externalConversionOperators().first()->type()->cppSignature(), QLatin1String("A")); - QCOMPARE(classA->externalConversionOperators().first()->ownerClass()->name(), QLatin1String("B")); - QCOMPARE(classA->implicitConversions().count(), 1); - QCOMPARE(classA->implicitConversions().first()->type()->cppSignature(), QLatin1String("A")); - QCOMPARE(classA->implicitConversions().first()->ownerClass()->name(), QLatin1String("B")); -} - -QTEST_APPLESS_MAIN(TestConversionOperator) diff --git a/ApiExtractor/tests/testconversionoperator.h b/ApiExtractor/tests/testconversionoperator.h deleted file mode 100644 index f28747ab5..000000000 --- a/ApiExtractor/tests/testconversionoperator.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTCONVERSIONOPERATOR_H -#define TESTCONVERSIONOPERATOR_H -#include - -class TestConversionOperator : public QObject -{ - Q_OBJECT -private slots: - void testConversionOperator(); - void testConversionOperatorOfDiscardedClass(); - void testRemovedConversionOperator(); - void testConversionOperatorReturningReference(); - void testConversionOperatorReturningConstReference(); -}; - -#endif diff --git a/ApiExtractor/tests/testconversionruletag.cpp b/ApiExtractor/tests/testconversionruletag.cpp deleted file mode 100644 index fb9290795..000000000 --- a/ApiExtractor/tests/testconversionruletag.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testconversionruletag.h" -#include -#include "testutil.h" -#include -#include -#include -#include - -void TestConversionRuleTag::testConversionRuleTagWithFile() -{ - // temp file used later - const char conversionData[] = "Hi! I'm a conversion rule."; - QTemporaryFile file; - file.open(); - QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1)); - file.close(); - - const char cppCode[] = "struct A {};\n"; - QString xmlCode = QLatin1String("\ - \n\ - \n\ - \n\ - \n\ - \n"); - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data())); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const ComplexTypeEntry* typeEntry = classA->typeEntry(); - QVERIFY(typeEntry->hasConversionRule()); - QCOMPARE(typeEntry->conversionRule(), QLatin1String(conversionData)); -} - -void TestConversionRuleTag::testConversionRuleTagReplace() -{ - const char cppCode[] = "\ - struct A {\n\ - A();\n\ - A(const char*, int);\n\ - };\n\ - struct B {\n\ - A createA();\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - DoThis();\n\ - return ConvertFromCppToPython(%IN);\n\ - \n\ - \n\ - \n\ - DoThat();\n\ - DoSomething();\n\ - %OUT = A();\n\ - \n\ - \n\ - %OUT = %IN.createA();\n\ - \n\ - \n\ - %OUT = new A(String_AsString(%IN), String_GetSize(%IN));\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); - PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(QLatin1String("A")); - QVERIFY(typeA); - - CustomConversion* conversion = typeA->customConversion(); - QVERIFY(conversion); - - QCOMPARE(typeA, conversion->ownerType()); - QCOMPARE(conversion->nativeToTargetConversion().simplified(), - QLatin1String("DoThis(); return ConvertFromCppToPython(%IN);")); - - QVERIFY(conversion->replaceOriginalTargetToNativeConversions()); - QVERIFY(conversion->hasTargetToNativeConversions()); - QCOMPARE(conversion->targetToNativeConversions().size(), 3); - - CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().at(0); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), QLatin1String("TargetNone")); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); - QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("%IN == Target_None")); - QCOMPARE(toNative->conversion().simplified(), - QLatin1String("DoThat(); DoSomething(); %OUT = A();")); - - toNative = conversion->targetToNativeConversions().at(1); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), QLatin1String("B")); - QVERIFY(!toNative->isCustomType()); - TypeEntry* typeB = typeDb->findType(QLatin1String("B")); - QVERIFY(typeB); - QCOMPARE(toNative->sourceType(), typeB); - QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("CheckIfInputObjectIsB(%IN)")); - QCOMPARE(toNative->conversion().trimmed(), QLatin1String("%OUT = %IN.createA();")); - - toNative = conversion->targetToNativeConversions().at(2); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), QLatin1String("String")); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); - QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("String_Check(%IN)")); - QCOMPARE(toNative->conversion().trimmed(), QLatin1String("%OUT = new A(String_AsString(%IN), String_GetSize(%IN));")); -} - -void TestConversionRuleTag::testConversionRuleTagAdd() -{ - const char cppCode[] = "\ - struct Date {\n\ - Date();\n\ - Date(int, int, int);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ -if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ -%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));\n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("Date")); - QVERIFY(classA); - - CustomConversion* conversion = classA->typeEntry()->customConversion(); - QVERIFY(conversion); - - QCOMPARE(conversion->nativeToTargetConversion(), QString()); - - QVERIFY(!conversion->replaceOriginalTargetToNativeConversions()); - QVERIFY(conversion->hasTargetToNativeConversions()); - QCOMPARE(conversion->targetToNativeConversions().size(), 1); - - CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().first(); - QVERIFY(toNative); - QCOMPARE(toNative->sourceTypeName(), QLatin1String("TargetDate")); - QVERIFY(toNative->isCustomType()); - QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); - QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("TargetDate_Check(%IN)")); - QCOMPARE(toNative->conversion().trimmed(), - QLatin1String("if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));")); -} - -void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() -{ - const char cppCode[] = "struct A {};"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - const char nativeToTargetExpected[] = - "// TEMPLATE - native_to_target - START\n" - "return ConvertFromCppToPython(%IN);\n" - "// TEMPLATE - native_to_target - END"; - - const char targetToNativeExpected[] = - "// TEMPLATE - target_to_native - START\n" - "%OUT = %IN.createA();\n" - "// TEMPLATE - target_to_native - END"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - TypeDatabase* typeDb = TypeDatabase::instance(); - PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(QLatin1String("A")); - QVERIFY(typeA); - - CustomConversion* conversion = typeA->customConversion(); - QVERIFY(conversion); - - QCOMPARE(typeA, conversion->ownerType()); - QCOMPARE(conversion->nativeToTargetConversion().trimmed(), - QLatin1String(nativeToTargetExpected)); - - QVERIFY(conversion->hasTargetToNativeConversions()); - QCOMPARE(conversion->targetToNativeConversions().size(), 1); - - CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().first(); - QVERIFY(toNative); - QCOMPARE(toNative->conversion().trimmed(), - QLatin1String(targetToNativeExpected)); -} - -QTEST_APPLESS_MAIN(TestConversionRuleTag) diff --git a/ApiExtractor/tests/testconversionruletag.h b/ApiExtractor/tests/testconversionruletag.h deleted file mode 100644 index c02a9708b..000000000 --- a/ApiExtractor/tests/testconversionruletag.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTCONVERSIONRULE_H -#define TESTCONVERSIONRULE_H -#include - -class TestConversionRuleTag : public QObject -{ - Q_OBJECT -private slots: - void testConversionRuleTagWithFile(); - void testConversionRuleTagReplace(); - void testConversionRuleTagAdd(); - void testConversionRuleTagWithInsertTemplate(); -}; - -#endif diff --git a/ApiExtractor/tests/testctorinformation.cpp b/ApiExtractor/tests/testctorinformation.cpp deleted file mode 100644 index a4b4c2388..000000000 --- a/ApiExtractor/tests/testctorinformation.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testctorinformation.h" -#include "abstractmetabuilder.h" -#include -#include "testutil.h" -#include -#include - -void TestCtorInformation::testCtorIsPrivate() -{ - const char* cppCode = "class Control { public: Control() {} };\n\ - class Subject { private: Subject() {} };\n\ - class CtorLess { };\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasNonPrivateConstructor(), true); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasNonPrivateConstructor(), false); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("CtorLess"))->hasNonPrivateConstructor(), true); -} - -void TestCtorInformation::testHasNonPrivateCtor() -{ - const char* cppCode = "template\n\ - struct Base { Base(double) {} };\n\ - typedef Base Derived;\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - const AbstractMetaClass *base = AbstractMetaClass::findClass(classes, QLatin1String("Base")); - QCOMPARE(base->hasNonPrivateConstructor(), true); - const AbstractMetaClass *derived = AbstractMetaClass::findClass(classes, QLatin1String("Derived")); - QCOMPARE(derived->hasNonPrivateConstructor(), true); -} - -QTEST_APPLESS_MAIN(TestCtorInformation) diff --git a/ApiExtractor/tests/testctorinformation.h b/ApiExtractor/tests/testctorinformation.h deleted file mode 100644 index f5ffe5501..000000000 --- a/ApiExtractor/tests/testctorinformation.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTCTORINFORMATION_H -#define TESTCTORINFORMATION_H - -#include - -class AbstractMetaBuilder; - -class TestCtorInformation: public QObject -{ - Q_OBJECT -private slots: - void testCtorIsPrivate(); - void testHasNonPrivateCtor(); -}; - -#endif // TESTCTORINFORMATION_H diff --git a/ApiExtractor/tests/testdroptypeentries.cpp b/ApiExtractor/tests/testdroptypeentries.cpp deleted file mode 100644 index 6b6c5d011..000000000 --- a/ApiExtractor/tests/testdroptypeentries.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testdroptypeentries.h" -#include -#include "testutil.h" -#include -#include - -static const char* cppCode ="\ - struct ValueA {};\n\ - struct ValueB {};\n\ - struct ObjectA {};\n\ - struct ObjectB {};\n\ - namespace NamespaceA {\n\ - struct InnerClassA {};\n\ - namespace InnerNamespaceA {}\n\ - }\n\ - namespace NamespaceB {}\n\ - enum EnumA { Value0 };\n\ - enum EnumB { Value1 };\n\ - void funcA();\n\ - void funcB();\n"; - -static const char* xmlCode = "\ -\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ -\n"; - -void TestDropTypeEntries::testDropEntries() -{ - QStringList droppedEntries(QLatin1String("Foo.ValueB")); - droppedEntries << QLatin1String("Foo.ObjectB") << QLatin1String("Foo.NamespaceA.InnerClassA"); - droppedEntries << QLatin1String("Foo.NamespaceB") << QLatin1String("Foo.EnumB") << QLatin1String("Foo.funcB()"); - droppedEntries << QLatin1String("Foo.NamespaceA.InnerNamespaceA"); - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, Q_NULLPTR, droppedEntries)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueA"))); - QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("ValueB"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectA"))); - QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("ObjectB"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA"))); - QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA::InnerClassA"))); - QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("NamespaceB"))); - - AbstractMetaEnumList globalEnums = builder->globalEnums(); - QCOMPARE(globalEnums.count(), 1); - QCOMPARE(globalEnums.first()->name(), QLatin1String("EnumA")); - - TypeDatabase* td = TypeDatabase::instance(); - QVERIFY(td->findType(QLatin1String("funcA"))); - QVERIFY(!td->findType(QLatin1String("funcB"))); -} - -void TestDropTypeEntries::testDontDropEntries() -{ - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueA"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueB"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectA"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectB"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA::InnerClassA"))); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceB"))); - - QCOMPARE(builder->globalEnums().size(), 2); - - TypeDatabase* td = TypeDatabase::instance(); - QVERIFY(td->findType(QLatin1String("funcA"))); - QVERIFY(td->findType(QLatin1String("funcB"))); -} - -static const char* cppCode2 ="\ - struct ValueA {\n\ - void func();\n\ - };\n"; - -static const char* xmlCode2 = "\ -\n\ - \n\ - \n\ - \n\ - \n\ - \n\ -\n"; - -void TestDropTypeEntries::testDropEntryWithChildTags() -{ - QStringList droppedEntries(QLatin1String("Foo.ValueA")); - QScopedPointer builder(TestUtil::parse(cppCode2, xmlCode2, false, Q_NULLPTR, droppedEntries)); - QVERIFY(!builder.isNull()); - QVERIFY(!AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA"))); -} - - -void TestDropTypeEntries::testDontDropEntryWithChildTags() -{ - QScopedPointer builder(TestUtil::parse(cppCode2, xmlCode2, false)); - QVERIFY(!builder.isNull()); - QVERIFY(AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA"))); -} - -QTEST_APPLESS_MAIN(TestDropTypeEntries) diff --git a/ApiExtractor/tests/testdroptypeentries.h b/ApiExtractor/tests/testdroptypeentries.h deleted file mode 100644 index d04c6dc92..000000000 --- a/ApiExtractor/tests/testdroptypeentries.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTDROPTYPEENTRIES_H -#define TESTDROPTYPEENTRIES_H - -#include - -class TestDropTypeEntries : public QObject -{ - Q_OBJECT - private slots: - void testDropEntries(); - void testDontDropEntries(); - void testDropEntryWithChildTags(); - void testDontDropEntryWithChildTags(); -}; - -#endif diff --git a/ApiExtractor/tests/testdtorinformation.cpp b/ApiExtractor/tests/testdtorinformation.cpp deleted file mode 100644 index 63b745c12..000000000 --- a/ApiExtractor/tests/testdtorinformation.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testdtorinformation.h" -#include "abstractmetabuilder.h" -#include -#include "testutil.h" -#include -#include - -void TestDtorInformation::testDtorIsPrivate() -{ - const char* cppCode ="class Control { public: ~Control() {} }; class Subject { private: ~Subject() {} };"; - const char* xmlCode = ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasPrivateDestructor(), false); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasPrivateDestructor(), true); -} - -void TestDtorInformation::testDtorIsProtected() -{ - const char* cppCode ="class Control { public: ~Control() {} }; class Subject { protected: ~Subject() {} };"; - const char* xmlCode = ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasProtectedDestructor(), false); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasProtectedDestructor(), true); -} - -void TestDtorInformation::testDtorIsVirtual() -{ - const char* cppCode ="class Control { public: ~Control() {} }; class Subject { protected: virtual ~Subject() {} };"; - const char* xmlCode = ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasVirtualDestructor(), false); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasVirtualDestructor(), true); -} - -void TestDtorInformation::testClassWithVirtualDtorIsPolymorphic() -{ - const char* cppCode ="class Control { public: virtual ~Control() {} }; class Subject { protected: virtual ~Subject() {} };"; - const char* xmlCode = ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->isPolymorphic(), true); - QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->isPolymorphic(), true); -} - -QTEST_APPLESS_MAIN(TestDtorInformation) - - diff --git a/ApiExtractor/tests/testdtorinformation.h b/ApiExtractor/tests/testdtorinformation.h deleted file mode 100644 index 21a3b1822..000000000 --- a/ApiExtractor/tests/testdtorinformation.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTDTORINFORMATION_H -#define TESTDTORINFORMATION_H - -#include - -class AbstractMetaBuilder; - -class TestDtorInformation: public QObject -{ - Q_OBJECT -private slots: - void testDtorIsPrivate(); - void testDtorIsProtected(); - void testDtorIsVirtual(); - void testClassWithVirtualDtorIsPolymorphic(); -}; - -#endif // TESTDTORINFORMATION_H diff --git a/ApiExtractor/tests/testenum.cpp b/ApiExtractor/tests/testenum.cpp deleted file mode 100644 index 98e56b86e..000000000 --- a/ApiExtractor/tests/testenum.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testenum.h" -#include -#include "testutil.h" -#include -#include - -void TestEnum::testEnumCppSignature() -{ - const char* cppCode ="\ - enum GlobalEnum { A, B };\n\ - \n\ - struct A {\n\ - enum ClassEnum { CA, CB };\n\ - void method(ClassEnum);\n\ - };\n\ - void func(A::ClassEnum);\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - - AbstractMetaEnumList globalEnums = builder->globalEnums(); - QCOMPARE(globalEnums.count(), 1); - QCOMPARE(globalEnums.first()->name(), QLatin1String("GlobalEnum")); - - // enum as parameter of a function - AbstractMetaFunctionList functions = builder->globalFunctions(); - QCOMPARE(functions.count(), 1); - QCOMPARE(functions.first()->arguments().count(), 1); - QCOMPARE(functions.first()->arguments().first()->type()->cppSignature(), QLatin1String("A::ClassEnum")); - - // enum as parameter of a method - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QCOMPARE(classA->enums().count(), 1); - AbstractMetaFunctionList funcs = classA->queryFunctionsByName(QLatin1String("method")); - QVERIFY(!funcs.isEmpty()); - AbstractMetaFunction* method = funcs.first(); - QVERIFY(method); - AbstractMetaArgument* arg = method->arguments().first(); - QCOMPARE(arg->type()->name(), QLatin1String("ClassEnum")); - QCOMPARE(arg->type()->cppSignature(), QLatin1String("A::ClassEnum")); - QCOMPARE(functions.first()->arguments().count(), 1); - arg = functions.first()->arguments().first(); - QCOMPARE(arg->type()->name(), QLatin1String("ClassEnum")); - QCOMPARE(arg->type()->cppSignature(), QLatin1String("A::ClassEnum")); - - AbstractMetaEnumList classEnums = classA->enums(); - QCOMPARE(classEnums.first()->name(), QLatin1String("ClassEnum")); -} - -void TestEnum::testEnumWithApiVersion() -{ - const char* cppCode ="\ - struct A {\n\ - enum ClassEnum { EnumA, EnumB };\n\ - enum ClassEnum2 { EnumC, EnumD };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - QCOMPARE(classes[0]->enums().count(), 1); -} - -void TestEnum::testAnonymousEnum() -{ - const char* cppCode ="\ - enum { Global0, Global1 };\n\ - struct A {\n\ - enum { A0, A1 };\n\ - enum { isThis = true, isThat = false };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaEnumList globalEnums = builder->globalEnums(); - QCOMPARE(globalEnums.count(), 1); - QCOMPARE(globalEnums.first()->typeEntry()->qualifiedCppName(), QLatin1String("Global0")); - QVERIFY(globalEnums.first()->isAnonymous()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - QCOMPARE(classes[0]->enums().count(), 2); - - AbstractMetaEnum* anonEnumA1 = classes[0]->findEnum(QLatin1String("A1")); - QVERIFY(anonEnumA1); - QVERIFY(anonEnumA1->isAnonymous()); - QCOMPARE(anonEnumA1->typeEntry()->qualifiedCppName(), QLatin1String("A::A1")); - - AbstractMetaEnumValue* enumValueA0 = anonEnumA1->values().first(); - QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); - QCOMPARE(enumValueA0->stringValue(), QString()); - - AbstractMetaEnumValue* enumValueA1 = anonEnumA1->values().last(); - QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); - QCOMPARE(enumValueA1->stringValue(), QString()); - - AbstractMetaEnum* anonEnumIsThis = classes[0]->findEnum(QLatin1String("isThis")); - QVERIFY(anonEnumIsThis); - QVERIFY(anonEnumIsThis->isAnonymous()); - QCOMPARE(anonEnumIsThis->typeEntry()->qualifiedCppName(), QLatin1String("A::isThis")); - - AbstractMetaEnumValue* enumValueIsThis = anonEnumIsThis->values().first(); - QCOMPARE(enumValueIsThis->name(), QLatin1String("isThis")); - QCOMPARE(enumValueIsThis->value(), static_cast(true)); - QCOMPARE(enumValueIsThis->stringValue(), QLatin1String("true")); - - AbstractMetaEnumValue* enumValueIsThat = anonEnumIsThis->values().last(); - QCOMPARE(enumValueIsThat->name(), QLatin1String("isThat")); - QCOMPARE(enumValueIsThat->value(), static_cast(false)); - QCOMPARE(enumValueIsThat->stringValue(), QLatin1String("false")); -} - -void TestEnum::testGlobalEnums() -{ - const char* cppCode ="\ - enum EnumA { A0, A1 };\n\ - enum EnumB { B0 = 2, B1 = 0x4 };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaEnumList globalEnums = builder->globalEnums(); - QCOMPARE(globalEnums.count(), 2); - - AbstractMetaEnum* enumA = globalEnums.first(); - QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("EnumA")); - - AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); - QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); - QCOMPARE(enumValueA0->stringValue(), QString()); - - AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); - QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); - QCOMPARE(enumValueA1->stringValue(), QString()); - - AbstractMetaEnum* enumB = globalEnums.last(); - QCOMPARE(enumB->typeEntry()->qualifiedCppName(), QLatin1String("EnumB")); - - AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); - QCOMPARE(enumValueB0->name(), QLatin1String("B0")); - QCOMPARE(enumValueB0->value(), 2); - QCOMPARE(enumValueB0->stringValue(), QLatin1String("2")); - - AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); - QCOMPARE(enumValueB1->name(), QLatin1String("B1")); - QCOMPARE(enumValueB1->value(), 4); - QCOMPARE(enumValueB1->stringValue(), QLatin1String("0x4")); -} - -void TestEnum::testEnumValueFromNeighbourEnum() -{ - const char* cppCode ="\ - namespace A {\n\ - enum EnumA { ValueA0, ValueA1 };\n\ - enum EnumB { ValueB0 = A::ValueA1, ValueB1 = ValueA0 };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - QCOMPARE(classes[0]->enums().count(), 2); - - AbstractMetaEnum* enumA = classes[0]->findEnum(QLatin1String("EnumA")); - QVERIFY(enumA); - QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumA")); - - AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); - QCOMPARE(enumValueA0->name(), QLatin1String("ValueA0")); - QCOMPARE(enumValueA0->value(), 0); - QCOMPARE(enumValueA0->stringValue(), QString()); - - AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); - QCOMPARE(enumValueA1->name(), QLatin1String("ValueA1")); - QCOMPARE(enumValueA1->value(), 1); - QCOMPARE(enumValueA1->stringValue(), QString()); - - AbstractMetaEnum* enumB = classes[0]->findEnum(QLatin1String("EnumB")); - QVERIFY(enumB); - QCOMPARE(enumB->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumB")); - - AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); - QCOMPARE(enumValueB0->name(), QLatin1String("ValueB0")); - QCOMPARE(enumValueB0->value(), 1); - QCOMPARE(enumValueB0->stringValue(), QLatin1String("A::ValueA1")); - - AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); - QCOMPARE(enumValueB1->name(), QLatin1String("ValueB1")); - QCOMPARE(enumValueB1->value(), 0); - QCOMPARE(enumValueB1->stringValue(), QLatin1String("ValueA0")); -} - -void TestEnum::testEnumValueFromExpression() -{ - const char* cppCode ="\ - struct A {\n\ - enum EnumA {\n\ - ValueA0 = 3u,\n\ - ValueA1 = ~3u,\n\ - ValueA2 = ~3,\n\ - ValueA3 = 0xf0,\n\ - ValueA4 = 8 |ValueA3,\n\ - ValueA5 = ValueA3|32,\n\ - ValueA6 = ValueA3 >> 1,\n\ - ValueA7 = ValueA3 << 1\n\ - };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - - AbstractMetaEnum* enumA = classA->findEnum(QLatin1String("EnumA")); - QVERIFY(enumA); - QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumA")); - - AbstractMetaEnumValue* valueA0 = enumA->values().at(0); - QCOMPARE(valueA0->name(), QLatin1String("ValueA0")); - QCOMPARE(valueA0->stringValue(), QLatin1String("3u")); - QCOMPARE(valueA0->value(), (int) 3u); - - AbstractMetaEnumValue* valueA1 = enumA->values().at(1); - QCOMPARE(valueA1->name(), QLatin1String("ValueA1")); - QCOMPARE(valueA1->stringValue(), QLatin1String("~3u")); - QCOMPARE(valueA1->value(), (int) ~3u); - - AbstractMetaEnumValue* valueA2 = enumA->values().at(2); - QCOMPARE(valueA2->name(), QLatin1String("ValueA2")); - QCOMPARE(valueA2->stringValue(), QLatin1String("~3")); - QCOMPARE(valueA2->value(), ~3); - - AbstractMetaEnumValue* valueA3 = enumA->values().at(3); - QCOMPARE(valueA3->name(), QLatin1String("ValueA3")); - QCOMPARE(valueA3->stringValue(), QLatin1String("0xf0")); - QCOMPARE(valueA3->value(), 0xf0); - - AbstractMetaEnumValue* valueA4 = enumA->values().at(4); - QCOMPARE(valueA4->name(), QLatin1String("ValueA4")); - QCOMPARE(valueA4->stringValue(), QLatin1String("8 |ValueA3")); - QCOMPARE(valueA4->value(), 8|0xf0); - - AbstractMetaEnumValue* valueA5 = enumA->values().at(5); - QCOMPARE(valueA5->name(), QLatin1String("ValueA5")); - QCOMPARE(valueA5->stringValue(), QLatin1String("ValueA3|32")); - QCOMPARE(valueA5->value(), 0xf0|32); - - AbstractMetaEnumValue* valueA6 = enumA->values().at(6); - QCOMPARE(valueA6->name(), QLatin1String("ValueA6")); - QCOMPARE(valueA6->stringValue(), QLatin1String("ValueA3 >> 1")); - QCOMPARE(valueA6->value(), 0xf0 >> 1); - - AbstractMetaEnumValue* valueA7 = enumA->values().at(7); - QCOMPARE(valueA7->name(), QLatin1String("ValueA7")); - QCOMPARE(valueA7->stringValue(), QLatin1String("ValueA3 << 1")); - QCOMPARE(valueA7->value(), 0xf0 << 1); -} - -void TestEnum::testPrivateEnum() -{ - 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 = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->enums().count(), 2); - - AbstractMetaEnum* privateEnum = classA->findEnum(QLatin1String("PrivateEnum")); - QVERIFY(privateEnum); - QVERIFY(privateEnum->isPrivate()); - QCOMPARE(privateEnum->typeEntry()->qualifiedCppName(), QLatin1String("A::PrivateEnum")); - - AbstractMetaEnum* publicEnum = classA->findEnum(QLatin1String("PublicEnum")); - QVERIFY(publicEnum); - QCOMPARE(publicEnum->typeEntry()->qualifiedCppName(), QLatin1String("A::PublicEnum")); - - AbstractMetaEnumValue* pub0 = publicEnum->values().first(); - QCOMPARE(pub0->name(), QLatin1String("Pub0")); - QCOMPARE(pub0->value(), 0x0f); - QCOMPARE(pub0->stringValue(), QLatin1String("Priv0")); - - AbstractMetaEnumValue* pub1 = publicEnum->values().last(); - QCOMPARE(pub1->name(), QLatin1String("Pub1")); - QCOMPARE(pub1->value(), 0xf0); - QCOMPARE(pub1->stringValue(), QLatin1String("A::Priv1")); -} - -void TestEnum::testTypedefEnum() -{ - const char* cppCode ="\ - typedef enum EnumA {\n\ - A0,\n\ - A1,\n\ - } EnumA;\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaEnumList globalEnums = builder->globalEnums(); - QEXPECT_FAIL("", "APIExtractor does not handle typedef enum correctly yet", Abort); - QCOMPARE(globalEnums.count(), 1); - - AbstractMetaEnum* enumA = globalEnums.first(); - QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("EnumA")); - - AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); - QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); - QCOMPARE(enumValueA0->stringValue(), QLatin1String("")); - - AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); - QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); - QCOMPARE(enumValueA1->stringValue(), QString()); -} - -QTEST_APPLESS_MAIN(TestEnum) diff --git a/ApiExtractor/tests/testenum.h b/ApiExtractor/tests/testenum.h deleted file mode 100644 index 8b46b1bd6..000000000 --- a/ApiExtractor/tests/testenum.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTENUM_H -#define TESTENUM_H -#include - -class TestEnum : public QObject -{ - Q_OBJECT -private slots: - void testEnumCppSignature(); - void testEnumWithApiVersion(); - void testAnonymousEnum(); - void testGlobalEnums(); - void testEnumValueFromNeighbourEnum(); - void testEnumValueFromExpression(); - void testPrivateEnum(); - void testTypedefEnum(); -}; - -#endif diff --git a/ApiExtractor/tests/testextrainclude.cpp b/ApiExtractor/tests/testextrainclude.cpp deleted file mode 100644 index 97f0d568e..000000000 --- a/ApiExtractor/tests/testextrainclude.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testextrainclude.h" -#include -#include "testutil.h" -#include -#include - -void TestExtraInclude::testClassExtraInclude() -{ - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - - QVector includes = classA->typeEntry()->extraIncludes(); - QCOMPARE(includes.count(), 1); - QCOMPARE(includes.first().name(), QLatin1String("header.h")); -} - -void TestExtraInclude::testGlobalExtraIncludes() -{ - const char* cppCode ="struct A {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("A"))); - - TypeDatabase* td = TypeDatabase::instance(); - TypeEntry* module = td->findType(QLatin1String("Foo")); - QVERIFY(module); - - QVector includes = module->extraIncludes(); - QCOMPARE(includes.count(), 2); - QCOMPARE(includes.first().name(), QLatin1String("header1.h")); - QCOMPARE(includes.last().name(), QLatin1String("header2.h")); -} - -QTEST_APPLESS_MAIN(TestExtraInclude) diff --git a/ApiExtractor/tests/testextrainclude.h b/ApiExtractor/tests/testextrainclude.h deleted file mode 100644 index c569901e1..000000000 --- a/ApiExtractor/tests/testextrainclude.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTEXTRAINCLUDE_H -#define TESTEXTRAINCLUDE_H - -#include - -class TestExtraInclude : public QObject -{ - Q_OBJECT - private slots: - void testClassExtraInclude(); - void testGlobalExtraIncludes(); -}; - -#endif diff --git a/ApiExtractor/tests/testfunctiontag.cpp b/ApiExtractor/tests/testfunctiontag.cpp deleted file mode 100644 index a29d740bf..000000000 --- a/ApiExtractor/tests/testfunctiontag.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testfunctiontag.h" -#include -#include "testutil.h" -#include -#include - -void TestFunctionTag::testFunctionTagForSpecificSignature() -{ - const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("globalFunction")); - QVERIFY(func); - QCOMPARE(builder->globalFunctions().size(), 1); -} - -void TestFunctionTag::testFunctionTagForAllSignatures() -{ - const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();\n"; - const char xmlCode[] = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("globalFunction")); - QVERIFY(func); - QCOMPARE(builder->globalFunctions().size(), 2); -} - -void TestFunctionTag::testRenameGlobalFunction() -{ - const char* cppCode ="void global_function_with_ugly_name();\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("global_function_with_ugly_name")); - QVERIFY(func); - - QCOMPARE(builder->globalFunctions().size(), 1); - const AbstractMetaFunction* metaFunc = builder->globalFunctions().first(); - - QVERIFY(metaFunc); - QCOMPARE(metaFunc->modifications().size(), 1); - QVERIFY(metaFunc->modifications().first().isRenameModifier()); - QCOMPARE(metaFunc->modifications().first().renamedTo(), QLatin1String("smooth")); - - QCOMPARE(metaFunc->name(), QLatin1String("smooth")); - QCOMPARE(metaFunc->originalName(), QLatin1String("global_function_with_ugly_name")); - QCOMPARE(metaFunc->minimalSignature(), QLatin1String("global_function_with_ugly_name()")); -} - -QTEST_APPLESS_MAIN(TestFunctionTag) - diff --git a/ApiExtractor/tests/testfunctiontag.h b/ApiExtractor/tests/testfunctiontag.h deleted file mode 100644 index d4b6c7d2c..000000000 --- a/ApiExtractor/tests/testfunctiontag.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTFUNCTIONTAG_H -#define TESTFUNCTIONTAG_H -#include - -class TestFunctionTag : public QObject -{ - Q_OBJECT -private slots: - void testFunctionTagForSpecificSignature(); - void testFunctionTagForAllSignatures(); - void testRenameGlobalFunction(); -}; - -#endif diff --git a/ApiExtractor/tests/testimplicitconversions.cpp b/ApiExtractor/tests/testimplicitconversions.cpp deleted file mode 100644 index 7e8db42f3..000000000 --- a/ApiExtractor/tests/testimplicitconversions.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testimplicitconversions.h" -#include "testutil.h" -#include -#include -#include - -void TestImplicitConversions::testWithPrivateCtors() -{ - const char* cppCode ="\ - class B;\n\ - class C;\n\ - class A {\n\ - A(const B&);\n\ - public:\n\ - A(const C&);\n\ - };\n\ - class B {};\n\ - class C {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); - AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); - QCOMPARE(implicitConvs.count(), 1); - QCOMPARE(implicitConvs.first()->arguments().first()->type()->typeEntry(), classC->typeEntry()); -} - -void TestImplicitConversions::testWithModifiedVisibility() -{ - const char* cppCode ="\ - class B;\n\ - class A {\n\ - public:\n\ - A(const B&);\n\ - };\n\ - class B {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); - QCOMPARE(implicitConvs.count(), 1); - QCOMPARE(implicitConvs.first()->arguments().first()->type()->typeEntry(), classB->typeEntry()); -} - - -void TestImplicitConversions::testWithAddedCtor() -{ - const char* cppCode ="\ - class B;\n\ - class A {\n\ - public:\n\ - A(const B&);\n\ - };\n\ - class B {};\n\ - class C {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); - QCOMPARE(implicitConvs.count(), 2); - - // Added constructors with custom types should never result in implicit converters. - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - implicitConvs = classB->implicitConversions(); - QCOMPARE(implicitConvs.count(), 0); -} - -void TestImplicitConversions::testWithExternalConversionOperator() -{ - const char* cppCode ="\ - class A {};\n\ - struct B {\n\ - operator A() const;\n\ - };\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); - QCOMPARE(implicitConvs.count(), 1); - AbstractMetaFunctionList externalConvOps = classA->externalConversionOperators(); - QCOMPARE(externalConvOps.count(), 1); - - const AbstractMetaFunction* convOp = 0; - for (const AbstractMetaFunction *func : classB->functions()) { - if (func->isConversionOperator()) - convOp = func; - } - QVERIFY(convOp); - QCOMPARE(implicitConvs.first(), convOp); -} - -QTEST_APPLESS_MAIN(TestImplicitConversions) diff --git a/ApiExtractor/tests/testimplicitconversions.h b/ApiExtractor/tests/testimplicitconversions.h deleted file mode 100644 index 657c1a558..000000000 --- a/ApiExtractor/tests/testimplicitconversions.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTIMPLICITCONVERSIONS_H -#define TESTIMPLICITCONVERSIONS_H - -#include - -class AbstractMetaBuilder; - -class TestImplicitConversions : public QObject -{ - Q_OBJECT -private slots: - void testWithPrivateCtors(); - void testWithModifiedVisibility(); - void testWithAddedCtor(); - void testWithExternalConversionOperator(); -}; - -#endif diff --git a/ApiExtractor/tests/testinserttemplate.cpp b/ApiExtractor/tests/testinserttemplate.cpp deleted file mode 100644 index ecadf311b..000000000 --- a/ApiExtractor/tests/testinserttemplate.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testinserttemplate.h" -#include -#include "testutil.h" -#include -#include - -void TestInsertTemplate::testInsertTemplateOnClassInjectCode() -{ - const char* cppCode ="struct A{};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); - QString code = classA->typeEntry()->codeSnips().first().code(); - QVERIFY(code.contains(QLatin1String("code template content"))); -} - -void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() -{ - const char* cppCode =""; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QVERIFY(classes.isEmpty()); - - TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); - QVERIFY(module); - QCOMPARE(module->codeSnips().count(), 1); - QString code = module->codeSnips().first().code().trimmed(); - QVERIFY(code.contains(QLatin1String("code template content"))); -} - -void TestInsertTemplate::testInvalidTypeSystemTemplate() -{ - const char* cppCode =""; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QVERIFY(classes.isEmpty()); - - TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); - QVERIFY(module); - QCOMPARE(module->codeSnips().count(), 1); - QString code = module->codeSnips().first().code().trimmed(); - QVERIFY(code.isEmpty()); -} - -void TestInsertTemplate::testValidAndInvalidTypeSystemTemplate() -{ - const char* cppCode =""; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QVERIFY(classes.isEmpty()); - - TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); - QVERIFY(module); - QCOMPARE(module->codeSnips().count(), 1); - QString code = module->codeSnips().first().code().trimmed(); - QVERIFY(code.contains(QLatin1String("code template content"))); -} - -QTEST_APPLESS_MAIN(TestInsertTemplate) diff --git a/ApiExtractor/tests/testinserttemplate.h b/ApiExtractor/tests/testinserttemplate.h deleted file mode 100644 index 0e2a882fe..000000000 --- a/ApiExtractor/tests/testinserttemplate.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTINSERTTEMPLATE_H -#define TESTINSERTTEMPLATE_H - -#include - -class TestInsertTemplate : public QObject -{ - Q_OBJECT - private slots: - void testInsertTemplateOnClassInjectCode(); - void testInsertTemplateOnModuleInjectCode(); - void testInvalidTypeSystemTemplate(); - void testValidAndInvalidTypeSystemTemplate(); -}; - -#endif diff --git a/ApiExtractor/tests/testmodifydocumentation.cpp b/ApiExtractor/tests/testmodifydocumentation.cpp deleted file mode 100644 index 96bd0251b..000000000 --- a/ApiExtractor/tests/testmodifydocumentation.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testmodifydocumentation.h" - -#include -#include -#include "testutil.h" -#include -#include -#include - -void TestModifyDocumentation::testModifyDocumentation() -{ - const char* cppCode ="struct B { void b(); }; class A {};\n"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - <para>Some changed contents here</para>\n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); - QVERIFY(classA); - DocModificationList docMods = classA->typeEntry()->docModifications(); - QCOMPARE(docMods.count(), 1); - QCOMPARE(docMods[0].code().trimmed(), QLatin1String("Some changed contents here")); - QCOMPARE(docMods[0].signature(), QString()); - QtDocParser docParser; - docParser.setDocumentationDataDirectory(QDir::currentPath()); - docParser.fillDocumentation(classA); - - QVERIFY(!classA->documentation().value().trimmed().isEmpty()); - QCOMPARE(classA->documentation().value(), QLatin1String("\n\ -oi\n\ - Paragraph number 1\n\ - Paragraph number 2\n\ - Some changed contents here\n\ -\n")); -} - -// 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 -int main(int argc, char** argv) -{ - QCoreApplication app(argc, argv); - TestModifyDocumentation tc; - return QTest::qExec(&tc, argc, argv); -} diff --git a/ApiExtractor/tests/testmodifydocumentation.h b/ApiExtractor/tests/testmodifydocumentation.h deleted file mode 100644 index fb8f6fc01..000000000 --- a/ApiExtractor/tests/testmodifydocumentation.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTMODIFYDOCUMENTATION_H -#define TESTMODIFYDOCUMENTATION_H - -#include - -class TestModifyDocumentation : public QObject -{ -Q_OBJECT -private slots: - void testModifyDocumentation(); -}; - -#endif diff --git a/ApiExtractor/tests/testmodifyfunction.cpp b/ApiExtractor/tests/testmodifyfunction.cpp deleted file mode 100644 index 3d4ef9c89..000000000 --- a/ApiExtractor/tests/testmodifyfunction.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testmodifyfunction.h" -#include -#include "testutil.h" -#include -#include - -void TestModifyFunction::testRenameArgument() -{ - const char* cppCode ="\ - struct A {\n\ - void method(int=0);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - const AbstractMetaFunction* func = classA->findFunction(QLatin1String("method")); - Q_ASSERT(func); - - QCOMPARE(func->argumentName(1), QLatin1String("otherArg")); -} - -void TestModifyFunction::testOwnershipTransfer() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {\n\ - virtual A* method();\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("method")); - - QCOMPARE(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0), TypeSystem::CppOwnership); -} - - -void TestModifyFunction::invalidateAfterUse() -{ - const char* cppCode ="\ - struct A {\n\ - virtual void call(int *a);\n\ - };\n\ - struct B : A {\n\ - };\n\ - struct C : B {\n\ - virtual void call2(int *a);\n\ - };\n\ - struct D : C {\n\ - virtual void call2(int *a);\n\ - };\n\ - struct E : D {\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("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, QLatin1String("C")); - QVERIFY(classC); - func = classC->findFunction(QLatin1String("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(QLatin1String("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, QLatin1String("D")); - QVERIFY(classD); - func = classD->findFunction(QLatin1String("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(QLatin1String("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, QLatin1String("E")); - QVERIFY(classE); - func = classE->findFunction(QLatin1String("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(QLatin1String("call2")); - 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); -} - -void TestModifyFunction::testWithApiVersion() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {\n\ - virtual A* method();\n\ - virtual B* methodB();\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("method")); - - QCOMPARE(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0), TypeSystem::CppOwnership); - - func = classB->findFunction(QLatin1String("methodB")); - QVERIFY(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0) != TypeSystem::CppOwnership); -} - -void TestModifyFunction::testGlobalFunctionModification() -{ - const char* cppCode ="\ - struct A {};\n\ - void function(A* a = 0);\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - QCOMPARE(builder->globalFunctions().size(), 1); - - FunctionModificationList mods = TypeDatabase::instance()->functionModifications(QLatin1String("function(A*)")); - QCOMPARE(mods.count(), 1); - QVector argMods = mods.first().argument_mods; - QCOMPARE(argMods.count(), 1); - ArgumentModification argMod = argMods.first(); - QCOMPARE(argMod.replacedDefaultExpression, QLatin1String("A()")); - - const AbstractMetaFunction* func = builder->globalFunctions().first(); - QVERIFY(func); - QCOMPARE(func->arguments().count(), 1); - const AbstractMetaArgument* arg = func->arguments().first(); - QCOMPARE(arg->type()->cppSignature(), QLatin1String("A *")); - QCOMPARE(arg->originalDefaultValueExpression(), QLatin1String("0")); - QCOMPARE(arg->defaultValueExpression(), QLatin1String("A()")); -} - -QTEST_APPLESS_MAIN(TestModifyFunction) diff --git a/ApiExtractor/tests/testmodifyfunction.h b/ApiExtractor/tests/testmodifyfunction.h deleted file mode 100644 index fcaa0f9db..000000000 --- a/ApiExtractor/tests/testmodifyfunction.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTABSTRACTMETACLASS_H -#define TESTABSTRACTMETACLASS_H - -#include - -class TestModifyFunction : public QObject -{ - Q_OBJECT - private slots: - void testOwnershipTransfer(); - void testWithApiVersion(); - void testRenameArgument(); - void invalidateAfterUse(); - void testGlobalFunctionModification(); -}; - -#endif diff --git a/ApiExtractor/tests/testmultipleinheritance.cpp b/ApiExtractor/tests/testmultipleinheritance.cpp deleted file mode 100644 index b78e6ec01..000000000 --- a/ApiExtractor/tests/testmultipleinheritance.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testmultipleinheritance.h" -#include -#include "testutil.h" -#include -#include - -void TestMultipleInheritance::testVirtualClass() -{ - const char* cppCode ="\ - struct A {\n\ - virtual ~A();\n\ - virtual void theBug();\n\ - };\n\ - struct B {\n\ - virtual ~B();\n\ - };\n\ - struct C : A, B {\n\ - };\n\ - struct D : C {\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 4); - - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, QLatin1String("D")); - bool functionFound = false; - const AbstractMetaFunctionList &functions = classD->functions(); - for (AbstractMetaFunction *f : functions) { - if (f->name() == QLatin1String("theBug")) { - functionFound = true; - break; - } - } - QVERIFY(functionFound); - -} - -QTEST_APPLESS_MAIN(TestMultipleInheritance) diff --git a/ApiExtractor/tests/testmultipleinheritance.h b/ApiExtractor/tests/testmultipleinheritance.h deleted file mode 100644 index 2313073bb..000000000 --- a/ApiExtractor/tests/testmultipleinheritance.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTMULTIPLEINHERITANCE_H -#define TESTMULTIPLEINHERITANCE_H - -#include - -class AbstractMetaBuilder; - -class TestMultipleInheritance : public QObject -{ - Q_OBJECT - private slots: - void testVirtualClass(); -}; - -#endif diff --git a/ApiExtractor/tests/testnamespace.cpp b/ApiExtractor/tests/testnamespace.cpp deleted file mode 100644 index ca6ce0589..000000000 --- a/ApiExtractor/tests/testnamespace.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testnamespace.h" -#include -#include "testutil.h" -#include -#include - -void NamespaceTest::testNamespaceMembers() -{ - const char* cppCode = "\ - namespace Namespace\n\ - {\n\ - enum Option {\n\ - OpZero,\n\ - OpOne\n\ - };\n\ - void foo(Option opt);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass *ns = AbstractMetaClass::findClass(classes, QLatin1String("Namespace")); - QVERIFY(ns); - const AbstractMetaEnum* metaEnum = ns->findEnum(QLatin1String("Option")); - QVERIFY(metaEnum); - const AbstractMetaFunction* func = ns->findFunction(QLatin1String("foo")); - QVERIFY(func); -} - -void NamespaceTest::testNamespaceInnerClassMembers() -{ - const char* cppCode = "\ - namespace OuterNamespace\n\ - {\n\ - namespace InnerNamespace {\n\ - struct SomeClass {\n\ - void method();\n\ - };\n\ - };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace")); - QVERIFY(ons); - const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace")); - QVERIFY(ins); - const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); - QVERIFY(sc); - const AbstractMetaFunction* meth = sc->findFunction(QLatin1String("method")); - QVERIFY(meth); -} - -QTEST_APPLESS_MAIN(NamespaceTest) - diff --git a/ApiExtractor/tests/testnamespace.h b/ApiExtractor/tests/testnamespace.h deleted file mode 100644 index d4451a938..000000000 --- a/ApiExtractor/tests/testnamespace.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTNAMESPACE_H -#define TESTNAMESPACE_H - -#include - -// The class is named 'NamespaceTest' to avoid clashes with Qt COIN using -// '-qtnamespace TestNamespace'. -class NamespaceTest : public QObject -{ - Q_OBJECT - private slots: - void testNamespaceMembers(); - void testNamespaceInnerClassMembers(); -}; - -#endif diff --git a/ApiExtractor/tests/testnestedtypes.cpp b/ApiExtractor/tests/testnestedtypes.cpp deleted file mode 100644 index 296aa4385..000000000 --- a/ApiExtractor/tests/testnestedtypes.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testnestedtypes.h" -#include -#include "testutil.h" -#include -#include - -void TestNestedTypes::testNestedTypesModifications() -{ - const char* cppCode ="\ - namespace OuterNamespace {\n\ - namespace InnerNamespace {\n\ - struct SomeClass {\n\ - void method() {}\n\ - };\n\ - };\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - custom_code1();\n\ - \n\ - custom_code2();\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace")); - QVERIFY(ons); - - const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace")); - QVERIFY(ins); - QCOMPARE(ins->functions().count(), 1); - QCOMPARE(ins->typeEntry()->codeSnips().count(), 1); - CodeSnip snip = ins->typeEntry()->codeSnips().first(); - QCOMPARE(snip.code(), QLatin1String("custom_code1();")); - - AbstractMetaFunction* addedFunc = ins->functions().first(); - QVERIFY(addedFunc->isUserAdded()); - QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); - QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); - QCOMPARE(addedFunc->type()->minimalSignature(), QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); - - QCOMPARE(addedFunc->modifications().size(), 1); - QVERIFY(addedFunc->modifications().first().isCodeInjection()); - snip = addedFunc->modifications().first().snips.first(); - QCOMPARE(snip.code(), QLatin1String("custom_code2();")); - - const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); - QVERIFY(ins); - QCOMPARE(sc->functions().count(), 2); // default constructor and removed method - AbstractMetaFunction* removedFunc = sc->functions().last(); - QVERIFY(removedFunc->isModifiedRemoved()); -} - - -void TestNestedTypes::testDuplicationOfNestedTypes() -{ - const char* cppCode ="\ - namespace Namespace {\n\ - class SomeClass {};\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 2); - const AbstractMetaClass *nspace = AbstractMetaClass::findClass(classes, QLatin1String("Namespace")); - QVERIFY(nspace); - const AbstractMetaClass *cls1 = AbstractMetaClass::findClass(classes, QLatin1String("SomeClass")); - QVERIFY(cls1); - const AbstractMetaClass *cls2 = AbstractMetaClass::findClass(classes, QLatin1String("Namespace::SomeClass")); - QVERIFY(cls2); - QCOMPARE(cls1, cls2); - QCOMPARE(cls1->name(), QLatin1String("SomeClass")); - QCOMPARE(cls1->qualifiedCppName(), QLatin1String("Namespace::SomeClass")); - - TypeEntry* t1 = TypeDatabase::instance()->findType(QLatin1String("Namespace::SomeClass")); - QVERIFY(t1); - TypeEntry* t2 = TypeDatabase::instance()->findType(QLatin1String("SomeClass")); - QVERIFY(!t2); -} - -QTEST_APPLESS_MAIN(TestNestedTypes) diff --git a/ApiExtractor/tests/testnestedtypes.h b/ApiExtractor/tests/testnestedtypes.h deleted file mode 100644 index 737e81fab..000000000 --- a/ApiExtractor/tests/testnestedtypes.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTNESTEDTYPES_H -#define TESTNESTEDTYPES_H -#include - -class TestNestedTypes : public QObject -{ - Q_OBJECT -private slots: - void testNestedTypesModifications(); - void testDuplicationOfNestedTypes(); -}; - -#endif diff --git a/ApiExtractor/tests/testnumericaltypedef.cpp b/ApiExtractor/tests/testnumericaltypedef.cpp deleted file mode 100644 index 3491d5cb4..000000000 --- a/ApiExtractor/tests/testnumericaltypedef.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testnumericaltypedef.h" -#include -#include "testutil.h" -#include -#include - -void TestNumericalTypedef::testNumericalTypedef() -{ - const char* cppCode ="\ - typedef double real;\n\ - void funcDouble(double);\n\ - void funcReal(real);\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - QCOMPARE(builder->globalFunctions().size(), 2); - const AbstractMetaFunction* funcDouble = builder->globalFunctions().first(); - QVERIFY(funcDouble); - const AbstractMetaFunction* funcReal = builder->globalFunctions().last(); - QVERIFY(funcReal); - - if (funcDouble->name() == QLatin1String("funcReal")) - std::swap(funcDouble, funcReal); - - QCOMPARE(funcDouble->minimalSignature(), QLatin1String("funcDouble(double)")); - QCOMPARE(funcReal->minimalSignature(), QLatin1String("funcReal(real)")); - - const AbstractMetaType* doubleType = funcDouble->arguments().first()->type(); - QVERIFY(doubleType); - QCOMPARE(doubleType->cppSignature(), QLatin1String("double")); - QVERIFY(doubleType->isPrimitive()); - QVERIFY(doubleType->typeEntry()->isCppPrimitive()); - - const AbstractMetaType* realType = funcReal->arguments().first()->type(); - QVERIFY(realType); - QCOMPARE(realType->cppSignature(), QLatin1String("real")); - QVERIFY(realType->isPrimitive()); - QVERIFY(realType->typeEntry()->isCppPrimitive()); -} - -void TestNumericalTypedef::testUnsignedNumericalTypedef() -{ - const char* cppCode ="\ - typedef unsigned short ushort;\n\ - void funcUnsignedShort(unsigned short);\n\ - void funcUShort(ushort);\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - QCOMPARE(builder->globalFunctions().size(), 2); - const AbstractMetaFunction* funcUnsignedShort = builder->globalFunctions().first(); - QVERIFY(funcUnsignedShort); - const AbstractMetaFunction* funcUShort = builder->globalFunctions().last(); - QVERIFY(funcUShort); - - if (funcUnsignedShort->name() == QLatin1String("funcUShort")) - std::swap(funcUnsignedShort, funcUShort); - - QCOMPARE(funcUnsignedShort->minimalSignature(), QLatin1String("funcUnsignedShort(unsigned short)")); - QCOMPARE(funcUShort->minimalSignature(), QLatin1String("funcUShort(ushort)")); - - const AbstractMetaType* unsignedShortType = funcUnsignedShort->arguments().first()->type(); - QVERIFY(unsignedShortType); - QCOMPARE(unsignedShortType->cppSignature(), QLatin1String("unsigned short")); - QVERIFY(unsignedShortType->isPrimitive()); - QVERIFY(unsignedShortType->typeEntry()->isCppPrimitive()); - - const AbstractMetaType* ushortType = funcUShort->arguments().first()->type(); - QVERIFY(ushortType); - QCOMPARE(ushortType->cppSignature(), QLatin1String("ushort")); - QVERIFY(ushortType->isPrimitive()); - QVERIFY(ushortType->typeEntry()->isCppPrimitive()); -} - -QTEST_APPLESS_MAIN(TestNumericalTypedef) - diff --git a/ApiExtractor/tests/testnumericaltypedef.h b/ApiExtractor/tests/testnumericaltypedef.h deleted file mode 100644 index e8af1fa8e..000000000 --- a/ApiExtractor/tests/testnumericaltypedef.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTNUMERICALTYPEDEF_H -#define TESTNUMERICALTYPEDEF_H - -#include - -class TestNumericalTypedef : public QObject -{ - Q_OBJECT - private slots: - void testNumericalTypedef(); - void testUnsignedNumericalTypedef(); -}; - -#endif diff --git a/ApiExtractor/tests/testprimitivetypetag.cpp b/ApiExtractor/tests/testprimitivetypetag.cpp deleted file mode 100644 index 7646dd23a..000000000 --- a/ApiExtractor/tests/testprimitivetypetag.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testprimitivetypetag.h" -#include -#include "testutil.h" -#include -#include - -void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {};\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - - PrimitiveTypeEntry* typeEntry = TypeDatabase::instance()->findPrimitiveType(QLatin1String("A")); - QVERIFY(typeEntry); - QVERIFY(typeEntry->hasDefaultConstructor()); - QCOMPARE(typeEntry->defaultConstructor(), QLatin1String("A()")); -} - -QTEST_APPLESS_MAIN(TestPrimitiveTypeTag) - diff --git a/ApiExtractor/tests/testprimitivetypetag.h b/ApiExtractor/tests/testprimitivetypetag.h deleted file mode 100644 index ea9276de3..000000000 --- a/ApiExtractor/tests/testprimitivetypetag.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTPRIMITIVETYPETAG_H -#define TESTPRIMITIVETYPETAG_H - -#include - -class TestPrimitiveTypeTag : public QObject -{ - Q_OBJECT - private slots: - void testPrimitiveTypeDefaultConstructor(); -}; - -#endif diff --git a/ApiExtractor/tests/testrefcounttag.cpp b/ApiExtractor/tests/testrefcounttag.cpp deleted file mode 100644 index e9f9f0ab7..000000000 --- a/ApiExtractor/tests/testrefcounttag.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testrefcounttag.h" -#include -#include "testutil.h" -#include -#include - -void TestRefCountTag::testReferenceCountTag() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {\n\ - void keepObject(B* b);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("keepObject")); - QVERIFY(func); - ReferenceCount refCount = func->modifications().first().argument_mods.first().referenceCounts.first(); - QCOMPARE(refCount.action, ReferenceCount::Add); -} - -void TestRefCountTag::testWithApiVersion() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {\n\ - void keepObject(B*, B*);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("keepObject")); - QVERIFY(func); - ReferenceCount refCount = func->modifications().first().argument_mods.first().referenceCounts.first(); - QCOMPARE(refCount.action, ReferenceCount::Add); - - QCOMPARE(func->modifications().size(), 1); -} - - -QTEST_APPLESS_MAIN(TestRefCountTag) - - diff --git a/ApiExtractor/tests/testrefcounttag.h b/ApiExtractor/tests/testrefcounttag.h deleted file mode 100644 index a95661293..000000000 --- a/ApiExtractor/tests/testrefcounttag.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREFCOUNTTAG_H -#define TESTREFCOUNTTAG_H - -#include - -class TestRefCountTag : public QObject -{ - Q_OBJECT - private slots: - void testReferenceCountTag(); - void testWithApiVersion(); -}; - -#endif diff --git a/ApiExtractor/tests/testreferencetopointer.cpp b/ApiExtractor/tests/testreferencetopointer.cpp deleted file mode 100644 index f594cdd25..000000000 --- a/ApiExtractor/tests/testreferencetopointer.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testreferencetopointer.h" -#include -#include "testutil.h" -#include -#include - -void TestReferenceToPointer::testReferenceToPointerArgument() -{ - const char* cppCode ="\ - struct A {};\n\ - struct B {\n\ - void dummy(A*&);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("dummy")); - QVERIFY(func); - QCOMPARE(func->arguments().first()->type()->minimalSignature(), QLatin1String("A*&")); -} - -QTEST_APPLESS_MAIN(TestReferenceToPointer) - - diff --git a/ApiExtractor/tests/testreferencetopointer.h b/ApiExtractor/tests/testreferencetopointer.h deleted file mode 100644 index 83b0b6fad..000000000 --- a/ApiExtractor/tests/testreferencetopointer.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREFERENCETOPOINTER_H -#define TESTREFERENCETOPOINTER_H - -#include - -class TestReferenceToPointer : public QObject -{ - Q_OBJECT - private slots: - void testReferenceToPointerArgument(); -}; - -#endif diff --git a/ApiExtractor/tests/testremovefield.cpp b/ApiExtractor/tests/testremovefield.cpp deleted file mode 100644 index 7ebe49160..000000000 --- a/ApiExtractor/tests/testremovefield.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testremovefield.h" -#include -#include "testutil.h" -#include -#include - -void TestRemoveField::testRemoveField() -{ - const char* cppCode ="\ - struct A {\n\ - int fieldA;\n\ - int fieldB;\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->fields().size(), 1); - const AbstractMetaField* fieldA = classA->fields().first(); - QVERIFY(fieldA); - QCOMPARE(fieldA->name(), QLatin1String("fieldA")); -} - -QTEST_APPLESS_MAIN(TestRemoveField) - - diff --git a/ApiExtractor/tests/testremovefield.h b/ApiExtractor/tests/testremovefield.h deleted file mode 100644 index ea103e0cc..000000000 --- a/ApiExtractor/tests/testremovefield.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREMOVEFIELD_H -#define TESTREMOVEFIELD_H - -#include - -class TestRemoveField : public QObject -{ - Q_OBJECT - private slots: - void testRemoveField(); -}; - -#endif diff --git a/ApiExtractor/tests/testremoveimplconv.cpp b/ApiExtractor/tests/testremoveimplconv.cpp deleted file mode 100644 index a81380873..000000000 --- a/ApiExtractor/tests/testremoveimplconv.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testremoveimplconv.h" -#include "testutil.h" -#include -#include -#include - -// 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 ="\ - struct A {};\n\ - struct B {};\n\ - struct C {\n\ - C(const A&);\n\ - C(const B&);\n\ - };\n"; - const char* xmlCode = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); - QVERIFY(classC); - AbstractMetaFunctionList implConv = classC->implicitConversions(); - QCOMPARE(implConv.count(), 1); - QCOMPARE(implConv.first()->arguments().first()->type()->typeEntry(), classB->typeEntry()); -} - -QTEST_APPLESS_MAIN(TestRemoveImplConv) diff --git a/ApiExtractor/tests/testremoveimplconv.h b/ApiExtractor/tests/testremoveimplconv.h deleted file mode 100644 index 62d5f74e6..000000000 --- a/ApiExtractor/tests/testremoveimplconv.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREMOVEIMPLCONV_H -#define TESTREMOVEIMPLCONV_H - -#include - -class TestRemoveImplConv : public QObject -{ -Q_OBJECT -private slots: - void testRemoveImplConv(); -}; - -#endif // TESTREMOVEIMPLCONV_H diff --git a/ApiExtractor/tests/testremoveoperatormethod.cpp b/ApiExtractor/tests/testremoveoperatormethod.cpp deleted file mode 100644 index 508cff586..000000000 --- a/ApiExtractor/tests/testremoveoperatormethod.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testremoveoperatormethod.h" -#include -#include "testutil.h" -#include -#include - -void TestRemoveOperatorMethod::testRemoveOperatorMethod() -{ - const char* cppCode ="\ - #include \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 = "\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n"; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().size(), 14); - QStringList removedSignatures; - removedSignatures.append(QLatin1String("operator>>(char&)")); - removedSignatures.append(QLatin1String("operator>>(char*)")); - removedSignatures.append(QLatin1String("operator>>(short&)")); - removedSignatures.append(QLatin1String("operator>>(unsigned short&)")); - removedSignatures.append(QLatin1String("operator>>(int&)")); - removedSignatures.append(QLatin1String("operator>>(unsigned int&)")); - removedSignatures.append(QLatin1String("operator>>(int64_t&)")); - removedSignatures.append(QLatin1String("operator>>(uint64_t&)")); - removedSignatures.append(QLatin1String("operator>>(float&)")); - removedSignatures.append(QLatin1String("operator>>(double&)")); - removedSignatures.append(QLatin1String("operator>>(Char&)")); - removedSignatures.append(QLatin1String("operator>>(String&)")); - int notRemoved = classA->functions().size(); - const AbstractMetaFunctionList &functions = classA->functions(); - for (const AbstractMetaFunction *f : functions) { - QCOMPARE(f->isModifiedRemoved(), bool(removedSignatures.contains(f->minimalSignature()))); - notRemoved -= int(f->isModifiedRemoved()); - } - QCOMPARE(notRemoved, 2); -} - -QTEST_APPLESS_MAIN(TestRemoveOperatorMethod) - diff --git a/ApiExtractor/tests/testremoveoperatormethod.h b/ApiExtractor/tests/testremoveoperatormethod.h deleted file mode 100644 index 17ff75d74..000000000 --- a/ApiExtractor/tests/testremoveoperatormethod.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREMOVEOPERATORMETHOD_H -#define TESTREMOVEOPERATORMETHOD_H - -#include - -class TestRemoveOperatorMethod : public QObject -{ - Q_OBJECT - private slots: - void testRemoveOperatorMethod(); -}; - -#endif diff --git a/ApiExtractor/tests/testresolvetype.cpp b/ApiExtractor/tests/testresolvetype.cpp deleted file mode 100644 index 69691e860..000000000 --- a/ApiExtractor/tests/testresolvetype.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testresolvetype.h" -#include -#include "testutil.h" -#include -#include - -void TestResolveType::testResolveReturnTypeFromParentScope() -{ - const char* cppCode = "\n\ - namespace A {\n\ - struct B {\n\ - struct C {};\n\ - };\n\ - struct D : public B::C {\n\ - C* foo = 0;\n\ - C* method();\n\ - };\n\ - };"; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, QLatin1String("A::D")); - QVERIFY(classD); - const AbstractMetaFunction* meth = classD->findFunction(QLatin1String("method")); - QVERIFY(meth); -} - -QTEST_APPLESS_MAIN(TestResolveType) - diff --git a/ApiExtractor/tests/testresolvetype.h b/ApiExtractor/tests/testresolvetype.h deleted file mode 100644 index 6164d0074..000000000 --- a/ApiExtractor/tests/testresolvetype.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTRESOLVETYPE_H -#define TESTRESOLVETYPE_H - -#include - -class TestResolveType : public QObject -{ - Q_OBJECT - private slots: - void testResolveReturnTypeFromParentScope(); -}; - -#endif diff --git a/ApiExtractor/tests/testreverseoperators.cpp b/ApiExtractor/tests/testreverseoperators.cpp deleted file mode 100644 index 18d6902c2..000000000 --- a/ApiExtractor/tests/testreverseoperators.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testreverseoperators.h" -#include -#include "testutil.h" -#include -#include - -void TestReverseOperators::testReverseSum() -{ - const char cppCode[] = "struct A {\n\ - A& operator+(int);\n\ - };\n\ - A& operator+(int, const A&);"; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().count(), 4); - - const AbstractMetaFunction* reverseOp = 0; - const AbstractMetaFunction* normalOp = 0; - for (const AbstractMetaFunction *func : classA->functions()) { - if (func->name() == QLatin1String("operator+")) { - if (func->isReverseOperator()) - reverseOp = func; - else - normalOp = func; - } - } - - QVERIFY(normalOp); - QVERIFY(!normalOp->isReverseOperator()); - QCOMPARE(normalOp->arguments().count(), 1); - QVERIFY(reverseOp); - QVERIFY(reverseOp->isReverseOperator()); - QCOMPARE(reverseOp->arguments().count(), 1); -} - -void TestReverseOperators::testReverseSumWithAmbiguity() -{ - const char cppCode[] = "\n\ - struct A { A operator+(int); };\n\ - A operator+(int, const A&);\n\ - struct B {};\n\ - B operator+(const A&, const B&);\n\ - B operator+(const B&, const A&);\n\ - int operator-(int, const A*);\n\ - int operator/(const A*, int);\n\ - "; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QEXPECT_FAIL("", "Clang: Does not compile", Abort); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QCOMPARE(classA->functions().count(), 6); - - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QCOMPARE(classB->functions().count(), 4); - - const AbstractMetaFunction* reverseOp = 0; - const AbstractMetaFunction* normalOp = 0; - for (const AbstractMetaFunction *func : classB->functions()) { - if (func->name() == QLatin1String("operator+")) { - if (func->isReverseOperator()) - reverseOp = func; - else - normalOp = func; - } - } - QVERIFY(normalOp); - QVERIFY(!normalOp->isReverseOperator()); - QCOMPARE(normalOp->arguments().count(), 1); - QCOMPARE(normalOp->minimalSignature(), QLatin1String("operator+(B,A)")); - QVERIFY(reverseOp); - QVERIFY(reverseOp->isReverseOperator()); - QCOMPARE(reverseOp->arguments().count(), 1); - QCOMPARE(reverseOp->minimalSignature(), QLatin1String("operator+(A,B)")); - - reverseOp = classA->findFunction(QLatin1String("operator-")); - QVERIFY(reverseOp); - QCOMPARE(reverseOp->arguments().count(), 1); - QVERIFY(reverseOp->isPointerOperator()); - QVERIFY(reverseOp->isReverseOperator()); - - normalOp = classA->findFunction(QLatin1String("operator/")); - QVERIFY(normalOp); - QCOMPARE(normalOp->arguments().count(), 1); - QVERIFY(normalOp->isPointerOperator()); - QVERIFY(!normalOp->isReverseOperator()); - -} - - - -QTEST_APPLESS_MAIN(TestReverseOperators) - diff --git a/ApiExtractor/tests/testreverseoperators.h b/ApiExtractor/tests/testreverseoperators.h deleted file mode 100644 index 3bd65fb85..000000000 --- a/ApiExtractor/tests/testreverseoperators.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTREVERSEOPERATORS_H -#define TESTREVERSEOPERATORS_H -#include - -class TestReverseOperators : public QObject -{ - Q_OBJECT -private slots: - void testReverseSum(); - void testReverseSumWithAmbiguity(); -}; - -#endif diff --git a/ApiExtractor/tests/testtemplates.cpp b/ApiExtractor/tests/testtemplates.cpp deleted file mode 100644 index 4a66264d8..000000000 --- a/ApiExtractor/tests/testtemplates.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testtemplates.h" -#include -#include -#include "testutil.h" -#include -#include - -void TestTemplates::testTemplateWithNamespace() -{ - const char cppCode[] = "\n\ - template struct QList {}; \n\ - struct Url {\n\ - void name();\n\ - };\n\ - namespace Internet {\n\ - struct Url{};\n\ - struct Bookmarks {\n\ - QList list();\n\ - };\n\ - }"; - const char xmlCode0[] = "\n\ - \n\ - \n\ - "; - - QTemporaryFile file; - QVERIFY(file.open()); - file.write(xmlCode0); - file.close(); - - QString xmlCode1 = QString::fromLatin1("\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - ").arg(file.fileName()); - - QScopedPointer builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Bookmarks")); - QVERIFY(classB); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("list")); - AbstractMetaType* funcType = func->type(); - QVERIFY(funcType); - QCOMPARE(funcType->cppSignature(), QLatin1String("QList")); -} - -void TestTemplates::testTemplateOnContainers() -{ - const char cppCode[] = "\n\ - struct Base {};\n\ - template struct QList {}; \n\ - namespace Namespace {\n\ - enum SomeEnum { E1, E2 };\n\ - template struct A {\n\ - A foo(const QList >& a);\n\ - };\n\ - typedef A B;\n\ - }\n\ - "; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isNull()); - const AbstractMetaFunction* func = classB->findFunction(QLatin1String("foo")); - AbstractMetaType* argType = func->arguments().first()->type(); - QCOMPARE(argType->instantiations().count(), 1); - QCOMPARE(argType->typeEntry()->qualifiedCppName(), QLatin1String("QList")); - - const AbstractMetaType* instance1 = argType->instantiations().first(); - QCOMPARE(instance1->instantiations().count(), 1); - QCOMPARE(instance1->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::A")); - - const AbstractMetaType* instance2 = instance1->instantiations().first(); - QCOMPARE(instance2->instantiations().count(), 0); - QCOMPARE(instance2->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::E1")); -} - -void TestTemplates::testTemplateValueAsArgument() -{ - const char cppCode[] = "\n\ - template struct List {};\n\ - void func(List arg) {}\n\ - "; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List")); -} - -void TestTemplates::testTemplatePointerAsArgument() -{ - const char cppCode[] = "\n\ - template struct List {};\n\ - void func(List* arg) {}\n\ - "; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List*)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List *")); -} - -void TestTemplates::testTemplateReferenceAsArgument() -{ - const char cppCode[] = "\n\ - template struct List {};\n\ - void func(List& arg) {}\n\ - "; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); - QCOMPARE(globalFuncs.count(), 1); - - AbstractMetaFunction* func = globalFuncs.first(); - QCOMPARE(func->minimalSignature(), QLatin1String("func(List&)")); - QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List &")); -} - -void TestTemplates::testTemplateParameterFixup() -{ - const char cppCode[] = "\n\ - template\n\ - struct List {\n\ - struct Iterator {};\n\ - void append(List l);\n\ - void erase(List::Iterator it);\n\ - };\n"; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n"; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - const AbstractMetaClassList templates = builder->templates(); - - QCOMPARE(templates.count(), 1); - const AbstractMetaClass *list = templates.first(); - // Verify that the parameter of "void append(List l)" gets fixed to "List" - const AbstractMetaFunction *append = list->findFunction(QStringLiteral("append")); - QVERIFY(append); - QCOMPARE(append->arguments().size(), 1); - QCOMPARE(append->arguments().at(0)->type()->cppSignature(), QLatin1String("List")); - // Verify that the parameter of "void erase(Iterator)" is not modified - const AbstractMetaFunction *erase = list->findFunction(QStringLiteral("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(), QLatin1String("List::Iterator")); -} - -void TestTemplates::testInheritanceFromContainterTemplate() -{ - const char cppCode[] = "\n\ - template\n\ - struct ListContainer {\n\ - inline void push_front(const T& t);\n\ - inline T& front();\n\ - };\n\ - struct FooBar {};\n\ - struct FooBars : public ListContainer {};\n\ - "; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - AbstractMetaClassList templates = builder->templates(); - QCOMPARE(classes.count(), 2); - QCOMPARE(templates.count(), 1); - - const AbstractMetaClass* foobars = AbstractMetaClass::findClass(classes, QLatin1String("FooBars")); - QCOMPARE(foobars->functions().count(), 4); - - const AbstractMetaClass* lc = templates.first(); - QCOMPARE(lc->functions().count(), 2); -} - -void TestTemplates::testTemplateInheritanceMixedWithForwardDeclaration() -{ - const char cppCode[] = "\n\ - enum SomeEnum { E1, E2 };\n\ - template struct Future;\n\ - template\n\ - struct A {\n\ - A();\n\ - void method();\n\ - friend struct Future;\n\ - };\n\ - typedef A B;\n\ - template struct Future {};\n\ - "; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isNull()); - // 3 functions: simple constructor, copy constructor and "method()". - QCOMPARE(classB->functions().count(), 3); -} - -void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration() -{ - const char cppCode[] = "\n\ - namespace Namespace {\n\ - enum SomeEnum { E1, E2 };\n\ - template struct Future;\n\ - template\n\ - struct A {\n\ - A();\n\ - void method();\n\ - friend struct Future;\n\ - };\n\ - typedef A B;\n\ - template struct Future {};\n\ - };\n\ - "; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - - AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Namespace::B")); - QVERIFY(classB); - QVERIFY(!classB->baseClass()); - QVERIFY(classB->baseClassName().isNull()); - // 3 functions: simple constructor, copy constructor and "method()". - QCOMPARE(classB->functions().count(), 3); -} - -void TestTemplates::testTypedefOfInstantiationOfTemplateClass() -{ - const char cppCode[] = "\n\ - namespace NSpace {\n\ - enum ClassType {\n\ - TypeOne\n\ - };\n\ - template\n\ - struct BaseTemplateClass {\n\ - inline ClassType getClassType() const { CLASS_TYPE; }\n\ - };\n\ - typedef BaseTemplateClass TypeOneClass;\n\ - }\n\ - "; - - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 3); - - const AbstractMetaClass* base = AbstractMetaClass::findClass(classes, QLatin1String("BaseTemplateClass")); - QVERIFY(base); - const AbstractMetaClass* one = AbstractMetaClass::findClass(classes, QLatin1String("TypeOneClass")); - QVERIFY(one); - QCOMPARE(one->templateBaseClass(), base); - QCOMPARE(one->functions().count(), base->functions().count()); - QVERIFY(one->isTypeDef()); - const ComplexTypeEntry* oneType = one->typeEntry(); - const ComplexTypeEntry* baseType = base->typeEntry(); - QCOMPARE(oneType->baseContainerType(), baseType); - QCOMPARE(one->baseClassNames(), QStringList(QLatin1String("BaseTemplateClass"))); - - QVERIFY(one->hasTemplateBaseClassInstantiations()); - AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); - QCOMPARE(instantiations.count(), 1); - const AbstractMetaType* inst = instantiations.first(); - QVERIFY(inst); - QVERIFY(!inst->isEnum()); - QVERIFY(!inst->typeEntry()->isEnum()); - QVERIFY(inst->typeEntry()->isEnumValue()); - QCOMPARE(inst->cppSignature(), QLatin1String("NSpace::TypeOne")); -} - -void TestTemplates::testContainerTypeIncompleteArgument() -{ - const char* cppCode ="\n\ - template\n\ - class Vector {\n\ - void method(const Vector& vector);\n\ - Vector otherMethod();\n\ - };\n\ - template \n\ - void Vector::method(const Vector& vector) {}\n\ - template \n\ - Vector Vector::otherMethod() { return Vector(); }\n\ - typedef Vector IntVector;\n\ - "; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - "; - - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - QCOMPARE(classes.count(), 1); - - AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, QLatin1String("IntVector")); - QVERIFY(vector); - QVERIFY(vector->typeEntry()->baseContainerType()); - QCOMPARE(reinterpret_cast(vector->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::VectorContainer); - QCOMPARE(vector->functions().count(), 4); - - const AbstractMetaFunction* method = vector->findFunction(QLatin1String("method")); - QVERIFY(method); - QCOMPARE(method->signature(), QLatin1String("method(const Vector & vector)")); - - const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod")); - QVERIFY(otherMethod); - QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()")); - QVERIFY(otherMethod->type()); - QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector")); -} - -QTEST_APPLESS_MAIN(TestTemplates) diff --git a/ApiExtractor/tests/testtemplates.h b/ApiExtractor/tests/testtemplates.h deleted file mode 100644 index 7b0d0f3b3..000000000 --- a/ApiExtractor/tests/testtemplates.h +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTTEMPLATES_H -#define TESTTEMPLATES_H - -#include - -class TestTemplates : public QObject -{ - Q_OBJECT -private slots: - void testTemplateOnContainers(); - void testTemplateWithNamespace(); - void testTemplateValueAsArgument(); - void testTemplatePointerAsArgument(); - void testTemplateReferenceAsArgument(); - void testTemplateParameterFixup(); - void testInheritanceFromContainterTemplate(); - void testTemplateInheritanceMixedWithForwardDeclaration(); - void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); - void testTypedefOfInstantiationOfTemplateClass(); - void testContainerTypeIncompleteArgument(); -}; - -#endif diff --git a/ApiExtractor/tests/testtoposort.cpp b/ApiExtractor/tests/testtoposort.cpp deleted file mode 100644 index 30d368a8a..000000000 --- a/ApiExtractor/tests/testtoposort.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testtoposort.h" -#include -#include "graph.h" -#include - -void TestTopoSort::testTopoSort() -{ - QLinkedList result; - { - Graph g(3); - g.addEdge(1, 2); - g.addEdge(0, 1); - result = g.topologicalSort(); - QCOMPARE(result.size(), 3); - QLinkedList::iterator it = result.begin(); - QCOMPARE(*it, 0); - QCOMPARE(*(++it), 1); - QCOMPARE(*(++it), 2); - } - { - Graph g(2); - result = g.topologicalSort(); - QCOMPARE(result.size(), 2); - QLinkedList::iterator it = result.begin(); - QCOMPARE(*it, 1); - QCOMPARE(*(++it), 0); - } -} - -void TestTopoSort::testCiclicGraph() -{ - Graph g(3); - g.addEdge(0, 1); - g.addEdge(1, 2); - g.addEdge(2, 0); - QLinkedList result = g.topologicalSort(); - QVERIFY(result.isEmpty()); -} - -QTEST_APPLESS_MAIN(TestTopoSort) - diff --git a/ApiExtractor/tests/testtoposort.h b/ApiExtractor/tests/testtoposort.h deleted file mode 100644 index ae8a2bab8..000000000 --- a/ApiExtractor/tests/testtoposort.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTTOPOSORT_H -#define TESTTOPOSORT_H - -#include - -class TestTopoSort : public QObject -{ -Q_OBJECT -private slots: - void testTopoSort(); - void testCiclicGraph(); -}; - -#endif diff --git a/ApiExtractor/tests/testtyperevision.cpp b/ApiExtractor/tests/testtyperevision.cpp deleted file mode 100644 index 804683140..000000000 --- a/ApiExtractor/tests/testtyperevision.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testtyperevision.h" -#include -#include "testutil.h" -#include -#include - -void TestTypeRevision::testRevisionAttr() -{ - const char* cppCode = "class Rev_0 {};" - "class Rev_1 {};" - "class Rev_2 { public: enum Rev_3 { X }; enum Rev_5 { Y }; };"; - const char* xmlCode = "" - "" - "" - "" - " " - " " - "" - ""; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_0")); - QCOMPARE(getTypeRevision(rev0->typeEntry()), 0); - - const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_1")); - QCOMPARE(getTypeRevision(rev1->typeEntry()), 1); - - AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_2")); - QCOMPARE(getTypeRevision(rev2->typeEntry()), 2); - - AbstractMetaEnum* rev3 = rev2->findEnum(QLatin1String("Rev_3")); - QCOMPARE(getTypeRevision(rev3->typeEntry()), 3); - FlagsTypeEntry* rev4 = rev3->typeEntry()->flags(); - QCOMPARE(getTypeRevision(rev4), 4); - AbstractMetaEnum* rev5 = rev2->findEnum(QLatin1String("Rev_5")); - QCOMPARE(getTypeRevision(rev5->typeEntry()), 5); - QCOMPARE(getTypeRevision(rev5->typeEntry()->flags()), 5); -} - -QTEST_APPLESS_MAIN(TestTypeRevision) - - diff --git a/ApiExtractor/tests/testtyperevision.h b/ApiExtractor/tests/testtyperevision.h deleted file mode 100644 index dcb2d8794..000000000 --- a/ApiExtractor/tests/testtyperevision.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTTYPEREVISION_H -#define TESTTYPEREVISION_H - -#include - -class TestTypeRevision : public QObject -{ - Q_OBJECT - -private slots: - void testRevisionAttr(); -}; - -#endif diff --git a/ApiExtractor/tests/testutil.h b/ApiExtractor/tests/testutil.h deleted file mode 100644 index 200fdb104..000000000 --- a/ApiExtractor/tests/testutil.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTUTIL_H -#define TESTUTIL_H -#include -#include -#include -#include -#include "abstractmetabuilder.h" -#include "reporthandler.h" -#include "typedatabase.h" - -namespace TestUtil -{ - static AbstractMetaBuilder *parse(const char *cppCode, const char *xmlCode, - bool silent = true, - const char *apiVersion = Q_NULLPTR, - const QStringList &dropTypeEntries = QStringList()) - { - ReportHandler::setSilent(silent); - TypeDatabase* td = TypeDatabase::instance(true); - if (apiVersion && !td->setApiVersion(QLatin1String("*"), QLatin1String(apiVersion))) - return Q_NULLPTR; - td->setDropTypeEntries(dropTypeEntries); - QBuffer buffer; - // parse typesystem - buffer.setData(xmlCode); - if (!buffer.open(QIODevice::ReadOnly)) - return Q_NULLPTR; - td->parseFile(&buffer); - buffer.close(); - // parse C++ code - QTemporaryFile tempSource(QDir::tempPath() + QLatin1String("/st_XXXXXX_main.cpp")); - if (!tempSource.open()) { - qWarning().noquote().nospace() << "Creation of temporary file failed: " - << tempSource.errorString(); - return nullptr; - } - QByteArrayList arguments; - arguments.append(QFile::encodeName(tempSource.fileName())); - tempSource.write(cppCode, qint64(strlen(cppCode))); - tempSource.close(); - AbstractMetaBuilder *builder = new AbstractMetaBuilder; - if (!builder->build(arguments, 0)) { - delete builder; - return Q_NULLPTR; - } - return builder; - } -} // namespace TestUtil - -#endif diff --git a/ApiExtractor/tests/testvaluetypedefaultctortag.cpp b/ApiExtractor/tests/testvaluetypedefaultctortag.cpp deleted file mode 100644 index 627255d37..000000000 --- a/ApiExtractor/tests/testvaluetypedefaultctortag.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testvaluetypedefaultctortag.h" -#include -#include "testutil.h" -#include -#include - -void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument() -{ - const char* cppCode ="\n\ - struct A {\n\ - A(int,int);\n\ - };\n\ - struct B {};\n\ - "; - const char* xmlCode = "\n\ - \n\ - \n\ - \n\ - \n\ - "; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); - QVERIFY(!builder.isNull()); - - AbstractMetaClassList classes = builder->classes(); - - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - QVERIFY(classA->typeEntry()->hasDefaultConstructor()); - QCOMPARE(classA->typeEntry()->defaultConstructor(), QLatin1String("A(0, 0)")); - - const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); - QVERIFY(classB); - QVERIFY(!classB->typeEntry()->hasDefaultConstructor()); -} - -QTEST_APPLESS_MAIN(TestValueTypeDefaultCtorTag) diff --git a/ApiExtractor/tests/testvaluetypedefaultctortag.h b/ApiExtractor/tests/testvaluetypedefaultctortag.h deleted file mode 100644 index 2d2efe79d..000000000 --- a/ApiExtractor/tests/testvaluetypedefaultctortag.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTVALUETYPEDEFAULTCTORTAG_H -#define TESTVALUETYPEDEFAULTCTORTAG_H - -#include - -class TestValueTypeDefaultCtorTag : public QObject -{ - Q_OBJECT - private slots: - void testValueTypeDefaultCtorTagArgument(); -}; - -#endif diff --git a/ApiExtractor/tests/testvoidarg.cpp b/ApiExtractor/tests/testvoidarg.cpp deleted file mode 100644 index 5f0b47389..000000000 --- a/ApiExtractor/tests/testvoidarg.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "testvoidarg.h" -#include -#include "testutil.h" -#include -#include - -void TestVoidArg::testVoidParsedFunction() -{ - const char cppCode[] = "struct A { void a(void); };"; - const char xmlCode[] = "\n\ - \n\ - \n\ - "; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); - QCOMPARE(addedFunc->arguments().count(), 0); -} - -void TestVoidArg::testVoidAddedFunction() -{ - const char cppCode[] = "struct A { };"; - const char xmlCode[] = "\n\ - \n\ - \n\ - \n\ - \n\ - "; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); - QCOMPARE(addedFunc->arguments().count(), 0); - -} - -void TestVoidArg::testVoidPointerParsedFunction() -{ - const char cppCode[] = "struct A { void a(void*); };"; - const char xmlCode[] = "\n\ - \n\ - \n\ - "; - QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); - QVERIFY(!builder.isNull()); - AbstractMetaClassList classes = builder->classes(); - const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); - QVERIFY(classA); - const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); - QCOMPARE(addedFunc->arguments().count(), 1); - -} - -QTEST_APPLESS_MAIN(TestVoidArg) diff --git a/ApiExtractor/tests/testvoidarg.h b/ApiExtractor/tests/testvoidarg.h deleted file mode 100644 index 40d96a4ff..000000000 --- a/ApiExtractor/tests/testvoidarg.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TESTVOIDARG_H -#define TESTVOIDARG_H -#include - -class TestVoidArg : public QObject -{ - Q_OBJECT -private slots: - void testVoidParsedFunction(); - void testVoidPointerParsedFunction(); - void testVoidAddedFunction(); -}; - -#endif diff --git a/ApiExtractor/tests/utf8code.txt b/ApiExtractor/tests/utf8code.txt deleted file mode 100644 index 6d5fa9dcf..000000000 --- a/ApiExtractor/tests/utf8code.txt +++ /dev/null @@ -1 +0,0 @@ -áéíóú \ No newline at end of file diff --git a/ApiExtractor/typedatabase.cpp b/ApiExtractor/typedatabase.cpp deleted file mode 100644 index a1b28070b..000000000 --- a/ApiExtractor/typedatabase.cpp +++ /dev/null @@ -1,745 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typedatabase.h" -#include "typesystem.h" -#include "typesystem_p.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "reporthandler.h" -// #include -#include - -// package -> api-version - -static QString wildcardToRegExp(QString w) -{ - w.replace(QLatin1Char('?'), QLatin1Char('.')); - w.replace(QLatin1Char('*'), QStringLiteral(".*")); - return w; -} - -typedef QPair ApiVersion; -typedef QVector ApiVersions; - -Q_GLOBAL_STATIC(ApiVersions, apiVersions) - -TypeDatabase::TypeDatabase() : m_suppressWarnings(true) -{ - addType(new VoidTypeEntry()); - addType(new VarargsTypeEntry()); -} - -TypeDatabase::~TypeDatabase() -{ -} - -TypeDatabase* TypeDatabase::instance(bool newInstance) -{ - static TypeDatabase* db = 0; - if (!db || newInstance) { - if (db) - delete db; - db = new TypeDatabase; - } - return db; -} - -// A list of regex/replacements to fix int types like "ushort" to "unsigned short" -// unless present in TypeDatabase -struct IntTypeNormalizationEntry -{ - QRegularExpression regex; - QString replacement; -}; - -typedef QVector IntTypeNormalizationEntries; - -static const IntTypeNormalizationEntries &intTypeNormalizationEntries() -{ - static IntTypeNormalizationEntries result; - static bool firstTime = true; - if (firstTime) { - firstTime = false; - static const char *intTypes[] = {"char", "short", "int", "long"}; - const size_t size = sizeof(intTypes) / sizeof(intTypes[0]); - for (size_t i = 0; i < size; ++i) { - const QString intType = QLatin1String(intTypes[i]); - if (!TypeDatabase::instance()->findType(QLatin1Char('u') + intType)) { - IntTypeNormalizationEntry entry; - entry.replacement = QStringLiteral("unsigned ") + intType; - entry.regex.setPattern(QStringLiteral("\\bu") + intType + QStringLiteral("\\b")); - Q_ASSERT(entry.regex.isValid()); - result.append(entry); - } - } - } - return result; -} - -QString TypeDatabase::normalizedSignature(const QString &signature) -{ - QString normalized = QLatin1String(QMetaObject::normalizedSignature(signature.toUtf8().constData())); - - if (instance() && signature.contains(QLatin1String("unsigned"))) { - const IntTypeNormalizationEntries &entries = intTypeNormalizationEntries(); - for (int i = 0, size = entries.size(); i < size; ++i) - normalized.replace(entries.at(i).regex, entries.at(i).replacement); - } - - return normalized; -} - -QStringList TypeDatabase::requiredTargetImports() const -{ - return m_requiredTargetImports; -} - -void TypeDatabase::addRequiredTargetImport(const QString& moduleName) -{ - if (!m_requiredTargetImports.contains(moduleName)) - 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 - m_typesystemPaths += typesystem_paths.split(QLatin1Char(path_splitter)); -} - -IncludeList TypeDatabase::extraIncludes(const QString& className) const -{ - ComplexTypeEntry* typeEntry = findComplexType(className); - if (typeEntry) - return typeEntry->extraIncludes(); - else - return IncludeList(); -} - -ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const -{ - QString template_name = name; - - int pos = name.indexOf(QLatin1Char('<')); - if (pos > 0) - template_name = name.left(pos); - - TypeEntry* type_entry = findType(template_name); - if (type_entry && type_entry->isContainer()) - return static_cast(type_entry); - return 0; -} - -FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const -{ - TypeEntry* entry = findType(name); - if (entry && entry->type() == TypeEntry::FunctionType) - return static_cast(entry); - return 0; -} - -TypeEntry* TypeDatabase::findType(const QString& name) const -{ - const TypeEntryList &entries = findTypes(name); - for (TypeEntry *entry : entries) { - if (entry && - (!entry->isPrimitive() || static_cast(entry)->preferredTargetLangType())) { - return entry; - } - } - return 0; -} - -TypeEntryList TypeDatabase::findTypes(const QString &name) const -{ - return m_entries.value(name); -} - -SingleTypeEntryHash TypeDatabase::entries() const -{ - TypeEntryHash entries = allEntries(); - - SingleTypeEntryHash returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) - returned.insert(it.key(), findType(it.key())); - - return returned; -} - -PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const -{ - TypeEntryHash entries = allEntries(); - PrimitiveTypeEntryList returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - for (TypeEntry *typeEntry : it.value()) { - if (typeEntry->isPrimitive()) - returned.append(static_cast(typeEntry)); - } - } - return returned; -} - -ContainerTypeEntryList TypeDatabase::containerTypes() const -{ - TypeEntryHash entries = allEntries(); - ContainerTypeEntryList returned; - for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { - for (TypeEntry *typeEntry : it.value()) { - if (typeEntry->isContainer()) - returned.append(static_cast(typeEntry)); - } - } - return returned; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeRejection &r) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TypeRejection(type=" << r.matchType << ", class=" - << r.className.pattern() << ", pattern=" << r.pattern.pattern() << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -void TypeDatabase::addRejection(const TypeRejection &r) -{ - m_rejections << r; -} - -static inline QString msgRejectReason(const TypeRejection &r, const QString &needle = QString()) -{ - QString result; - QTextStream str(&result); - switch (r.matchType) { - case TypeRejection::ExcludeClass: - str << " matches class exclusion \"" << r.className.pattern() << '"'; - break; - case TypeRejection::Function: - case TypeRejection::Field: - case TypeRejection::Enum: - str << " matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; - break; - case TypeRejection::ArgumentType: - case TypeRejection::ReturnType: - str << " matches class \"" << r.className.pattern() << "\" and \"" << needle - << "\" matches \"" << r.pattern.pattern() << '"'; - break; - } - return result; -} - -// Match class name only -bool TypeDatabase::isClassRejected(const QString& className, QString *reason) const -{ - for (const TypeRejection& r : m_rejections) { - if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { - if (reason) - *reason = msgRejectReason(r); - return true; - } - } - return false; -} - -// Match class name and function/enum/field -static bool findRejection(const QVector &rejections, - TypeRejection::MatchType matchType, - const QString& className, const QString& name, - QString *reason = nullptr) -{ - Q_ASSERT(matchType != TypeRejection::ExcludeClass); - for (const TypeRejection& r : rejections) { - if (r.matchType == matchType && r.pattern.match(name).hasMatch() - && r.className.match(className).hasMatch()) { - if (reason) - *reason = msgRejectReason(r, name); - return true; - } - } - return false; -} - -bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName, QString *reason) const -{ - return findRejection(m_rejections, TypeRejection::Enum, className, enumName, reason); -} - -void TypeDatabase::addType(TypeEntry *e) -{ - m_entries[e->qualifiedCppName()].append(e); -} - -bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, - QString *reason) const -{ - return findRejection(m_rejections, TypeRejection::Function, className, functionName, reason); -} - -bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName, - QString *reason) const -{ - return findRejection(m_rejections, TypeRejection::Field, className, fieldName, reason); -} - -bool TypeDatabase::isArgumentTypeRejected(const QString& className, const QString& typeName, - QString *reason) const -{ - return findRejection(m_rejections, TypeRejection::ArgumentType, className, typeName, reason); -} - -bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& typeName, - QString *reason) const -{ - return findRejection(m_rejections, TypeRejection::ReturnType, className, typeName, reason); -} - -FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const -{ - TypeEntry *fte = findType(name); - if (!fte) { - fte = m_flagsEntries.value(name); - if (!fte) { - //last hope, search for flag without scope inside of flags hash - for (SingleTypeEntryHash::const_iterator it = m_flagsEntries.cbegin(), end = m_flagsEntries.cend(); it != end; ++it) { - if (it.key().endsWith(name)) { - fte = it.value(); - break; - } - } - } - } - return static_cast(fte); -} - -void TypeDatabase::addFlagsType(FlagsTypeEntry *fte) -{ - m_flagsEntries[fte->originalName()] = fte; -} - -void TypeDatabase::addTemplate(TemplateEntry *t) -{ - m_templates[t->name()] = t; -} - -void TypeDatabase::addGlobalUserFunctions(const AddedFunctionList &functions) -{ - m_globalUserFunctions << functions; -} - -AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const -{ - AddedFunctionList addedFunctions; - for (const AddedFunction &func : m_globalUserFunctions) { - if (func.name() == name) - addedFunctions.append(func); - } - return addedFunctions; -} - -void TypeDatabase::addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications) -{ - m_functionMods << functionModifications; -} - -QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) -{ - return QLatin1String("Global"); -} - -FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const -{ - FunctionModificationList lst; - for (int i = 0; i < m_functionMods.count(); ++i) { - const FunctionModification& mod = m_functionMods.at(i); - if (mod.signature == signature) - lst << mod; - } - - return lst; -} - -void TypeDatabase::addSuppressedWarning(const QString &s) -{ - m_suppressedWarnings.append(s); -} - -bool TypeDatabase::isSuppressedWarning(const QString& s) const -{ - if (!m_suppressWarnings) - return false; - - for (QString warning : m_suppressedWarnings) { - warning.replace(QLatin1String("\\*"), QLatin1String("&place_holder_for_asterisk;")); - - QStringList segs = warning.split(QLatin1Char('*'), QString::SkipEmptyParts); - if (!segs.size()) - continue; - - int i = 0; - int pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*"))); - //qDebug() << "s == " << s << ", warning == " << segs; - while (pos != -1) { - if (i == segs.size()) - return true; - pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*")), pos); - } - } - - return false; -} - -QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) const -{ - const QFileInfo tsFi(tsFile); - if (tsFi.isAbsolute()) // No point in further lookups - return tsFi.absoluteFilePath(); - if (tsFi.isFile()) // Make path absolute - return tsFi.absoluteFilePath(); - const QString fileName = tsFi.fileName(); - for (const QString &path : m_typesystemPaths) { - const QFileInfo fi(path + QLatin1Char('/') + fileName); - if (fi.isFile()) - return fi.absoluteFilePath(); - } - return tsFile; -} - -bool TypeDatabase::parseFile(const QString &filename, bool generate) -{ - QString filepath = modifiedTypesystemFilepath(filename); - if (m_parsedTypesystemFiles.contains(filepath)) - return m_parsedTypesystemFiles[filepath]; - - m_parsedTypesystemFiles[filepath] = true; // Prevent recursion when including self. - - QFile file(filepath); - if (!file.exists()) { - m_parsedTypesystemFiles[filepath] = false; - qCWarning(lcShiboken).noquote().nospace() - << "Can't find " << filename << ", typesystem paths: " << m_typesystemPaths.join(QLatin1String(", ")); - return false; - } - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - m_parsedTypesystemFiles[filepath] = false; - qCWarning(lcShiboken).noquote().nospace() - << "Can't open " << QDir::toNativeSeparators(filename) << ": " << file.errorString(); - return false; - } - - int count = m_entries.size(); - bool ok = parseFile(&file, generate); - m_parsedTypesystemFiles[filepath] = ok; - int newCount = m_entries.size(); - - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("Parsed: '%1', %2 new entries").arg(filename).arg(newCount - count); - } - return ok; -} - -bool TypeDatabase::parseFile(QIODevice* device, bool generate) -{ - QXmlStreamReader reader(device); - Handler handler(this, generate); - return handler.parse(reader); -} - -PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const -{ - const TypeEntryList &entries = findTypes(name); - - for (TypeEntry *entry : entries) { - if (entry && entry->isPrimitive() && static_cast(entry)->preferredTargetLangType()) - return static_cast(entry); - } - - return 0; -} - -ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const -{ - const TypeEntryList &entries = findTypes(name); - for (TypeEntry *entry : entries) { - if (entry && entry->isComplex()) - return static_cast(entry); - } - return 0; -} - -ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const -{ - const TypeEntryList &entries = findTypes(name); - for (TypeEntry *entry : entries) { - if (entry && entry->isObject()) - return static_cast(entry); - } - return 0; -} - -NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const -{ - const TypeEntryList &entries = findTypes(name); - for (TypeEntry *entry : entries) { - if (entry && entry->isNamespace()) - return static_cast(entry); - } - return 0; -} - -bool TypeDatabase::shouldDropTypeEntry(const QString& fullTypeName) const -{ - return m_dropTypeEntries.contains(fullTypeName); -} - -void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) -{ - m_dropTypeEntries = dropTypeEntries; - m_dropTypeEntries.sort(); -} - -// Using std::pair to save some memory -// the pair means (revision, typeIndex) -// This global variable exists only because we can't break the ABI -typedef QHash > TypeRevisionMap; -Q_GLOBAL_STATIC(TypeRevisionMap, typeEntryFields); -static bool computeTypeIndexes = true; -static int maxTypeIndex; - -int getTypeRevision(const TypeEntry* typeEntry) -{ - return typeEntryFields()->value(typeEntry).first; -} - -void setTypeRevision(TypeEntry* typeEntry, int revision) -{ - (*typeEntryFields())[typeEntry].first = revision; - computeTypeIndexes = true; -} - -static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) -{ - return t1->qualifiedCppName() < t2->qualifiedCppName(); -} - -static void _computeTypeIndexes() -{ - TypeDatabase* tdb = TypeDatabase::instance(); - typedef QMap GroupedTypeEntries; - GroupedTypeEntries groupedEntries; - - // Group type entries by revision numbers - const TypeEntryHash &allEntries = tdb->allEntries(); - for (TypeEntryHash::const_iterator tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { - for (TypeEntry *entry : tit.value()) { - if (entry->isPrimitive() - || entry->isContainer() - || entry->isFunction() - || !entry->generateCode() - || entry->isEnumValue() - || entry->isVarargs() - || entry->isTypeSystem() - || entry->isVoid() - || entry->isCustom()) - continue; - groupedEntries[getTypeRevision(entry)] << entry; - } - } - - maxTypeIndex = 0; - GroupedTypeEntries::iterator it = groupedEntries.begin(); - for (; it != groupedEntries.end(); ++it) { - // Remove duplicates - TypeEntryList::iterator newEnd = std::unique(it.value().begin(), it.value().end()); - it.value().erase(newEnd, it.value().end()); - // Sort the type entries by name - qSort(it.value().begin(), newEnd, compareTypeEntriesByName); - - for (TypeEntry *entry : qAsConst(it.value())) { - (*typeEntryFields())[entry].second = maxTypeIndex++; - } - } - computeTypeIndexes = false; -} - -int getTypeIndex(const TypeEntry* typeEntry) -{ - if (computeTypeIndexes) - _computeTypeIndexes(); - return typeEntryFields()->value(typeEntry).second; -} - -int getMaxTypeIndex() -{ - if (computeTypeIndexes) - _computeTypeIndexes(); - return maxTypeIndex; -} - -bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QString &version) -{ - const QString packagePattern = wildcardToRegExp(packageWildcardPattern.trimmed()); - const QVersionNumber versionNumber = QVersionNumber::fromString(version); - if (versionNumber.isNull()) - return false; - ApiVersions &versions = *apiVersions(); - for (int i = 0, size = versions.size(); i < size; ++i) { - if (versions.at(i).first.pattern() == packagePattern) { - versions[i].second = versionNumber; - return true; - } - } - const QRegularExpression packageRegex(packagePattern); - if (!packageRegex.isValid()) - return false; - versions.append(qMakePair(packageRegex, versionNumber)); - return true; -} - -bool TypeDatabase::checkApiVersion(const QString& package, const QString& version) const -{ - const QVersionNumber versionNumber = QVersionNumber::fromString(version); - if (versionNumber.isNull()) { - qCWarning(lcShiboken).noquote().nospace() - << "checkApiVersion: Invalid version \"" << version << "\" specified for package " - << package << '.'; - return false; - } - const ApiVersions &versions = *apiVersions(); - for (int i = 0, size = versions.size(); i < size; ++i) { - if (versions.at(i).first.match(package).hasMatch()) - return versions.at(i).second >= versionNumber; - } - return false; -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeEntry *te) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TypeEntry("; - if (te) { - d << '"' << te->qualifiedCppName() << "\", type=" << te->type(); - if (te->include().isValid()) - d << ", include=" << te->include(); - const IncludeList &extraIncludes = te->extraIncludes(); - if (const int count = extraIncludes.size()) { - d << ", extraIncludes[" << count << "]="; - for (int i = 0; i < count; ++i) { - if (i) - d << ", "; - d << extraIncludes.at(i); - } - } - } else { - d << '0'; - } - d << ')'; - return d; -} - -QDebug operator<<(QDebug d, const TemplateEntry *te) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TemplateEntry("; - if (te) { - d << '"' << te->name() << "\", version=" << te->version(); - } else { - d << '0'; - } - d << ')'; - return d; -} - -void TypeDatabase::formatDebug(QDebug &d) const -{ - typedef TypeEntryHash::ConstIterator Eit; - typedef SingleTypeEntryHash::ConstIterator Sit; - typedef TemplateEntryHash::ConstIterator TplIt; - d << "TypeDatabase(" - << "entries[" << m_entries.size() << "]="; - for (Eit it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { - const int count = it.value().size(); - d << '"' << it.key() << "\" [" << count << "]: ("; - for (int t = 0; t < count; ++t) { - if (t) - d << ", "; - d << it.value().at(t); - } - d << ")\n"; - } - if (!m_templates.isEmpty()) { - d << "templates[" << m_templates.size() << "]=("; - const TplIt begin = m_templates.cbegin(); - for (TplIt it = begin, end = m_templates.cend(); it != end; ++it) { - if (it != begin) - d << ", "; - d << it.value(); - } - d << ")\n"; - } - if (!m_flagsEntries.isEmpty()) { - d << "flags[" << m_flagsEntries.size() << "]=("; - const Sit begin = m_flagsEntries.cbegin(); - for (Sit it = begin, end = m_flagsEntries.cend(); it != end; ++it) { - if (it != begin) - d << ", "; - d << it.value(); - } - d << ")\n"; - } - d <<"\nglobalUserFunctions=" << m_globalUserFunctions << ')'; -} - -QDebug operator<<(QDebug d, const TypeDatabase &db) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - db.formatDebug(d); - return d; -} -#endif // !QT_NO_DEBUG_STREAM diff --git a/ApiExtractor/typedatabase.h b/ApiExtractor/typedatabase.h deleted file mode 100644 index 86f933448..000000000 --- a/ApiExtractor/typedatabase.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPEDATABASE_H -#define TYPEDATABASE_H - -#include "apiextractormacros.h" -#include "include.h" -#include "typedatabase_typedefs.h" -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" - -#include - -QT_FORWARD_DECLARE_CLASS(QIODevice) - -class ComplexTypeEntry; -class ContainerTypeEntry; -class FlagsTypeEntry; -class FunctionTypeEntry; -class NamespaceTypeEntry; -class ObjectTypeEntry; -class TemplateEntry; -class TypeEntry; - -struct TypeRejection; - -QT_FORWARD_DECLARE_CLASS(QDebug) - -void setTypeRevision(TypeEntry* typeEntry, int revision); -int getTypeRevision(const TypeEntry* typeEntry); -int getTypeIndex(const TypeEntry* typeEntry); -int getMaxTypeIndex(); - -class ContainerTypeEntry; -class PrimitiveTypeEntry; -class TypeDatabase -{ - TypeDatabase(); - Q_DISABLE_COPY(TypeDatabase) -public: - ~TypeDatabase(); - - /** - * Return the type system instance. - * \param newInstance This parameter is useful just for unit testing, because singletons causes - * too many side effects on unit testing. - */ - static TypeDatabase* instance(bool newInstance = false); - - static QString normalizedSignature(const QString &signature); - - QStringList requiredTargetImports() const; - - void addRequiredTargetImport(const QString& moduleName); - - void addTypesystemPath(const QString& typesystem_paths); - - IncludeList extraIncludes(const QString& className) const; - - PrimitiveTypeEntry* findPrimitiveType(const QString& name) const; - ComplexTypeEntry* findComplexType(const QString& name) const; - ObjectTypeEntry* findObjectType(const QString& name) const; - NamespaceTypeEntry* findNamespaceType(const QString& name) const; - ContainerTypeEntry* findContainerType(const QString& name) const; - FunctionTypeEntry* findFunctionType(const QString& name) const; - - TypeEntry* findType(const QString& name) const; - - TypeEntryHash allEntries() const { return m_entries; } - - SingleTypeEntryHash entries() const; - - PrimitiveTypeEntryList primitiveTypes() const; - - ContainerTypeEntryList containerTypes() const; - - void addRejection(const TypeRejection &); - bool isClassRejected(const QString& className, QString *reason = nullptr) const; - bool isFunctionRejected(const QString& className, const QString& functionName, - QString *reason = nullptr) const; - bool isFieldRejected(const QString& className, const QString& fieldName, - QString *reason = nullptr) const; - bool isEnumRejected(const QString& className, const QString& enumName, - QString *reason = nullptr) const; - bool isArgumentTypeRejected(const QString& className, const QString& typeName, - QString *reason = nullptr) const; - bool isReturnTypeRejected(const QString& className, const QString& typeName, - QString *reason = nullptr) const; - - void addType(TypeEntry* e); - - FlagsTypeEntry* findFlagsType(const QString& name) const; - void addFlagsType(FlagsTypeEntry* fte); - - TemplateEntry *findTemplate(const QString& name) const { return m_templates[name]; } - - void addTemplate(TemplateEntry* t); - - AddedFunctionList globalUserFunctions() const { return m_globalUserFunctions; } - - void addGlobalUserFunctions(const AddedFunctionList &functions); - - AddedFunctionList findGlobalUserFunctions(const QString& name) const; - - void addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications); - - FunctionModificationList functionModifications(const QString& signature) const; - - void setSuppressWarnings(bool on) { m_suppressWarnings = on; } - - void addSuppressedWarning(const QString &s); - - bool isSuppressedWarning(const QString& s) const; - - static QString globalNamespaceClassName(const TypeEntry *te); - - bool parseFile(const QString &filename, bool generate = true); - bool parseFile(QIODevice* device, bool generate = true); - - bool setApiVersion(const QString& package, const QString& version); - - bool checkApiVersion(const QString& package, const QString &version) const; - - bool hasDroppedTypeEntries() const { return !m_dropTypeEntries.isEmpty(); } - - bool shouldDropTypeEntry(const QString& fullTypeName) const; - - void setDropTypeEntries(QStringList dropTypeEntries); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &d) const; -#endif -private: - TypeEntryList findTypes(const QString &name) const; - QString modifiedTypesystemFilepath(const QString &tsFile) const; - - bool m_suppressWarnings; - TypeEntryHash m_entries; - SingleTypeEntryHash m_flagsEntries; - TemplateEntryHash m_templates; - QStringList m_suppressedWarnings; - - AddedFunctionList m_globalUserFunctions; - FunctionModificationList m_functionMods; - - QStringList m_requiredTargetImports; - - QStringList m_typesystemPaths; - QHash m_parsedTypesystemFiles; - - QVector m_rejections; - - QStringList m_dropTypeEntries; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeEntry *te); -QDebug operator<<(QDebug d, const TypeDatabase &db); -#endif -#endif // TYPEDATABASE_H diff --git a/ApiExtractor/typedatabase_typedefs.h b/ApiExtractor/typedatabase_typedefs.h deleted file mode 100644 index 95859a399..000000000 --- a/ApiExtractor/typedatabase_typedefs.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPEDATABASE_TYPEDEFS_H -#define TYPEDATABASE_TYPEDEFS_H - -#include -#include -#include - -class ContainerTypeEntry; -class PrimitiveTypeEntry; -class TemplateEntry; -class TypeEntry; - -typedef QVector TypeEntryList; -typedef QHash TypeEntryHash; -typedef QHash SingleTypeEntryHash; -typedef QHash TemplateEntryHash; - -typedef QVector ContainerTypeEntryList; -typedef QVector PrimitiveTypeEntryList; - -#endif // TYPEDATABASE_TYPEDEFS_H diff --git a/ApiExtractor/typeparser.cpp b/ApiExtractor/typeparser.cpp deleted file mode 100644 index 8165bfe44..000000000 --- a/ApiExtractor/typeparser.cpp +++ /dev/null @@ -1,318 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typeparser.h" - -#include -#include -#include - -class Scanner -{ -public: - enum Token { - StarToken, - AmpersandToken, - LessThanToken, - ColonToken, - CommaToken, - OpenParenToken, - CloseParenToken, - SquareBegin, - SquareEnd, - GreaterThanToken, - - ConstToken, - Identifier, - NoToken, - InvalidToken - }; - - Scanner(const QString &s) - : m_pos(0), m_length(s.length()), m_chars(s.constData()) - { - } - - Token nextToken(QString *errorMessage = Q_NULLPTR); - QString identifier() const; - - QString msgParseError(const QString &why) const; - -private: - int m_pos; - int m_length; - int m_tokenStart; - const QChar *m_chars; -}; - -QString Scanner::identifier() const -{ - return QString(m_chars + m_tokenStart, m_pos - m_tokenStart); -} - -Scanner::Token Scanner::nextToken(QString *errorMessage) -{ - Token tok = NoToken; - - // remove whitespace - while (m_pos < m_length && m_chars[m_pos] == QLatin1Char(' ')) - ++m_pos; - - m_tokenStart = m_pos; - - while (m_pos < m_length) { - - const QChar &c = m_chars[m_pos]; - - if (tok == NoToken) { - switch (c.toLatin1()) { - case '*': tok = StarToken; break; - case '&': tok = AmpersandToken; break; - case '<': tok = LessThanToken; break; - case '>': tok = GreaterThanToken; break; - case ',': tok = CommaToken; break; - case '(': tok = OpenParenToken; break; - case ')': tok = CloseParenToken; break; - case '[': tok = SquareBegin; break; - case ']' : tok = SquareEnd; break; - case ':': - tok = ColonToken; - Q_ASSERT(m_pos + 1 < m_length); - ++m_pos; - break; - default: - if (c.isLetterOrNumber() || c == QLatin1Char('_')) { - tok = Identifier; - } else { - QString message; - QTextStream (&message) << ": Unrecognized character in lexer at " - << m_pos << " : '" << c << '\''; - message = msgParseError(message); - if (errorMessage) - *errorMessage = message; - else - qWarning().noquote().nospace() << message; - return InvalidToken; - } - break; - } - } - - if (tok <= GreaterThanToken) { - ++m_pos; - break; - } - - if (tok == Identifier) { - if (c.isLetterOrNumber() || c == QLatin1Char('_')) - ++m_pos; - else - break; - } - } - - if (tok == Identifier && m_pos - m_tokenStart == 5) { - if (m_chars[m_tokenStart] == QLatin1Char('c') - && m_chars[m_tokenStart + 1] == QLatin1Char('o') - && m_chars[m_tokenStart + 2] == QLatin1Char('n') - && m_chars[m_tokenStart + 3] == QLatin1Char('s') - && m_chars[m_tokenStart + 4] == QLatin1Char('t')) - tok = ConstToken; - } - - return tok; - -} - -QString Scanner::msgParseError(const QString &why) const -{ - return QStringLiteral("TypeParser: Unable to parse \"") - + QString(m_chars, m_length) + QStringLiteral("\": ") + why; -} - -static TypeParser::Info invalidInfo() -{ - TypeParser::Info result; - result.is_busted = true; - return result; -} - -TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) -{ - Scanner scanner(str); - - Info info; - QStack stack; - stack.push(&info); - - bool colon_prefix = false; - bool in_array = false; - QString array; - - Scanner::Token tok = scanner.nextToken(errorMessage); - while (tok != Scanner::NoToken) { - if (tok == Scanner::InvalidToken) - return invalidInfo(); - -// switch (tok) { -// case Scanner::StarToken: printf(" - *\n"); break; -// case Scanner::AmpersandToken: printf(" - &\n"); break; -// case Scanner::LessThanToken: printf(" - <\n"); break; -// case Scanner::GreaterThanToken: printf(" - >\n"); break; -// case Scanner::ColonToken: printf(" - ::\n"); break; -// case Scanner::CommaToken: printf(" - ,\n"); break; -// case Scanner::ConstToken: printf(" - const\n"); break; -// case Scanner::SquareBegin: printf(" - [\n"); break; -// case Scanner::SquareEnd: printf(" - ]\n"); break; -// case Scanner::Identifier: printf(" - '%s'\n", qPrintable(scanner.identifier())); break; -// default: -// break; -// } - - switch (tok) { - - case Scanner::StarToken: - ++stack.top()->indirections; - break; - - case Scanner::AmpersandToken: - switch (stack.top()->referenceType) { - case NoReference: - stack.top()->referenceType = LValueReference; - break; - case LValueReference: - stack.top()->referenceType = RValueReference; - break; - case RValueReference: - const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers")); - if (errorMessage) - *errorMessage = message; - else - qWarning().noquote().nospace() << message; - return invalidInfo(); - } - break; - case Scanner::LessThanToken: - stack.top()->template_instantiations << Info(); - stack.push(&stack.top()->template_instantiations.last()); - break; - - case Scanner::CommaToken: - stack.pop(); - stack.top()->template_instantiations << Info(); - stack.push(&stack.top()->template_instantiations.last()); - break; - - case Scanner::GreaterThanToken: - stack.pop(); - break; - - case Scanner::ColonToken: - colon_prefix = true; - break; - - case Scanner::ConstToken: - stack.top()->is_constant = true; - break; - - case Scanner::OpenParenToken: // function pointers not supported - case Scanner::CloseParenToken: { - const QString message = scanner.msgParseError(QStringLiteral("Function pointers are not supported")); - if (errorMessage) - *errorMessage = message; - else - qWarning().noquote().nospace() << message; - return invalidInfo(); - } - - case Scanner::Identifier: - if (in_array) { - array = scanner.identifier(); - } else if (colon_prefix || stack.top()->qualified_name.isEmpty()) { - stack.top()->qualified_name << scanner.identifier(); - colon_prefix = false; - } else { - stack.top()->qualified_name.last().append(QLatin1Char(' ') + scanner.identifier()); - } - break; - - case Scanner::SquareBegin: - in_array = true; - break; - - case Scanner::SquareEnd: - in_array = false; - stack.top()->arrays += array; - break; - - - default: - break; - } - - tok = scanner.nextToken(); - } - - return info; -} - -QString TypeParser::Info::instantiationName() const -{ - QString s(qualified_name.join(QLatin1String("::"))); - if (!template_instantiations.isEmpty()) { - QStringList insts; - for (const Info &info : template_instantiations) - insts << info.toString(); - s += QLatin1String("< ") + insts.join(QLatin1String(", ")) + QLatin1String(" >"); - } - - return s; -} - -QString TypeParser::Info::toString() const -{ - QString s; - - if (is_constant) - s += QLatin1String("const "); - s += instantiationName(); - for (int i = 0; i < arrays.size(); ++i) - s += QLatin1Char('[') + arrays.at(i) + QLatin1Char(']'); - s += QString(indirections, QLatin1Char('*')); - switch (referenceType) { - case NoReference: - break; - case LValueReference: - s += QLatin1Char('&'); - break; - case RValueReference: - s += QLatin1String("&&"); - break; - } - return s; -} diff --git a/ApiExtractor/typeparser.h b/ApiExtractor/typeparser.h deleted file mode 100644 index f42c42a5e..000000000 --- a/ApiExtractor/typeparser.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPEPARSER_H -#define TYPEPARSER_H - -#include "parser/codemodel_enums.h" - -#include -#include -#include -#include - -class TypeParser -{ -public: - struct Info - { - Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { } - QStringList qualified_name; - QStringList arrays; - QVector template_instantiations; - ReferenceType referenceType; - uint is_constant : 1; - uint is_busted : 1; - uint indirections : 6; - - QString toString() const; - QString instantiationName() const; - }; - - static Info parse(const QString &str, QString *errorMessage = Q_NULLPTR); -}; - -#endif // TYPEPARSER_H diff --git a/ApiExtractor/typesystem.cpp b/ApiExtractor/typesystem.cpp deleted file mode 100644 index 3ec82c56d..000000000 --- a/ApiExtractor/typesystem.cpp +++ /dev/null @@ -1,2737 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typesystem.h" -#include "typesystem_p.h" -#include "typedatabase.h" -#include "reporthandler.h" -#include -#include -#include -#include -#include - -static QString strings_Object = QLatin1String("Object"); -static QString strings_String = QLatin1String("String"); -static QString strings_char = QLatin1String("char"); -static QString strings_jchar = QLatin1String("jchar"); -static QString strings_jobject = QLatin1String("jobject"); - -static inline QString colonColon() { return QStringLiteral("::"); } -static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); } -static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); } -static inline QString nameAttribute() { return QStringLiteral("name"); } -static inline QString sinceAttribute() { return QStringLiteral("since"); } -static inline QString flagsAttribute() { return QStringLiteral("flags"); } -static inline QString classAttribute() { return QStringLiteral("class"); } -static inline QString functionNameAttribute() { return QStringLiteral("function-name"); } -static inline QString fieldNameAttribute() { return QStringLiteral("field-name"); } -static inline QString enumNameAttribute() { return QStringLiteral("enum-name"); } -static inline QString argumentTypeAttribute() { return QStringLiteral("argument-type"); } -static inline QString returnTypeAttribute() { return QStringLiteral("return-type"); } - -static QVector customConversionsForReview; - -// Set a regular expression for rejection from text. By legacy, those are fixed -// strings, except for '*' meaning 'match all'. Enclosing in "^..$" -// indicates regular expression. -static bool setRejectionRegularExpression(const QString &patternIn, - QRegularExpression *re, - QString *errorMessage) -{ - QString pattern; - if (patternIn.startsWith(QLatin1Char('^')) && patternIn.endsWith(QLatin1Char('$'))) - pattern = patternIn; - else if (patternIn == QLatin1String("*")) - pattern = QStringLiteral("^.*$"); - else - pattern = QLatin1Char('^') + QRegularExpression::escape(patternIn) + QLatin1Char('$'); - re->setPattern(pattern); - if (!re->isValid()) { - *errorMessage = QLatin1String("Invalid pattern \"") + patternIn - + QLatin1String("\": ") + re->errorString(); - return false; - } - return true; -} - -static bool addRejection(TypeDatabase *database, const QHash &attributes, - QString *errorMessage) -{ - typedef QPair AttributeMatchTypePair; - - TypeRejection rejection; - - const QString className = attributes.value(classAttribute()); - if (!setRejectionRegularExpression(className, &rejection.className, errorMessage)) - return false; - - static const AttributeMatchTypePair attributeMatchTypeMapping[] = - {{functionNameAttribute(), TypeRejection::Function}, - {fieldNameAttribute(), TypeRejection::Field}, - {enumNameAttribute(), TypeRejection::Enum}, - {argumentTypeAttribute(), TypeRejection::ArgumentType}, - {returnTypeAttribute(), TypeRejection::ReturnType} - }; - - // Search for non-empty attribute (function, field, enum) - const auto aend = attributes.cend(); - for (const AttributeMatchTypePair &mapping : attributeMatchTypeMapping) { - const auto it = attributes.constFind(mapping.first); - if (it != aend && !it.value().isEmpty()) { - if (!setRejectionRegularExpression(it.value(), &rejection.pattern, errorMessage)) - return false; - rejection.matchType = mapping.second; - database->addRejection(rejection); - return true; - } - } - - // Special case: When all fields except class are empty, completely exclude class - if (className == QLatin1String("*")) { - *errorMessage = QLatin1String("bad reject entry, neither 'class', 'function-name'" - " nor 'field' specified"); - return false; - } - rejection.matchType = TypeRejection::ExcludeClass; - database->addRejection(rejection); - return true; -} - - -Handler::Handler(TypeDatabase* database, bool generate) - : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass) -{ - m_currentEnum = 0; - m_current = 0; - m_currentDroppedEntry = 0; - m_currentDroppedEntryDepth = 0; - m_ignoreDepth = 0; - - tagNames.insert(QLatin1String("rejection"), StackElement::Rejection); - tagNames.insert(QLatin1String("custom-type"), StackElement::CustomTypeEntry); - tagNames.insert(QLatin1String("primitive-type"), StackElement::PrimitiveTypeEntry); - tagNames.insert(QLatin1String("container-type"), StackElement::ContainerTypeEntry); - tagNames.insert(QLatin1String("object-type"), StackElement::ObjectTypeEntry); - tagNames.insert(QLatin1String("value-type"), StackElement::ValueTypeEntry); - tagNames.insert(QLatin1String("interface-type"), StackElement::InterfaceTypeEntry); - tagNames.insert(QLatin1String("namespace-type"), StackElement::NamespaceTypeEntry); - tagNames.insert(QLatin1String("enum-type"), StackElement::EnumTypeEntry); - tagNames.insert(QLatin1String("smart-pointer-type"), StackElement::SmartPointerTypeEntry); - tagNames.insert(QLatin1String("function"), StackElement::FunctionTypeEntry); - tagNames.insert(QLatin1String("extra-includes"), StackElement::ExtraIncludes); - tagNames.insert(QLatin1String("include"), StackElement::Include); - tagNames.insert(QLatin1String("inject-code"), StackElement::InjectCode); - tagNames.insert(QLatin1String("modify-function"), StackElement::ModifyFunction); - tagNames.insert(QLatin1String("modify-field"), StackElement::ModifyField); - tagNames.insert(QLatin1String("access"), StackElement::Access); - tagNames.insert(QLatin1String("remove"), StackElement::Removal); - tagNames.insert(QLatin1String("rename"), StackElement::Rename); - tagNames.insert(QLatin1String("typesystem"), StackElement::Root); - tagNames.insert(QLatin1String("custom-constructor"), StackElement::CustomMetaConstructor); - tagNames.insert(QLatin1String("custom-destructor"), StackElement::CustomMetaDestructor); - tagNames.insert(QLatin1String("argument-map"), StackElement::ArgumentMap); - tagNames.insert(QLatin1String("suppress-warning"), StackElement::SuppressedWarning); - tagNames.insert(QLatin1String("load-typesystem"), StackElement::LoadTypesystem); - tagNames.insert(QLatin1String("define-ownership"), StackElement::DefineOwnership); - tagNames.insert(QLatin1String("replace-default-expression"), StackElement::ReplaceDefaultExpression); - tagNames.insert(QLatin1String("reject-enum-value"), StackElement::RejectEnumValue); - tagNames.insert(QLatin1String("replace-type"), StackElement::ReplaceType); - tagNames.insert(QLatin1String("conversion-rule"), StackElement::ConversionRule); - tagNames.insert(QLatin1String("native-to-target"), StackElement::NativeToTarget); - tagNames.insert(QLatin1String("target-to-native"), StackElement::TargetToNative); - tagNames.insert(QLatin1String("add-conversion"), StackElement::AddConversion); - tagNames.insert(QLatin1String("modify-argument"), StackElement::ModifyArgument); - tagNames.insert(QLatin1String("remove-argument"), StackElement::RemoveArgument); - tagNames.insert(QLatin1String("remove-default-expression"), StackElement::RemoveDefaultExpression); - tagNames.insert(QLatin1String("template"), StackElement::Template); - tagNames.insert(QLatin1String("insert-template"), StackElement::TemplateInstanceEnum); - tagNames.insert(QLatin1String("replace"), StackElement::Replace); - tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers); - tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount); - tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner); - tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation); - tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation); - tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction); -} - -static QString msgReaderError(const QXmlStreamReader &reader, const QString &what) -{ - QString message; - QTextStream str(&message); - str << "Error: "; - if (const QFile *file = qobject_cast(reader.device())) - str << "file=" << QDir::toNativeSeparators(file->fileName()) << ", "; - str << "line=" << reader.lineNumber() << ", column=" << reader.columnNumber() - << ", message=" << what; - return message; -} - -static QString msgReaderError(const QXmlStreamReader &reader) -{ - return msgReaderError(reader, reader.errorString()); -} - -bool Handler::parse(QXmlStreamReader &reader) -{ - m_error.clear(); - while (!reader.atEnd()) { - switch (reader.readNext()) { - case QXmlStreamReader::NoToken: - case QXmlStreamReader::Invalid: - qCWarning(lcShiboken).noquote().nospace() << msgReaderError(reader); - return false; - case QXmlStreamReader::StartElement: - if (!startElement(reader.name(), reader.attributes())) { - m_error = msgReaderError(reader, m_error); - return false; - } - - break; - case QXmlStreamReader::EndElement: - if (!endElement(reader.name())) { - m_error = msgReaderError(reader, m_error); - return false; - } - break; - case QXmlStreamReader::Characters: - if (!characters(reader.text())) { - m_error = msgReaderError(reader, m_error); - return false; - } - break; - case QXmlStreamReader::StartDocument: - case QXmlStreamReader::EndDocument: - case QXmlStreamReader::Comment: - case QXmlStreamReader::DTD: - case QXmlStreamReader::EntityReference: - case QXmlStreamReader::ProcessingInstruction: - break; - } - } - return true; -} - -void Handler::fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts, - QHash *acceptedAttributes) -{ - Q_ASSERT(acceptedAttributes); - - for (int i = 0; i < atts.length(); ++i) { - const QString key = atts.at(i).name().toString().toLower(); - if (!acceptedAttributes->contains(key)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Unknown attribute for '%1': '%2'").arg(name, key); - } else { - acceptedAttributes->insert(key, atts.at(i).value().toString()); - } - } -} - -bool Handler::endElement(const QStringRef &localName) -{ - if (m_ignoreDepth) { - --m_ignoreDepth; - return true; - } - - if (m_currentDroppedEntry) { - if (m_currentDroppedEntryDepth == 1) { - m_current = m_currentDroppedEntry->parent; - delete m_currentDroppedEntry; - m_currentDroppedEntry = 0; - m_currentDroppedEntryDepth = 0; - } else { - ++m_currentDroppedEntryDepth; - } - return true; - } - - if (!localName.compare(QLatin1String("import-file"), Qt::CaseInsensitive)) - return true; - - if (!m_current) - return true; - - switch (m_current->type) { - case StackElement::Root: - if (m_generate == TypeEntry::GenerateAll) { - TypeDatabase::instance()->addGlobalUserFunctions(m_contextStack.top()->addedFunctions); - TypeDatabase::instance()->addGlobalUserFunctionModifications(m_contextStack.top()->functionMods); - for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) { - const CustomConversion::TargetToNativeConversions &toNatives = customConversion->targetToNativeConversions(); - for (CustomConversion::TargetToNativeConversion *toNative : toNatives) - toNative->setSourceType(m_database->findType(toNative->sourceTypeName())); - } - } - break; - case StackElement::ObjectTypeEntry: - case StackElement::ValueTypeEntry: - case StackElement::InterfaceTypeEntry: - case StackElement::NamespaceTypeEntry: { - ComplexTypeEntry *centry = static_cast(m_current->entry); - centry->setAddedFunctions(m_contextStack.top()->addedFunctions); - centry->setFunctionModifications(m_contextStack.top()->functionMods); - centry->setFieldModifications(m_contextStack.top()->fieldMods); - centry->setCodeSnips(m_contextStack.top()->codeSnips); - centry->setDocModification(m_contextStack.top()->docModifications); - - if (centry->designatedInterface()) { - centry->designatedInterface()->setCodeSnips(m_contextStack.top()->codeSnips); - centry->designatedInterface()->setFunctionModifications(m_contextStack.top()->functionMods); - } - } - break; - case StackElement::NativeToTarget: - case StackElement::AddConversion: { - CustomConversion* customConversion = static_cast(m_current->entry)->customConversion(); - if (!customConversion) { - m_error = QLatin1String("CustomConversion object is missing."); - return false; - } - - QString code = m_contextStack.top()->codeSnips.takeLast().code(); - if (m_current->type == StackElement::AddConversion) { - if (customConversion->targetToNativeConversions().isEmpty()) { - m_error = QLatin1String("CustomConversion's target to native conversions missing."); - return false; - } - customConversion->targetToNativeConversions().last()->setConversion(code); - } else { - customConversion->setNativeToTargetConversion(code); - } - } - break; - case StackElement::CustomMetaConstructor: { - m_current->entry->setCustomConstructor(*m_current->value.customFunction); - delete m_current->value.customFunction; - } - break; - case StackElement::CustomMetaDestructor: { - m_current->entry->setCustomDestructor(*m_current->value.customFunction); - delete m_current->value.customFunction; - } - break; - case StackElement::EnumTypeEntry: - m_current->entry->setDocModification(m_contextStack.top()->docModifications); - m_contextStack.top()->docModifications = DocModificationList(); - m_currentEnum = 0; - break; - case StackElement::Template: - m_database->addTemplate(m_current->value.templateEntry); - break; - case StackElement::TemplateInstanceEnum: - switch (m_current->parent->type) { - case StackElement::InjectCode: - if (m_current->parent->parent->type == StackElement::Root) { - CodeSnipList snips = m_current->parent->entry->codeSnips(); - CodeSnip snip = snips.takeLast(); - snip.addTemplateInstance(m_current->value.templateInstance); - snips.append(snip); - m_current->parent->entry->setCodeSnips(snips); - break; - } - case StackElement::NativeToTarget: - case StackElement::AddConversion: - m_contextStack.top()->codeSnips.last().addTemplateInstance(m_current->value.templateInstance); - break; - case StackElement::Template: - m_current->parent->value.templateEntry->addTemplateInstance(m_current->value.templateInstance); - break; - case StackElement::CustomMetaConstructor: - case StackElement::CustomMetaDestructor: - m_current->parent->value.customFunction->addTemplateInstance(m_current->value.templateInstance); - break; - case StackElement::ConversionRule: - m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.last().addTemplateInstance(m_current->value.templateInstance); - break; - case StackElement::InjectCodeInFunction: - m_contextStack.top()->functionMods.last().snips.last().addTemplateInstance(m_current->value.templateInstance); - break; - default: - break; // nada - }; - break; - default: - break; - } - - if (m_current->type == StackElement::Root - || m_current->type == StackElement::NamespaceTypeEntry - || m_current->type == StackElement::InterfaceTypeEntry - || m_current->type == StackElement::ObjectTypeEntry - || m_current->type == StackElement::ValueTypeEntry - || m_current->type == StackElement::PrimitiveTypeEntry) { - StackElementContext* context = m_contextStack.pop(); - delete context; - } - - StackElement *child = m_current; - m_current = m_current->parent; - delete(child); - - return true; -} - -template // QString/QStringRef -bool Handler::characters(const String &ch) -{ - if (m_currentDroppedEntry || m_ignoreDepth) - return true; - - if (m_current->type == StackElement::Template) { - m_current->value.templateEntry->addCode(ch); - return true; - } - - if (m_current->type == StackElement::CustomMetaConstructor || m_current->type == StackElement::CustomMetaDestructor) { - m_current->value.customFunction->addCode(ch); - return true; - } - - if (m_current->type == StackElement::ConversionRule - && m_current->parent->type == StackElement::ModifyArgument) { - m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.last().addCode(ch); - return true; - } - - if (m_current->type == StackElement::NativeToTarget || m_current->type == StackElement::AddConversion) { - m_contextStack.top()->codeSnips.last().addCode(ch); - return true; - } - - if (m_current->parent) { - if ((m_current->type & StackElement::CodeSnipMask)) { - CodeSnipList snips; - switch (m_current->parent->type) { - case StackElement::Root: - snips = m_current->parent->entry->codeSnips(); - snips.last().addCode(ch); - m_current->parent->entry->setCodeSnips(snips); - break; - case StackElement::ModifyFunction: - case StackElement::AddFunction: - m_contextStack.top()->functionMods.last().snips.last().addCode(ch); - m_contextStack.top()->functionMods.last().modifiers |= FunctionModification::CodeInjection; - break; - case StackElement::NamespaceTypeEntry: - case StackElement::ObjectTypeEntry: - case StackElement::ValueTypeEntry: - case StackElement::InterfaceTypeEntry: - m_contextStack.top()->codeSnips.last().addCode(ch); - break; - default: - Q_ASSERT(false); - }; - return true; - } - } - - if (m_current->type & StackElement::DocumentationMask) - m_contextStack.top()->docModifications.last().setCode(ch); - - return true; -} - -bool Handler::importFileElement(const QXmlStreamAttributes &atts) -{ - const QString fileName = atts.value(nameAttribute()).toString(); - if (fileName.isEmpty()) { - m_error = QLatin1String("Required attribute 'name' missing for include-file tag."); - return false; - } - - QFile file(fileName); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - file.setFileName(QLatin1String(":/trolltech/generator/") + fileName); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - m_error = QString::fromLatin1("Could not open file: '%1'").arg(QDir::toNativeSeparators(fileName)); - return false; - } - } - - const QStringRef quoteFrom = atts.value(quoteAfterLineAttribute()); - bool foundFromOk = quoteFrom.isEmpty(); - bool from = quoteFrom.isEmpty(); - - const QStringRef quoteTo = atts.value(quoteBeforeLineAttribute()); - bool foundToOk = quoteTo.isEmpty(); - bool to = true; - - QTextStream in(&file); - while (!in.atEnd()) { - QString line = in.readLine(); - if (from && to && line.contains(quoteTo)) { - to = false; - foundToOk = true; - break; - } - if (from && to) - characters(line + QLatin1Char('\n')); - if (!from && line.contains(quoteFrom)) { - from = true; - foundFromOk = true; - } - } - 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); - - if (!foundToOk) - m_error = toError; - if (!foundFromOk) - m_error = fromError; - if (!foundFromOk && !foundToOk) - m_error = fromError + QLatin1Char(' ') + toError; - return false; - } - - return true; -} - -bool Handler::convertBoolean(const QString &_value, const QString &attributeName, bool defaultValue) -{ - QString value = _value.toLower(); - if (value == QLatin1String("true") || value == QLatin1String("yes")) - return true; - else if (value == QLatin1String("false") || value == QLatin1String("no")) - return false; - else { - QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") - .arg(value, attributeName, - defaultValue ? QLatin1String("yes") : QLatin1String("no")); - - qCWarning(lcShiboken).noquote().nospace() << warn; - return defaultValue; - } -} - -static bool convertRemovalAttribute(const QString& removalAttribute, Modification& mod, QString& errorMsg) -{ - QString remove = removalAttribute.toLower(); - if (!remove.isEmpty()) { - if (remove == QLatin1String("all")) { - mod.removal = TypeSystem::All; - } else if (remove == QLatin1String("target")) { - mod.removal = TypeSystem::TargetLangAndNativeCode; - } else { - errorMsg = QString::fromLatin1("Bad removal type '%1'").arg(remove); - return false; - } - } - return true; -} - -static void getNamePrefixRecursive(StackElement* element, QStringList& names) -{ - if (!element->parent || !element->parent->entry) - return; - getNamePrefixRecursive(element->parent, names); - names << element->parent->entry->name(); -} - -static QString getNamePrefix(StackElement* element) -{ - QStringList names; - getNamePrefixRecursive(element, names); - return names.join(QLatin1Char('.')); -} - -// Returns empty string if there's no error. -static QString checkSignatureError(const QString& signature, const QString& tag) -{ - QString funcName = signature.left(signature.indexOf(QLatin1Char('('))).trimmed(); - static const QRegularExpression whiteSpace(QStringLiteral("\\s")); - Q_ASSERT(whiteSpace.isValid()); - if (!funcName.startsWith(QLatin1String("operator ")) && funcName.contains(whiteSpace)) { - return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n" - "White spaces aren't allowed in function names, " - "and return types should not be part of the signature.") - .arg(tag, signature); - } - return QString(); -} - -void Handler::addFlags(const QString &name, QString flagName, - const QHash &attributes, double since) -{ - FlagsTypeEntry *ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), since); - ftype->setOriginator(m_currentEnum); - // Try to get the guess the qualified flag name - const int lastSepPos = name.lastIndexOf(colonColon()); - if (lastSepPos >= 0 && !flagName.contains(colonColon())) - flagName.prepend(name.left(lastSepPos + 2)); - - ftype->setOriginalName(flagName); - ftype->setCodeGeneration(m_generate); - QString n = ftype->originalName(); - - QStringList lst = n.split(colonColon()); - if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != m_currentEnum->targetLangQualifier()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("enum %1 and flags %2 differ in qualifiers") - // avoid constFirst to stay Qt 5.5 compatible - .arg(m_currentEnum->targetLangQualifier(), lst.first()); - } - - ftype->setFlagsName(lst.last()); - m_currentEnum->setFlags(ftype); - - m_database->addFlagsType(ftype); - m_database->addType(ftype); - - QString revision = attributes.value(QLatin1String("flags-revision")); - if (revision.isEmpty()) - revision = attributes.value(QLatin1String("revision")); - setTypeRevision(ftype, revision.toInt()); -} - -bool Handler::handleSmartPointerEntry(StackElement *element, - QHash &attributes, - const QString &name, - double since) -{ - QString smartPointerType = attributes[QLatin1String("type")]; - if (smartPointerType.isEmpty()) { - m_error = QLatin1String("No type specified for the smart pointer. Currently supported types: 'shared',"); - return false; - } - if (smartPointerType != QLatin1String("shared")) { - m_error = QLatin1String("Currently only the 'shared' type is supported."); - return false; - } - - QString getter = attributes[QLatin1String("getter")]; - if (getter.isEmpty()) { - m_error = QLatin1String("No function getter name specified for getting the raw pointer held by the smart pointer."); - return false; - } - - QString refCountMethodName = attributes[QLatin1String("ref-count-method")]; - QString signature = getter + QLatin1String("()"); - - signature = TypeDatabase::normalizedSignature(signature); - if (signature.isEmpty()) { - m_error = QLatin1String("No signature for the smart pointer getter found."); - return false; - } - - QString errorString = checkSignatureError(signature, - QLatin1String("smart-pointer-type")); - if (!errorString.isEmpty()) { - m_error = errorString; - return false; - } - - SmartPointerTypeEntry *type = new SmartPointerTypeEntry(name, - getter, - smartPointerType, - refCountMethodName, - since); - type->setTargetLangPackage(m_defaultPackage); - type->setCodeGeneration(m_generate); - element->entry = type; - return true; -} - -bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts) -{ - if (m_ignoreDepth) { - ++m_ignoreDepth; - return true; - } - - if (!m_defaultPackage.isEmpty() && atts.hasAttribute(sinceAttribute())) { - TypeDatabase* td = TypeDatabase::instance(); - if (!td->checkApiVersion(m_defaultPackage, atts.value(sinceAttribute()).toString())) { - ++m_ignoreDepth; - return true; - } - } - - const QString tagName = n.toString().toLower(); - if (tagName == QLatin1String("import-file")) - return importFileElement(atts); - - const QHash::const_iterator tit = tagNames.constFind(tagName); - if (tit == tagNames.constEnd()) { - m_error = QStringLiteral("Unknown tag name: '%1'").arg(tagName); - return false; - } - - if (m_currentDroppedEntry) { - ++m_currentDroppedEntryDepth; - return true; - } - - StackElement* element = new StackElement(m_current); - element->type = tit.value(); - - if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateAll) - customConversionsForReview.clear(); - - if (element->type == StackElement::Root - || element->type == StackElement::NamespaceTypeEntry - || element->type == StackElement::InterfaceTypeEntry - || element->type == StackElement::ObjectTypeEntry - || element->type == StackElement::ValueTypeEntry - || element->type == StackElement::PrimitiveTypeEntry) { - m_contextStack.push(new StackElementContext()); - } - - if (element->type & StackElement::TypeEntryMask) { - QHash attributes; - attributes.insert(nameAttribute(), QString()); - attributes.insert(QLatin1String("revision"), QLatin1String("0")); - attributes.insert(sinceAttribute(), QLatin1String("0")); - - switch (element->type) { - case StackElement::PrimitiveTypeEntry: - attributes.insert(QLatin1String("target-lang-name"), QString()); - attributes.insert(QLatin1String("target-lang-api-name"), QString()); - attributes.insert(QLatin1String("preferred-conversion"), QLatin1String("yes")); - attributes.insert(QLatin1String("preferred-target-lang-type"), QLatin1String("yes")); - attributes.insert(QLatin1String("default-constructor"), QString()); - break; - case StackElement::ContainerTypeEntry: - attributes.insert(QLatin1String("type"), QString()); - break; - case StackElement::SmartPointerTypeEntry: - attributes.insert(QLatin1String("type"), QString()); - attributes.insert(QLatin1String("getter"), QString()); - attributes.insert(QLatin1String("ref-count-method"), QString()); - break; - case StackElement::EnumTypeEntry: - attributes.insert(flagsAttribute(), QString()); - attributes.insert(QLatin1String("flags-revision"), QString()); - attributes.insert(QLatin1String("upper-bound"), QString()); - attributes.insert(QLatin1String("lower-bound"), QString()); - attributes.insert(QLatin1String("force-integer"), QLatin1String("no")); - attributes.insert(QLatin1String("extensible"), QLatin1String("no")); - attributes.insert(QLatin1String("identified-by-value"), QString()); - break; - case StackElement::ValueTypeEntry: - attributes.insert(QLatin1String("default-constructor"), QString()); - // fall throooough - case StackElement::ObjectTypeEntry: - attributes.insert(QLatin1String("force-abstract"), QLatin1String("no")); - attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); - attributes.insert(QLatin1String("hash-function"), QString()); - attributes.insert(QLatin1String("stream"), QLatin1String("no")); - // fall throooough - case StackElement::InterfaceTypeEntry: - attributes[QLatin1String("default-superclass")] = m_defaultSuperclass; - attributes.insert(QLatin1String("polymorphic-id-expression"), QString()); - attributes.insert(QLatin1String("delete-in-main-thread"), QLatin1String("no")); - attributes.insert(QLatin1String("held-type"), QString()); - attributes.insert(QLatin1String("copyable"), QString()); - // fall through - case StackElement::NamespaceTypeEntry: - attributes.insert(QLatin1String("target-lang-name"), QString()); - attributes[QLatin1String("package")] = m_defaultPackage; - attributes.insert(QLatin1String("expense-cost"), QLatin1String("1")); - attributes.insert(QLatin1String("expense-limit"), QLatin1String("none")); - attributes.insert(QLatin1String("polymorphic-base"), QLatin1String("no")); - attributes.insert(QLatin1String("generate"), QLatin1String("yes")); - attributes.insert(QLatin1String("target-type"), QString()); - attributes.insert(QLatin1String("generic-class"), QLatin1String("no")); - break; - case StackElement::FunctionTypeEntry: - attributes.insert(QLatin1String("signature"), QString()); - attributes.insert(QLatin1String("rename"), QString()); - break; - default: - { } // nada - }; - - fetchAttributeValues(tagName, atts, &attributes); - QString name = attributes[nameAttribute()]; - double since = attributes[sinceAttribute()].toDouble(); - - if (m_database->hasDroppedTypeEntries()) { - QString identifier = getNamePrefix(element) + QLatin1Char('.'); - identifier += (element->type == StackElement::FunctionTypeEntry ? attributes[QLatin1String("signature")] : name); - if (m_database->shouldDropTypeEntry(identifier)) { - m_currentDroppedEntry = element; - m_currentDroppedEntryDepth = 1; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { - qCDebug(lcShiboken) - << QStringLiteral("Type system entry '%1' was intentionally dropped from generation.").arg(identifier); - } - return true; - } - } - - // The top level tag 'function' has only the 'signature' tag - // and we should extract the 'name' value from it. - if (element->type == StackElement::FunctionTypeEntry) { - QString signature = attributes[QLatin1String("signature")]; - name = signature.left(signature.indexOf(QLatin1Char('('))).trimmed(); - QString errorString = checkSignatureError(signature, QLatin1String("function")); - if (!errorString.isEmpty()) { - m_error = errorString; - return false; - } - QString rename = attributes[QLatin1String("rename")]; - if (!rename.isEmpty()) { - static const QRegularExpression functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$")); - Q_ASSERT(functionNameRegExp.isValid()); - if (!functionNameRegExp.match(rename).hasMatch()) { - m_error = QLatin1String("can not rename '") + signature + QLatin1String("', '") - + rename + QLatin1String("' is not a valid function name"); - return false; - } - FunctionModification mod(since); - mod.signature = signature; - mod.renamedToName = attributes[QLatin1String("rename")]; - mod.modifiers |= Modification::Rename; - m_contextStack.top()->functionMods << mod; - } - } - - // We need to be able to have duplicate primitive type entries, - // or it's not possible to cover all primitive target language - // types (which we need to do in order to support fake meta objects) - if (element->type != StackElement::PrimitiveTypeEntry - && element->type != StackElement::FunctionTypeEntry) { - TypeEntry *tmp = m_database->findType(name); - if (tmp) - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Duplicate type entry: '%1'").arg(name); - } - - if (element->type == StackElement::EnumTypeEntry) { - if (name.isEmpty()) { - name = attributes[QLatin1String("identified-by-value")]; - } else if (!attributes[QLatin1String("identified-by-value")].isEmpty()) { - m_error = QLatin1String("can't specify both 'name' and 'identified-by-value' attributes"); - return false; - } - } - - // Fix type entry name using nesting information. - if (element->type & StackElement::TypeEntryMask - && element->parent && element->parent->type != StackElement::Root) { - name = element->parent->entry->name() + colonColon() + name; - } - - - if (name.isEmpty()) { - m_error = QLatin1String("no 'name' attribute specified"); - return false; - } - - switch (element->type) { - case StackElement::CustomTypeEntry: - element->entry = new TypeEntry(name, TypeEntry::CustomType, since); - break; - case StackElement::PrimitiveTypeEntry: { - QString targetLangName = attributes[QLatin1String("target-lang-name")]; - QString targetLangApiName = attributes[QLatin1String("target-lang-api-name")]; - QString preferredConversion = attributes[QLatin1String("preferred-conversion")].toLower(); - QString preferredTargetLangType = attributes[QLatin1String("preferred-target-lang-type")].toLower(); - QString defaultConstructor = attributes[QLatin1String("default-constructor")]; - - if (targetLangName.isEmpty()) - targetLangName = name; - if (targetLangApiName.isEmpty()) - targetLangApiName = name; - - PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name, since); - type->setCodeGeneration(m_generate); - type->setTargetLangName(targetLangName); - type->setTargetLangApiName(targetLangApiName); - type->setTargetLangPackage(m_defaultPackage); - type->setDefaultConstructor(defaultConstructor); - - bool preferred; - preferred = convertBoolean(preferredConversion, QLatin1String("preferred-conversion"), true); - type->setPreferredConversion(preferred); - preferred = convertBoolean(preferredTargetLangType, - QLatin1String("preferred-target-lang-type"), true); - type->setPreferredTargetLangType(preferred); - - element->entry = type; - } - break; - - case StackElement::ContainerTypeEntry: { - QString typeName = attributes[QLatin1String("type")]; - ContainerTypeEntry::Type containerType = - ContainerTypeEntry::containerTypeFromString(typeName); - if (typeName.isEmpty()) { - m_error = QLatin1String("no 'type' attribute specified"); - return false; - } else if (containerType == ContainerTypeEntry::NoContainer) { - m_error = QLatin1String("there is no container of type ") + typeName; - return false; - } - - ContainerTypeEntry *type = new ContainerTypeEntry(name, containerType, since); - type->setCodeGeneration(m_generate); - element->entry = type; - } - break; - - case StackElement::SmartPointerTypeEntry: { - bool result = handleSmartPointerEntry(element, attributes, name, since); - if (!result) - return result; - } - break; - - case StackElement::EnumTypeEntry: { - QStringList names = name.split(colonColon()); - if (names.size() == 1) - m_currentEnum = new EnumTypeEntry(QString(), name, since); - else - m_currentEnum = - new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join(colonColon()), - names.last(), since); - m_currentEnum->setAnonymous(!attributes[QLatin1String("identified-by-value")].isEmpty()); - element->entry = m_currentEnum; - m_currentEnum->setCodeGeneration(m_generate); - m_currentEnum->setTargetLangPackage(m_defaultPackage); - m_currentEnum->setUpperBound(attributes[QLatin1String("upper-bound")]); - m_currentEnum->setLowerBound(attributes[QLatin1String("lower-bound")]); - m_currentEnum->setForceInteger(convertBoolean(attributes[QLatin1String("force-integer")], QLatin1String("force-integer"), false)); - m_currentEnum->setExtensible(convertBoolean(attributes[QLatin1String("extensible")], QLatin1String("extensible"), false)); - - // put in the flags parallel... - const QString flagNames = attributes.value(flagsAttribute()); - if (!flagNames.isEmpty()) { - const QStringList &flagNameList = flagNames.split(QLatin1Char(',')); - for (const QString &flagName : flagNameList) - addFlags(name, flagName.trimmed(), attributes, since); - } - } - break; - - case StackElement::InterfaceTypeEntry: { - ObjectTypeEntry *otype = new ObjectTypeEntry(name, since); - QString targetLangName = attributes[QLatin1String("target-lang-name")]; - if (targetLangName.isEmpty()) - targetLangName = name; - InterfaceTypeEntry *itype = - new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since); - - if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true)) - itype->setCodeGeneration(TypeEntry::GenerateForSubclass); - else - itype->setCodeGeneration(m_generate); - otype->setDesignatedInterface(itype); - itype->setOrigin(otype); - element->entry = otype; - } - // fall through - case StackElement::ValueTypeEntry: { - if (!element->entry) { - ValueTypeEntry* typeEntry = new ValueTypeEntry(name, since); - QString defaultConstructor = attributes[QLatin1String("default-constructor")]; - if (!defaultConstructor.isEmpty()) - typeEntry->setDefaultConstructor(defaultConstructor); - element->entry = typeEntry; - } - - // fall through - case StackElement::NamespaceTypeEntry: - if (!element->entry) - element->entry = new NamespaceTypeEntry(name, since); - - // fall through - case StackElement::ObjectTypeEntry: - if (!element->entry) - element->entry = new ObjectTypeEntry(name, since); - - element->entry->setStream(attributes[QLatin1String("stream")] == QLatin1String("yes")); - - ComplexTypeEntry *ctype = static_cast(element->entry); - ctype->setTargetLangPackage(attributes[QLatin1String("package")]); - ctype->setDefaultSuperclass(attributes[QLatin1String("default-superclass")]); - ctype->setGenericClass(convertBoolean(attributes[QLatin1String("generic-class")], QLatin1String("generic-class"), false)); - - if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true)) - element->entry->setCodeGeneration(TypeEntry::GenerateForSubclass); - else - element->entry->setCodeGeneration(m_generate); - - QString targetLangName = attributes[QLatin1String("target-lang-name")]; - if (!targetLangName.isEmpty()) - ctype->setTargetLangName(targetLangName); - - // The expense policy - QString limit = attributes[QLatin1String("expense-limit")]; - if (!limit.isEmpty() && limit != QLatin1String("none")) { - ExpensePolicy ep; - ep.limit = limit.toInt(); - ep.cost = attributes[QLatin1String("expense-cost")]; - ctype->setExpensePolicy(ep); - } - - - ctype->setIsPolymorphicBase(convertBoolean(attributes[QLatin1String("polymorphic-base")], QLatin1String("polymorphic-base"), false)); - ctype->setPolymorphicIdValue(attributes[QLatin1String("polymorphic-id-expression")]); - //Copyable - if (attributes[QLatin1String("copyable")].isEmpty()) - ctype->setCopyable(ComplexTypeEntry::Unknown); - else { - if (convertBoolean(attributes[QLatin1String("copyable")], QLatin1String("copyable"), false)) - ctype->setCopyable(ComplexTypeEntry::CopyableSet); - else - ctype->setCopyable(ComplexTypeEntry::NonCopyableSet); - - } - - if (element->type == StackElement::ObjectTypeEntry || element->type == StackElement::ValueTypeEntry) - ctype->setHashFunction(attributes[QLatin1String("hash-function")]); - - - ctype->setHeldType(attributes[QLatin1String("held-type")]); - - if (element->type == StackElement::ObjectTypeEntry - || element->type == StackElement::ValueTypeEntry) { - if (convertBoolean(attributes[QLatin1String("force-abstract")], QLatin1String("force-abstract"), false)) - ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract); - if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false)) - ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); - } - - if (element->type == StackElement::InterfaceTypeEntry - || element->type == StackElement::ValueTypeEntry - || element->type == StackElement::ObjectTypeEntry) { - if (convertBoolean(attributes[QLatin1String("delete-in-main-thread")], QLatin1String("delete-in-main-thread"), false)) - ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread); - } - - QString targetType = attributes[QLatin1String("target-type")]; - if (!targetType.isEmpty() && element->entry->isComplex()) - static_cast(element->entry)->setTargetType(targetType); - - // ctype->setInclude(Include(Include::IncludePath, ctype->name())); - ctype = ctype->designatedInterface(); - if (ctype) - ctype->setTargetLangPackage(attributes[QLatin1String("package")]); - - } - break; - case StackElement::FunctionTypeEntry: { - QString signature = attributes[QLatin1String("signature")]; - signature = TypeDatabase::normalizedSignature(signature); - element->entry = m_database->findType(name); - if (element->entry) { - if (element->entry->type() == TypeEntry::FunctionType) { - reinterpret_cast(element->entry)->addSignature(signature); - } else { - 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); - return false; - } - } else { - element->entry = new FunctionTypeEntry(name, signature, since); - element->entry->setCodeGeneration(m_generate); - } - } - break; - default: - Q_ASSERT(false); - }; - - if (element->entry) { - m_database->addType(element->entry); - setTypeRevision(element->entry, attributes[QLatin1String("revision")].toInt()); - } else { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Type: %1 was rejected by typesystem").arg(name); - } - - } else if (element->type == StackElement::InjectDocumentation) { - // check the XML tag attributes - QHash attributes; - attributes.insert(QLatin1String("mode"), QLatin1String("replace")); - attributes.insert(QLatin1String("format"), QLatin1String("native")); - attributes.insert(sinceAttribute(), QLatin1String("0")); - - fetchAttributeValues(tagName, atts, &attributes); - double since = attributes[sinceAttribute()].toDouble(); - - const int validParent = StackElement::TypeEntryMask - | StackElement::ModifyFunction - | StackElement::ModifyField; - if (m_current->parent && m_current->parent->type & validParent) { - QString modeName = attributes[QLatin1String("mode")]; - TypeSystem::DocModificationMode mode; - if (modeName == QLatin1String("append")) { - mode = TypeSystem::DocModificationAppend; - } else if (modeName == QLatin1String("prepend")) { - mode = TypeSystem::DocModificationPrepend; - } else if (modeName == QLatin1String("replace")) { - mode = TypeSystem::DocModificationReplace; - } else { - m_error = QLatin1String("Unknow documentation injection mode: ") + modeName; - return false; - } - - static QHash languageNames; - if (languageNames.isEmpty()) { - languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; - languageNames[QLatin1String("native")] = TypeSystem::NativeCode; - } - - QString format = attributes[QLatin1String("format")].toLower(); - TypeSystem::Language lang = languageNames.value(format, TypeSystem::NoLanguage); - if (lang == TypeSystem::NoLanguage) { - m_error = QStringLiteral("unsupported class attribute: '%1'").arg(format); - return false; - } - - QString signature = m_current->type & StackElement::TypeEntryMask ? QString() : m_currentSignature; - DocModification mod(mode, signature, since); - mod.format = lang; - m_contextStack.top()->docModifications << mod; - } else { - m_error = QLatin1String("inject-documentation must be inside modify-function, " - "modify-field or other tags that creates a type"); - return false; - } - } else if (element->type == StackElement::ModifyDocumentation) { - // check the XML tag attributes - QHash attributes; - attributes.insert(QLatin1String("xpath"), QString()); - attributes.insert(sinceAttribute(), QLatin1String("0")); - fetchAttributeValues(tagName, atts, &attributes); - double since = attributes[sinceAttribute()].toDouble(); - - const int validParent = StackElement::TypeEntryMask - | StackElement::ModifyFunction - | StackElement::ModifyField; - if (m_current->parent && m_current->parent->type & validParent) { - QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature; - m_contextStack.top()->docModifications << DocModification(attributes[QLatin1String("xpath")], signature, since); - } else { - m_error = QLatin1String("modify-documentation must be inside modify-function, " - "modify-field or other tags that creates a type"); - return false; - } - } else if (element->type != StackElement::None) { - bool topLevel = element->type == StackElement::Root - || element->type == StackElement::SuppressedWarning - || element->type == StackElement::Rejection - || element->type == StackElement::LoadTypesystem - || element->type == StackElement::InjectCode - || element->type == StackElement::ExtraIncludes - || element->type == StackElement::ConversionRule - || element->type == StackElement::AddFunction - || element->type == StackElement::Template; - - if (!topLevel && m_current->type == StackElement::Root) { - m_error = QStringLiteral("Tag requires parent: '%1'").arg(tagName); - return false; - } - - StackElement topElement = !m_current ? StackElement(0) : *m_current; - element->entry = topElement.entry; - - QHash attributes; - attributes.insert(sinceAttribute(), QLatin1String("0")); - switch (element->type) { - case StackElement::Root: - attributes.insert(QLatin1String("package"), QString()); - attributes.insert(QLatin1String("default-superclass"), QString()); - break; - case StackElement::LoadTypesystem: - attributes.insert(nameAttribute(), QString()); - attributes.insert(QLatin1String("generate"), QLatin1String("yes")); - break; - case StackElement::NoNullPointers: - attributes.insert(QLatin1String("default-value"), QString()); - break; - case StackElement::SuppressedWarning: - attributes.insert(QLatin1String("text"), QString()); - break; - case StackElement::ReplaceDefaultExpression: - attributes.insert(QLatin1String("with"), QString()); - break; - case StackElement::DefineOwnership: - attributes.insert(QLatin1String("class"), QLatin1String("target")); - attributes.insert(QLatin1String("owner"), QString()); - break; - case StackElement::AddFunction: - attributes.insert(QLatin1String("signature"), QString()); - attributes.insert(QLatin1String("return-type"), QLatin1String("void")); - attributes.insert(QLatin1String("access"), QLatin1String("public")); - attributes.insert(QLatin1String("static"), QLatin1String("no")); - break; - case StackElement::ModifyFunction: - attributes.insert(QLatin1String("signature"), QString()); - attributes.insert(QLatin1String("access"), QString()); - attributes.insert(QLatin1String("remove"), QString()); - attributes.insert(QLatin1String("rename"), QString()); - attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); - attributes.insert(QLatin1String("associated-to"), QString()); - attributes.insert(QLatin1String("virtual-slot"), QLatin1String("no")); - attributes.insert(QLatin1String("thread"), QLatin1String("no")); - attributes.insert(QLatin1String("allow-thread"), QLatin1String("no")); - break; - case StackElement::ModifyArgument: - attributes.insert(QLatin1String("index"), QString()); - attributes.insert(QLatin1String("replace-value"), QString()); - attributes.insert(QLatin1String("invalidate-after-use"), QLatin1String("no")); - break; - case StackElement::ModifyField: - attributes.insert(nameAttribute(), QString()); - attributes.insert(QLatin1String("write"), QLatin1String("true")); - attributes.insert(QLatin1String("read"), QLatin1String("true")); - attributes.insert(QLatin1String("remove"), QString()); - break; - case StackElement::Access: - attributes.insert(QLatin1String("modifier"), QString()); - break; - case StackElement::Include: - attributes.insert(QLatin1String("file-name"), QString()); - attributes.insert(QLatin1String("location"), QString()); - break; - case StackElement::CustomMetaConstructor: - attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_create"); - attributes.insert(QLatin1String("param-name"), QLatin1String("copy")); - break; - case StackElement::CustomMetaDestructor: - attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_delete"); - attributes.insert(QLatin1String("param-name"), QLatin1String("copy")); - break; - case StackElement::ReplaceType: - attributes.insert(QLatin1String("modified-type"), QString()); - break; - case StackElement::InjectCode: - attributes.insert(QLatin1String("class"), QLatin1String("target")); - attributes.insert(QLatin1String("position"), QLatin1String("beginning")); - attributes.insert(QLatin1String("file"), QString()); - break; - case StackElement::ConversionRule: - attributes.insert(QLatin1String("class"), QString()); - attributes.insert(QLatin1String("file"), QString()); - break; - case StackElement::TargetToNative: - attributes.insert(QLatin1String("replace"), QLatin1String("yes")); - break; - case StackElement::AddConversion: - attributes.insert(QLatin1String("type"), QString()); - attributes.insert(QLatin1String("check"), QString()); - break; - case StackElement::RejectEnumValue: - attributes.insert(nameAttribute(), QString()); - break; - case StackElement::ArgumentMap: - attributes.insert(QLatin1String("index"), QLatin1String("1")); - attributes.insert(QLatin1String("meta-name"), QString()); - break; - case StackElement::Rename: - attributes.insert(QLatin1String("to"), QString()); - break; - case StackElement::Rejection: - attributes.insert(classAttribute(), QString()); - attributes.insert(functionNameAttribute(), QString()); - attributes.insert(fieldNameAttribute(), QString()); - attributes.insert(enumNameAttribute(), QString()); - attributes.insert(argumentTypeAttribute(), QString()); - attributes.insert(returnTypeAttribute(), QString()); - break; - case StackElement::Removal: - attributes.insert(QLatin1String("class"), QLatin1String("all")); - break; - case StackElement::Template: - attributes.insert(nameAttribute(), QString()); - break; - case StackElement::TemplateInstanceEnum: - attributes.insert(nameAttribute(), QString()); - break; - case StackElement::Replace: - attributes.insert(QLatin1String("from"), QString()); - attributes.insert(QLatin1String("to"), QString()); - break; - case StackElement::ReferenceCount: - attributes.insert(QLatin1String("action"), QString()); - attributes.insert(QLatin1String("variable-name"), QString()); - break; - case StackElement::ParentOwner: - attributes.insert(QLatin1String("index"), QString()); - attributes.insert(QLatin1String("action"), QString()); - default: - { }; - }; - - double since = 0; - if (attributes.count() > 0) { - fetchAttributeValues(tagName, atts, &attributes); - since = attributes[sinceAttribute()].toDouble(); - } - - switch (element->type) { - case StackElement::Root: - m_defaultPackage = attributes[QLatin1String("package")]; - m_defaultSuperclass = attributes[QLatin1String("default-superclass")]; - element->type = StackElement::Root; - { - TypeSystemTypeEntry* moduleEntry = reinterpret_cast( - m_database->findType(m_defaultPackage)); - element->entry = moduleEntry ? moduleEntry : new TypeSystemTypeEntry(m_defaultPackage, since); - element->entry->setCodeGeneration(m_generate); - } - - if ((m_generate == TypeEntry::GenerateForSubclass || - m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty()) - TypeDatabase::instance()->addRequiredTargetImport(m_defaultPackage); - - if (!element->entry->qualifiedCppName().isEmpty()) - m_database->addType(element->entry); - break; - case StackElement::LoadTypesystem: { - QString name = attributes[nameAttribute()]; - if (name.isEmpty()) { - m_error = QLatin1String("No typesystem name specified"); - return false; - } - bool generateChild = (convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true) && (m_generate == TypeEntry::GenerateAll)); - if (!m_database->parseFile(name, generateChild)) { - m_error = QStringLiteral("Failed to parse: '%1'").arg(name); - return false; - } - } - break; - case StackElement::RejectEnumValue: { - if (!m_currentEnum) { - m_error = QLatin1String(" node must be used inside a node"); - return false; - } - QString name = attributes[nameAttribute()]; - } break; - case StackElement::ReplaceType: { - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("Type replacement can only be specified for argument modifications"); - return false; - } - - if (attributes[QLatin1String("modified-type")].isEmpty()) { - m_error = QLatin1String("Type replacement requires 'modified-type' attribute"); - return false; - } - - m_contextStack.top()->functionMods.last().argument_mods.last().modified_type = attributes[QLatin1String("modified-type")]; - } - break; - case StackElement::ConversionRule: { - if (topElement.type != StackElement::ModifyArgument - && topElement.type != StackElement::ValueTypeEntry - && topElement.type != StackElement::PrimitiveTypeEntry - && topElement.type != StackElement::ContainerTypeEntry) { - m_error = QLatin1String("Conversion rules can only be specified for argument modification, " - "value-type, primitive-type or container-type conversion."); - return false; - } - - static QHash languageNames; - if (languageNames.isEmpty()) { - languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; - languageNames[QLatin1String("native")] = TypeSystem::NativeCode; - } - - QString languageAttribute = attributes[QLatin1String("class")].toLower(); - TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); - - if (topElement.type == StackElement::ModifyArgument) { - if (lang == TypeSystem::NoLanguage) { - m_error = QStringLiteral("unsupported class attribute: '%1'").arg(lang); - return false; - } - - CodeSnip snip(since); - snip.language = lang; - m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.append(snip); - } else { - if (topElement.entry->hasConversionRule() || topElement.entry->hasCustomConversion()) { - m_error = QLatin1String("Types can have only one conversion rule"); - return false; - } - - // The old conversion rule tag that uses a file containing the conversion - // will be kept temporarily for compatibility reasons. - QString sourceFile = attributes[QLatin1String("file")]; - if (!sourceFile.isEmpty()) { - if (m_generate != TypeEntry::GenerateForSubclass - && m_generate != TypeEntry::GenerateNothing) { - - const char* conversionFlag = NATIVE_CONVERSION_RULE_FLAG; - if (lang == TypeSystem::TargetLangCode) - conversionFlag = TARGET_CONVERSION_RULE_FLAG; - - QFile conversionSource(sourceFile); - if (conversionSource.open(QIODevice::ReadOnly | QIODevice::Text)) { - topElement.entry->setConversionRule(QLatin1String(conversionFlag) + QString::fromUtf8(conversionSource.readAll())); - } else { - qCWarning(lcShiboken).noquote().nospace() - << "File containing conversion code for " - << topElement.entry->name() << " type does not exist or is not readable: " - << sourceFile; - } - } - } - - CustomConversion* customConversion = new CustomConversion(static_cast(m_current->entry)); - customConversionsForReview.append(customConversion); - } - } - break; - case StackElement::NativeToTarget: { - if (topElement.type != StackElement::ConversionRule) { - m_error = QLatin1String("Native to Target conversion code can only be specified for custom conversion rules."); - return false; - } - m_contextStack.top()->codeSnips << CodeSnip(0); - } - break; - case StackElement::TargetToNative: { - if (topElement.type != StackElement::ConversionRule) { - m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules."); - return false; - } - bool replace = attributes[QLatin1String("replace")] == QLatin1String("yes"); - static_cast(m_current->entry)->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); - } - break; - case StackElement::AddConversion: { - if (topElement.type != StackElement::TargetToNative) { - m_error = QLatin1String("Target to Native conversions can only be added inside 'target-to-native' tags."); - return false; - } - QString sourceTypeName = attributes[QLatin1String("type")]; - if (sourceTypeName.isEmpty()) { - m_error = QLatin1String("Target to Native conversions must specify the input type with the 'type' attribute."); - return false; - } - QString typeCheck = attributes[QLatin1String("check")]; - static_cast(m_current->entry)->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); - m_contextStack.top()->codeSnips << CodeSnip(0); - } - break; - case StackElement::ModifyArgument: { - if (topElement.type != StackElement::ModifyFunction - && topElement.type != StackElement::AddFunction) { - m_error = QString::fromLatin1("argument modification requires function" - " modification as parent, was %1") - .arg(topElement.type, 0, 16); - return false; - } - - QString index = attributes[QLatin1String("index")]; - if (index == QLatin1String("return")) - index = QLatin1String("0"); - else if (index == QLatin1String("this")) - index = QLatin1String("-1"); - - bool ok = false; - int idx = index.toInt(&ok); - if (!ok) { - m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index); - return false; - } - - QString replace_value = attributes[QLatin1String("replace-value")]; - - if (!replace_value.isEmpty() && idx) { - m_error = QLatin1String("replace-value is only supported for return values (index=0)."); - return false; - } - - ArgumentModification argumentModification = ArgumentModification(idx, since); - argumentModification.replace_value = replace_value; - argumentModification.resetAfterUse = convertBoolean(attributes[QLatin1String("invalidate-after-use")], QLatin1String("invalidate-after-use"), false); - m_contextStack.top()->functionMods.last().argument_mods.append(argumentModification); - } - break; - case StackElement::NoNullPointers: { - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("no-null-pointer requires argument modification as parent"); - return false; - } - - m_contextStack.top()->functionMods.last().argument_mods.last().noNullPointers = true; - if (!m_contextStack.top()->functionMods.last().argument_mods.last().index) - m_contextStack.top()->functionMods.last().argument_mods.last().nullPointerDefaultValue = attributes[QLatin1String("default-value")]; - else if (!attributes[QLatin1String("default-value")].isEmpty()) - qCWarning(lcShiboken) << "default values for null pointer guards are only effective for return values"; - - } - break; - case StackElement::DefineOwnership: { - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("define-ownership requires argument modification as parent"); - return false; - } - - static QHash languageNames; - if (languageNames.isEmpty()) { - languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; - languageNames[QLatin1String("native")] = TypeSystem::NativeCode; - } - - QString classAttribute = attributes[QLatin1String("class")].toLower(); - TypeSystem::Language lang = languageNames.value(classAttribute, TypeSystem::NoLanguage); - if (lang == TypeSystem::NoLanguage) { - m_error = QStringLiteral("unsupported class attribute: '%1'").arg(classAttribute); - return false; - } - - static QHash ownershipNames; - if (ownershipNames.isEmpty()) { - ownershipNames[QLatin1String("target")] = TypeSystem::TargetLangOwnership; - ownershipNames[QLatin1String("c++")] = TypeSystem::CppOwnership; - ownershipNames[QLatin1String("default")] = TypeSystem::DefaultOwnership; - } - - QString ownershipAttribute = attributes[QLatin1String("owner")].toLower(); - TypeSystem::Ownership owner = ownershipNames.value(ownershipAttribute, TypeSystem::InvalidOwnership); - if (owner == TypeSystem::InvalidOwnership) { - m_error = QStringLiteral("unsupported owner attribute: '%1'").arg(ownershipAttribute); - return false; - } - - m_contextStack.top()->functionMods.last().argument_mods.last().ownerships[lang] = owner; - } - break; - case StackElement::SuppressedWarning: - if (attributes[QLatin1String("text")].isEmpty()) - qCWarning(lcShiboken) << "Suppressed warning with no text specified"; - else - m_database->addSuppressedWarning(attributes[QLatin1String("text")]); - break; - case StackElement::ArgumentMap: { - if (!(topElement.type & StackElement::CodeSnipMask)) { - m_error = QLatin1String("Argument maps requires code injection as parent"); - return false; - } - - bool ok; - int pos = attributes[QLatin1String("index")].toInt(&ok); - if (!ok) { - m_error = QStringLiteral("Can't convert position '%1' to integer") - .arg(attributes[QLatin1String("position")]); - return false; - } - - if (pos <= 0) { - m_error = QStringLiteral("Argument position %1 must be a positive number").arg(pos); - return false; - } - - QString meta_name = attributes[QLatin1String("meta-name")]; - if (meta_name.isEmpty()) - qCWarning(lcShiboken) << "Empty meta name in argument map"; - - - if (topElement.type == StackElement::InjectCodeInFunction) - m_contextStack.top()->functionMods.last().snips.last().argumentMap[pos] = meta_name; - else { - qCWarning(lcShiboken) << "Argument maps are only useful for injection of code " - "into functions."; - } - } - break; - case StackElement::Removal: { - if (topElement.type != StackElement::ModifyFunction) { - m_error = QLatin1String("Function modification parent required"); - return false; - } - - static QHash languageNames; - if (languageNames.isEmpty()) { - languageNames.insert(QLatin1String("target"), TypeSystem::TargetLangAndNativeCode); - languageNames.insert(QLatin1String("all"), TypeSystem::All); - } - - QString languageAttribute = attributes[QLatin1String("class")].toLower(); - TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); - if (lang == TypeSystem::NoLanguage) { - m_error = QStringLiteral("unsupported class attribute: '%1'").arg(languageAttribute); - return false; - } - - m_contextStack.top()->functionMods.last().removal = lang; - } - break; - case StackElement::Rename: - case StackElement::Access: { - if (topElement.type != StackElement::ModifyField - && topElement.type != StackElement::ModifyFunction - && topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("Function, field or argument modification parent required"); - return false; - } - - Modification *mod = 0; - if (topElement.type == StackElement::ModifyFunction) - mod = &m_contextStack.top()->functionMods.last(); - else if (topElement.type == StackElement::ModifyField) - mod = &m_contextStack.top()->fieldMods.last(); - - QString modifier; - if (element->type == StackElement::Rename) { - modifier = QLatin1String("rename"); - QString renamed_to = attributes[QLatin1String("to")]; - if (renamed_to.isEmpty()) { - m_error = QLatin1String("Rename modifier requires 'to' attribute"); - return false; - } - - if (topElement.type == StackElement::ModifyFunction) - mod->setRenamedTo(renamed_to); - else if (topElement.type == StackElement::ModifyField) - mod->setRenamedTo(renamed_to); - else - m_contextStack.top()->functionMods.last().argument_mods.last().renamed_to = renamed_to; - } else - modifier = attributes[QLatin1String("modifier")].toLower(); - - - if (modifier.isEmpty()) { - m_error = QLatin1String("No access modification specified"); - return false; - } - - static QHash modifierNames; - if (modifierNames.isEmpty()) { - modifierNames[QLatin1String("private")] = Modification::Private; - modifierNames[QLatin1String("public")] = Modification::Public; - modifierNames[QLatin1String("protected")] = Modification::Protected; - modifierNames[QLatin1String("friendly")] = Modification::Friendly; - modifierNames[QLatin1String("rename")] = Modification::Rename; - modifierNames[QLatin1String("final")] = Modification::Final; - modifierNames[QLatin1String("non-final")] = Modification::NonFinal; - } - - if (!modifierNames.contains(modifier)) { - m_error = QStringLiteral("Unknown access modifier: '%1'").arg(modifier); - return false; - } - - if (mod) - mod->modifiers |= modifierNames[modifier]; - } - break; - case StackElement::RemoveArgument: - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("Removing argument requires argument modification as parent"); - return false; - } - - m_contextStack.top()->functionMods.last().argument_mods.last().removed = true; - break; - - case StackElement::ModifyField: { - QString name = attributes[nameAttribute()]; - if (name.isEmpty()) - break; - FieldModification fm; - fm.name = name; - fm.modifiers = 0; - - if (!convertRemovalAttribute(attributes[QLatin1String("remove")], fm, m_error)) - return false; - - QString read = attributes[QLatin1String("read")]; - QString write = attributes[QLatin1String("write")]; - - if (read == QLatin1String("true")) fm.modifiers |= FieldModification::Readable; - if (write == QLatin1String("true")) fm.modifiers |= FieldModification::Writable; - - m_contextStack.top()->fieldMods << fm; - } - break; - case StackElement::AddFunction: { - if (!(topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::Root))) { - m_error = QString::fromLatin1("Add function requires a complex type or a root tag as parent" - ", was=%1").arg(topElement.type, 0, 16); - return false; - } - QString signature = attributes[QLatin1String("signature")]; - - signature = TypeDatabase::normalizedSignature(signature); - if (signature.isEmpty()) { - m_error = QLatin1String("No signature for the added function"); - return false; - } - - QString errorString = checkSignatureError(signature, QLatin1String("add-function")); - if (!errorString.isEmpty()) { - m_error = errorString; - return false; - } - - AddedFunction func(signature, attributes[QLatin1String("return-type")], since); - func.setStatic(attributes[QLatin1String("static")] == QLatin1String("yes")); - if (!signature.contains(QLatin1Char('('))) - signature += QLatin1String("()"); - m_currentSignature = signature; - - QString access = attributes[QLatin1String("access")].toLower(); - if (!access.isEmpty()) { - if (access == QLatin1String("protected")) { - func.setAccess(AddedFunction::Protected); - } else if (access == QLatin1String("public")) { - func.setAccess(AddedFunction::Public); - } else { - m_error = QString::fromLatin1("Bad access type '%1'").arg(access); - return false; - } - } - - m_contextStack.top()->addedFunctions << func; - - FunctionModification mod(since); - mod.signature = m_currentSignature; - m_contextStack.top()->functionMods << mod; - } - break; - case StackElement::ModifyFunction: { - if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { - m_error = QString::fromLatin1("Modify function requires complex type as parent" - ", was=%1").arg(topElement.type, 0, 16); - return false; - } - QString signature = attributes[QLatin1String("signature")]; - - signature = TypeDatabase::normalizedSignature(signature); - if (signature.isEmpty()) { - m_error = QLatin1String("No signature for modified function"); - return false; - } - - QString errorString = checkSignatureError(signature, QLatin1String("modify-function")); - if (!errorString.isEmpty()) { - m_error = errorString; - return false; - } - - FunctionModification mod(since); - m_currentSignature = mod.signature = signature; - - QString access = attributes[QLatin1String("access")].toLower(); - if (!access.isEmpty()) { - if (access == QLatin1String("private")) - mod.modifiers |= Modification::Private; - else if (access == QLatin1String("protected")) - mod.modifiers |= Modification::Protected; - else if (access == QLatin1String("public")) - mod.modifiers |= Modification::Public; - else if (access == QLatin1String("final")) - mod.modifiers |= Modification::Final; - else if (access == QLatin1String("non-final")) - mod.modifiers |= Modification::NonFinal; - else { - m_error = QString::fromLatin1("Bad access type '%1'").arg(access); - return false; - } - } - - if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false)) - mod.modifiers |= Modification::Deprecated; - - if (!convertRemovalAttribute(attributes[QLatin1String("remove")], mod, m_error)) - return false; - - QString rename = attributes[QLatin1String("rename")]; - if (!rename.isEmpty()) { - mod.renamedToName = rename; - mod.modifiers |= Modification::Rename; - } - - QString association = attributes[QLatin1String("associated-to")]; - if (!association.isEmpty()) - mod.association = association; - - mod.setIsThread(convertBoolean(attributes[QLatin1String("thread")], QLatin1String("thread"), false)); - mod.setAllowThread(convertBoolean(attributes[QLatin1String("allow-thread")], QLatin1String("allow-thread"), false)); - - mod.modifiers |= (convertBoolean(attributes[QLatin1String("virtual-slot")], QLatin1String("virtual-slot"), false) ? Modification::VirtualSlot : 0); - - m_contextStack.top()->functionMods << mod; - } - break; - case StackElement::ReplaceDefaultExpression: - if (!(topElement.type & StackElement::ModifyArgument)) { - m_error = QLatin1String("Replace default expression only allowed as child of argument modification"); - return false; - } - - if (attributes[QLatin1String("with")].isEmpty()) { - m_error = QLatin1String("Default expression replaced with empty string. Use remove-default-expression instead."); - return false; - } - - m_contextStack.top()->functionMods.last().argument_mods.last().replacedDefaultExpression = attributes[QLatin1String("with")]; - break; - case StackElement::RemoveDefaultExpression: - m_contextStack.top()->functionMods.last().argument_mods.last().removedDefaultExpression = true; - break; - case StackElement::CustomMetaConstructor: - case StackElement::CustomMetaDestructor: { - CustomFunction *func = new CustomFunction(attributes[nameAttribute()]); - func->paramName = attributes[QLatin1String("param-name")]; - element->value.customFunction = func; - } - break; - case StackElement::ReferenceCount: { - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("reference-count must be child of modify-argument"); - return false; - } - - ReferenceCount rc; - - static QHash actions; - if (actions.isEmpty()) { - actions[QLatin1String("add")] = ReferenceCount::Add; - actions[QLatin1String("add-all")] = ReferenceCount::AddAll; - actions[QLatin1String("remove")] = ReferenceCount::Remove; - actions[QLatin1String("set")] = ReferenceCount::Set; - actions[QLatin1String("ignore")] = ReferenceCount::Ignore; - } - rc.action = actions.value(attributes[QLatin1String("action")].toLower(), ReferenceCount::Invalid); - rc.varName = attributes[QLatin1String("variable-name")]; - - if (rc.action == ReferenceCount::Invalid) { - m_error = QLatin1String("unrecognized value for action attribute. supported actions:"); - for (QHash::const_iterator it = actions.cbegin(), end = actions.cend(); it != end; ++it) - m_error += QLatin1Char(' ') + it.key(); - } - - m_contextStack.top()->functionMods.last().argument_mods.last().referenceCounts.append(rc); - } - break; - - case StackElement::ParentOwner: { - if (topElement.type != StackElement::ModifyArgument) { - m_error = QLatin1String("parent-policy must be child of modify-argument"); - return false; - } - - ArgumentOwner ao; - - QString index = attributes[QLatin1String("index")]; - if (index == QLatin1String("return")) - index = QLatin1String("0"); - else if (index == QLatin1String("this")) - index = QLatin1String("-1"); - - bool ok = false; - int idx = index.toInt(&ok); - if (!ok) { - m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index); - return false; - } - - static QHash actions; - if (actions.isEmpty()) { - actions[QLatin1String("add")] = ArgumentOwner::Add; - actions[QLatin1String("remove")] = ArgumentOwner::Remove; - } - - ao.action = actions.value(attributes[QLatin1String("action")].toLower(), ArgumentOwner::Invalid); - if (!ao.action) { - m_error = QLatin1String("Invalid parent actionr"); - return false; - } - ao.index = idx; - m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao; - } - break; - - - case StackElement::InjectCode: { - if (!(topElement.type & StackElement::ComplexTypeEntryMask) - && (topElement.type != StackElement::AddFunction) - && (topElement.type != StackElement::ModifyFunction) - && (topElement.type != StackElement::Root)) { - m_error = QLatin1String("wrong parent type for code injection"); - return false; - } - - static QHash languageNames; - if (languageNames.isEmpty()) { - languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; // em algum lugar do cpp - languageNames[QLatin1String("native")] = TypeSystem::NativeCode; // em algum lugar do cpp - languageNames[QLatin1String("shell")] = TypeSystem::ShellCode; // coloca no header, mas antes da declaracao da classe - languageNames[QLatin1String("shell-declaration")] = TypeSystem::ShellDeclaration; // coloca no header, dentro da declaracao da classe - languageNames[QLatin1String("library-initializer")] = TypeSystem::PackageInitializer; - languageNames[QLatin1String("destructor-function")] = TypeSystem::DestructorFunction; - languageNames[QLatin1String("constructors")] = TypeSystem::Constructors; - languageNames[QLatin1String("interface")] = TypeSystem::Interface; - } - - QString className = attributes[QLatin1String("class")].toLower(); - if (!languageNames.contains(className)) { - m_error = QStringLiteral("Invalid class specifier: '%1'").arg(className); - return false; - } - - - static QHash positionNames; - if (positionNames.isEmpty()) { - positionNames.insert(QLatin1String("beginning"), TypeSystem::CodeSnipPositionBeginning); - positionNames.insert(QLatin1String("end"), TypeSystem::CodeSnipPositionEnd); - // QtScript - positionNames.insert(QLatin1String("declaration"), TypeSystem::CodeSnipPositionDeclaration); - positionNames.insert(QLatin1String("prototype-initialization"), TypeSystem::CodeSnipPositionPrototypeInitialization); - positionNames.insert(QLatin1String("constructor-initialization"), TypeSystem::CodeSnipPositionConstructorInitialization); - positionNames.insert(QLatin1String("constructor"), TypeSystem::CodeSnipPositionConstructor); - } - - QString position = attributes[QLatin1String("position")].toLower(); - if (!positionNames.contains(position)) { - m_error = QStringLiteral("Invalid position: '%1'").arg(position); - return false; - } - - CodeSnip snip(since); - snip.language = languageNames[className]; - snip.position = positionNames[position]; - bool in_file = false; - - QString file_name = attributes[QLatin1String("file")]; - - //Handler constructor.... - if (m_generate != TypeEntry::GenerateForSubclass && - m_generate != TypeEntry::GenerateNothing && - !file_name.isEmpty()) { - if (QFile::exists(file_name)) { - QFile codeFile(file_name); - if (codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) { - QString content = QLatin1String("// ========================================================================\n" - "// START of custom code block [file: "); - content += file_name; - content += QLatin1String("]\n"); - content += QString::fromUtf8(codeFile.readAll()); - content += QLatin1String("\n// END of custom code block [file: "); - content += file_name; - content += QLatin1String("]\n// ========================================================================\n"); - snip.addCode(content); - in_file = true; - } - } else { - qCWarning(lcShiboken).noquote().nospace() - << "File for inject code not exist: " << QDir::toNativeSeparators(file_name); - } - - } - - if (snip.language == TypeSystem::Interface && topElement.type != StackElement::InterfaceTypeEntry) { - m_error = QLatin1String("Interface code injections must be direct child of an interface type entry"); - return false; - } - - if (topElement.type == StackElement::ModifyFunction || topElement.type == StackElement::AddFunction) { - FunctionModification mod = m_contextStack.top()->functionMods.last(); - if (snip.language == TypeSystem::ShellDeclaration) { - m_error = QLatin1String("no function implementation in shell declaration in which to inject code"); - return false; - } - - m_contextStack.top()->functionMods.last().snips << snip; - if (in_file) - m_contextStack.top()->functionMods.last().modifiers |= FunctionModification::CodeInjection; - element->type = StackElement::InjectCodeInFunction; - } else if (topElement.type == StackElement::Root) { - element->entry->addCodeSnip(snip); - } else if (topElement.type != StackElement::Root) { - m_contextStack.top()->codeSnips << snip; - } - - } - break; - case StackElement::Include: { - QString location = attributes[QLatin1String("location")].toLower(); - - static QHash locationNames; - if (locationNames.isEmpty()) { - locationNames[QLatin1String("global")] = Include::IncludePath; - locationNames[QLatin1String("local")] = Include::LocalPath; - locationNames[QLatin1String("target")] = Include::TargetLangImport; - } - - if (!locationNames.contains(location)) { - m_error = QStringLiteral("Location not recognized: '%1'").arg(location); - return false; - } - - Include::IncludeType loc = locationNames[location]; - Include inc(loc, attributes[QLatin1String("file-name")]); - - ComplexTypeEntry *ctype = static_cast(element->entry); - if (topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::PrimitiveTypeEntry)) { - element->entry->setInclude(inc); - } else if (topElement.type == StackElement::ExtraIncludes) { - element->entry->addExtraInclude(inc); - } else { - m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); - return false; - } - - inc = ctype->include(); - IncludeList lst = ctype->extraIncludes(); - ctype = ctype->designatedInterface(); - if (ctype) { - ctype->setExtraIncludes(lst); - ctype->setInclude(inc); - } - } - break; - case StackElement::Rejection: - if (!addRejection(m_database, attributes, &m_error)) - return false; - break; - case StackElement::Template: - element->value.templateEntry = new TemplateEntry(attributes[nameAttribute()], since); - break; - case StackElement::TemplateInstanceEnum: - if (!(topElement.type & StackElement::CodeSnipMask) && - (topElement.type != StackElement::Template) && - (topElement.type != StackElement::CustomMetaConstructor) && - (topElement.type != StackElement::CustomMetaDestructor) && - (topElement.type != StackElement::NativeToTarget) && - (topElement.type != StackElement::AddConversion) && - (topElement.type != StackElement::ConversionRule)) { - m_error = QLatin1String("Can only insert templates into code snippets, templates, custom-constructors, "\ - "custom-destructors, conversion-rule, native-to-target or add-conversion tags."); - return false; - } - element->value.templateInstance = new TemplateInstance(attributes[nameAttribute()], since); - break; - case StackElement::Replace: - if (topElement.type != StackElement::TemplateInstanceEnum) { - m_error = QLatin1String("Can only insert replace rules into insert-template."); - return false; - } - element->parent->value.templateInstance->addReplaceRule(attributes[QLatin1String("from")], attributes[QLatin1String("to")]); - break; - default: - break; // nada - }; - } - - m_current = element; - return true; -} - -PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const -{ - if (!m_referencedTypeEntry) - return 0; - - PrimitiveTypeEntry *baseReferencedTypeEntry = m_referencedTypeEntry->basicReferencedTypeEntry(); - if (baseReferencedTypeEntry) - return baseReferencedTypeEntry; - else - return m_referencedTypeEntry; -} - -typedef QHash PrimitiveTypeEntryTargetLangPackageMap; -Q_GLOBAL_STATIC(PrimitiveTypeEntryTargetLangPackageMap, primitiveTypeEntryTargetLangPackages); - -void PrimitiveTypeEntry::setTargetLangPackage(const QString& package) -{ - primitiveTypeEntryTargetLangPackages()->insert(this, package); -} -QString PrimitiveTypeEntry::targetLangPackage() const -{ - if (!primitiveTypeEntryTargetLangPackages()->contains(this)) - return this->::TypeEntry::targetLangPackage(); - return primitiveTypeEntryTargetLangPackages()->value(this); -} - -CodeSnipList TypeEntry::codeSnips() const -{ - return m_codeSnips; -} - -QString Modification::accessModifierString() const -{ - if (isPrivate()) return QLatin1String("private"); - if (isProtected()) return QLatin1String("protected"); - if (isPublic()) return QLatin1String("public"); - if (isFriendly()) return QLatin1String("friendly"); - return QString(); -} - -FunctionModificationList ComplexTypeEntry::functionModifications(const QString &signature) const -{ - FunctionModificationList lst; - for (int i = 0; i < m_functionMods.count(); ++i) { - const FunctionModification &mod = m_functionMods.at(i); - if (mod.signature == signature) - lst << mod; - } - return lst; -} - -FieldModification ComplexTypeEntry::fieldModification(const QString &name) const -{ - for (int i = 0; i < m_fieldMods.size(); ++i) - if (m_fieldMods.at(i).name == name) - return m_fieldMods.at(i); - FieldModification mod; - mod.name = name; - mod.modifiers = FieldModification::Readable | FieldModification::Writable; - return mod; -} - -// The things we do not to break the ABI... -typedef QHash ComplexTypeEntryDefaultConstructorMap; -Q_GLOBAL_STATIC(ComplexTypeEntryDefaultConstructorMap, complexTypeEntryDefaultConstructors); - -void ComplexTypeEntry::setDefaultConstructor(const QString& defaultConstructor) -{ - if (!defaultConstructor.isEmpty()) - complexTypeEntryDefaultConstructors()->insert(this, defaultConstructor); -} -QString ComplexTypeEntry::defaultConstructor() const -{ - if (!complexTypeEntryDefaultConstructors()->contains(this)) - return QString(); - return complexTypeEntryDefaultConstructors()->value(this); -} -bool ComplexTypeEntry::hasDefaultConstructor() const -{ - return complexTypeEntryDefaultConstructors()->contains(this); -} - -QString ContainerTypeEntry::targetLangPackage() const -{ - return QString(); -} - -QString ContainerTypeEntry::targetLangName() const -{ - - switch (m_type) { - case StringListContainer: return QLatin1String("QStringList"); - case ListContainer: return QLatin1String("QList"); - case LinkedListContainer: return QLatin1String("QLinkedList"); - case VectorContainer: return QLatin1String("QVector"); - case StackContainer: return QLatin1String("QStack"); - case QueueContainer: return QLatin1String("QQueue"); - case SetContainer: return QLatin1String("QSet"); - case MapContainer: return QLatin1String("QMap"); - case MultiMapContainer: return QLatin1String("QMultiMap"); - case HashContainer: return QLatin1String("QHash"); - case MultiHashContainer: return QLatin1String("QMultiHash"); - case PairContainer: return QLatin1String("QPair"); - default: - qWarning("bad type... %d", m_type); - break; - } - return QString(); -} - -QString ContainerTypeEntry::qualifiedCppName() const -{ - if (m_type == StringListContainer) - return QLatin1String("QStringList"); - return ComplexTypeEntry::qualifiedCppName(); -} - -QString EnumTypeEntry::targetLangQualifier() const -{ - TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier); - if (te) - return te->targetLangName(); - else - return m_qualifier; -} - -QString EnumTypeEntry::targetLangApiName() const -{ - return QLatin1String("jint"); -} - -QString FlagsTypeEntry::targetLangApiName() const -{ - return QLatin1String("jint"); -} - -void EnumTypeEntry::addEnumValueRedirection(const QString &rejected, const QString &usedValue) -{ - m_enumRedirections << EnumValueRedirection(rejected, usedValue); -} - -QString EnumTypeEntry::enumValueRedirection(const QString &value) const -{ - for (int i = 0; i < m_enumRedirections.size(); ++i) - if (m_enumRedirections.at(i).rejected == value) - return m_enumRedirections.at(i).used; - return QString(); -} - -QString FlagsTypeEntry::qualifiedTargetLangName() const -{ - return targetLangPackage() + QLatin1Char('.') + m_enum->targetLangQualifier() - + QLatin1Char('.') + targetLangName(); -} - -/*! - * The Visual Studio 2002 compiler doesn't support these symbols, - * which our typedefs unforntuatly expand to. - */ -QString fixCppTypeName(const QString &name) -{ - if (name == QLatin1String("long long")) - return QLatin1String("qint64"); - else if (name == QLatin1String("unsigned long long")) - return QLatin1String("quint64"); - return name; -} - -QString TemplateInstance::expandCode() const -{ - TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name); - if (templateEntry) { - typedef QHash::const_iterator ConstIt; - QString code = templateEntry->code(); - for (ConstIt it = replaceRules.begin(), end = replaceRules.end(); it != end; ++it) - code.replace(it.key(), it.value()); - while (!code.isEmpty() && code.at(code.size() - 1).isSpace()) - code.chop(1); - QString result = QLatin1String("// TEMPLATE - ") + m_name + QLatin1String(" - START"); - if (!code.startsWith(QLatin1Char('\n'))) - result += QLatin1Char('\n'); - result += code; - result += QLatin1String("\n// TEMPLATE - ") + m_name + QLatin1String(" - END"); - return result; - } else { - qCWarning(lcShiboken).noquote().nospace() - << "insert-template referring to non-existing template '" << m_name << '\''; - } - - return QString(); -} - - -QString CodeSnipAbstract::code() const -{ - QString res; - for (const CodeSnipFragment &codeFrag : codeList) - res.append(codeFrag.code()); - - return res; -} - -QString CodeSnipFragment::code() const -{ - if (m_instance) - return m_instance->expandCode(); - else - return m_code; -} - -QString FunctionModification::toString() const -{ - QString str = signature + QLatin1String("->"); - if (modifiers & AccessModifierMask) { - switch (modifiers & AccessModifierMask) { - case Private: str += QLatin1String("private"); break; - case Protected: str += QLatin1String("protected"); break; - case Public: str += QLatin1String("public"); break; - case Friendly: str += QLatin1String("friendly"); break; - } - } - - if (modifiers & Final) str += QLatin1String("final"); - if (modifiers & NonFinal) str += QLatin1String("non-final"); - - if (modifiers & Readable) str += QLatin1String("readable"); - if (modifiers & Writable) str += QLatin1String("writable"); - - if (modifiers & CodeInjection) { - for (const CodeSnip &s : snips) { - str += QLatin1String("\n//code injection:\n"); - str += s.code(); - } - } - - if (modifiers & Rename) str += QLatin1String("renamed:") + renamedToName; - - if (modifiers & Deprecated) str += QLatin1String("deprecate"); - - if (modifiers & ReplaceExpression) str += QLatin1String("replace-expression"); - - return str; -} - -bool FunctionModification::operator!=(const FunctionModification& other) const -{ - return !(*this == other); -} - -bool FunctionModification::operator==(const FunctionModification& other) const -{ - if (signature != other.signature) - return false; - - if (association != other.association) - return false; - - if (modifiers != other.modifiers) - return false; - - if (removal != other.removal) - return false; - - if (m_thread != other.m_thread) - return false; - - if (m_allowThread != other.m_allowThread) - return false; - - if (m_version != other.m_version) - return false; - - return true; -} - -static AddedFunction::TypeInfo parseType(const QString& signature, int startPos = 0, int* endPos = 0) -{ - AddedFunction::TypeInfo result; - static const QRegularExpression regex(QLatin1String("\\w")); - Q_ASSERT(regex.isValid()); - int length = signature.length(); - int start = signature.indexOf(regex, startPos); - if (start == -1) { - if (signature.midRef(startPos + 1, 3) == QLatin1String("...")) { // varargs - if (endPos) - *endPos = startPos + 4; - result.name = QLatin1String("..."); - } else { // error - if (endPos) - *endPos = length; - } - return result; - } - - int cantStop = 0; - QString paramString; - QChar c; - int i = start; - for (; i < length; ++i) { - c = signature[i]; - if (c == QLatin1Char('<')) - cantStop++; - if (c == QLatin1Char('>')) - cantStop--; - if (cantStop < 0) - break; // FIXME: report error? - if ((c == QLatin1Char(')') || c == QLatin1Char(',')) && !cantStop) - break; - paramString += signature[i]; - } - if (endPos) - *endPos = i; - - // Check default value - if (paramString.contains(QLatin1Char('='))) { - QStringList lst = paramString.split(QLatin1Char('=')); - paramString = lst[0].trimmed(); - result.defaultValue = lst[1].trimmed(); - } - - // check constness - if (paramString.startsWith(QLatin1String("const "))) { - result.isConstant = true; - paramString.remove(0, sizeof("const")/sizeof(char)); - paramString = paramString.trimmed(); - } - // check reference - if (paramString.endsWith(QLatin1Char('&'))) { - result.isReference = true; - paramString.chop(1); - paramString = paramString.trimmed(); - } - // check Indirections - while (paramString.endsWith(QLatin1Char('*'))) { - result.indirections++; - paramString.chop(1); - paramString = paramString.trimmed(); - } - result.name = paramString; - - return result; -} - -AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : m_access(Public), m_version(vr) -{ - Q_ASSERT(!returnType.isEmpty()); - m_returnType = parseType(returnType); - signature = signature.trimmed(); - int endPos = signature.indexOf(QLatin1Char('(')); - if (endPos < 0) { - m_isConst = false; - m_name = signature; - } else { - m_name = signature.left(endPos).trimmed(); - int signatureLength = signature.length(); - while (endPos < signatureLength) { - TypeInfo arg = parseType(signature, endPos, &endPos); - if (!arg.name.isEmpty()) - m_arguments.append(arg); - // end of parameters... - if (signature[endPos] == QLatin1Char(')')) - break; - } - // is const? - m_isConst = signature.right(signatureLength - endPos).contains(QLatin1String("const")); - } -} - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "TypeInfo("; - if (ti.isConstant) - d << "const"; - if (ti.indirections) - d << QByteArray(ti.indirections, '*'); - if (ti.isReference) - d << " &"; - d << ti.name; - if (!ti.defaultValue.isEmpty()) - d << " = " << ti.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"; - return d; -} -#endif // !QT_NO_DEBUG_STREAM - -AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& signature) -{ - return parseType(signature); -} - -QString ComplexTypeEntry::targetLangApiName() const -{ - return strings_jobject; -} -QString StringTypeEntry::targetLangApiName() const -{ - return strings_jobject; -} -QString StringTypeEntry::targetLangName() const -{ - return strings_String; -} -QString StringTypeEntry::targetLangPackage() const -{ - return QString(); -} -QString CharTypeEntry::targetLangApiName() const -{ - return strings_jchar; -} -QString CharTypeEntry::targetLangName() const -{ - return strings_char; -} -QString VariantTypeEntry::targetLangApiName() const -{ - return strings_jobject; -} -QString VariantTypeEntry::targetLangName() const -{ - return strings_Object; -} -QString VariantTypeEntry::targetLangPackage() const -{ - return QString(); -} - -QString ContainerTypeEntry::typeName() const -{ - switch(m_type) { - case LinkedListContainer: - return QLatin1String("linked-list"); - case ListContainer: - return QLatin1String("list"); - case StringListContainer: - return QLatin1String("string-list"); - case VectorContainer: - return QLatin1String("vector"); - case StackContainer: - return QLatin1String("stack"); - case QueueContainer: - return QLatin1String("queue"); - case SetContainer: - return QLatin1String("set"); - case MapContainer: - return QLatin1String("map"); - case MultiMapContainer: - return QLatin1String("multi-map"); - case HashContainer: - return QLatin1String("hash"); - case MultiHashContainer: - return QLatin1String("multi-hash"); - case PairContainer: - return QLatin1String("pair"); - case NoContainer: - default: - return QLatin1String("?"); - } -} - -static bool strLess(const char* a, const char* b) -{ - return ::strcmp(a, b) < 0; -} - -bool TypeEntry::isCppPrimitive() const -{ - if (!isPrimitive()) - return false; - - const PrimitiveTypeEntry *referencedType = - static_cast(this)->basicReferencedTypeEntry(); - QByteArray typeName = (referencedType ? referencedType->name() : m_name).toUtf8(); - - if (typeName.contains(' ') || m_type == VoidType) - return true; - // Keep this sorted!! - static const char* cppTypes[] = { "bool", "char", "double", "float", "int", "long", "long long", "short", "wchar_t" }; - const int N = sizeof(cppTypes)/sizeof(char*); - - const char** res = qBinaryFind(&cppTypes[0], &cppTypes[N], typeName.constData(), strLess); - - return res != &cppTypes[N]; -} - -// Again, stuff to avoid ABI breakage. -typedef QHash TypeEntryCustomConversionMap; -Q_GLOBAL_STATIC(TypeEntryCustomConversionMap, typeEntryCustomConversionMap); - -TypeEntry::~TypeEntry() -{ - if (typeEntryCustomConversionMap()->contains(this)) { - CustomConversion* customConversion = typeEntryCustomConversionMap()->value(this); - typeEntryCustomConversionMap()->remove(this); - delete customConversion; - } -} - -bool TypeEntry::hasCustomConversion() const -{ - return typeEntryCustomConversionMap()->contains(this); -} -void TypeEntry::setCustomConversion(CustomConversion* customConversion) -{ - if (customConversion) - typeEntryCustomConversionMap()->insert(this, customConversion); - else if (typeEntryCustomConversionMap()->contains(this)) - typeEntryCustomConversionMap()->remove(this); -} -CustomConversion* TypeEntry::customConversion() const -{ - if (typeEntryCustomConversionMap()->contains(this)) - return typeEntryCustomConversionMap()->value(this); - return 0; -} - -/* -static void injectCode(ComplexTypeEntry *e, - const char *signature, - const QByteArray &code, - const ArgumentMap &args) -{ - CodeSnip snip; - snip.language = TypeSystem::NativeCode; - snip.position = CodeSnip::Beginning; - snip.addCode(QString::fromLatin1(code)); - snip.argumentMap = args; - - FunctionModification mod; - mod.signature = QMetaObject::normalizedSignature(signature); - mod.snips << snip; - mod.modifiers = Modification::CodeInjection; -} -*/ - -struct CustomConversion::CustomConversionPrivate -{ - CustomConversionPrivate(const TypeEntry* ownerType) - : ownerType(ownerType), replaceOriginalTargetToNativeConversions(false) - { - } - const TypeEntry* ownerType; - QString nativeToTargetConversion; - bool replaceOriginalTargetToNativeConversions; - TargetToNativeConversions targetToNativeConversions; -}; - -struct CustomConversion::TargetToNativeConversion::TargetToNativeConversionPrivate -{ - TargetToNativeConversionPrivate() - : sourceType(0) - { - } - const TypeEntry* sourceType; - QString sourceTypeName; - QString sourceTypeCheck; - QString conversion; -}; - -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() -{ - return m_d->targetToNativeConversions; -} - -const CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions() const -{ - return m_d->targetToNativeConversions; -} - -void CustomConversion::addTargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion) -{ - m_d->targetToNativeConversions.append(new TargetToNativeConversion(sourceTypeName, sourceTypeCheck, conversion)); -} - -CustomConversion::TargetToNativeConversion::TargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion) -{ - m_d = new TargetToNativeConversionPrivate; - m_d->sourceTypeName = sourceTypeName; - m_d->sourceTypeCheck = sourceTypeCheck; - m_d->conversion = conversion; -} - -CustomConversion::TargetToNativeConversion::~TargetToNativeConversion() -{ - delete m_d; -} - -const TypeEntry* CustomConversion::TargetToNativeConversion::sourceType() const -{ - return m_d->sourceType; -} - -void CustomConversion::TargetToNativeConversion::setSourceType(const TypeEntry* sourceType) -{ - m_d->sourceType = sourceType; -} - -bool CustomConversion::TargetToNativeConversion::isCustomType() const -{ - return !(m_d->sourceType); -} - -QString CustomConversion::TargetToNativeConversion::sourceTypeName() const -{ - return m_d->sourceTypeName; -} - -QString CustomConversion::TargetToNativeConversion::sourceTypeCheck() const -{ - return m_d->sourceTypeCheck; -} - -QString CustomConversion::TargetToNativeConversion::conversion() const -{ - return m_d->conversion; -} - -void CustomConversion::TargetToNativeConversion::setConversion(const QString& conversion) -{ - m_d->conversion = conversion; -} diff --git a/ApiExtractor/typesystem.h b/ApiExtractor/typesystem.h deleted file mode 100644 index b75da48ba..000000000 --- a/ApiExtractor/typesystem.h +++ /dev/null @@ -1,1975 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPESYSTEM_H -#define TYPESYSTEM_H - -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" -#include "include.h" - -#include -#include -#include -#include -#include -#include -#include - -//Used to identify the conversion rule to avoid break API -#define TARGET_CONVERSION_RULE_FLAG "0" -#define NATIVE_CONVERSION_RULE_FLAG "1" - -class Indentor; - -class AbstractMetaType; -QT_BEGIN_NAMESPACE -class QDebug; -class QTextStream; -QT_END_NAMESPACE - -class EnumTypeEntry; -class FlagsTypeEntry; - -typedef QMap ArgumentMap; - -class TemplateInstance; - -struct ReferenceCount -{ - ReferenceCount() {} - enum Action { // 0x01 - 0xff - Invalid = 0x00, - Add = 0x01, - AddAll = 0x02, - Remove = 0x04, - Set = 0x08, - Ignore = 0x10, - - ActionsMask = 0xff, - - Padding = 0xffffffff - }; - - Action action; - QString varName; -}; - -struct ArgumentOwner -{ - enum Action { - Invalid = 0x00, - Add = 0x01, - Remove = 0x02 - }; - enum { - InvalidIndex = -2, - ThisIndex = -1, - ReturnIndex = 0, - FirstArgumentIndex = 1 - }; - ArgumentOwner() : action(ArgumentOwner::Invalid), index(ArgumentOwner::InvalidIndex) {} - - Action action; - int index; -}; - -class CodeSnipFragment -{ -private: - QString m_code; - TemplateInstance *m_instance; - -public: - CodeSnipFragment() : m_instance(0) {} - CodeSnipFragment(const QString &code) - : m_code(code), - m_instance(0) {} - - CodeSnipFragment(TemplateInstance *instance) - : m_instance(instance) {} - - QString code() const; -}; - -class CodeSnipAbstract -{ -public: - QString code() const; - - void addCode(const QString &code) { codeList.append(CodeSnipFragment(code)); } - void addCode(const QStringRef &code) { addCode(code.toString()); } - - void addTemplateInstance(TemplateInstance *ti) - { - codeList.append(CodeSnipFragment(ti)); - } - - QVector codeList; -}; - -class CustomFunction : public CodeSnipAbstract -{ -public: - CustomFunction(const QString &n = QString()) : name(n) { } - - QString name; - QString paramName; -}; - -class TemplateEntry : public CodeSnipAbstract -{ -public: - TemplateEntry(const QString &name, double vr) - : m_name(name), m_version(vr) - { - }; - - QString name() const - { - return m_name; - }; - - double version() const - { - return m_version; - } - -private: - QString m_name; - double m_version; -}; - -class TemplateInstance -{ -public: - TemplateInstance(const QString &name, double vr) - : m_name(name), m_version(vr) {} - - void addReplaceRule(const QString &name, const QString &value) - { - replaceRules[name] = value; - } - - QString expandCode() const; - - QString name() const - { - return m_name; - } - - double version() const - { - return m_version; - } - -private: - const QString m_name; - double m_version; - QHash replaceRules; -}; - - -class CodeSnip : public CodeSnipAbstract -{ -public: - CodeSnip() : language(TypeSystem::TargetLangCode), version(0) {} - CodeSnip(double vr) : language(TypeSystem::TargetLangCode), version(vr) { } - CodeSnip(double vr, TypeSystem::Language lang) : language(lang), version(vr) { } - - TypeSystem::Language language; - TypeSystem::CodeSnipPosition position; - ArgumentMap argumentMap; - double version; -}; - -struct ArgumentModification -{ - ArgumentModification() : removedDefaultExpression(false), removed(false), - noNullPointers(false), index(-1), version(0) {} - ArgumentModification(int idx, double vr) - : removedDefaultExpression(false), removed(false), - noNullPointers(false), index(idx), version(vr) {} - - // Should the default expression be removed? - uint removedDefaultExpression : 1; - uint removed : 1; - uint noNullPointers : 1; - uint resetAfterUse : 1; - - // The index of this argument - int index; - - // Reference count flags for this argument - QVector referenceCounts; - - // The text given for the new type of the argument - QString modified_type; - - QString replace_value; - - // The code to be used to construct a return value when noNullPointers is true and - // the returned value is null. If noNullPointers is true and this string is - // empty, then the base class implementation will be used (or a default construction - // if there is no implementation) - QString nullPointerDefaultValue; - - // The text of the new default expression of the argument - QString replacedDefaultExpression; - - // The new definition of ownership for a specific argument - QHash ownerships; - - // Different conversion rules - CodeSnipList conversion_rules; - - //QObject parent(owner) of this argument - ArgumentOwner owner; - - //Api version - double version; - - //New name - QString renamed_to; -}; - -struct Modification -{ - enum Modifiers { - Private = 0x0001, - Protected = 0x0002, - Public = 0x0003, - Friendly = 0x0004, - AccessModifierMask = 0x000f, - - Final = 0x0010, - NonFinal = 0x0020, - FinalMask = Final | NonFinal, - - Readable = 0x0100, - Writable = 0x0200, - - CodeInjection = 0x1000, - Rename = 0x2000, - Deprecated = 0x4000, - ReplaceExpression = 0x8000, - VirtualSlot = 0x10000 | NonFinal - }; - - Modification() : modifiers(0), removal(TypeSystem::NoLanguage) { } - - bool isAccessModifier() const - { - return modifiers & AccessModifierMask; - } - Modifiers accessModifier() const - { - return Modifiers(modifiers & AccessModifierMask); - } - bool isPrivate() const - { - return accessModifier() == Private; - } - bool isProtected() const - { - return accessModifier() == Protected; - } - bool isPublic() const - { - return accessModifier() == Public; - } - bool isFriendly() const - { - return accessModifier() == Friendly; - } - bool isFinal() const - { - return modifiers & Final; - } - bool isNonFinal() const - { - return modifiers & NonFinal; - } - bool isVirtualSlot() const - { - return (modifiers & VirtualSlot) == VirtualSlot; - } - QString accessModifierString() const; - - bool isDeprecated() const - { - return modifiers & Deprecated; - } - - void setRenamedTo(const QString &name) - { - renamedToName = name; - } - QString renamedTo() const - { - return renamedToName; - } - bool isRenameModifier() const - { - return modifiers & Rename; - } - - bool isRemoveModifier() const - { - return removal != TypeSystem::NoLanguage; - } - - uint modifiers; - QString renamedToName; - TypeSystem::Language removal; -}; - -struct FunctionModification: public Modification -{ - FunctionModification() : m_thread(false), m_allowThread(false), m_version(0) {} - FunctionModification(double vr) : m_thread(false), m_allowThread(false), m_version(vr) {} - - bool isCodeInjection() const - { - return modifiers & CodeInjection; - } - void setIsThread(bool flag) - { - m_thread = flag; - } - bool isThread() const - { - return m_thread; - } - bool allowThread() const - { - return m_allowThread; - } - void setAllowThread(bool allow) - { - m_allowThread = allow; - } - double version() const - { - return m_version; - } - - bool operator!=(const FunctionModification& other) const; - bool operator==(const FunctionModification& other) const; - - - QString toString() const; - - QString signature; - QString association; - CodeSnipList snips; - - QVector argument_mods; - -private: - bool m_thread; - bool m_allowThread; - double m_version; - - -}; - -struct FieldModification: public Modification -{ - bool isReadable() const - { - return modifiers & Readable; - } - bool isWritable() const - { - return modifiers & Writable; - } - - QString name; -}; - -/** -* \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 -{ - /// Function access types. - enum Access { - Protected = 0x1, - Public = 0x2 - }; - - /** - * \internal - * Internal struct used to store information about arguments and return type of the - * functions added by the type system. This information is later used to create - * AbstractMetaType and AbstractMetaArgument for the AbstractMetaFunctions. - */ - struct TypeInfo { - TypeInfo() : isConstant(false), indirections(0), isReference(false) {} - static TypeInfo fromSignature(const QString& signature); - - QString name; - bool isConstant; - int indirections; - bool isReference; - QString defaultValue; - }; - - /// Creates a new AddedFunction with a signature and a return type. - AddedFunction(QString signature, QString returnType, double vr); - AddedFunction() : m_access(Protected), m_isConst(false), m_isStatic(false), m_version(0) {} - - /// 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. - QVector arguments() const - { - return m_arguments; - } - - /// Returns true if this is a constant method. - bool isConstant() const - { - return m_isConst; - } - - /// Set this method static. - void setStatic(bool value) - { - m_isStatic = value; - } - - /// Returns true if this is a static method. - bool isStatic() const - { - return m_isStatic; - } - - double version() const - { - return m_version; - } -private: - QString m_name; - Access m_access; - QVector m_arguments; - TypeInfo m_returnType; - bool m_isConst; - bool m_isStatic; - double m_version; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti); -QDebug operator<<(QDebug d, const AddedFunction &af); -#endif - -struct ExpensePolicy -{ - ExpensePolicy() : limit(-1) {} - int limit; - QString cost; - bool isValid() const - { - return limit >= 0; - } -}; - -class InterfaceTypeEntry; -class ObjectTypeEntry; - -class DocModification -{ -public: - DocModification() : format(TypeSystem::NativeCode), m_mode(TypeSystem::DocModificationXPathReplace), m_version(0) {} - DocModification(const QString& xpath, const QString& signature, double vr) - : format(TypeSystem::NativeCode), m_mode(TypeSystem::DocModificationXPathReplace), - m_xpath(xpath), m_signature(signature), m_version(vr) {} - DocModification(TypeSystem::DocModificationMode mode, const QString& signature, double vr) - : m_mode(mode), m_signature(signature), m_version(vr) {} - - void setCode(const QString& code) { m_code = code; } - void setCode(const QStringRef& code) { m_code = code.toString(); } - - QString code() const - { - return m_code; - } - QString xpath() const - { - return m_xpath; - } - QString signature() const - { - return m_signature; - } - TypeSystem::DocModificationMode mode() const - { - return m_mode; - } - double version() const - { - return m_version; - } - - TypeSystem::Language format; - -private: - TypeSystem::DocModificationMode m_mode; - QString m_code; - QString m_xpath; - QString m_signature; - double m_version; -}; - -class CustomConversion; - -class TypeEntry -{ - Q_GADGET -public: - enum Type { - PrimitiveType, - VoidType, - VarargsType, - FlagsType, - EnumType, - EnumValue, - TemplateArgumentType, - ThreadType, - BasicValueType, - StringType, - ContainerType, - InterfaceType, - ObjectType, - NamespaceType, - VariantType, - JObjectWrapperType, - CharType, - ArrayType, - TypeSystemType, - CustomType, - TargetLangType, - FunctionType, - SmartPointerType - }; - Q_ENUM(Type) - - enum CodeGeneration { - GenerateTargetLang = 0x0001, - GenerateCpp = 0x0002, - GenerateForSubclass = 0x0004, - - GenerateNothing = 0, - GenerateAll = 0xffff, - GenerateCode = GenerateTargetLang | GenerateCpp - }; - Q_ENUM(CodeGeneration) - - TypeEntry(const QString &name, Type t, double vr) - : m_name(name), - m_type(t), - m_codeGeneration(GenerateAll), - m_preferredConversion(true), - m_stream(false), - m_version(vr) - { - }; - - virtual ~TypeEntry(); - - Type type() const - { - return m_type; - } - bool isPrimitive() const - { - return m_type == PrimitiveType; - } - bool isEnum() const - { - return m_type == EnumType; - } - bool isFlags() const - { - return m_type == FlagsType; - } - bool isInterface() const - { - return m_type == InterfaceType; - } - bool isObject() const - { - return m_type == ObjectType; - } - bool isString() const - { - return m_type == StringType; - } - bool isChar() const - { - return m_type == CharType; - } - bool isNamespace() const - { - return m_type == NamespaceType; - } - bool isContainer() const - { - return m_type == ContainerType; - } - bool isSmartPointer() const - { - return m_type == SmartPointerType; - } - bool isVariant() const - { - return m_type == VariantType; - } - bool isJObjectWrapper() const - { - return m_type == JObjectWrapperType; - } - bool isArray() const - { - return m_type == ArrayType; - } - bool isTemplateArgument() const - { - return m_type == TemplateArgumentType; - } - bool isVoid() const - { - return m_type == VoidType; - } - bool isVarargs() const - { - return m_type == VarargsType; - } - bool isThread() const - { - return m_type == ThreadType; - } - bool isCustom() const - { - return m_type == CustomType; - } - bool isBasicValue() const - { - return m_type == BasicValueType; - } - bool isTypeSystem() const - { - return m_type == TypeSystemType; - } - bool isFunction() const - { - return m_type == FunctionType; - } - bool isEnumValue() const - { - return m_type == EnumValue; - } - - virtual bool preferredConversion() const - { - return m_preferredConversion; - } - virtual void setPreferredConversion(bool b) - { - m_preferredConversion = b; - } - - bool stream() const - { - return m_stream; - } - - void setStream(bool b) - { - m_stream = b; - } - - // The type's name in C++, fully qualified - QString name() const - { - return m_name; - } - - uint codeGeneration() const - { - return m_codeGeneration; - } - void setCodeGeneration(uint cg) - { - m_codeGeneration = cg; - } - - // Returns true if code must be generated for this entry, - // it will return false in case of types coming from typesystems - // included for reference only. - // NOTE: 'GenerateForSubclass' means 'generate="no"' - // on 'load-typesystem' tag - inline bool generateCode() const - { - return m_codeGeneration != TypeEntry::GenerateForSubclass - && m_codeGeneration != TypeEntry::GenerateNothing; - } - - virtual QString qualifiedCppName() const - { - return m_name; - } - - /** - * Its type's name in target language API - * The target language API name represents how this type is - * referred on low level code for the target language. - * Examples: for Java this would be a JNI name, for Python - * it should represent the CPython type name. - * /return string representing the target language API name - * for this type entry - */ - virtual QString targetLangApiName() const - { - return m_name; - } - - // The type's name in TargetLang - virtual QString targetLangName() const - { - return m_name; - } - - // The type to lookup when converting to TargetLang - virtual QString lookupName() const - { - return targetLangName(); - } - - // The package - virtual QString targetLangPackage() const - { - return QString(); - } - - virtual QString qualifiedTargetLangName() const - { - QString pkg = targetLangPackage(); - if (pkg.isEmpty()) - return targetLangName(); - return pkg + QLatin1Char('.') + targetLangName(); - } - - virtual InterfaceTypeEntry *designatedInterface() const - { - return 0; - } - - void setCustomConstructor(const CustomFunction &func) - { - m_customConstructor = func; - } - CustomFunction customConstructor() const - { - return m_customConstructor; - } - - void setCustomDestructor(const CustomFunction &func) - { - m_customDestructor = func; - } - CustomFunction customDestructor() const - { - return m_customDestructor; - } - - virtual bool isValue() const - { - return false; - } - virtual bool isComplex() const - { - return false; - } - - virtual bool isNativeIdBased() const - { - return false; - } - - CodeSnipList codeSnips() const; - void setCodeSnips(const CodeSnipList &codeSnips) - { - m_codeSnips = codeSnips; - } - void addCodeSnip(const CodeSnip &codeSnip) - { - m_codeSnips << codeSnip; - } - - void setDocModification(const DocModificationList& docMods) - { - m_docModifications << docMods; - } - DocModificationList docModifications() const - { - return m_docModifications; - } - - IncludeList extraIncludes() const - { - return m_extraIncludes; - } - void setExtraIncludes(const IncludeList &includes) - { - m_extraIncludes = includes; - } - void addExtraInclude(const Include &include) - { - if (!m_includesUsed.value(include.name(), false)) { - m_extraIncludes << include; - m_includesUsed[include.name()] = true; - } - } - - Include include() const - { - return m_include; - } - void setInclude(const Include &inc) - { - // This is a workaround for preventing double inclusion of the QSharedPointer implementation - // header, which does not use header guards. In the previous parser this was not a problem - // because the Q_QDOC define was set, and the implementation header was never included. - if (inc.name() == QLatin1String("qsharedpointer_impl.h")) - m_include = Include(inc.type(), QLatin1String("qsharedpointer.h")); - else - m_include = inc; - } - - // Replace conversionRule arg to CodeSnip in future version - /// Set the type convertion rule - void setConversionRule(const QString& conversionRule) - { - m_conversionRule = conversionRule; - } - - /// Returns the type convertion rule - QString conversionRule() const - { - //skip conversions flag - return m_conversionRule.mid(1); - } - - /// Returns true if there are any conversiton rule for this type, false otherwise. - bool hasConversionRule() const - { - return !m_conversionRule.isEmpty(); - } - - double version() const - { - return m_version; - } - - /// TODO-CONVERTER: mark as deprecated - bool hasNativeConversionRule() const - { - return m_conversionRule.startsWith(QLatin1String(NATIVE_CONVERSION_RULE_FLAG)); - } - - /// TODO-CONVERTER: mark as deprecated - bool hasTargetConversionRule() const - { - return m_conversionRule.startsWith(QLatin1String(TARGET_CONVERSION_RULE_FLAG)); - } - - bool isCppPrimitive() const; - - bool hasCustomConversion() const; - void setCustomConversion(CustomConversion* customConversion); - CustomConversion* customConversion() const; -private: - QString m_name; - Type m_type; - uint m_codeGeneration; - CustomFunction m_customConstructor; - CustomFunction m_customDestructor; - bool m_preferredConversion; - CodeSnipList m_codeSnips; - DocModificationList m_docModifications; - IncludeList m_extraIncludes; - Include m_include; - QHash m_includesUsed; - QString m_conversionRule; - bool m_stream; - double m_version; -}; - -class TypeSystemTypeEntry : public TypeEntry -{ -public: - TypeSystemTypeEntry(const QString &name, double vr) - : TypeEntry(name, TypeSystemType, vr) - { - }; -}; - -class VoidTypeEntry : public TypeEntry -{ -public: - VoidTypeEntry() : TypeEntry(QLatin1String("void"), VoidType, 0) { } -}; - -class VarargsTypeEntry : public TypeEntry -{ -public: - VarargsTypeEntry() : TypeEntry(QLatin1String("..."), VarargsType, 0) { } -}; - -class TemplateArgumentEntry : public TypeEntry -{ -public: - TemplateArgumentEntry(const QString &name, double vr) - : TypeEntry(name, TemplateArgumentType, vr), m_ordinal(0) - { - } - - int ordinal() const - { - return m_ordinal; - } - void setOrdinal(int o) - { - m_ordinal = o; - } - -private: - int m_ordinal; -}; - -class ArrayTypeEntry : public TypeEntry -{ -public: - ArrayTypeEntry(const TypeEntry *nested_type, double vr) - : TypeEntry(QLatin1String("Array"), ArrayType, vr), m_nestedType(nested_type) - { - Q_ASSERT(m_nestedType); - } - - void setNestedTypeEntry(TypeEntry *nested) - { - m_nestedType = nested; - } - const TypeEntry *nestedTypeEntry() const - { - return m_nestedType; - } - - QString targetLangName() const override - { - return m_nestedType->targetLangName() + QLatin1String("[]"); - } - QString targetLangApiName() const override - { - if (m_nestedType->isPrimitive()) - return m_nestedType->targetLangApiName() + QLatin1String("Array"); - else - return QLatin1String("jobjectArray"); - } - -private: - const TypeEntry *m_nestedType; -}; - - -class PrimitiveTypeEntry : public TypeEntry -{ -public: - PrimitiveTypeEntry(const QString &name, double vr) - : TypeEntry(name, PrimitiveType, vr), - m_preferredConversion(true), - m_preferredTargetLangType(true), - m_referencedTypeEntry(0) - { - } - - QString targetLangName() const override - { - return m_targetLangName; - } - void setTargetLangName(const QString &targetLangName) - { - m_targetLangName = targetLangName; - } - - QString targetLangApiName() const override - { - return m_targetLangApiName; - } - void setTargetLangApiName(const QString &targetLangApiName) - { - m_targetLangApiName = targetLangApiName; - } - - QString defaultConstructor() const - { - return m_defaultConstructor; - } - void setDefaultConstructor(const QString& defaultConstructor) - { - m_defaultConstructor = defaultConstructor; - } - bool hasDefaultConstructor() const - { - return !m_defaultConstructor.isEmpty(); - } - - /** - * The PrimitiveTypeEntry pointed by this type entry if it - * represents a typedef). - * /return the type referenced by the typedef, or a null pointer - * if the current object is not an typedef - */ - PrimitiveTypeEntry* referencedTypeEntry() const { return m_referencedTypeEntry; } - - /** - * Defines type referenced by this entry. - * /param referencedTypeEntry type referenced by this entry - */ - void setReferencedTypeEntry(PrimitiveTypeEntry* referencedTypeEntry) - { - m_referencedTypeEntry = 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 - */ - PrimitiveTypeEntry* basicReferencedTypeEntry() const; - - bool preferredConversion() const override - { - return m_preferredConversion; - } - void setPreferredConversion(bool b) override - { - m_preferredConversion = b; - } - - bool preferredTargetLangType() const - { - return m_preferredTargetLangType; - } - void setPreferredTargetLangType(bool b) - { - m_preferredTargetLangType = b; - } - - void setTargetLangPackage(const QString& package); - QString targetLangPackage() const override; -private: - QString m_targetLangName; - QString m_targetLangApiName; - QString m_defaultConstructor; - uint m_preferredConversion : 1; - uint m_preferredTargetLangType : 1; - PrimitiveTypeEntry* m_referencedTypeEntry; -}; - -struct EnumValueRedirection -{ - EnumValueRedirection() {} - EnumValueRedirection(const QString &rej, const QString &us) - : rejected(rej), - used(us) - { - } - QString rejected; - QString used; -}; - -class EnumTypeEntry : public TypeEntry -{ -public: - EnumTypeEntry(const QString &nspace, const QString &enumName, double vr) - : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, - EnumType, vr), - m_qualifier(nspace), - m_targetLangName(enumName), - m_flags(0), - m_extensible(false), - m_forceInteger(false), - m_anonymous(false) - { - } - - QString targetLangPackage() const - { - return m_packageName; - } - void setTargetLangPackage(const QString &package) - { - m_packageName = package; - } - - QString targetLangName() const - { - return m_targetLangName; - } - QString targetLangQualifier() const; - QString qualifiedTargetLangName() const override - { - QString qualifiedName; - QString pkg = targetLangPackage(); - QString qualifier = targetLangQualifier(); - - if (!pkg.isEmpty()) - qualifiedName += pkg + QLatin1Char('.'); - if (!qualifier.isEmpty()) - qualifiedName += qualifier + QLatin1Char('.'); - qualifiedName += targetLangName(); - - return qualifiedName; - } - - QString targetLangApiName() const override; - - QString qualifier() const - { - return m_qualifier; - } - void setQualifier(const QString &q) - { - m_qualifier = q; - } - - bool preferredConversion() const override - { - return false; - } - - bool isBoundsChecked() const - { - return m_lowerBound.isEmpty() && m_upperBound.isEmpty(); - } - - QString upperBound() const - { - return m_upperBound; - } - void setUpperBound(const QString &bound) - { - m_upperBound = bound; - } - - QString lowerBound() const - { - return m_lowerBound; - } - void setLowerBound(const QString &bound) - { - m_lowerBound = bound; - } - - void setFlags(FlagsTypeEntry *flags) - { - m_flags = flags; - } - FlagsTypeEntry *flags() const - { - return m_flags; - } - - bool isExtensible() const - { - return m_extensible; - } - void setExtensible(bool is) - { - m_extensible = is; - } - - bool isEnumValueRejected(const QString &name) - { - return m_rejectedEnums.contains(name); - } - void addEnumValueRejection(const QString &name) - { - m_rejectedEnums << name; - } - QStringList enumValueRejections() const - { - return m_rejectedEnums; - } - - void addEnumValueRedirection(const QString &rejected, const QString &usedValue); - QString enumValueRedirection(const QString &value) const; - - bool forceInteger() const - { - return m_forceInteger; - } - void setForceInteger(bool force) - { - m_forceInteger = force; - } - - bool isAnonymous() const - { - return m_anonymous; - } - void setAnonymous(bool anonymous) - { - m_anonymous = anonymous; - } - -private: - QString m_packageName; - QString m_qualifier; - QString m_targetLangName; - - QString m_lowerBound; - QString m_upperBound; - - QStringList m_rejectedEnums; - QVector m_enumRedirections; - - FlagsTypeEntry *m_flags; - - bool m_extensible; - bool m_forceInteger; - bool m_anonymous; -}; - -class EnumValueTypeEntry : public TypeEntry -{ -public: - EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr) - : TypeEntry(name, TypeEntry::EnumValue, vr), m_value(value), m_enclosingEnum(enclosingEnum) - { - } - - QString value() const { return m_value; } - const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } -private: - QString m_value; - const EnumTypeEntry* m_enclosingEnum; -}; - -class FlagsTypeEntry : public TypeEntry -{ -public: - FlagsTypeEntry(const QString &name, double vr) : TypeEntry(name, FlagsType, vr), m_enum(0) - { - } - - QString qualifiedTargetLangName() const override; - QString targetLangName() const override - { - return m_targetLangName; - } - QString targetLangApiName() const override; - bool preferredConversion() const override - { - return false; - } - - QString originalName() const - { - return m_originalName; - } - void setOriginalName(const QString &s) - { - m_originalName = s; - } - - QString flagsName() const - { - return m_targetLangName; - } - void setFlagsName(const QString &name) - { - m_targetLangName = name; - } - - bool forceInteger() const - { - return m_enum->forceInteger(); - } - - EnumTypeEntry *originator() const - { - return m_enum; - } - void setOriginator(EnumTypeEntry *e) - { - m_enum = e; - } - - QString targetLangPackage() const override - { - return m_enum->targetLangPackage(); - } - -private: - QString m_originalName; - QString m_targetLangName; - EnumTypeEntry *m_enum; -}; - - -class ComplexTypeEntry : public TypeEntry -{ -public: - enum TypeFlag { - ForceAbstract = 0x1, - DeleteInMainThread = 0x2, - Deprecated = 0x4 - }; - typedef QFlags TypeFlags; - - enum CopyableFlag { - CopyableSet, - NonCopyableSet, - Unknown - }; - - ComplexTypeEntry(const QString &name, Type t, double vr) - : TypeEntry(QString(name).replace(QLatin1String(".*::"), QString()), t, vr), - m_qualifiedCppName(name), - m_qobject(false), - m_polymorphicBase(false), - m_genericClass(false), - m_typeFlags(0), - m_copyableFlag(Unknown), - m_baseContainerType(0) - { - } - - bool isComplex() const - { - return true; - } - - ComplexTypeEntry *copy() const - { - ComplexTypeEntry *centry = new ComplexTypeEntry(name(), type(), version()); - centry->setInclude(include()); - centry->setExtraIncludes(extraIncludes()); - centry->setAddedFunctions(addedFunctions()); - centry->setFunctionModifications(functionModifications()); - centry->setFieldModifications(fieldModifications()); - centry->setQObject(isQObject()); - centry->setDefaultSuperclass(defaultSuperclass()); - centry->setCodeSnips(codeSnips()); - centry->setTargetLangPackage(targetLangPackage()); - centry->setBaseContainerType(baseContainerType()); - centry->setDefaultConstructor(defaultConstructor()); - - return centry; - } - - void setLookupName(const QString &name) - { - m_lookupName = name; - } - - QString lookupName() const override - { - return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; - } - - QString targetLangApiName() const override; - - void setTypeFlags(TypeFlags flags) - { - m_typeFlags = flags; - } - - TypeFlags typeFlags() const - { - return m_typeFlags; - } - - FunctionModificationList functionModifications() const - { - return m_functionMods; - } - void setFunctionModifications(const FunctionModificationList &functionModifications) - { - m_functionMods = functionModifications; - } - void addFunctionModification(const FunctionModification &functionModification) - { - m_functionMods << functionModification; - } - FunctionModificationList functionModifications(const QString &signature) const; - - AddedFunctionList addedFunctions() const - { - return m_addedFunctions; - } - void setAddedFunctions(const AddedFunctionList &addedFunctions) - { - m_addedFunctions = addedFunctions; - } - void addNewFunction(const AddedFunction &addedFunction) - { - m_addedFunctions << addedFunction; - } - - FieldModification fieldModification(const QString &name) const; - void setFieldModifications(const FieldModificationList &mods) - { - m_fieldMods = mods; - } - FieldModificationList fieldModifications() const - { - return m_fieldMods; - } - - QString targetLangPackage() const - { - return m_package; - } - void setTargetLangPackage(const QString &package) - { - m_package = package; - } - - bool isQObject() const - { - return m_qobject; - } - void setQObject(bool qobject) - { - m_qobject = qobject; - } - - QString defaultSuperclass() const - { - return m_defaultSuperclass; - } - void setDefaultSuperclass(const QString &sc) - { - m_defaultSuperclass = sc; - } - - QString qualifiedCppName() const override - { - return m_qualifiedCppName; - } - - - void setIsPolymorphicBase(bool on) - { - m_polymorphicBase = on; - } - bool isPolymorphicBase() const - { - return m_polymorphicBase; - } - - void setPolymorphicIdValue(const QString &value) - { - m_polymorphicIdValue = value; - } - QString polymorphicIdValue() const - { - return m_polymorphicIdValue; - } - - void setHeldType(const QString &value) - { - m_heldTypeValue = value; - } - QString heldTypeValue() const - { - return m_heldTypeValue; - } - - - void setExpensePolicy(const ExpensePolicy &policy) - { - m_expensePolicy = policy; - } - const ExpensePolicy &expensePolicy() const - { - return m_expensePolicy; - } - - QString targetType() const - { - return m_targetType; - } - void setTargetType(const QString &code) - { - m_targetType = code; - } - - QString targetLangName() const override - { - return m_targetLangName.isEmpty() - ? TypeEntry::targetLangName() - : m_targetLangName; - } - void setTargetLangName(const QString &name) - { - m_targetLangName = name; - } - - bool isGenericClass() const - { - return m_genericClass; - } - void setGenericClass(bool isGeneric) - { - m_genericClass = isGeneric; - } - - CopyableFlag copyable() const - { - return m_copyableFlag; - } - void setCopyable(CopyableFlag flag) - { - m_copyableFlag = flag; - } - - QString hashFunction() const - { - return m_hashFunction; - } - void setHashFunction(QString hashFunction) - { - m_hashFunction = hashFunction; - } - - void setBaseContainerType(const ComplexTypeEntry *baseContainer) - { - m_baseContainerType = baseContainer; - } - - const ComplexTypeEntry* baseContainerType() const - { - return m_baseContainerType; - } - - QString defaultConstructor() const; - void setDefaultConstructor(const QString& defaultConstructor); - bool hasDefaultConstructor() const; - -private: - AddedFunctionList m_addedFunctions; - FunctionModificationList m_functionMods; - FieldModificationList m_fieldMods; - QString m_package; - QString m_defaultSuperclass; - QString m_qualifiedCppName; - QString m_targetLangName; - - uint m_qobject : 1; - uint m_polymorphicBase : 1; - uint m_genericClass : 1; - - QString m_polymorphicIdValue; - QString m_heldTypeValue; - QString m_lookupName; - QString m_targetType; - ExpensePolicy m_expensePolicy; - TypeFlags m_typeFlags; - CopyableFlag m_copyableFlag; - QString m_hashFunction; - - const ComplexTypeEntry* m_baseContainerType; -}; - -class ContainerTypeEntry : public ComplexTypeEntry -{ - Q_GADGET -public: - enum Type { - NoContainer, - ListContainer, - StringListContainer, - LinkedListContainer, - VectorContainer, - StackContainer, - QueueContainer, - SetContainer, - MapContainer, - MultiMapContainer, - HashContainer, - MultiHashContainer, - PairContainer, - }; - Q_ENUM(Type) - - ContainerTypeEntry(const QString &name, Type type, double vr) - : ComplexTypeEntry(name, ContainerType, vr), m_type(type) - { - setCodeGeneration(GenerateForSubclass); - } - - Type type() const - { - return m_type; - } - - QString typeName() const; - QString targetLangName() const; - QString targetLangPackage() const; - QString qualifiedCppName() const; - - static Type containerTypeFromString(QString typeName) - { - static QHash m_stringToContainerType; - if (m_stringToContainerType.isEmpty()) { - m_stringToContainerType.insert(QLatin1String("list"), ListContainer); - m_stringToContainerType.insert(QLatin1String("string-list"), StringListContainer); - m_stringToContainerType.insert(QLatin1String("linked-list"), LinkedListContainer); - m_stringToContainerType.insert(QLatin1String("vector"), VectorContainer); - m_stringToContainerType.insert(QLatin1String("stack"), StackContainer); - m_stringToContainerType.insert(QLatin1String("queue"), QueueContainer); - m_stringToContainerType.insert(QLatin1String("set"), SetContainer); - m_stringToContainerType.insert(QLatin1String("map"), MapContainer); - m_stringToContainerType.insert(QLatin1String("multi-map"), MultiMapContainer); - m_stringToContainerType.insert(QLatin1String("hash"), HashContainer); - m_stringToContainerType.insert(QLatin1String("multi-hash"), MultiHashContainer); - m_stringToContainerType.insert(QLatin1String("pair"), PairContainer); - } - return m_stringToContainerType.value(typeName, NoContainer); - } - -private: - Type m_type; -}; - -class SmartPointerTypeEntry : public ComplexTypeEntry -{ -public: - SmartPointerTypeEntry(const QString &name, - const QString &getterName, - const QString &smartPointerType, - const QString &refCountMethodName, - double vr) - : ComplexTypeEntry(name, SmartPointerType, vr), - m_getterName(getterName), - m_smartPointerType(smartPointerType), - m_refCountMethodName(refCountMethodName) - { - } - - QString getter() const - { - return m_getterName; - } - - QString refCountMethodName() const - { - return m_refCountMethodName; - } - -private: - QString m_getterName; - QString m_smartPointerType; - QString m_refCountMethodName; -}; - -class NamespaceTypeEntry : public ComplexTypeEntry -{ -public: - NamespaceTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, NamespaceType, vr) { } -}; - - -class ValueTypeEntry : public ComplexTypeEntry -{ -public: - ValueTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, BasicValueType, vr) { } - - bool isValue() const override - { - return true; - } - - bool isNativeIdBased() const override - { - return true; - } - -protected: - ValueTypeEntry(const QString &name, Type t, double vr) : ComplexTypeEntry(name, t, vr) { } -}; - - -class StringTypeEntry : public ValueTypeEntry -{ -public: - StringTypeEntry(const QString &name, double vr) - : ValueTypeEntry(name, StringType, vr) - { - setCodeGeneration(GenerateNothing); - } - - QString targetLangApiName() const override; - QString targetLangName() const override; - QString targetLangPackage() const override; - - bool isNativeIdBased() const override - { - return false; - } -}; - -class CharTypeEntry : public ValueTypeEntry -{ -public: - CharTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, CharType, vr) - { - setCodeGeneration(GenerateNothing); - } - - QString targetLangApiName() const override; - QString targetLangName() const override; - QString targetLangPackage() const override - { - return QString(); - } - - bool isNativeIdBased() const override - { - return false; - } -}; - -class VariantTypeEntry: public ValueTypeEntry -{ -public: - VariantTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, VariantType, vr) { } - - QString targetLangApiName() const override; - QString targetLangName() const override; - QString targetLangPackage() const override; - - bool isNativeIdBased() const override - { - return false; - } -}; - - -class InterfaceTypeEntry : public ComplexTypeEntry -{ -public: - InterfaceTypeEntry(const QString &name, double vr) - : ComplexTypeEntry(name, InterfaceType, vr) {} - - static QString interfaceName(const QString &name) - { - return name + QLatin1String("Interface"); - } - - ObjectTypeEntry *origin() const - { - return m_origin; - } - void setOrigin(ObjectTypeEntry *origin) - { - m_origin = origin; - } - - bool isNativeIdBased() const override - { - return true; - } - QString qualifiedCppName() const override - { - const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); - return ComplexTypeEntry::qualifiedCppName().left(len); - } - -private: - ObjectTypeEntry *m_origin; -}; - - -class FunctionTypeEntry : public TypeEntry -{ -public: - FunctionTypeEntry(const QString& name, const QString& signature, double vr) - : TypeEntry(name, FunctionType, vr) - { - addSignature(signature); - } - void addSignature(const QString& signature) - { - m_signatures << signature; - } - - QStringList signatures() const - { - return m_signatures; - } - - bool hasSignature(const QString& signature) const - { - return m_signatures.contains(signature); - } -private: - QStringList m_signatures; -}; - -class ObjectTypeEntry : public ComplexTypeEntry -{ -public: - ObjectTypeEntry(const QString &name, double vr) - : ComplexTypeEntry(name, ObjectType, vr), m_interface(0) {} - - InterfaceTypeEntry *designatedInterface() const - { - return m_interface; - } - void setDesignatedInterface(InterfaceTypeEntry *entry) - { - m_interface = entry; - } - - bool isNativeIdBased() const override - { - return true; - } - -private: - InterfaceTypeEntry *m_interface; -}; - -struct TypeRejection -{ - enum MatchType - { - ExcludeClass, // Match className only - Function, // Match className and function name - Field, // Match className and field name - Enum, // Match className and enum name - ArgumentType, // Match className and argument type - ReturnType // Match className and return type - }; - - QRegularExpression className; - QRegularExpression pattern; - MatchType matchType; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug d, const TypeRejection &r); -#endif - -QString fixCppTypeName(const QString &name); - -class CustomConversion -{ -public: - CustomConversion(TypeEntry* ownerType); - ~CustomConversion(); - - const TypeEntry* 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. - */ - bool replaceOriginalTargetToNativeConversions() const; - void setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions); - - typedef QVector TargetToNativeConversions; - bool hasTargetToNativeConversions() const; - TargetToNativeConversions& targetToNativeConversions(); - const TargetToNativeConversions& targetToNativeConversions() const; - void addTargetToNativeConversion(const QString& sourceTypeName, - const QString& sourceTypeCheck, - const QString& conversion = QString()); -private: - struct CustomConversionPrivate; - CustomConversionPrivate* m_d; -}; - -#endif // TYPESYSTEM_H diff --git a/ApiExtractor/typesystem_enums.h b/ApiExtractor/typesystem_enums.h deleted file mode 100644 index 2d67d7cc5..000000000 --- a/ApiExtractor/typesystem_enums.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPESYSTEM_ENUMS_H -#define TYPESYSTEM_ENUMS_H - -namespace TypeSystem -{ -enum Language { - NoLanguage = 0x0000, - TargetLangCode = 0x0001, - NativeCode = 0x0002, - ShellCode = 0x0004, - ShellDeclaration = 0x0008, - PackageInitializer = 0x0010, - DestructorFunction = 0x0020, - Constructors = 0x0040, - Interface = 0x0080, - - // masks - All = TargetLangCode - | NativeCode - | ShellCode - | ShellDeclaration - | PackageInitializer - | Constructors - | Interface - | DestructorFunction, - - TargetLangAndNativeCode = TargetLangCode | NativeCode -}; - -enum Ownership { - InvalidOwnership, - DefaultOwnership, - TargetLangOwnership, - CppOwnership -}; - -enum CodeSnipPosition { - CodeSnipPositionBeginning, - CodeSnipPositionEnd, - CodeSnipPositionAfterThis, - // QtScript - CodeSnipPositionDeclaration, - CodeSnipPositionPrototypeInitialization, - CodeSnipPositionConstructorInitialization, - CodeSnipPositionConstructor, - CodeSnipPositionAny -}; - -enum DocModificationMode { - DocModificationAppend, - DocModificationPrepend, - DocModificationReplace, - DocModificationXPathReplace -}; - -} // namespace TypeSystem - -#endif // TYPESYSTEM_ENUMS_H diff --git a/ApiExtractor/typesystem_p.h b/ApiExtractor/typesystem_p.h deleted file mode 100644 index f2105a631..000000000 --- a/ApiExtractor/typesystem_p.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef TYPESYSTEM_P_H -#define TYPESYSTEM_P_H - -#include -#include "typesystem.h" - -QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) -QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) - -class TypeDatabase; -class StackElement -{ - public: - enum ElementType { - None = 0x0, - - // Type tags (0x1, ... , 0xff) - ObjectTypeEntry = 0x1, - ValueTypeEntry = 0x2, - InterfaceTypeEntry = 0x3, - NamespaceTypeEntry = 0x4, - ComplexTypeEntryMask = 0x7, - - // Non-complex type tags (0x8, 0x9, ... , 0xf) - PrimitiveTypeEntry = 0x8, - EnumTypeEntry = 0x9, - ContainerTypeEntry = 0xa, - FunctionTypeEntry = 0xb, - CustomTypeEntry = 0xc, - SmartPointerTypeEntry = 0xd, - TypeEntryMask = 0xf, - - // Documentation tags - InjectDocumentation = 0x10, - ModifyDocumentation = 0x20, - DocumentationMask = 0xf0, - - // Simple tags (0x100, 0x200, ... , 0xf00) - ExtraIncludes = 0x0100, - Include = 0x0200, - ModifyFunction = 0x0300, - ModifyField = 0x0400, - Root = 0x0500, - CustomMetaConstructor = 0x0600, - CustomMetaDestructor = 0x0700, - ArgumentMap = 0x0800, - SuppressedWarning = 0x0900, - Rejection = 0x0a00, - LoadTypesystem = 0x0b00, - RejectEnumValue = 0x0c00, - Template = 0x0d00, - TemplateInstanceEnum = 0x0e00, - Replace = 0x0f00, - AddFunction = 0x1000, - NativeToTarget = 0x1100, - TargetToNative = 0x1200, - AddConversion = 0x1300, - SimpleMask = 0x3f00, - - // Code snip tags (0x1000, 0x2000, ... , 0xf000) - InjectCode = 0x4000, - InjectCodeInFunction = 0x8000, - CodeSnipMask = 0xc000, - - // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) - Access = 0x010000, - Removal = 0x020000, - Rename = 0x040000, - ModifyArgument = 0x080000, - Thread = 0x100000, - FunctionModifiers = 0xff0000, - - // Argument modifier tags (0x01000000 ... 0xf0000000) - ConversionRule = 0x01000000, - ReplaceType = 0x02000000, - ReplaceDefaultExpression = 0x04000000, - RemoveArgument = 0x08000000, - DefineOwnership = 0x10000000, - RemoveDefaultExpression = 0x20000000, - NoNullPointers = 0x40000000, - ReferenceCount = 0x80000000, - ParentOwner = 0x90000000, - ArgumentModifiers = 0xff000000 - }; - - StackElement(StackElement *p) : entry(0), type(None), parent(p) { } - - TypeEntry* entry; - ElementType type; - StackElement *parent; - - union { - TemplateInstance* templateInstance; - TemplateEntry* templateEntry; - CustomFunction* customFunction; - } value; -}; - -struct StackElementContext -{ - CodeSnipList codeSnips; - AddedFunctionList addedFunctions; - FunctionModificationList functionMods; - FieldModificationList fieldMods; - DocModificationList docModifications; -}; - -class Handler -{ -public: - Handler(TypeDatabase* database, bool generate); - - bool parse(QXmlStreamReader &reader); - -private: - bool startElement(const QStringRef& localName, const QXmlStreamAttributes& atts); - bool handleSmartPointerEntry(StackElement *element, - QHash &attributes, - const QString &name, - double since); - bool endElement(const QStringRef& localName); - template // QString/QStringRef - bool characters(const String &ch); - void fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts, - QHash *acceptedAttributes); - - bool importFileElement(const QXmlStreamAttributes &atts); - bool convertBoolean(const QString &, const QString &, bool); - void addFlags(const QString &name, QString flagName, - const QHash &attributes, double since); - - TypeDatabase* m_database; - StackElement* m_current; - StackElement* m_currentDroppedEntry; - int m_currentDroppedEntryDepth; - int m_ignoreDepth; - QString m_defaultPackage; - QString m_defaultSuperclass; - QString m_error; - TypeEntry::CodeGeneration m_generate; - - EnumTypeEntry* m_currentEnum; - QStack m_contextStack; - - QHash tagNames; - QString m_currentSignature; -}; - -#endif diff --git a/ApiExtractor/typesystem_typedefs.h b/ApiExtractor/typesystem_typedefs.h deleted file mode 100644 index 4f29deced..000000000 --- a/ApiExtractor/typesystem_typedefs.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPESYSTEM_TYPEDEFS_H -#define TYPESYSTEM_TYPEDEFS_H - -#include -#include -#include - -class CodeSnip; -class DocModification; - -struct AddedFunction; -struct FieldModification; -struct FunctionModification; - -typedef QVector AddedFunctionList; -typedef QVector CodeSnipList; -typedef QVector DocModificationList; -typedef QVector FieldModificationList; -typedef QVector FunctionModificationList; - -#endif // TYPESYSTEM_TYPEDEFS_H diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index ddba62df8..000000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,285 +0,0 @@ -Include(icecc.cmake) -project(shiboken2) - -cmake_minimum_required(VERSION 3.0) -cmake_policy(VERSION 3.0) - -set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ - ${CMAKE_MODULE_PATH}) - -find_package(Qt5 REQUIRED COMPONENTS Core Xml XmlPatterns) - -add_definitions(${Qt5Core_DEFINITIONS}) - -set(shiboken_MAJOR_VERSION "2") -set(shiboken_MINOR_VERSION "0") -set(shiboken_MICRO_VERSION "0") -set(shiboken2_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") - -option(BUILD_TESTS "Build tests." TRUE) -option(USE_PYTHON_VERSION "Use specific python version to build shiboken2." "") - -if (USE_PYTHON_VERSION) - find_package(PythonInterp ${USE_PYTHON_VERSION} REQUIRED) - find_package(PythonLibs ${USE_PYTHON_VERSION} REQUIRED) -else() - find_package(PythonInterp 2.6) - find_package(PythonLibs 2.6) -endif() - -set(CLANG_DIR "") -set(CLANG_DIR_SOURCE "") - -if (DEFINED ENV{LLVM_INSTALL_DIR}) - set(CLANG_DIR $ENV{LLVM_INSTALL_DIR}) - set(CLANG_DIR_SOURCE "LLVM_INSTALL_DIR") -elseif (DEFINED ENV{CLANG_INSTALL_DIR}) - set(CLANG_DIR $ENV{CLANG_INSTALL_DIR}) - set(CLANG_DIR_SOURCE "CLANG_INSTALL_DIR") -else () - EXEC_PROGRAM("llvm-config" ARGS "--prefix" OUTPUT_VARIABLE CLANG_DIR) - set(CLANG_DIR_SOURCE "llvm-config") - if (NOT "${CLANG_DIR}" STREQUAL "") - EXEC_PROGRAM("llvm-config" ARGS "--version" OUTPUT_VARIABLE CLANG_VERSION) - if (CLANG_VERSION VERSION_LESS 3.9) - message(FATAL_ERROR "LLVM version 3.9 is required (llvm-config detected ${CLANG_VERSION} at ${CLANG_DIR}).") - endif() - endif() -endif() - -if ("${CLANG_DIR}" STREQUAL "") - message(FATAL_ERROR "Unable to detect CLANG location by checking LLVM_INSTALL_DIR, CLANG_INSTALL_DIR or running llvm-config.") -elseif (NOT IS_DIRECTORY ${CLANG_DIR}) - message(FATAL_ERROR "${CLANG_DIR} detected by ${CLANG_DIR_SOURCE} does not exist.") -endif() - -set(CLANG_LIB_NAME "clang") -if(MSVC) - set(CLANG_LIB_NAME "libclang") -endif() - -find_library(CLANG_LIBRARY ${CLANG_LIB_NAME} HINTS ${CLANG_DIR}/lib) -if (NOT EXISTS ${CLANG_LIBRARY}) - message(FATAL_ERROR "Unable to find Clang library ${CLANG_LIB_NAME} in ${CLANG_DIR}.") -endif() - -message(STATUS "CLANG: ${CLANG_DIR}, ${CLANG_LIBRARY} detected by ${CLANG_DIR_SOURCE}") - -set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include) -set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY}) - -## For debugging the PYTHON* variables -message("PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) -message("PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) -message("PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) -message("PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) -message("PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) -message("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) -message("PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}) - -# Queries the python sysconfig for the abi flags which need to be inserted into extension suffixes. -# Only present starting with Python 3.2. -# Corresponding configure switches to single letter flags: -# --with-pymalloc -> m -# --with-pydebug -> d -# --with-unicode -> u (rare) -macro(get_python3_abi_flags) - if (NOT PYTHON_ABI_FLAGS) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import sysconfig - print(sysconfig.get_config_var('abiflags')) - " - OUTPUT_VARIABLE PYTHON_ABI_FLAGS - OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - message("PYTHON_ABI_FLAGS: " ${PYTHON_ABI_FLAGS}) -endmacro() - -macro(get_python_multi_arch_suffix) - # TODO: This part needs testing to check if it is available on Windows. - # It is present on macOS, but is not used yet. - # Result is something like 'x86_64-linux-gnu'. - if (NOT PYTHON_MULTIARCH_SUFFIX) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import sysconfig - print(sysconfig.get_config_var('MULTIARCH')) - " - OUTPUT_VARIABLE PYTHON_MULTIARCH_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - endif() - message("PYTHON_MULTIARCH_SUFFIX: " ${PYTHON_MULTIARCH_SUFFIX}) -endmacro() - -macro(get_python2_release_suffix) - # Result of imp.get_suffixes() is something like: - # [('_d.so', 'rb', 3), ('module_d.so', 'rb', 3), ('.x86_64-linux-gnu_d.so', 'rb', 3)] - # or alternatively the same but withut the '_d' part. - # The list comprehension is used to choose which suffix to include in library names. - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import imp - print('_d' if any([tup[0].endswith('_d.so') for tup in imp.get_suffixes()]) else '') - " - OUTPUT_VARIABLE PYTHON_MODULE_RELEASE_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - message("PYTHON_MODULE_RELEASE_SUFFIX: " ${PYTHON_MODULE_RELEASE_SUFFIX}) -endmacro() - -# Note the quirk that UNIX includes Apple! -if (UNIX AND NOT APPLE) - if (NOT PYTHON_EXTENSION_SUFFIX) - get_python_multi_arch_suffix() - # The suffix added to .so libraries should be differenet between Python 2 and 3. - # The position of the multiarch suffix is different, and the way the debug flag is set - # computed differently. - # In Python 2 there is no standard way to query if the python interpeter was built in debug or - # release build (sysconfig.get_config_var('Py_Debug') can have a different value than you would - # expect if you do a custom Python build). The solution is to query for the import - # suffixes and check if _d is present there. It is present on Linux distribution - # packages of Python, but not in custom built Python builds, because the distros apply their - # custom patches too append the '_d's. - # In Python 3 (starting with 3.2) there is a standard way to check if '_d' needs to be added, - # as well as any other letters, by querying the abiflags sysconfig variable. - if (PYTHON_VERSION_MAJOR EQUAL 2) - get_python2_release_suffix() - if(PYTHON_MULTIARCH_SUFFIX) - set(PYTHON_EXTENSION_SUFFIX ".${PYTHON_MULTIARCH_SUFFIX}") - endif() - set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}${PYTHON_MODULE_RELEASE_SUFFIX}") - elseif (PYTHON_VERSION_MAJOR EQUAL 3) - get_python3_abi_flags() - set(PYTHON_EXTENSION_SUFFIX ".cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}${PYTHON_ABI_FLAGS}") - if(PYTHON_MULTIARCH_SUFFIX) - set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}-${PYTHON_MULTIARCH_SUFFIX}") - endif() - else() - message(FATAL_ERROR "Unsupported PYTHON_VERSION=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}!") - endif() - endif() - message(STATUS "PYTHON_EXTENSION_SUFFIX: ${PYTHON_EXTENSION_SUFFIX}") -endif () - -if (NOT PYTHON_SITE_PACKAGES) - execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - from distutils import sysconfig - from os.path import sep - print(sysconfig.get_python_lib(1, 0, prefix='${CMAKE_INSTALL_PREFIX}').replace(sep, '/')) - " - OUTPUT_VARIABLE PYTHON_SITE_PACKAGES - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (NOT PYTHON_SITE_PACKAGES) - message(FATAL_ERROR "Could not detect Python module installation directory.") - elseif (APPLE) - message(STATUS "!!! The generated bindings will be installed on ${PYTHON_SITE_PACKAGES}, is it right!?") - endif() -endif() - -if(MSVC) - # Qt5: this flag has changed from /Zc:wchar_t- in Qt4.X - set(CMAKE_CXX_FLAGS "/Zc:wchar_t /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") -else() - if(CMAKE_HOST_UNIX AND NOT CYGWIN) - add_definitions(-fPIC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") - endif() - set(CMAKE_CXX_FLAGS_DEBUG "-g") - option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library size and performance. Only available on Release Mode" 0) - if(ENABLE_GCC_OPTIMIZATION) - set(CMAKE_BUILD_TYPE Release) - set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -Os -Wl,-O1") - if(NOT CMAKE_HOST_APPLE) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--hash-style=gnu") - endif() - endif() -endif() - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_TO_ASCII") - -set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) -set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) - -if (WIN32) - set(PATH_SEP "\;") -else() - set(PATH_SEP ":") -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.") - if(OSX_USE_LIBCPP) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") - endif() -endif() - -add_subdirectory(ApiExtractor) - -set(generator_plugin_DIR ${LIB_INSTALL_DIR}/generatorrunner${generator_SUFFIX}) - -# uninstall target -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - IMMEDIATE @ONLY) -add_custom_target(uninstall "${CMAKE_COMMAND}" - -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") - -set(SHIBOKEN_BUILD_TYPE "Release") -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(NOT PYTHON_DEBUG_LIBRARIES) - message(WARNING "Python debug shared library not found; assuming python was built with shared library support disabled.") - endif() - if(NOT PYTHON_WITH_DEBUG) - message(WARNING "Compiling shiboken2 with debug enabled, but the python executable was not compiled with debug support.") - else() - add_definitions("-DPy_DEBUG") - set(SBK_ADD_PY_DEBUG_DEFINITION "add_definitions(\"-DPy_DEBUG\")") - set(SBK_PKG_CONFIG_PY_DEBUG_DEFINITION " -DPy_DEBUG") - endif() - set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) - set(SHIBOKEN_BUILD_TYPE "Debug") -else() - set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) - add_definitions("-DNDEBUG") -endif() -if(APPLE) - set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") -endif() - -if(CMAKE_VERSION VERSION_LESS 2.8) - set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_PATH}) -else() - set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS}) -endif() - -add_subdirectory(libshiboken) -add_subdirectory(doc) - -# deps found, compile the generator. -if (Qt5Core_FOUND AND PYTHONINTERP_FOUND) - add_subdirectory(generator) - add_subdirectory(shibokenmodule) - - if (BUILD_TESTS) - enable_testing() - add_subdirectory(tests) - endif() -else() - message(WARNING "Some dependencies were not found, shiboken2 generator compilation disabled!") -endif() - -add_subdirectory(data) - -# dist target -set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${shiboken2_VERSION}) -add_custom_target(dist - COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" && - git log > "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}/ChangeLog" && - git archive --prefix=${ARCHIVE_NAME}/ HEAD --format=tar --output="${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && - tar -C "${CMAKE_BINARY_DIR}" --owner=root --group=root -r "${ARCHIVE_NAME}/ChangeLog" -f "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && - bzip2 -f9 "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && - echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2." - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - - diff --git a/COPYING b/COPYING deleted file mode 100644 index 4ccd71466..000000000 --- a/COPYING +++ /dev/null @@ -1,342 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Library General -Public License instead of this License. - -------------------------------------------------------------------------- diff --git a/COPYING.libsample b/COPYING.libsample deleted file mode 100644 index 9315102f7..000000000 --- a/COPYING.libsample +++ /dev/null @@ -1,501 +0,0 @@ -GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - diff --git a/COPYING.libshiboken b/COPYING.libshiboken deleted file mode 100644 index 9315102f7..000000000 --- a/COPYING.libshiboken +++ /dev/null @@ -1,501 +0,0 @@ -GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - diff --git a/Doxyfile b/Doxyfile deleted file mode 100644 index 9be56a0e4..000000000 --- a/Doxyfile +++ /dev/null @@ -1,311 +0,0 @@ -# Doxyfile 1.5.7.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "Generator Runner" -PROJECT_NUMBER = 0.1 -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = /tmp/src/generatorrunner/ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = YES -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -SIP_SUPPORT = NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -TYPEDEF_HIDES_STRUCT = NO -SYMBOL_CACHE_SIZE = 0 -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -SHOW_FILES = YES -SHOW_NAMESPACES = YES -FILE_VERSION_FILTER = -LAYOUT_FILE = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = /tmp/src/generatorrunner -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.f90 \ - *.f \ - *.vhd \ - *.vhdl \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.PY \ - *.F90 \ - *.F \ - *.VHD \ - *.VHDL -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -HTML_DYNAMIC_SECTIONS = NO -GENERATE_DOCSET = NO -DOCSET_FEEDNAME = "Doxygen generated docs" -DOCSET_BUNDLE_ID = org.doxygen.Project -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -CHM_INDEX_ENCODING = -BINARY_TOC = NO -TOC_EXPAND = NO -GENERATE_QHP = NO -QCH_FILE = -QHP_NAMESPACE = org.doxygen.Project -QHP_VIRTUAL_FOLDER = doc -QHG_LOCATION = -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NONE -TREEVIEW_WIDTH = 250 -FORMULA_FONTSIZE = 10 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = ../libgenrunner/libgenrunner.tag=../libgenrunner -GENERATE_TAGFILE = generatorrunner.tag -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -DOT_FONTNAME = FreeSans -DOT_FONTSIZE = 10 -DOT_FONTPATH = -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = NO -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO diff --git a/LICENSE.GPLv3 b/LICENSE.GPLv3 deleted file mode 100644 index 71c4ad49c..000000000 --- a/LICENSE.GPLv3 +++ /dev/null @@ -1,686 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - - The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - You may use, distribute and copy the Qt Toolkit under the terms of - GNU Lesser General Public License version 3. That license references - the General Public License version 3, that is displayed below. Other - portions of the Qt Toolkit may be licensed directly under this license. - -------------------------------------------------------------------------- - - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/LICENSE.LGPLv21 b/LICENSE.LGPLv21 deleted file mode 100644 index 15a208b48..000000000 --- a/LICENSE.LGPLv21 +++ /dev/null @@ -1,514 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - - The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - You may use, distribute and copy the Qt Toolkit under the terms of - GNU Lesser General Public License version 2.1, which is displayed below. - -------------------------------------------------------------------------- - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/LICENSE.LGPLv3 b/LICENSE.LGPLv3 deleted file mode 100644 index 849103ad9..000000000 --- a/LICENSE.LGPLv3 +++ /dev/null @@ -1,175 +0,0 @@ - GNU LESSER GENERAL PUBLIC LICENSE - - The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. - Contact: http://www.qt.io/licensing/ - - You may use, distribute and copy the Qt Toolkit under the terms of - GNU Lesser General Public License version 3, which is displayed below. - This license makes reference to the version 3 of the GNU General - Public License, which you can find in the LICENSE.GPLv3 file. - -------------------------------------------------------------------------- - - GNU LESSER GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright © 2007 Free Software Foundation, Inc. -Everyone is permitted to copy and distribute verbatim copies of this -licensedocument, but changing it is not allowed. - -This version of the GNU Lesser General Public License incorporates -the terms and conditions of version 3 of the GNU General Public -License, supplemented by the additional permissions listed below. - -0. Additional Definitions. - - As used herein, “this License” refers to version 3 of the GNU Lesser -General Public License, and the “GNU GPL” refers to version 3 of the -GNU General Public License. - - “The Library” refers to a covered work governed by this License, -other than an Application or a Combined Work as defined below. - - An “Application” is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - - A “Combined Work” is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the “Linked -Version”. - - The “Minimal Corresponding Source” for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - - The “Corresponding Application Code” for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - -1. Exception to Section 3 of the GNU GPL. - - You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - -2. Conveying Modified Versions. - - If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - - a) under this License, provided that you make a good faith effort - to ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or - - b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - -3. Object Code Incorporating Material from Library Header Files. - - The object code form of an Application may incorporate material from -a header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - - a) Give prominent notice with each copy of the object code that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the object code with a copy of the GNU GPL and this - license document. - -4. Combined Works. - - You may convey a Combined Work under terms of your choice that, taken -together, effectively do not restrict modification of the portions of -the Library contained in the Combined Work and reverse engineering for -debugging such modifications, if you also do each of the following: - - a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. - - b) Accompany the Combined Work with a copy of the GNU GPL and this - license document. - - c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. - - d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of - this License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with - the Library. A suitable mechanism is one that (a) uses at run - time a copy of the Library already present on the user's - computer system, and (b) will operate properly with a modified - version of the Library that is interface-compatible with the - Linked Version. - - e) Provide Installation Information, but only if you would - otherwise be required to provide such information under section 6 - of the GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the Application - with a modified version of the Linked Version. (If you use option - 4d0, the Installation Information must accompany the Minimal - Corresponding Source and Corresponding Application Code. If you - use option 4d1, you must provide the Installation Information in - the manner specified by section 6 of the GNU GPL for conveying - Corresponding Source.) - -5. Combined Libraries. - - You may place library facilities that are a work based on the Library -side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities, conveyed under the terms of this License. - - b) Give prominent notice with the combined library that part of - it is a work based on the Library, and explaining where to find - the accompanying uncombined form of the same work. - -6. Revised Versions of the GNU Lesser General Public License. - - The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -as you received it specifies that a certain numbered version of the -GNU Lesser General Public License “or any later version” applies to -it, you have the option of following the terms and conditions either -of that published version or of any later version published by the -Free Software Foundation. If the Library as you received it does not -specify a version number of the GNU Lesser General Public License, -you may choose any version of the GNU Lesser General Public License -ever published by the Free Software Foundation. - -If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the Library. - diff --git a/LICENSE.PREVIEW.COMMERCIAL b/LICENSE.PREVIEW.COMMERCIAL deleted file mode 100644 index 0f96e738c..000000000 --- a/LICENSE.PREVIEW.COMMERCIAL +++ /dev/null @@ -1,630 +0,0 @@ -TECHNOLOGY PREVIEW LICENSE AGREEMENT - -For individuals and/or legal entities resident in the Americas (North -America, Central America and South America), the applicable licensing -terms are specified under the heading "Technology Preview License -Agreement: The Americas". - -For individuals and/or legal entities not resident in The Americas, the -applicable licensing terms are specified under the heading "Technology -Preview License Agreement: Rest of the World". - - -TECHNOLOGY PREVIEW LICENSE AGREEMENT: The Americas -Agreement version 2.4 - -This Technology Preview License Agreement ("Agreement")is a legal agreement -between The Qt Company USA, Inc. ("The Qt Company"), with its registered -office at 2350 Mission College Blvd., Suite 1020, Santa Clara, California -95054, U.S.A. and you (either an individual or a legal entity) ("Licensee") -for the Licensed Software (as defined below). - -1. DEFINITIONS - -"Affiliate" of a Party shall mean an entity (i) which is directly or -indirectly controlling such Party; (ii) which is under the same direct -or indirect ownership or control as such Party; or (iii) which is -directly or indirectly owned or controlled by such Party. For these -purposes, an entity shall be treated as being controlled by another if -that other entity has fifty percent (50 %) or more of the votes in such -entity, is able to direct its affairs and/or to control the composition -of its board of directors or equivalent body. - -"Applications" shall mean Licensee's software products created using the -Licensed Software which may include portions of the Licensed Software. - -"Term" shall mean the period of time six (6) months from the later of -(a) the Effective Date; or (b) the date the Licensed Software was -initially delivered to Licensee by The Qt Company. If no specific Effective -Date is set forth in the Agreement, the Effective Date shall be deemed to be -the date the Licensed Software was initially delivered to Licensee. - -"Licensed Software" shall mean the computer software, "online" or -electronic documentation, associated media and printed materials, -including the source code, example programs and the documentation -delivered by The Qt Company to Licensee in conjunction with this Agreement. - -"Party" or "Parties" shall mean Licensee and/or The Qt Company. - - -2. OWNERSHIP - -The Licensed Software is protected by copyright laws and international -copyright treaties, as well as other intellectual property laws and -treaties. The Licensed Software is licensed, not sold. - -If Licensee provides any findings, proposals, suggestions or other -feedback ("Feedback") to The Qt Company regarding the Licensed Software, -The Qt Company shall own all right, title and interest including the -intellectual property rights in and to such Feedback, excluding however any -existing patent rights of Licensee. To the extent Licensee owns or controls -any patents for such Feedback Licensee hereby grants to The Qt Company and its -Affiliates, a worldwide, perpetual, non-transferable, sublicensable, -royalty-free license to (i) use, copy and modify Feedback and to create -derivative works thereof, (ii) to make (and have made), use, import, -sell, offer for sale, lease, dispose, offer for disposal or otherwise -exploit any products or services of The Qt Company containing Feedback, and -(iii) sublicense all the foregoing rights to third party licensees and -customers of The Qt Company and/or its Affiliates. - - -3. VALIDITY OF THE AGREEMENT - -By installing, copying, or otherwise using the Licensed Software, -Licensee agrees to be bound by the terms of this Agreement. If Licensee -does not agree to the terms of this Agreement, Licensee may not install, -copy, or otherwise use the Licensed Software. Upon Licensee's acceptance -of the terms and conditions of this Agreement, The Qt Company grants Licensee -the right to use the Licensed Software in the manner provided below. - - -4. LICENSES - -4.1. Using and Copying - -The Qt Company grants to Licensee a non-exclusive, non-transferable, -time-limited license to use and copy the Licensed Software for sole purpose -of designing, developing and testing Applications, and evaluating and the -Licensed Software during the Term. - -Licensee may install copies of the Licensed Software on an unlimited -number of computers provided that (a) if an individual, only such -individual; or (b) if a legal entity only its employees; use the -Licensed Software for the authorized purposes. - -4.2 No Distribution or Modifications - -Licensee may not disclose, modify, sell, market, commercialise, -distribute, loan, rent, lease, or license the Licensed Software or any -copy of it or use the Licensed Software for any purpose that is not -expressly granted in this Section 4. Licensee may not alter or remove -any details of ownership, copyright, trademark or other property right -connected with the Licensed Software. Licensee may not distribute any -software statically or dynamically linked with the Licensed Software. - -4.3 No Technical Support - -The Qt Company has no obligation to furnish Licensee with any technical -support whatsoever. Any such support is subject to separate agreement between -the Parties. - - -5. PRE-RELEASE CODE -The Licensed Software contains pre-release code that is not at the level -of performance and compatibility of a final, generally available, -product offering. The Licensed Software may not operate correctly and -may be substantially modified prior to the first commercial product -release, if any. The Qt Company is not obligated to make this or any later -version of the Licensed Software commercially available. The License -Software is "Not for Commercial Use" and may only be used for the -purposes described in Section 4. The Licensed Software may not be used -in a live operating environment where it may be relied upon to perform -in the same manner as a commercially released product or with data that -has not been sufficiently backed up. - -6. THIRD PARTY SOFTWARE - -The Licensed Software may provide links to third party libraries or code -(collectively "Third Party Software") to implement various functions. -Third Party Software does not comprise part of the Licensed Software. In -some cases, access to Third Party Software may be included along with -the Licensed Software delivery as a convenience for development and -testing only. Such source code and libraries may be listed in the -".../src/3rdparty" source tree delivered with the Licensed Software or -documented in the Licensed Software where the Third Party Software is -used, as may be amended from time to time, do not comprise the Licensed -Software. Licensee acknowledges (1) that some part of Third Party -Software may require additional licensing of copyright and patents from -the owners of such, and (2) that distribution of any of the Licensed -Software referencing any portion of a Third Party Software may require -appropriate licensing from such third parties. - - -7. LIMITED WARRANTY AND WARRANTY DISCLAIMER - -The Licensed Software is licensed to Licensee "as is". To the maximum -extent permitted by applicable law, The Qt Company on behalf of itself and -its suppliers, disclaims all warranties and conditions, either express or -implied, including, but not limited to, implied warranties of -merchantability, fitness for a particular purpose, title and -non-infringement with regard to the Licensed Software. - - -8. LIMITATION OF LIABILITY - -If, The Qt Company's warranty disclaimer notwithstanding, The Qt Company is -held liable to Licensee, whether in contract, tort or any other legal theory, -based on the Licensed Software, The Qt Company's entire liability to Licensee -and Licensee's exclusive remedy shall be, at The Qt Company's option, either -(A) return of the price Licensee paid for the Licensed Software, or (B) -repair or replacement of the Licensed Software, provided Licensee -returns to The Qt Company all copies of the Licensed Software as originally -delivered to Licensee. The Qt Company shall not under any circumstances be -liable to Licensee based on failure of the Licensed Software if the failure -resulted from accident, abuse or misapplication, nor shall The Qt Company -under any circumstances be liable for special damages, punitive or exemplary -damages, damages for loss of profits or interruption of business or for -loss or corruption of data. Any award of damages from The Qt Company to -Licensee shall not exceed the total amount Licensee has paid to The Qt -Company in connection with this Agreement. - - -9. CONFIDENTIALITY - -Each party acknowledges that during the Term of this Agreement it shall -have access to information about the other party's business, business -methods, business plans, customers, business relations, technology, and -other information, including the terms of this Agreement, that is -confidential and of great value to the other party, and the value of -which would be significantly reduced if disclosed to third parties (the -"Confidential Information"). Accordingly, when a party (the "Receiving -Party") receives Confidential Information from another party (the -"Disclosing Party"), the Receiving Party shall, and shall obligate its -employees and agents and employees and agents of its Affiliates to: (i) -maintain the Confidential Information in strict confidence; (ii) not -disclose the Confidential Information to a third party without the -Disclosing Party's prior written approval; and (iii) not, directly or -indirectly, use the Confidential Information for any purpose other than -for exercising its rights and fulfilling its responsibilities pursuant -to this Agreement. Each party shall take reasonable measures to protect -the Confidential Information of the other party, which measures shall -not be less than the measures taken by such party to protect its own -confidential and proprietary information. - -"Confidential Information" shall not include information that (a) is or -becomes generally known to the public through no act or omission of the -Receiving Party; (b) was in the Receiving Party's lawful possession -prior to the disclosure hereunder and was not subject to limitations on -disclosure or use; (c) is developed by the Receiving Party without -access to the Confidential Information of the Disclosing Party or by -persons who have not had access to the Confidential Information of the -Disclosing Party as proven by the written records of the Receiving -Party; (d) is lawfully disclosed to the Receiving Party without -restrictions, by a third party not under an obligation of -confidentiality; or (e) the Receiving Party is legally compelled to -disclose the information, in which case the Receiving Party shall assert -the privileged and confidential nature of the information and cooperate -fully with the Disclosing Party to protect against and prevent -disclosure of any Confidential Information and to limit the scope of -disclosure and the dissemination of disclosed Confidential Information -by all legally available means. - -The obligations of the Receiving Party under this Section shall continue -during the Initial Term and for a period of five (5) years after -expiration or termination of this Agreement. To the extent that the -terms of the Non-Disclosure Agreement between The Qt Company and Licensee -conflict with the terms of this Section 9, this Section 9 shall be -controlling over the terms of the Non-Disclosure Agreement. - - -10. GENERAL PROVISIONS - -10.1 No Assignment - -Licensee shall not be entitled to assign or transfer all or any of its -rights, benefits and obligations under this Agreement without the prior -written consent of The Qt Company, which shall not be unreasonably withheld. - -10.2 Termination - -The Qt Company may terminate the Agreement at any time immediately upon -written notice by The Qt Company to Licensee if Licensee breaches this -Agreement. - -Upon termination of this Agreement, Licensee shall return to The Qt Company -all copies of Licensed Software that were supplied by The Qt Company. All -other copies of Licensed Software in the possession or control of Licensee -must be erased or destroyed. An officer of Licensee must promptly -deliver to The Qt Company a written confirmation that this has occurred. - -10.3 Surviving Sections - -Any terms and conditions that by their nature or otherwise reasonably -should survive a cancellation or termination of this Agreement shall -also be deemed to survive. Such terms and conditions include, but are -not limited to the following Sections: 2, 5, 6, 7, 8, 9, 10.2, 10.3, 10.4, -10.5, 10.6, 10.7, and 10.8 of this Agreement. - -10.4 Entire Agreement - -This Agreement constitutes the complete agreement between the parties -and supersedes all prior or contemporaneous discussions, -representations, and proposals, written or oral, with respect to the -subject matters discussed herein, with the exception of the -non-disclosure agreement executed by the parties in connection with this -Agreement ("Non-Disclosure Agreement"), if any, shall be subject to -Section 9. No modification of this Agreement shall be effective unless -contained in a writing executed by an authorized representative of each -party. No term or condition contained in Licensee's purchase order shall -apply unless expressly accepted by The Qt Company in writing. If any -provision of the Agreement is found void or unenforceable, the remainder -shall remain valid and enforceable according to its terms. If any remedy -provided is determined to have failed for its essential purpose, all -limitations of liability and exclusions of damages set forth in this -Agreement shall remain in effect. - -10.5 Export Control - -Licensee acknowledges that the Licensed Software may be subject to -export control restrictions of various countries. Licensee shall fully -comply with all applicable export license restrictions and requirements -as well as with all laws and regulations relating to the importation of -the Licensed Software and shall procure all necessary governmental -authorizations, including without limitation, all necessary licenses, -approvals, permissions or consents, where necessary for the -re-exportation of the Licensed Software., - -10.6 Governing Law and Legal Venue - -This Agreement shall be governed by and construed in accordance with the -federal laws of the United States of America and the internal laws of -the State of New York without given effect to any choice of law rule -that would result in the application of the laws of any other -jurisdiction. The United Nations Convention on Contracts for the -International Sale of Goods (CISG) shall not apply. Each Party (a) -hereby irrevocably submits itself to and consents to the jurisdiction of -the United States District Court for the Southern District of New York -(or if such court lacks jurisdiction, the state courts of the State of -New York) for the purposes of any action, claim, suit or proceeding -between the Parties in connection with any controversy, claim, or -dispute arising out of or relating to this Agreement; and (b) hereby -waives, and agrees not to assert by way of motion, as a defense or -otherwise, in any such action, claim, suit or proceeding, any claim that -is not personally subject to the jurisdiction of such court(s), that the -action, claim, suit or proceeding is brought in an inconvenient forum or -that the venue of the action, claim, suit or proceeding is improper. -Notwithstanding the foregoing, nothing in this Section 9.6 is intended -to, or shall be deemed to, constitute a submission or consent to, or -selection of, jurisdiction, forum or venue for any action for patent -infringement, whether or not such action relates to this Agreement. - -10.7 No Implied License - -There are no implied licenses or other implied rights granted under this -Agreement, and all rights, save for those expressly granted hereunder, -shall remain with The Qt Company and its licensors. In addition, no licenses -or immunities are granted to the combination of the Licensed Software with -any other software or hardware not delivered by The Qt Company under this -Agreement. - -10.8 Government End Users - -A "U.S. Government End User" shall mean any agency or entity of the -government of the United States. The following shall apply if Licensee -is a U.S. Government End User. The Licensed Software is a "commercial -item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), -consisting of "commercial computer software" and "commercial computer -software documentation," as such terms are used in 48 C.F.R. 12.212 -(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 -through 227.7202-4 (June 1995), all U.S. Government End Users acquire -the Licensed Software with only those rights set forth herein. The -Licensed Software (including related documentation) is provided to U.S. -Government End Users: (a) only as a commercial end item; and (b) only -pursuant to this Agreement. - - - - - -TECHNOLOGY PREVIEW LICENSE AGREEMENT: Rest of the World -Agreement version 2.4 - -This Technology Preview License Agreement ("Agreement") is a legal -agreement between The Qt Company Ltd ("The Qt Company"), with its registered -office at Valimotie 21,FI-00380 Helsinki, Finland and you (either an -individual or a legal entity) ("Licensee") for the Licensed Software. - -1. DEFINITIONS - -"Affiliate" of a Party shall mean an entity (i) which is directly or -indirectly controlling such Party; (ii) which is under the same direct -or indirect ownership or control as such Party; or (iii) which is -directly or indirectly owned or controlled by such Party. For these -purposes, an entity shall be treated as being controlled by another if -that other entity has fifty percent (50 %) or more of the votes in such -entity, is able to direct its affairs and/or to control the composition -of its board of directors or equivalent body. - -"Applications" shall mean Licensee's software products created using the -Licensed Software which may include portions of the Licensed Software. - -"Term" shall mean the period of time six (6) months from the later of -(a) the Effective Date; or (b) the date the Licensed Software was -initially delivered to Licensee by The Qt Company. If no specific Effective -Date is set forth in the Agreement, the Effective Date shall be deemed to be -the date the Licensed Software was initially delivered to Licensee. - -"Licensed Software" shall mean the computer software, "online" or -electronic documentation, associated media and printed materials, -including the source code, example programs and the documentation -delivered by The Qt Company to Licensee in conjunction with this Agreement. - -"Party" or "Parties" shall mean Licensee and/or The Qt Company. - - -2. OWNERSHIP - -The Licensed Software is protected by copyright laws and international -copyright treaties, as well as other intellectual property laws and -treaties. The Licensed Software is licensed, not sold. - -If Licensee provides any findings, proposals, suggestions or other -feedback ("Feedback") to The Qt Company regarding the Licensed Software, -The Qt Companyshall own all right, title and interest including the -intellectual property rights in and to such Feedback, excluding however any -existing patent rights of Licensee. To the extent Licensee owns or controls -any patents for such Feedback Licensee hereby grants to The Qt Company and -its Affiliates, a worldwide, perpetual, non-transferable, sublicensable, -royalty-free license to (i) use, copy and modify Feedback and to create -derivative works thereof, (ii) to make (and have made), use, import, -sell, offer for sale, lease, dispose, offer for disposal or otherwise -exploit any products or services of The Qt Company containing Feedback, and -(iii) sublicense all the foregoing rights to third party licensees and -customers of The Qt Company and/or its Affiliates. - -3. VALIDITY OF THE AGREEMENT - -By installing, copying, or otherwise using the Licensed Software, -Licensee agrees to be bound by the terms of this Agreement. If Licensee -does not agree to the terms of this Agreement, Licensee may not install, -copy, or otherwise use the Licensed Software. Upon Licensee's acceptance -of the terms and conditions of this Agreement, The Qt Company grants Licensee -the right to use the Licensed Software in the manner provided below. - - -4. LICENSES - -4.1. Using and Copying - -The Qt Company grants to Licensee a non-exclusive, non-transferable, -time-limited license to use and copy the Licensed Software for sole purpose -of designing, developing and testing Applications, and evaluating and the -Licensed Software during the Term. - -Licensee may install copies of the Licensed Software on an unlimited -number of computers provided that (a) if an individual, only such -individual; or (b) if a legal entity only its employees; use the -Licensed Software for the authorized purposes. - -4.2 No Distribution or Modifications - -Licensee may not disclose, modify, sell, market, commercialise, -distribute, loan, rent, lease, or license the Licensed Software or any -copy of it or use the Licensed Software for any purpose that is not -expressly granted in this Section 4. Licensee may not alter or remove -any details of ownership, copyright, trademark or other property right -connected with the Licensed Software. Licensee may not distribute any -software statically or dynamically linked with the Licensed Software. - -4.3 No Technical Support - -The Qt Company has no obligation to furnish Licensee with any technical -support whatsoever. Any such support is subject to separate agreement -between the Parties. - - -5. PRE-RELEASE CODE - -The Licensed Software contains pre-release code that is not at the level -of performance and compatibility of a final, generally available, -product offering. The Licensed Software may not operate correctly and -may be substantially modified prior to the first commercial product -release, if any. The Qt Company is not obligated to make this or any later -version of the Licensed Software commercially available. The License -Software is "Not for Commercial Use" and may only be used for the -purposes described in Section 4. The Licensed Software may not be used -in a live operating environment where it may be relied upon to perform -in the same manner as a commercially released product or with data that -has not been sufficiently backed up. - -6. THIRD PARTY SOFTWARE - -The Licensed Software may provide links to third party libraries or code -(collectively "Third Party Software") to implement various functions. -Third Party Software does not comprise part of the Licensed Software. In -some cases, access to Third Party Software may be included along with -the Licensed Software delivery as a convenience for development and -testing only. Such source code and libraries may be listed in the -".../src/3rdparty" source tree delivered with the Licensed Software or -documented in the Licensed Software where the Third Party Software is -used, as may be amended from time to time, do not comprise the Licensed -Software. Licensee acknowledges (1) that some part of Third Party -Software may require additional licensing of copyright and patents from -the owners of such, and (2) that distribution of any of the Licensed -Software referencing any portion of a Third Party Software may require -appropriate licensing from such third parties. - - -7. LIMITED WARRANTY AND WARRANTY DISCLAIMER - -The Licensed Software is licensed to Licensee "as is". To the maximum -extent permitted by applicable law, The Qt Company on behalf of itself and -its suppliers, disclaims all warranties and conditions, either express or -implied, including, but not limited to, implied warranties of -merchantability, fitness for a particular purpose, title and -non-infringement with regard to the Licensed Software. - - -8. LIMITATION OF LIABILITY - -If, The Qt Company's warranty disclaimer notwithstanding, The Qt Company is -held liable to Licensee, whether in contract, tort or any other legal theory, -based on the Licensed Software, The Qt Company's entire liability to Licensee -and Licensee's exclusive remedy shall be, at The Qt Company's option, either -(A) return of the price Licensee paid for the Licensed Software, or (B) -repair or replacement of the Licensed Software, provided Licensee -returns to The Qt Company all copies of the Licensed Software as originally -delivered to Licensee. The Qt Company shall not under any circumstances be -liable to Licensee based on failure of the Licensed Software if the failure -resulted from accident, abuse or misapplication, nor shall The Qt Company -under any circumstances be liable for special damages, punitive or exemplary -damages, damages for loss of profits or interruption of business or for -loss or corruption of data. Any award of damages from The Qt Company to -Licensee shall not exceed the total amount Licensee has paid to -The Qt Company in connection with this Agreement. - - -9. CONFIDENTIALITY - -Each party acknowledges that during the Term of this Agreement it shall -have access to information about the other party's business, business -methods, business plans, customers, business relations, technology, and -other information, including the terms of this Agreement, that is -confidential and of great value to the other party, and the value of -which would be significantly reduced if disclosed to third parties (the -"Confidential Information"). Accordingly, when a party (the "Receiving -Party") receives Confidential Information from another party (the -"Disclosing Party"), the Receiving Party shall, and shall obligate its -employees and agents and employees and agents of its Affiliates to: (i) -maintain the Confidential Information in strict confidence; (ii) not -disclose the Confidential Information to a third party without the -Disclosing Party's prior written approval; and (iii) not, directly or -indirectly, use the Confidential Information for any purpose other than -for exercising its rights and fulfilling its responsibilities pursuant -to this Agreement. Each party shall take reasonable measures to protect -the Confidential Information of the other party, which measures shall -not be less than the measures taken by such party to protect its own -confidential and proprietary information. - -"Confidential Information" shall not include information that (a) is or -becomes generally known to the public through no act or omission of the -Receiving Party; (b) was in the Receiving Party's lawful possession -prior to the disclosure hereunder and was not subject to limitations on -disclosure or use; (c) is developed by the Receiving Party without -access to the Confidential Information of the Disclosing Party or by -persons who have not had access to the Confidential Information of the -Disclosing Party as proven by the written records of the Receiving -Party; (d) is lawfully disclosed to the Receiving Party without -restrictions, by a third party not under an obligation of -confidentiality; or (e) the Receiving Party is legally compelled to -disclose the information, in which case the Receiving Party shall assert -the privileged and confidential nature of the information and cooperate -fully with the Disclosing Party to protect against and prevent -disclosure of any Confidential Information and to limit the scope of -disclosure and the dissemination of disclosed Confidential Information -by all legally available means. - -The obligations of the Receiving Party under this Section shall continue -during the Initial Term and for a period of five (5) years after -expiration or termination of this Agreement. To the extent that the -terms of the Non-Disclosure Agreement between The Qt Company and Licensee -conflict with the terms of this Section 9, this Section 9 shall be -controlling over the terms of the Non-Disclosure Agreement. - - -10. GENERAL PROVISIONS - -10.1 No Assignment - -Licensee shall not be entitled to assign or transfer all or any of its -rights, benefits and obligations under this Agreement without the prior -written consent of The Qt Company, which shall not be unreasonably withheld. - -10.2 Termination - -The Qt Company may terminate the Agreement at any time immediately upon -written notice by The Qt Company to Licensee if Licensee breaches this -Agreement. - -Upon termination of this Agreement, Licensee shall return to The Qt Company -all copies of Licensed Software that were supplied by The Qt Company. All -other copies of Licensed Software in the possession or control of Licensee -must be erased or destroyed. An officer of Licensee must promptly -deliver to The Qt Company a written confirmation that this has occurred. - -10.3 Surviving Sections - -Any terms and conditions that by their nature or otherwise reasonably -should survive a cancellation or termination of this Agreement shall -also be deemed to survive. Such terms and conditions include, but are -not limited to the following Sections: 2, 5, 6, 7, 8, 9, 10.2, 10.3, 10.4, -10.5, 10.6, 10.7, and 10.8 of this Agreement. - -10.4 Entire Agreement - -This Agreement constitutes the complete agreement between the parties -and supersedes all prior or contemporaneous discussions, -representations, and proposals, written or oral, with respect to the -subject matters discussed herein, with the exception of the -non-disclosure agreement executed by the parties in connection with this -Agreement ("Non-Disclosure Agreement"), if any, shall be subject to -Section 9. No modification of this Agreement shall be effective unless -contained in a writing executed by an authorized representative of each -party. No term or condition contained in Licensee's purchase order shall -apply unless expressly accepted by The Qt Company in writing. If any provision -of the Agreement is found void or unenforceable, the remainder shall remain -valid and enforceable according to its terms. If any remedy provided is -determined to have failed for its essential purpose, all limitations of -liability and exclusions of damages set forth in this Agreement shall -remain in effect. - -10.5 Export Control - -Licensee acknowledges that the Licensed Software may be subject to -export control restrictions of various countries. Licensee shall fully -comply with all applicable export license restrictions and requirements -as well as with all laws and regulations relating to the importation of -the Licensed Software and shall procure all necessary governmental -authorizations, including without limitation, all necessary licenses, -approvals, permissions or consents, where necessary for the -re-exportation of the Licensed Software., - -10.6 Governing Law and Legal Venue - -This Agreement shall be construed and interpreted in accordance with the -laws of Finland, excluding its choice of law provisions. Any disputes -arising out of or relating to this Agreement shall be resolved in -arbitration under the Rules of Arbitration of the Chamber of Commerce of -Helsinki, Finland. The arbitration tribunal shall consist of one (1), or -if either Party so requires, of three (3), arbitrators. The award shall -be final and binding and enforceable in any court of competent -jurisdiction. The arbitration shall be held in Helsinki, Finland and the -process shall be conducted in the English language. - -10.7 No Implied License - -There are no implied licenses or other implied rights granted under this -Agreement, and all rights, save for those expressly granted hereunder, -shall remain with The Qt Company and its licensors. In addition, no licenses -or immunities are granted to the combination of the Licensed Software with -any other software or hardware not delivered by The Qt Company under this -Agreement. - -10.8 Government End Users - -A "U.S. Government End User" shall mean any agency or entity of the -government of the United States. The following shall apply if Licensee -is a U.S. Government End User. The Licensed Software is a "commercial -item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), -consisting of "commercial computer software" and "commercial computer -software documentation," as such terms are used in 48 C.F.R. 12.212 -(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 -through 227.7202-4 (June 1995), all U.S. Government End Users acquire -the Licensed Software with only those rights set forth herein. The -Licensed Software (including related documentation) is provided to U.S. -Government End Users: (a) only as a commercial end item; and (b) only -pursuant to this Agreement. - - - - diff --git a/README.md b/README.md deleted file mode 100644 index b64f97d36..000000000 --- a/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# shiboken2 - -This is shiboken2, the code generator for PySide2. It is part of pyside2-setup, which you -should download for building and getting further information. - -Resources: - -* [PySide2-setup](https://github.com/PySide/pyside2-setup) - The container-project with the setup.py script. It contains the following sub-projects: - * [PySide2 Wiki](https://github.com/PySide/pyside2/wiki) - Developer information - * [PySide2](https://github.com/PySide/pyside2) - The PySide2 project - * [Shiboken2](https://github.com/PySide/shiboken2) - The Shiboken2 project - * [PySide2-tools](https://github.com/PySide/pyside2-examples) - The PySide2-tools project - * [PySide2-examples](https://github.com/PySide/pyside2-examples) - The PySide2 example scripts diff --git a/cmake_uninstall.cmake b/cmake_uninstall.cmake deleted file mode 100644 index df95fb9d8..000000000 --- a/cmake_uninstall.cmake +++ /dev/null @@ -1,21 +0,0 @@ -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") - -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) - MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt deleted file mode 100644 index c36cb148d..000000000 --- a/data/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) -else() - set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_RELEASE_POSTFIX}) -endif() - -add_custom_target(data) -add_dependencies(data shiboken2) -get_target_property(SHIBOKEN_GENERATOR shiboken2 OUTPUT_NAME) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2Config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config.cmake" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2Config-spec.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2ConfigVersion.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2ConfigVersion.cmake" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken2.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/shiboken2${shiboken2_SUFFIX}.pc" @ONLY) - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2ConfigVersion.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shiboken2${shiboken2_SUFFIX}.pc" - DESTINATION "${LIB_INSTALL_DIR}/pkgconfig") - diff --git a/data/GeneratorRunnerConfig.cmake.in b/data/GeneratorRunnerConfig.cmake.in deleted file mode 100644 index cf973e2a6..000000000 --- a/data/GeneratorRunnerConfig.cmake.in +++ /dev/null @@ -1,17 +0,0 @@ -# GENERATORRUNNER_INCLUDE_DIR - Directories to include to use GENERATORRUNNER -# GENERATORRUNNER_LIBRARIES - Files to link against to use GENERATORRUNNER -# GENERATORRUNNER_PLUGIN_DIR - Where to find/put plugins for generator runner -# GENERATORRUNNER_BINARY - Executable name - -SET(GENERATORRUNNER_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/generatorrunner@generator_SUFFIX@") -if(MSVC) - SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@.lib") -elseif(CYGWIN) - SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_IMPORT_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") -elseif(WIN32) - SET(GENERATORRUNNER_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -else() - SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -endif() -SET(GENERATORRUNNER_PLUGIN_DIR "@generator_plugin_DIR@") -SET(GENERATORRUNNER_BINARY "@CMAKE_INSTALL_PREFIX@/bin/generatorrunner@generator_SUFFIX@") diff --git a/data/GeneratorRunnerConfigVersion.cmake.in b/data/GeneratorRunnerConfigVersion.cmake.in deleted file mode 100644 index 8eb5ba479..000000000 --- a/data/GeneratorRunnerConfigVersion.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -set(PACKAGE_VERSION @generator_VERSION@) - -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") -endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/data/Shiboken2Config-spec.cmake.in b/data/Shiboken2Config-spec.cmake.in deleted file mode 100644 index 1aac9caa0..000000000 --- a/data/Shiboken2Config-spec.cmake.in +++ /dev/null @@ -1,29 +0,0 @@ -# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN -# SHIBOKEN_LIBRARY - Files to link against to use SHIBOKEN -# SHIBOKEN_BINARY - Executable name -# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. -# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. -# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. - -SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken2@shiboken2_SUFFIX@") -if(MSVC) - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@.lib") -elseif(CYGWIN) - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_IMPORT_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") -elseif(WIN32) - SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -else() - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -endif() -SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") -SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") -SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") -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_LIBRARIES "@SBK_PYTHON_LIBRARIES@") -SET(SHIBOKEN_PYTHON_EXTENSION_SUFFIX "@PYTHON_EXTENSION_SUFFIX@") -message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") -@SBK_ADD_PY_DEBUG_DEFINITION@ - -set(SHIBOKEN_BINARY "@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@") diff --git a/data/Shiboken2Config.cmake.in b/data/Shiboken2Config.cmake.in deleted file mode 100644 index 5f7ecaec1..000000000 --- a/data/Shiboken2Config.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -if (NOT PYTHON_EXTENSION_SUFFIX) - message(STATUS "Shiboken2Config: Using default python: @PYTHON_EXTENSION_SUFFIX@") - SET(PYTHON_EXTENSION_SUFFIX @PYTHON_EXTENSION_SUFFIX@) -endif() -include(@LIB_INSTALL_DIR@/cmake/Shiboken2-@shiboken2_VERSION@/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake) diff --git a/data/Shiboken2ConfigVersion.cmake.in b/data/Shiboken2ConfigVersion.cmake.in deleted file mode 100644 index 9460099b2..000000000 --- a/data/Shiboken2ConfigVersion.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -set(PACKAGE_VERSION @shiboken2_VERSION@) - -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") -endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/data/docgenerator.1 b/data/docgenerator.1 deleted file mode 120000 index c65282f98..000000000 --- a/data/docgenerator.1 +++ /dev/null @@ -1 +0,0 @@ -generatorrunner.1 \ No newline at end of file diff --git a/data/generatorrunner.1 b/data/generatorrunner.1 deleted file mode 100644 index 045b55ad4..000000000 --- a/data/generatorrunner.1 +++ /dev/null @@ -1,76 +0,0 @@ -.TH GENERATORRUNNER 1 "SEPTEMBER 2009" Linux "User Manuals" -.SH NAME -generatorrunner - plugin-based binding source code generator -.SH SYNOPSIS -.B generatorrunner \-\-generator-set= [options] header-file typesystem-file -.SH DESCRIPTION -.B generatorrunner -is a utility that uses the information taken from APIExtractor -related to the provided C++ headers and typesystem files and execute -generators using this information. Generators are plugins and you need -to specify one using the \-\-generator-set parameter. At the moment there -are two generators available: - -.B qtdoc -\- Generates Sphinx-based documentation for C++ libraries documented using -.B qdoc3 -documentation syntax, using the XML files created by the documentation tool -.B (qdoc3). -Can be called supplying -.B \-\-generator-set=qtdoc -to -.B generatorrunner -or by calling the convenience executable -.B docgenerator. - -Other plugins can be used with -.B generatorrunner, -provided that they follow the generator front-end specifications, -and can be written to generate code or documentation for any target -languague you desire. For more information about the generator front-end -architecture and current limitations, refer to http://www.pyside.org/home-binding. - -.SH OPTIONS -.SS "General options" -.IP \-\-api-version= -Specify the supported api version used to generate the bindings. -.IP \-\-debug-level=[sparse|medium|full] -The amount of messages displayed. -.IP \-\-documentation-only -Only generates the documentation. -.IP \-\-drop-type-entries="[;TypeEntry1;...]" -Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation. -.IP \-\-help \fR,\fP \-h \fR,\fP -? -Prints the usage message. -.IP \-\-project-file= -Text file containing a description of the binding project. Replaces and overrides command line arguments. -.IP \-\-include\-paths=\fI[:path:..]\fR -The directories where the generator will search for the -headers. Works like gcc's \-I flag. -.IP \-\-license\-file=\fI[licensefile]\fR -Template for copyright headers of generated files. -.IP \-\-no\-supress\-warnings -Show all warnings. -.IP \-\-output\-directory=\fI[dir]\fR -The directory where the generated files will be written. -.IP \-\-silent -Avoid printing any messages. -.IP \-\-typesytem\-paths=\fI[:path:..]\fR -The directories where the generator will search for the -external typesystems referred by the main one. -.IP \-\-version -Displays the current version. -Drops support for named args. -.SS "Specific to qtdoc plugin" -.IP \-\-documentation\-code\-snippets\-dir -Directory used to search code snippets used by the documentation -.IP \-\-documentation\-data\-dir -Directory with XML files generated by documentation tool (qdoc3 or Doxygen) -.IP \-\-documentation\-out\-dir -The directory where the generated documentation files will be written -.IP \-\-library\-source\-dir -Directory where library source code is located - -.SH AUTHORS -Lauro Moura , Bruno Araujo , Hugo Lima - diff --git a/data/generatorrunner.pc.in b/data/generatorrunner.pc.in deleted file mode 100644 index a566f4356..000000000 --- a/data/generatorrunner.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/include - - -Name: generatorrunner@generator_SUFFIX@ -Description: Generator Runner loads and calls binding generator front-ends. -Requires: apiextractor -Version: @generatorrunner_VERSION@ -Libs: -L${libdir} -lgenrunner@generator_SUFFIX@ -Cflags: -I${includedir}@generator_SUFFIX@ - diff --git a/data/shiboken2.pc.in b/data/shiboken2.pc.in deleted file mode 100644 index aec210c5c..000000000 --- a/data/shiboken2.pc.in +++ /dev/null @@ -1,13 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken2 -generator_location=@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@ -python_interpreter=@PYTHON_EXECUTABLE@ -python_include_dir=@SBK_PYTHON_INCLUDE_DIR@ - -Name: shiboken2 -Description: Support library for Python bindings created with the Shiboken2 generator. -Version: @shiboken2_VERSION@ -Libs: @SBK_PYTHON_LIBRARIES@ -L${libdir} -lshiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ -Cflags: -I@SBK_PYTHON_INCLUDE_DIR@ -I${includedir}/@shiboken2_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@ diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt deleted file mode 100644 index 7bd0161ad..000000000 --- a/doc/CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ - -find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") - -if (SPHINX) - message("-- sphinx-build - found") - configure_file(conf.py.in conf.py @ONLY) - add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) -else() - message("-- sphinx-build - not found! doc target disabled") - if (WIN32) - # if jom is used and we have no sphinx, then jom will crash. - # so for windows, we always create a doc target (until jom gets fixed...) - add_custom_target(doc echo. - COMMAND echo +++ This is a fake build, to make 'jom' happy. - COMMAND echo +++ The documentation was _not_ built! - COMMAND echo. - ) - endif() -endif() - -if (NOT WIN32) - file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") - install(FILES ${manpages} DESTINATION share/man/man1) -endif() diff --git a/doc/_templates/index.html b/doc/_templates/index.html deleted file mode 100644 index 00ac64271..000000000 --- a/doc/_templates/index.html +++ /dev/null @@ -1,35 +0,0 @@ -{% extends "layout.html" %} -{% set title = 'Overview' %} -{% block body %} -
-

{{ project }} {{ version }}

- -

{{ project }} is a plugin (front-end) for Generator Runner. It generates bindings for C++ libraries using CPython source code.

- -

Documentation

- - - -
- - - - - - - - - - -
-
-{% endblock %} diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html deleted file mode 100644 index 94ff3534e..000000000 --- a/doc/_templates/layout.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "!layout.html" %} - -# Invert sidebars -{%- block sidebar1 %}{{ sidebar() }}{%- endblock %} -{%- block sidebar2 %}{%- endblock %} - -{%- block header %} -
-
-
- - {{ relbar() }} -
-
-{%- endblock -%} - -{%- block footer %} - -
-{%- endblock %} - -# No top relbar. -{%- block relbar1 %}{%- endblock %} - -# No bottom relbar. -{%- block relbar2 %}{%- endblock %} diff --git a/doc/_themes/pysidedocs/searchbox.html b/doc/_themes/pysidedocs/searchbox.html deleted file mode 100644 index 55a972156..000000000 --- a/doc/_themes/pysidedocs/searchbox.html +++ /dev/null @@ -1,12 +0,0 @@ -{%- if pagename != "search" %} - - -{%- endif %} diff --git a/doc/_themes/pysidedocs/static/bg_header.png b/doc/_themes/pysidedocs/static/bg_header.png deleted file mode 100644 index 843e7e2c5..000000000 Binary files a/doc/_themes/pysidedocs/static/bg_header.png and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/bg_topo.jpg b/doc/_themes/pysidedocs/static/bg_topo.jpg deleted file mode 100644 index 4229ae8db..000000000 Binary files a/doc/_themes/pysidedocs/static/bg_topo.jpg and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/fakebar.png b/doc/_themes/pysidedocs/static/fakebar.png deleted file mode 100644 index b45830e00..000000000 Binary files a/doc/_themes/pysidedocs/static/fakebar.png and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/logo_python.jpg b/doc/_themes/pysidedocs/static/logo_python.jpg deleted file mode 100644 index cd474efba..000000000 Binary files a/doc/_themes/pysidedocs/static/logo_python.jpg and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/logo_qt.png b/doc/_themes/pysidedocs/static/logo_qt.png deleted file mode 100644 index 39a4a26f3..000000000 Binary files a/doc/_themes/pysidedocs/static/logo_qt.png and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/pysidedocs.css b/doc/_themes/pysidedocs/static/pysidedocs.css deleted file mode 100644 index 708ddf77c..000000000 --- a/doc/_themes/pysidedocs/static/pysidedocs.css +++ /dev/null @@ -1,475 +0,0 @@ -* { - font: 100% Verdana, Arial, Helvetica, sans-serif; - font-size:12px; -} - -html { - height: 100%; -} - -body { - margin: 0; - padding: 0; - background-color: #EBEBEB; - height: 100%; - color: #333; -} - -strong { - font-weight:bold; -} - -.document { - padding-bottom: 90px; -} - -#container { - position: relative; - min-height: 100%; - background-image: url(fakebar.png); - background-repeat: repeat-y; - background-color: white; -} - -.footer { - position: absolute; - bottom: 0px; - margin-top: 50px; - text-align:center; - background-color: white; - border-top: 2px solid #e0e0e0; - white-space: nowrap; - height: 90px; - width: 100%; -} - -.footer img { - margin-left: 8px; - margin-right: 8px; -} - -.sphinxsidebar { - float: left; - width: 250px; - padding: 0px 10px 0px 10px; - text-align: left; -} - -.sphinxsidebar ul { - padding: 0px; - margin: 0px; - list-style-position: inside; -} - -.sphinxsidebar > ul { - padding: 0px; - margin: 0px; -} - -.sphinxsidebar ul li { - margin-left: 10px; - padding: 0px; -} - -.sphinxsidebar h3, .sphinxsidebar h3 a { - font-weight: bold; - color: #333; -} - -.documentwrapper { - margin-left: 270px; - text-align: left; - background-color: #ffffff; - border-left: 1px solid #989898; - font-size:18px; - padding: 10px 50px 15px 50px; - height: 100%; -} - -h1 { - font-size:18px; - padding-left: 50px; - padding-bottom: 15px; - padding-top: 15px; - border-bottom: 1px solid #c2c2c2; - margin-right: -100px; - position: relative; - left: -50px; - top: -10px; -} - -h2 { - font-size:12px; - font-weight:bold; - border-left-width: 1px; - border-right-width: 1px; - border-top-width: 1px; - border-bottom-width: 2px; - border-style: solid; - border-left-color: #b1b1b1; - border-right-color: #b1b1b1; - border-top-color: #b1b1b1; - border-bottom-color: #009491; - background-color: #e0e0e0; - padding:5px; - margin-top: 20px; - -moz-border-radius:5px; - -webkit-border-radius:5px; - -khtml-border-radius:5px; -} - -h3, h4 { - font-weight: bolder; -} - -pre { - border-top: 1px solid #e0e0e0; - border-bottom: 1px solid #e0e0e0; - background-color: #fafafa; - padding: 5px; - font: 100% monospace; - overflow: auto; -} - -pre * { - font: 100% monospace; -} - -.pre { - font: 100% monospace; -} - -.headerlink { - font-size: 100%; - color: inherit; - float: right; - visibility: Hidden -} - -h1 .headerlink { - padding-right: 50px; -} - -h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink { - visibility: Visible; -} - -a, a:visited { - color: #009491; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -/* -- admonitions ----------------------------------------------------------- */ - -div.admonition { - margin-top: 10px; - margin-bottom: 10px; - padding: 7px; -} - -div.admonition dt { - font-weight: bold; -} - -div.admonition dl { - margin-bottom: 0; -} - -p.admonition-title { - margin: 0px 10px 5px 0px; - font-weight: bold; -} - -div.body p.centered { - text-align: center; - margin-top: 25px; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -div.seealso { - background-color: #ffffcc; - border: 1px solid #ffff66; -} - -div.note { - border: 1px solid #e3e3e3; -} - -table.docutils { - margin-left: auto; - margin-right: auto; - margin-bottom: 10px; - border: none; -} - -table.docutils td { - border: none; -} - -table.docutils th { - border: none; - font-weight: bold; - vertical-align: top; -} - -h2 em { - float: right; - font-size: 10px; - position: relative; - top: -20px; -} - -/* Table of pymaemo components */ - -#development table.docutils td { - border-bottom: 1px solid #EBEBEB; -} - -#development th { - background-color: #EBEBEB; - color: #FC7E00; - padding: 5px; -} - -#development th:first-child { - -moz-border-radius: 20px 0px 0px 0px; - -webkit-border-radius: 20px 0px 0px 0px; - -khtml-border-radius: 20px 0px 0px 0px; - padding-left: 10px; -} -#development th:last-child { - -moz-border-radius: 0px 20px 0px 0px; - -webkit-border-radius: 0px 20px 0px 0px; - -khtml-border-radius: 0px 20px 0px 0px; - padding-right: 10px; - width: 100px; -} - -hr { - border: none; - border-bottom: 1px dashed #EBEBEB; - width: 70% -} - -.oldnews { - text-align: right; -} - -/******************* TOPO *****************************/ -.header { - background-image: url(bg_topo.jpg); - background-repeat: repeat-x; - height: 147px; -} - -.header_container { - background-image: url(bg_header.png); - background-repeat: no-repeat; - background-position: 100px 0px; -} - -.logo { - text-align: left; - margin-bottom: 10px; -} - -#searchbox { - border-top: 1px solid #989898; - padding-top: 10px; - margin-left: -10px; - margin-right: -10px; - padding-left: 10px; - padding-right: 10px; -} - -#search_button { - border: 1px solid #3A393A; - background-color: #3A393A; - color: white; - cursor: pointer; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -khtml-border-radius: 5px; - -} - -form { - margin: 0px; - padding: 0px; -} - -/* search field */ -form #q { - width: 136px; -/* height: 22px; */ - border: none; - margin: 0px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - -khtml-border-radius: 5px; - margin-top: 2px; - padding: 4px; - line-height: 22px -} - -#search-results h2 { - display: none; -} - -#search-results h2 { - display: none; -} - -#search-results ul.search { - margin: 0px; - padding: 0px; -} - -ul.search div.context { - padding-left: 40px; -} - -#installation td { - text-align: center; - font-weight: bold; -} - -em { - color: inherit; - font-style:italic; -} - -/******** REL bar *********/ - -.related { - display: inline; -} - -.related ul { - padding: 0px 0px 0px 10px; - margin: 0px; - text-align: left; - background-image: url(relbar_bg.png); -} - -.related li { - display: inline; - color: white; - font-weight: bold; -} - -.related li a { - color: inherit; - line-height: 35px; - font-weight: bold; - vertical-align: middle; -} - -.related li.right { - float: right; - margin-right: 5px; -} - -.related h3 { - display: none; -} - -.align-center { - text-align: center; -} - -.contentstable { - width: 100%; -} - -.contentstable td { - padding-left: 30px; - vertical-align: top; -} - -p.biglink a { - font-size: 20px; -} - -dt:target, .highlight { - background-color: #fbe54e; -} - -img { - border: 0px; -} - -.figure .caption { - font-style:italic; -} - -table.footnote { - margin: 0px; -} - -#synopsis table, table.field-list { - margin: 0px; -} - -tt.descname { - font-size: 120%; - font-weight: bold; -} - -#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul { - list-style: none; - margin: 0px; - padding: 10px; - border: 1px solid #ddd; - background-color: #f4f4f4; - -moz-border-radius:10px; - -webkit-border-radius:10px; - -khtml-border-radius:10px; -} - -#synopsis span.pre { - color: #009491; - font-weight: bolder; -} - -#detailed-description .class dt, #detailed-description .method dt, #detailed-description .attribute dt, #detailed-description .function dt { - margin: 0px; - padding: 10px; - border: 1px solid #ddd; - background-color: #f4f4f4; - -moz-border-radius:10px; - -webkit-border-radius:10px; - -khtml-border-radius:10px; -} - -.pysidetoc ul { - list-style: none; - padding: 0px; - margin: 0px; -} - -.pysidetoc em { - font-style: normal; -} - -.pysidetoc strong { - display: block; - padding: 5px; - border: 1px solid #ddd; - background-color: #f4f4f4; - -moz-border-radius:6px; - -webkit-border-radius:6px; - -khtml-border-radius:6px; -} - -.hide { - display: none; -} diff --git a/doc/_themes/pysidedocs/static/pysidelogo.png b/doc/_themes/pysidedocs/static/pysidelogo.png deleted file mode 100644 index 076c1057c..000000000 Binary files a/doc/_themes/pysidedocs/static/pysidelogo.png and /dev/null differ diff --git a/doc/_themes/pysidedocs/static/relbar_bg.png b/doc/_themes/pysidedocs/static/relbar_bg.png deleted file mode 100644 index 4036733a7..000000000 Binary files a/doc/_themes/pysidedocs/static/relbar_bg.png and /dev/null differ diff --git a/doc/_themes/pysidedocs/theme.conf b/doc/_themes/pysidedocs/theme.conf deleted file mode 100644 index e0a652a5d..000000000 --- a/doc/_themes/pysidedocs/theme.conf +++ /dev/null @@ -1,7 +0,0 @@ -[theme] -inherit = default -stylesheet = pysidedocs.css -pygments_style = none - -[options] -nosidebar = false diff --git a/doc/codeinjectionsemantics.rst b/doc/codeinjectionsemantics.rst deleted file mode 100644 index d748a3aae..000000000 --- a/doc/codeinjectionsemantics.rst +++ /dev/null @@ -1,397 +0,0 @@ -************************ -Code Injection Semantics -************************ - -API Extractor provides the `inject-code -`_ tag -allowing the user to put custom written code to on specific locations of the generated code. -Yet this is only part of what is needed to generate proper binding code, where the custom code -should be written to depends upon the technology used on the generated binding code. - -This is the ``inject-code`` tag options that matters to |project|. - - .. code-block:: xml - - - // custom code - - -Conventions -=========== - -**C++ Wrapper** - This term refers to a generated C++ class that extends a class from the - wrapped library. It is used only when a wrapped C++ class is polymorphic, - i.e. it has or inherits any virtual methods. - -**Python Wrapper** - The code that exports the C++ wrapped class to Python. **Python wrapper** - refers to all the code needed to export a C++ class to Python, and - **Python method/function wrapper** means the specific function that calls - the C++ method/function on behalf of Python. - -**Native** - This is a possible value for the ``class`` attribute of the ``inject-code`` - tag, it means things more akin to the C++ side. - -**Target** - Another ``class`` attribute value, it indicates things more close to the - Python side. - -inject-code tag -=============== - -The following table describes the semantics of ``inject-code`` tag as used on -|project|. - - +---------------+------+---------+--------------------------------------------------------------+ - |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 |beginning|Used only for virtual functions. The code is injected when the| - | | | |function does not has a pyhton 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. | - +---------------+------+---------+--------------------------------------------------------------+ - - -Anatomy of Code Injection -========================= - -To make things clear let's use a simplified example of generated wrapper code -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++ - - 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 -generated wrapper code with the injection spots marked with comments. - -Noteworthy Cases ----------------- - -The type system description system gives the binding developer a lot of -flexibility, which is power, which comes with responsibility. Some modifications -to the wrapped API will not be complete without some code injection. - - -Removing arguments and setting a default values for them -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A simple case is when a function have one argument removed, as when the C++ -method ``METHOD(ARG)`` is modified to be used from Python as ``METHOD()``; -of course the binding developer must provide some guidelines to the generator -on what to do to call it. The most common solution is to remove the argument and -set a default value for it at the same time, so the original C++ method could be -called without problems. - -Removing arguments and calling the method with your own hands -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If the argument is removed and no default value is provided, the generator will -not write any call to the method and expect the ``modify-function - target/beginning`` -code injection to call the original C++ method on its own terms. If even this -custom code is not provided the generator will put an ``#error`` clause to -prevent compilation of erroneus binding code. - -Calling the method with your own hands always! -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If your custom code to be injected contains a call to the wrapped C++ method, -it surely means that you don't want the generator to write another call to the -same method. As expected |project| will detect the user written call on the code -injection and will not write its own call, but for this to work properly the -binding developer must use the template variable ``%FUNCTION_NAME`` instead -of writing the actual name of the wrapped method/function. - -In other words, use - - .. code-block:: xml - - - %CPPSELF.originalMethodName(); - - - -instead of - - - .. code-block:: xml - - - %CPPSELF.%FUNCTION_NAME(); - - - -Code Injection for Functions/Methods -==================================== - - -.. _codeinjecting_method_native: - -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++ - - 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 ...) - - // INJECT-CODE: - // Uses: pre method call custom code, modify the argument before the - // Python call. - - (... Python method call goes in here ...) - - // INJECT-CODE: - // Uses: post method call custom code, modify the result before delivering - // it to C++ caller. - - (... Python method and argument tuple are dereferenced here ...) - - return Shiboken::Converter::toCpp(method_result); - } - - -On The Target Side ------------------- - -All the overloads of a method from C++ are gathered together on a single Python -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++ - - static PyObject* - PyInjectCode_overloadedMethod(PyObject* self, PyObject* arg) - { - PyObject* py_result = 0; - if (PyFloat_Check(arg)) { - double cpp_arg0 = Shiboken::Converter::toCpp(arg); - - // INJECT-CODE: - // Uses: pre method call custom code. - - py_result = Shiboken::Converter::toPython( - PyInjectCode_cptr(self)->InjectCode::overloadedMethod(cpp_arg0) - ); - - // INJECT-CODE: - // Uses: post method call custom code. - - } else if (PyNumber_Check(arg)) { - (... other overload calling code ...) - } else goto PyInjectCode_overloadedMethod_TypeError; - - if (PyErr_Occurred() || !py_result) - return 0; - - return py_result; - - PyInjectCode_overloadedMethod_TypeError: - PyErr_SetString(PyExc_TypeError, "'overloadedMethod()' called with wrong parameters."); - return 0; - } - - -.. _codeinjecting_classes: - -Code Injection for Wrapped Classes -================================== - -.. _codeinjecting_classes_native: - -On The Native Side ------------------- - -Those injections go in the body of the ``CLASSNAME_wrapper.cpp`` file for the -wrapped class. - - .. code-block:: c++ - - // Start of ``CLASSNAME_wrapper.cpp`` - #define protected public - // default includes - #include - (...) - #include "injectcode_wrapper.h" - using namespace Shiboken; - - // INJECT-CODE: - // Uses: prototype declarations - - (... C++ wrapper virtual methods, if any ...) - - (... Python wrapper code ...) - - PyAPI_FUNC(void) - init_injectcode(PyObject *module) - { - (...) - } - - (...) - - // INJECT-CODE: - // Uses: definition of functions prototyped at ``native/beginning``. - - // End of ``CLASSNAME_wrapper.cpp`` - - -.. _codeinjecting_classes_target: - -On The Target Side ------------------- - -Code injections to the class Python initialization function. - - .. code-block:: c++ - - // Start of ``CLASSNAME_wrapper.cpp`` - - (...) - - PyAPI_FUNC(void) - init_injectcode(PyObject *module) - { - // INJECT-CODE: - // Uses: Alter something in the PyInjectCode_Type (tp_flags value for example) - // before registering it. - - if (PyType_Ready(&PyInjectCode_Type) < 0) - return; - - Py_INCREF(&PyInjectCode_Type); - PyModule_AddObject(module, "InjectCode", - ((PyObject*)&PyInjectCode_Type)); - - // INJECT-CODE: - // 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`` - -Code Injection for Modules -========================== - -The C++ libraries are wapped as Python modules, a collection of classes, -functions, enums and namespaces. |project| creates wrapper files for all of -them and also one extra ``MODULENAME_module_wrapper.cpp`` to register the whole -module. Code injection xml tags who have the ``typesystem`` tag as parent will -be put on this file. - -On The Native Side ------------------- - -This works exactly as the class wrapper code injections :ref:`codeinjecting_classes_native`. - -On The Target Side ------------------- - -This is very similar to class wrapper code injections :ref:`codeinjecting_classes_target`. -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++ - - // Start of ``MODULENAME_module_wrapper.cpp`` - - (...) - initMODULENAME() - { - // INJECT-CODE: - // Uses: do something before the module is created. - - PyObject* module = Py_InitModule("MODULENAME", MODULENAME_methods); - - (... initialization of wrapped classes, namespaces, functions and enums ...) - - // INJECT-CODE: - // Uses: do something after the module is registered and initialized. - - if (PyErr_Occurred()) - Py_FatalError("can't initialize module sample"); - } - - (...) - - // Start of ``MODULENAME_module_wrapper.cpp`` - diff --git a/doc/commandlineoptions.rst b/doc/commandlineoptions.rst deleted file mode 100644 index d373561cd..000000000 --- a/doc/commandlineoptions.rst +++ /dev/null @@ -1,105 +0,0 @@ -.. _command-line: - -Command line options -******************** - -Usage ------ - -:: - - shiboken [options] header-file typesystem-file - - -Options -------- - -``--disable-verbose-error-messages`` - Disable verbose error messages. Turn the CPython code hard to debug but saves a few kilobytes - in the generated binding. - -.. _parent-heuristic: - -``--enable-parent-ctor-heuristic`` - This flag enable an useful heuristic which can save a lot of work related to object ownership when - writing the typesystem. - For more info, check :ref:`ownership-parent-heuristics`. - -.. _pyside-extensions: - -``--enable-pyside-extensions`` - Enable pyside extensions like support for signal/slots. Use this if you are creating a binding based - on PySide. - -.. _return-heuristic: - -``--enable-return-value-heuristic`` - Enable heuristics to detect parent relationship on return values. - For more info, check :ref:`return-value-heuristics`. - -.. _api-version: - -``--api-version=`` - Specify the supported api version used to generate the bindings. - -.. _debug-level: - -``--debug-level=[sparse|medium|full]`` - Set the debug level. - -.. _documentation-only: - -``--documentation-only`` - Do not generate any code, just the documentation. - -.. _drop-type-entries: - -``--drop-type-entries="[;TypeEntry1;...]"`` - Semicolon separated list of type system entries (classes, namespaces, - global functions and enums) to be dropped from generation. - -.. _generation-set: - -``--generation-set`` - Generator set to be used (e.g. qtdoc). - -.. _help: - -``--help`` - Display this help and exit. - -.. _include-paths: - -``--include-paths=[::...]`` - Include paths used by the C++ parser. - -.. _license-file=[license-file]: - -``--license-file=[license-file]`` - File used for copyright headers of generated files. - -.. _no-suppress-warnings: - -``--no-suppress-warnings`` - Show all warnings. - -.. _output-directory: - -``--output-directory=[dir]`` - The directory where the generated files will be written. - -.. _silent: - -``--silent`` - Avoid printing any message. - -.. _typesystem-paths: - -``--typesystem-paths=[::...]`` - Paths used when searching for type system files. - -.. _version: - -``--version`` - Output version information and exit. - diff --git a/doc/conf.py.in b/doc/conf.py.in deleted file mode 100644 index ed61d2695..000000000 --- a/doc/conf.py.in +++ /dev/null @@ -1,166 +0,0 @@ -# -*- coding: utf-8 -*- -# -# PyQtB 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. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, 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('.')) - -# -- 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'] - -rst_epilog = """ -.. |project| replace:: Shiboken -""" - -# 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' - -# The encoding of source files. -source_encoding = 'utf-8' - -# The master toctree document. -#master_doc = 'contents' - -# General information about the project. -project = u'Shiboken' -copyright = u'Copyright (C) 2016 The Qt Company Ltd.' - -# 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@' -# The full version, including alpha/beta/rc tags. -release = '@shiboken_VERSION@' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of documents that shouldn't be included in the build. -#unused_docs = [] - -# List of directories, relative to source directory, that shouldn't be searched -# for source files. -exclude_trees = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. Major themes that come with -# Sphinx are currently 'default' and 'sphinxdoc'. -html_theme = 'pysidedocs' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = { -#} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# 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 = None - -# 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 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -#html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = { '' : ''} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -html_additional_pages = { 'index' : 'index.html'} - -# If false, no module index is generated. -html_use_modindex = False - -# If false, no index is generated. -html_use_index = False - -# If true, the index is split into individual pages for each letter. -html_split_index = False - -# If true, links to the reST sources are added to the pages. -html_show_sourcelink = False - -html_add_permalinks = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = '' - diff --git a/doc/contents.rst b/doc/contents.rst deleted file mode 100644 index 24adb1c68..000000000 --- a/doc/contents.rst +++ /dev/null @@ -1,17 +0,0 @@ -Table of contents -***************** -.. toctree:: - :numbered: - :maxdepth: 3 - - faq.rst - overview.rst - commandlineoptions.rst - projectfile.rst - typesystemvariables.rst - typeconverters.rst - codeinjectionsemantics.rst - sequenceprotocol.rst - ownership.rst - wordsofadvice.rst - shibokenmodule.rst diff --git a/doc/dependency-pyqtb.svg b/doc/dependency-pyqtb.svg deleted file mode 100644 index a458bf6fb..000000000 --- a/doc/dependency-pyqtb.svg +++ /dev/null @@ -1,600 +0,0 @@ - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - API Extractor - 0.2 - Headers and libraries - compile-time - LGPL version 2.1 - - - - - - Shiboken (generator) - 0.1 - Binary executable - compile-time - GPL version 2 - - - - - - boost::graph - 1.38.0 - headers and libraries - compile-time - Boost Software License 1.0 - - - - - - - - - Boost - - - - Qt Software - - - - INdT/Nokia - - - - Python Foundation - - - - - - - - libshiboken - 0.1 - Headers and libraries - compile-time - LGPL version 2.1 - - - - - - Qt 4.5 - 4.5 - headers and libraries - compile-time and run-time - GNU General Public License v3 /GNU Lesser General Public Licence v2.1 - - - - - - Python - 2.6 - Headers and libraries - compile-time and run-time - Python license - - - - - - diff --git a/doc/dependency-pyside.svg b/doc/dependency-pyside.svg deleted file mode 100644 index 786bdb8a6..000000000 --- a/doc/dependency-pyside.svg +++ /dev/null @@ -1,527 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - boost::python - 1.38.0 - headers and libraries - compile-time and run-time - Boost Software License 1.0 - - - - Qt 4.5 - 4.5 - headers and libraries - compile-time and run-time - GNU General Public License v3 /GNU Lesser General Public Licence v2.1 - - - - libapiextractor - 0.1 - headers and libraries - compile-time and run-time - LGPL version 2.1 - - - - BoostPythonGenerator - 0.1 - Binary executable - compile-time - LGPL version 2.1 - - - - Qt Python bindings - 0.1 - Target - LGPL version 2.1 - - - - boost::graph - 1.38.0 - headers and libraries - compile-time and run-time - Boost Software License 1.0 - - - - - - - - - Boost - Qt Software - INdT/Nokia - - - - - diff --git a/doc/faq.rst b/doc/faq.rst deleted file mode 100644 index 77e0fbdfc..000000000 --- a/doc/faq.rst +++ /dev/null @@ -1,67 +0,0 @@ -************************** -Frequently Asked Questions -************************** - -This is a list of Frequently Asked Questions about |project|. Feel free to -suggest new entries! - -General -======= - -What is Shiboken? ------------------ - -Shiboken is a `GeneratorRunner `_ -plugin that outputs C++ code for CPython extensions. The first version of PySide -had source code based on Boost templates. It was easier to produce code but a -paradigm change was needed, as the next question explains. - -Why did you switch from Boost.Python to Shiboken? -------------------------------------------------- - -The main reason was the size reduction. Boost.Python makes excessive use of templates -resulting in a significant increase of the binaries size. On the other hand, as Shiboken -generates CPython code, the resulting binaries are smaller. - -Creating bindings -================= - -Can I wrap non-Qt libraries? ----------------------------- - -Yes. Check Shiboken source code for an example (libsample). - - -Is there any runtime dependency on the generated binding? ---------------------------------------------------------- - -Yes. Only libshiboken, and the obvious Python interpreter -and the C++ library that is being wrapped. - -What do I have to do to create my bindings? -------------------------------------------- - -.. todo: put link to typesystem documentation - -Most of the work is already done by the API Extractor. The developer creates -a `typesystem `_ file -with any customization wanted in the generated code, like removing classes or -changing method signatures. The generator will output the .h and .cpp files -with the CPython code that will wrap the target library for python. - -Is there any recommended build system? --------------------------------------- - -Both API Extractor and generator uses and recommends the CMake build system. - -Can I write closed-source bindings with the generator? ------------------------------------------------------- - -Yes, as long as you use a LGPL version of Qt, due to runtime requirements. - -What is 'inject code'? ----------------------- - -That's how we call customized code that will be *injected* into the -generated at specific locations. They are specified inside the typesytem. - diff --git a/doc/images/.directory b/doc/images/.directory deleted file mode 100644 index e65475f65..000000000 --- a/doc/images/.directory +++ /dev/null @@ -1,3 +0,0 @@ -[Dolphin] -ShowPreview=true -Timestamp=2009,5,5,17,43,26 diff --git a/doc/images/bindinggen-development.png b/doc/images/bindinggen-development.png deleted file mode 100644 index 2dd64ba1d..000000000 Binary files a/doc/images/bindinggen-development.png and /dev/null differ diff --git a/doc/images/bindinggen-development.svg b/doc/images/bindinggen-development.svg deleted file mode 100644 index 3b6b3a26e..000000000 --- a/doc/images/bindinggen-development.svg +++ /dev/null @@ -1,543 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - Qt bindings(generated code) - - - - generatorfront-end - - - - - - - - - - - - - API Extractor - - - - 1 - - - - 2 - - - - - - - - - - - typesystem(handwritten) - - - - - - - - - - - injected code(handwritten) - - - - 3 - - - - 4 - - - - diff --git a/doc/images/boostgen.png b/doc/images/boostgen.png deleted file mode 100644 index ae9d9fc3d..000000000 Binary files a/doc/images/boostgen.png and /dev/null differ diff --git a/doc/images/boostqtarch.png b/doc/images/boostqtarch.png deleted file mode 100644 index f1b145e9c..000000000 Binary files a/doc/images/boostqtarch.png and /dev/null differ diff --git a/doc/images/boostqtarch.svg b/doc/images/boostqtarch.svg deleted file mode 100644 index 9fbb38271..000000000 --- a/doc/images/boostqtarch.svg +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - Boost::Pythonhelper library to interface with CPython APIand expose C++ entities to Python - - - - Qt-Python BindingsQt classes and functionsexported to Python - - - - - CPythonAPI - - - - Qt4Libraries - - - - - diff --git a/doc/images/converter.dot b/doc/images/converter.dot deleted file mode 100644 index 412341df9..000000000 --- a/doc/images/converter.dot +++ /dev/null @@ -1,14 +0,0 @@ -digraph Conversions { - rankdir=LR - CppType1 [ label="C++\nType" ] - Converter1 [ label="Converter\nPython -> C++", shape=hexagon ] - PythonType1 -> Converter1 - PythonType2 -> Converter1 - PythonType3 -> Converter1 - Converter1 -> CppType1 - - CppType2 [ label="C++\nType" ] - PythonType4 [ label="PythonType" ] - Converter2 [ label="Converter\nPython -> C++", shape=hexagon ] - CppType2 -> Converter2 -> PythonType4 -} \ No newline at end of file diff --git a/doc/images/converter.png b/doc/images/converter.png deleted file mode 100644 index 51cd2af71..000000000 Binary files a/doc/images/converter.png and /dev/null differ diff --git a/doc/images/genrunnerarch.png b/doc/images/genrunnerarch.png deleted file mode 100644 index db1077cd0..000000000 Binary files a/doc/images/genrunnerarch.png and /dev/null differ diff --git a/doc/images/genrunnerarch.svg b/doc/images/genrunnerarch.svg deleted file mode 100644 index ea7eb73e7..000000000 --- a/doc/images/genrunnerarch.svg +++ /dev/null @@ -1,654 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - API Extractor - - - ApiExtractorcommands the parsing andbuilding of the data modeland calls the user generators - - - front-end - - Generator Runner - - - Generatorbase class for front-endoutput classes - - - - SpecificGeneratorgenerators written for anydesired output, e.g.: HppGenerator,CppGenerator,ConverterGenerator - - - - - - Generator App* loads generators* setup API Extractor* executes each generator - - - - - - - AbstractMetaBuilderbuilds the data model with informationfrom headers and binding directives - - - - TypeDatabaseparses typesystemand stores information - - - - Parserparses thelib headers - - - - - diff --git a/doc/overview.rst b/doc/overview.rst deleted file mode 100644 index 5f50610ff..000000000 --- a/doc/overview.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. _gen-overview: - -****************** -Generator Overview -****************** - -In a few words, the Generator is a utility that parses a collection of header and -typesystem files, generating other files (code, documentation, etc.) as result. - -Creating new bindings -===================== - -.. figure:: images/bindinggen-development.png - :scale: 80 - :align: center - - Creating new bindings - -Each module of the generator system has an specific role. - -1. Provide enough data about the classes and functions. -2. Generate valid code, with modifications from typesystems and injected codes. -3. Modify the API to expose the objects in a way that fits you target language best. -4. Insert customizations where handwritten code is needed. - -.. figure:: images/boostqtarch.png - :scale: 80 - :align: center - - Runtime architecture - -The newly created binding will run on top of Boost.Python library which takes -care of interfacing Python and the underlying C++ library. - -Handwritten inputs -================== - -Creating new bindings involves creating two pieces of "code": the typesystem and -the inject code. - -:typesystem: XML files that provides the developer with a tool to customize the - way that the generators will see the classes and functions. For - example, functions can be renamed, have its signature changed and - many other actions. -:inject code: allows the developer to insert handwritten code where the generated - code is not suitable or needs some customization. diff --git a/doc/ownership.rst b/doc/ownership.rst deleted file mode 100644 index 69791f855..000000000 --- a/doc/ownership.rst +++ /dev/null @@ -1,153 +0,0 @@ -**************** -Object ownership -**************** - -One of the main things a binding developer should have in mind is -how the C++ instances lives will cope with Python's reference count. -The last thing you want is to crash a program due to a segfault -when your C++ instance was deleted and the -wrapper object tries to access the invalid memory there. - -In this section we'll show how |project| deals with object ownership -and parentship, taking advantage of the information provided by the -APIExtractor. - -Ownership basics -================ - -As any python binding, |project|-based bindings uses reference counting -to handle the life of the wrapper object (the Python object that contains the -C++ object, do not confuse with the *wrapped* C++ object). -When a reference count reaches zero, the wrapper is deleted by Python garbage -collector and tries to delete the wrapped instance, but sometimes the wrapped -C++ object is already deleted, or maybe the C++ object should not be freed after -the Python wrapper go out of scope and die, because C++ is already taking care of -the wrapped instance. - -In order to handle this, you should tell the -generator whether the instance's ownership belongs to the binding or -to the C++ Library. When belonging to the binding, we are sure that the C++ object -won't be deleted by C++ code and we can call the C++ destructor when the refcount -reaches 0. Otherwise, instances owned by C++ code can be destroyed arbitrarily, -without notifying the Python wrapper of its destruction. - -Invalidating objects -==================== - -To prevent segfaults and double frees, the wrapper objects are invalidated. -An invalidated can't be passed as argument or have an attributte or method accessed. -Trying to do this will raise RuntimeError. - -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 ` or the transfer is due to the special case - of :ref:`parent ownership `. - - Besides being passed as argument, the callee 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. - -.. _ownership-virt-method: - -Objects with virtual methods ----------------------------- - - A little bit of implementation details: - 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 overriden destructor is called. - - One exception to this rule is when the object is created in C++, like in a - factory method. This way 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: - -Parent-child relationship -========================= - -One special type of ownership is the parent-child relationship. -Being a child of an object means that when the object's parent dies, -the C++ instance also dies, so the Python references will be invalidated. -Qt's QObject system, for example, implements this behavior, but this is valid -for any C++ library with similar behavior. - -.. _ownership-parent-heuristics: - -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. - - 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. - - 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. - - To activate this heuristic, use the :ref:`--enable-parent-ctor-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. - - To activate this heuristic, use the :ref:`--enable-return-value-heuristic ` - -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 indifinitely, 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. - - .. code-block:: python - - renderer.setModel(Source()) - renderer.render() - - To solve this, you should hold a reference to the source object, like in - - .. code-block:: python - - source = Source() - renderer.setSource(source) - renderer.render() - - diff --git a/doc/projectfile.rst b/doc/projectfile.rst deleted file mode 100644 index 6c9808da4..000000000 --- a/doc/projectfile.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. _project-file: - -******************** -Binding Project File -******************** - -Instead of directing the Generator behaviour via command line, the binding developer -can write a text project file describing the same information, and avoid the hassle -of a long stream of command line arguments. - -.. _project-file-structure: - -The project file structure -========================== - -Here follows a comprehensive example of a generator project file. - - .. 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 - - -Project file tags -================= - -The generator project file tags are in direct relation to the -:ref:`command line arguments `. All of the current command line -options provided by |project| were already seen on the :ref:`project-file-structure`, -for new command line options provided by additional generator modules (e.g.: qtdoc, -Shiboken) could also be used in the generator project file following simple conversion rules. - -For tags without options, just write as an empty tag without any attributes. Example: - - .. code-block:: bash - - --BOOLEAN-ARGUMENT - -becomes - - .. code-block:: ini - - BOOLEAN-ARGUMENT - -and - - .. code-block:: bash - - --VALUE-ARGUMENT=VALUE - -becomes - - .. code-block:: ini - - VALUE-ARGUMENT = VALUE - - diff --git a/doc/sequenceprotocol.rst b/doc/sequenceprotocol.rst deleted file mode 100644 index 587c0f95b..000000000 --- a/doc/sequenceprotocol.rst +++ /dev/null @@ -1,23 +0,0 @@ -Sequence Protocol ------------------ - -Support for the sequence protocol is achieved adding functions with special names, this is done using the 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 - ============= =============================================== ==================== =================== - -You just need to inform the function name to the add-function tag, without any parameter or return type information, when you do it, |project| will create a C function with parameters and return type definied by the table above. - -The function needs to follow the same semantics of the *CPython equivalent* function, the only way to do it is using the :doc:`inject-code ` tag. - -A concrete exemple how to add sequence protocol support to a class can be found on shiboken tests, more precisely in the definition of the Str class in ``tests/samplebinding/typesystem_sample.xml``. - diff --git a/doc/shiboken2.1 b/doc/shiboken2.1 deleted file mode 100644 index e017bd9a9..000000000 --- a/doc/shiboken2.1 +++ /dev/null @@ -1,73 +0,0 @@ -.TH SHIBOKEN "1" "March 2010" "shiboken v0.2.0" "User Commands" -.SH NAME -shiboken \- CPython bindings generator for C++ libraries -.SH DESCRIPTION -.SS "Usage:" -.IP -shiboken [options] header\-file typesystem\-file -.SS "General options:" -.TP -\fB\-\-debug\-level\fR=\fI[sparse\fR|medium|full] -Set the debug level -.TP -\fB\-\-documentation\-only\fR -Do not generates any code, just the documentation -.TP -\fB\-\-generatorSet\fR -generatorSet to be used. e.g. qtdoc -.TP -\fB\-\-help\fR -Display this help and exit -.TP -\fB\-\-include\-paths=\fR[::...] -Include paths used by the C++ parser -.TP -\fB\-\-license\-file\fR=\fI[licensefile]\fR -File used for copyright headers of generated files -.TP -\fB\-\-no\-suppress\-warnings\fR -Show all warnings -.TP -\fB\-\-output\-directory\fR=\fI[dir]\fR -The directory where the generated files will be written -.TP -\fB\-\-silent\fR -Avoid printing any message -.TP -\fB\-\-typesystem\-paths=\fR[::...] -Paths used when searching for typesystems -.TP -\fB\-\-version\fR -Output version information and exit -.SS "Shiboken options:" -.TP -\fB\-\-disable\-verbose\-error\-messages\fR -Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. -.TP -\fB\-\-enable\-parent\-ctor\-heuristic\fR -Enable heuristics to detect parent relationship on constructors. -.TP -\fB\-\-enable\-pyside\-extensions\fR -Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. -.TP -\fB\-\-enable\-return\-value\-heuristic\fR -Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) -.SS "Shiboken options:" -.TP -\fB\-\-disable\-verbose\-error\-messages\fR -Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. -.TP -\fB\-\-enable\-parent\-ctor\-heuristic\fR -Enable heuristics to detect parent relationship on constructors. -.TP -\fB\-\-enable\-pyside\-extensions\fR -Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. -.TP -\fB\-\-enable\-return\-value\-heuristic\fR -Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) -.SH COPYRIGHT -Copyright \(co 2016 The Qt Company Ltd. -.SH AUTHOR -.PP -This manpage was written for Debian, starting with a help2man output, by -Didier Raboud , on the 26. March 2010. diff --git a/doc/shibokenmodule.rst b/doc/shibokenmodule.rst deleted file mode 100644 index 150998ccd..000000000 --- a/doc/shibokenmodule.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. module:: shiboken - -.. |maya| unicode:: Maya U+2122 - -Shiboken module -*************** - -Functions -^^^^^^^^^ - -.. container:: function_list - - * def :meth:`isValid` (obj) - * def :meth:`wrapInstance` (address, type) - * def :meth:`getCppPointer` (obj) - * def :meth:`delete` (obj) - * def :meth:`isOwnedByPython` (obj) - * def :meth:`wasCreatedByPython` (obj) - * def :meth:`dump` (obj) - -Detailed description -^^^^^^^^^^^^^^^^^^^^ - -This Python module can be used to access internal information related to our -binding technology. Access to this internal information is required to e.g.: -integrate PySide with Qt based programs that offer Python scripting like |maya| -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. - - -.. function:: isValid(obj) - - Given a Python object, returns True if the object methods can be called - without an exception being thrown. A Python wrapper becomes invalid when - the underlying C++ object is destroyed or unreachable. - -.. function:: wrapInstance(address, type) - - Creates a Python wrapper for a C++ object instantiated at a given memory - address - the returned object type will be the same given by the user. - - The type must be a Shiboken type, the C++ object will not be - destroyed when the returned Python object reach zero references. - - If the address is invalid or doesn't point to a C++ object of given type - the behavior is undefined. - -.. function:: getCppPointer(obj) - - Returns a tuple of longs that contain the memory addresses of the - C++ instances wrapped by the given object. - -.. function:: delete(obj) - - Deletes the C++ object wrapped by the given Python object. - -.. function:: isOwnedByPython(obj) - - Given a Python object, returns True if Python is responsible for deleting - the underlying C++ object, False otherwise. - - If the object was not a Shiboken based object, a TypeError is - thrown. - -.. function:: wasCreatedByPython(obj) - - Returns true if the given Python object was created by Python. - -.. function:: dump(obj) - - Returns a string with implementation-defined information about the - object. - This method should be used **only** for debug purposes by developers - 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. diff --git a/doc/typeconverters.rst b/doc/typeconverters.rst deleted file mode 100644 index 3779b26d7..000000000 --- a/doc/typeconverters.rst +++ /dev/null @@ -1,288 +0,0 @@ -**************************** -User Defined Type Conversion -**************************** - -In the process of creating Python bindings of a C++ library, most of the C++ classes will have wrappers representing them in Python land. But there may be other classes that are very simple and/or have a Python type as a direct counter part. (Example: a "Complex" class, that represents complex 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++ - - // 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 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 "" tag must be used. - - .. code-block:: xml - - - - - - - - return PyComplex_FromDoubles(%in.real(), %in.imag()); - - - - - - double real = PyComplex_RealAsDouble(%in); - double imag = PyComplex_ImagAsDouble(%in); - %out = %OUTTYPE(real, imag); - - - - - - - - -The details will be given later, but the gist of it are the tags -` `_, -which has only one conversion from C++ to Python, and -` `_, -that may define the conversion of multiple Python types to C++'s "Complex" type. - -.. image:: images/converter.png - :height: 240px - :align: center - -|project| expects the code for ` `_, -to directly return the Python result of the conversion, and the added conversions inside the -` `_ -must attribute the Python to C++ conversion result to the :ref:`%out ` variable. - - -Expanding on the last example, if the binding developer want a Python 2-tuple of numbers to be accepted -by wrapped C++ functions with "Complex" arguments, an -` `_ -tag and a custom check must be added. Here's how to do it: - - .. code-block:: xml - - - - static bool Check2TupleOfNumbers(PyObject* pyIn) { - if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) - return false; - Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); - if (!SbkNumber_Check(pyReal)) - return false; - Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); - if (!SbkNumber_Check(pyImag)) - return false; - return true; - } - - - - - - - - - return PyComplex_FromDoubles(%in.real(), %in.imag()); - - - - - - double real = PyComplex_RealAsDouble(%in); - double imag = PyComplex_ImagAsDouble(%in); - %out = %OUTTYPE(real, imag); - - - - 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); - - - - - - - - - - -.. _container_conversions: - -Container Conversions -===================== - -Converters for -` `_ -are pretty much the same as for other type, except that they make use of the type system variables -:ref:`%INTYPE_# ` and :ref:`%OUTTYPE_# `. |project| combines the conversion code for -containers with the conversion defined (or automatically generated) for the containees. - - - .. code-block:: xml - - - - - - - - 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; - - - - - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(%in, &pos, &key, &value)) { - %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); - %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); - %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); - } - - - - - - - -.. _variables_and_functions: - -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. - - -.. _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. - - -.. _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. - - -.. _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 - - - - - - - -And implemented in a separate C++ file, like this: - - - .. code-block:: c++ - - namespace Shiboken { - template<> struct Converter - { - 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(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 -` `_ -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/doc/typesystemvariables.rst b/doc/typesystemvariables.rst deleted file mode 100644 index 205430550..000000000 --- a/doc/typesystemvariables.rst +++ /dev/null @@ -1,336 +0,0 @@ -********************* -Type System Variables -********************* - -User written code can be placed in arbitrary places using the -:doc:`inject-code ` tag. To ease the binding developer -work, the injected code can make use of special variables that will be replaced -by the correct values. This also shields the developer from some |project| -implementation specifics. - - -.. _variables: - -Variables -========= - - -.. _cpp_return_argument: - -**%0** - - Replaced by the C++ return variable of the Python method/function wrapper. - - -.. _arg_number: - -**%#** - - Replaced by the name of a C++ argument in the position indicated by ``#``. - 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++ - - void argRemoval(int a0, int a1 = 123); - - - .. code-block:: xml - - - - - - - - The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the - value ``123``. - - -.. _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 - system), this value will be inserted in the argument list. If you want to remove - the argument so completely that it doesn't appear in any form on the - ``%ARGUMENT_NAMES`` replacement, don't forget to remove also its default value - with the ` - `_ - type system tag. - - Take the following method and related type system description as an example: - - .. code-block:: c++ - - void argRemoval(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 56); - - - .. code-block:: xml - - - - - - - - - - - - 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++ - - %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 - return type, as this is already done by the - :ref:`%RETURN_TYPE ` variable. - Example: - - .. code-block:: c++ - - void argRemoval(int a0, int a1 = 123); - - - .. code-block:: xml - - - - - - - - The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the - value ``123``. - - -.. _converttocpp: - -**%CONVERTTOCPP[CPPTYPE]** - - Replaced by a |project| conversion call that converts a Python variable - to a C++ variable of the type indicated by ``CPPTYPE``. - - -.. _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. - - -.. _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``. - - -.. _checktype: - -**%CHECKTYPE[CPPTYPE]** - - Replaced by a |project| "checkType" call that verifies if a Python - if of the type indicated by ``CPPTYPE``. - - -.. _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 - the :ref:`%TYPE ` variable, for this latter may be translated to the original - C++ class name or to the C++ wrapper class name. - - Namespaces will are treated as classes, so ``CPPTYPE`` will work for them and their - enclosed functions as well. - -.. _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_#** - - Similar to ``%#``, but is replaced by the Python arguments (PyObjects) - received by the Python wrapper method. - - If used in the context of a native code injection, i.e. in a virtual method - override, ``%PYARG_#`` will be translated to one item of the Python tuple - holding the arguments that should be passed to the Python override for this - virtual method. - - The example - - .. code-block:: c++ - - long a = PyInt_AS_LONG(%PYARG_1); - - - is equivalent of - - .. code-block:: c++ - - long a = PyInt_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); - - - The generator tries to be smart with attributions, but it will work for the - only simplest cases. - - This example - - .. code-block:: c++ - - Py_DECREF(%PYARG_1); - %PYARG_1 = PyInt_FromLong(10); - - - is equivalent of - - .. code-block:: c++ - - Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); - PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyInt_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. - - -.. _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 - C++ parent's one. - - -.. _python_method_override: - -**%PYTHON_METHOD_OVERRIDE** - - This variable is used only on :ref:`native method code injections - `, i.e. on the binding overrides for C++ virtual - methods. It is replaced by a pointer to the Python method override. - - -.. _pythontypeobject: - -**%PYTHONTYPEOBJECT** - - Replaced by the Python type object for the context in which it is inserted: - method or class modification. - - -.. _beginallowthreads: - -**%BEGIN_ALLOW_THREADS** - - Replaced by a thread state saving procedure. - Must match with a :ref:`%END_ALLOW_THREADS ` variable. - - -.. _endallowthreads: - -**%END_ALLOW_THREADS** - - Replaced by a thread state restoring procedure. - Must match with a :ref:`%BEGIN_ALLOW_THREADS ` variable. - - -.. _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. - - -.. _example: - -Example -======= - -Just to illustrate the usage of the variables described in the previous -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 - - - - - - - - - - int argc; - char** argv; - if (!PySequence_to_argc_argv(%PYARG_1, &argc, &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 < argc; ++i) - delete[] argv[i]; - delete[] argv; - - - diff --git a/doc/wordsofadvice.rst b/doc/wordsofadvice.rst deleted file mode 100644 index b66799338..000000000 --- a/doc/wordsofadvice.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _words-of-advice: - -*************** -Words of Advice -*************** - -When writing or using Python bindings there is some things you must keep in mind. - - -.. _duck-punching-and-virtual-methods: - -Duck punching and virtual methods -================================= - -The combination of duck punching, the practice of altering class characteristics -of already instantiated objects, and virtual methods of wrapped C++ classes, can -be tricky. That was an optimistic statement. - -Let's see duck punching in action for educational purposes. - - .. code-block:: python - - import types - import Binding - - obj = Binding.CppClass() - - # 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) - - -If some C++ code happens to call `CppClass::virtualMethod(...)` on the C++ object -held by "obj" Python object, the new duck punched "virtualMethod" method will be -properly called. That happens because the underlying C++ object is in fact an instance -of a generated C++ class that inherits from `CppClass`, let's call it `CppClassWrapper`, -responsible for receiving the C++ virtual method calls and finding out the proper Python -override to which handle such a call. - -Now that you know this, consider the case when C++ has a factory method that gives you -new C++ objects originated somewhere in C++-land, in opposition to the ones generated in -Python-land by the usage of class constructors, like in the example above. - -Brief interruption to show what I was saying: - - .. code-block:: python - - import types - import Binding - - obj = Binding.createCppClass() - def myVirtualMethod(self_obj, arg): - pass - - # Punching a dead duck... - obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass) - - -The `Binding.createCppClass()` factory method is just an example, C++ created objects -can pop out for a number of other reasons. Objects created this way have a Python wrapper -holding them as usual, but the object held is not a `CppClassWrapper`, but a regular -`CppClass`. All virtual method calls originated in C++ will stay in C++ and never reach -a Python virtual method overridden via duck punching. - -Although duck punching is an interesting Python feature, it don't mix well with wrapped -C++ virtual methods, specially when you can't tell the origin of every single wrapped -C++ object. In summary: don't do it! - - -.. _pyside-old-style-class: - -Python old style classes and PySide -=================================== - -Because of some architectural decisions and deprecated Python types. Since PySide 1.1 old style classes are not supported with multiple inheritance. - -Below you can check the examples: - -Example with old style class: - - .. code-block:: python - - from PySide2 import QtCore - - class 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 - - from PySide2 import QtCore - - class MyOldStyleObject(object): - pass - - class MyObject(QtCore, MyOldStyleObject): - pass - - -All classes used for multiple inheritance with other PySide types need to have 'object' as base class. diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt deleted file mode 100644 index 032118666..000000000 --- a/generator/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -project(shibokengenerator) - -find_package(Qt5Xml) -find_package(Qt5XmlPatterns) - -set(shiboken2_SRC -generator.cpp -shiboken2/cppgenerator.cpp -shiboken2/headergenerator.cpp -shiboken2/overloaddata.cpp -shiboken2/shibokengenerator.cpp -main.cpp -) - -if (NOT DISABLE_DOCSTRINGS) - set(shiboken2_SRC ${shiboken2_SRC} qtdoc/qtdocgenerator.cpp) - add_definitions(-DDOCSTRINGS_ENABLED) -endif() - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shiboken2 - ${CMAKE_CURRENT_SOURCE_DIR}/qtdoc - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${apiextractor_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${Qt5XmlPatterns_INCLUDE_DIRS} - ) - -add_executable(shiboken2 ${shiboken2_SRC}) -add_dependencies(shiboken2 apiextractor) -set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken2_SUFFIX}) -target_link_libraries(shiboken2 - apiextractor - ${Qt5Core_LIBRARIES} - ${Qt5XmlPatterns_LIBRARIES} - ) - -configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) - -install(TARGETS shiboken2 DESTINATION bin) diff --git a/generator/generator.cpp b/generator/generator.cpp deleted file mode 100644 index 76d104c12..000000000 --- a/generator/generator.cpp +++ /dev/null @@ -1,864 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "generator.h" -#include "abstractmetalang.h" -#include "reporthandler.h" -#include "fileout.h" -#include "apiextractor.h" -#include "typesystem.h" - -#include -#include -#include -#include -#include -#include - -struct Generator::GeneratorPrivate { - const ApiExtractor* apiextractor; - QString outDir; - // License comment - QString licenseComment; - QString packageName; - int numGenerated; - QStringList instantiatedContainersNames; - QStringList instantiatedSmartPointerNames; - QVector instantiatedContainers; - QVector instantiatedSmartPointers; - -}; - -Generator::Generator() : m_d(new GeneratorPrivate) -{ - m_d->numGenerated = 0; -} - -Generator::~Generator() -{ - delete m_d; -} - -bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args) -{ - m_d->apiextractor = &extractor; - TypeEntryHash allEntries = TypeDatabase::instance()->allEntries(); - TypeEntry* entryFound = 0; - for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { - for (TypeEntry *entry : it.value()) { - if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) { - entryFound = entry; - break; - } - } - if (entryFound) - break; - } - if (entryFound) - m_d->packageName = entryFound->name(); - else - qCWarning(lcShiboken) << "Couldn't find the package name!!"; - - collectInstantiatedContainersAndSmartPointers(); - - return doSetup(args); -} - -QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type) -{ - const QString signature = type->cppSignature(); - if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer()) - return signature; - QString typeName = signature; - if (type->isConstant()) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - switch (type->referenceType()) { - case NoReference: - break; - case LValueReference: - typeName.chop(1); - break; - case RValueReference: - typeName.chop(2); - break; - } - while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' '))) - typeName.chop(1); - return typeName; -} - -void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, - const QString &context) -{ - if (!type) - return; - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType* t : instantiations) - addInstantiatedContainersAndSmartPointers(t, context); - if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer()) - return; - bool isContainer = type->typeEntry()->isContainer(); - if (type->hasTemplateChildren()) { - QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer"); - QString warning = - QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template" - " arguments.").arg(piece).arg(type->originalTypeDescription()); - if (!context.isEmpty()) - warning.append(QStringLiteral(" Calling context: %1").arg(context)); - - qCWarning(lcShiboken).noquote().nospace() << warning; - return; - - } - QString typeName = getSimplifiedContainerTypeName(type); - if (isContainer) { - if (!m_d->instantiatedContainersNames.contains(typeName)) { - m_d->instantiatedContainersNames.append(typeName); - m_d->instantiatedContainers.append(type); - } - } else { - // Is smart pointer. - if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { - m_d->instantiatedSmartPointerNames.append(typeName); - m_d->instantiatedSmartPointers.append(type); - } - } - -} - -void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction *func) -{ - addInstantiatedContainersAndSmartPointers(func->type(), func->signature()); - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) - addInstantiatedContainersAndSmartPointers(arg->type(), func->signature()); -} - -void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass) -{ - if (!metaClass->typeEntry()->generateCode()) - return; - const AbstractMetaFunctionList &funcs = metaClass->functions(); - for (const AbstractMetaFunction *func : funcs) - collectInstantiatedContainersAndSmartPointers(func); - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField *field : fields) - addInstantiatedContainersAndSmartPointers(field->type(), field->name()); - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - collectInstantiatedContainersAndSmartPointers(innerClass); -} - -void Generator::collectInstantiatedContainersAndSmartPointers() -{ - const AbstractMetaFunctionList &funcs = globalFunctions(); - for (const AbstractMetaFunction *func : funcs) - collectInstantiatedContainersAndSmartPointers(func); - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) - collectInstantiatedContainersAndSmartPointers(metaClass); -} - -QVector Generator::instantiatedContainers() const -{ - return m_d->instantiatedContainers; -} - -QVector Generator::instantiatedSmartPointers() const -{ - return m_d->instantiatedSmartPointers; -} - -QMap< QString, QString > Generator::options() const -{ - return QMap(); -} - -AbstractMetaClassList Generator::classes() const -{ - return m_d->apiextractor->classes(); -} - -AbstractMetaClassList Generator::classesTopologicalSorted(const Dependencies &additionalDependencies) const -{ - return m_d->apiextractor->classesTopologicalSorted(additionalDependencies); -} - -AbstractMetaFunctionList Generator::globalFunctions() const -{ - return m_d->apiextractor->globalFunctions(); -} - -AbstractMetaEnumList Generator::globalEnums() const -{ - return m_d->apiextractor->globalEnums(); -} - -PrimitiveTypeEntryList Generator::primitiveTypes() const -{ - return m_d->apiextractor->primitiveTypes(); -} - -ContainerTypeEntryList Generator::containerTypes() const -{ - return m_d->apiextractor->containerTypes(); -} - -const AbstractMetaEnum* Generator::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const -{ - return m_d->apiextractor->findAbstractMetaEnum(typeEntry); -} - -const AbstractMetaEnum* Generator::findAbstractMetaEnum(const TypeEntry* typeEntry) const -{ - return m_d->apiextractor->findAbstractMetaEnum(typeEntry); -} - -const AbstractMetaEnum* Generator::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const -{ - return m_d->apiextractor->findAbstractMetaEnum(typeEntry); -} - -const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType* metaType) const -{ - return m_d->apiextractor->findAbstractMetaEnum(metaType); -} - -QSet< QString > Generator::qtMetaTypeDeclaredTypeNames() const -{ - return m_d->apiextractor->qtMetaTypeDeclaredTypeNames(); -} - -QString Generator::licenseComment() const -{ - return m_d->licenseComment; -} - -void Generator::setLicenseComment(const QString& licenseComment) -{ - m_d->licenseComment = licenseComment; -} - -QString Generator::packageName() const -{ - return m_d->packageName; -} - -QString Generator::moduleName() const -{ - QString& pkgName = m_d->packageName; - return QString(pkgName).remove(0, pkgName.lastIndexOf(QLatin1Char('.')) + 1); -} - -QString Generator::outputDirectory() const -{ - return m_d->outDir; -} - -void Generator::setOutputDirectory(const QString &outDir) -{ - m_d->outDir = outDir; -} - -int Generator::numGenerated() const -{ - return m_d->numGenerated; -} - -inline void touchFile(const QString &filePath) -{ - QFile toucher(filePath); - qint64 size = toucher.size(); - if (!toucher.open(QIODevice::ReadWrite)) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Failed to touch file '%1'") - .arg(QDir::toNativeSeparators(filePath)); - return; - } - toucher.resize(size+1); - toucher.resize(size); - toucher.close(); -} - -bool Generator::generateFileForContext(GeneratorContext &context) -{ - AbstractMetaClass *cls = context.metaClass(); - - if (!shouldGenerate(cls)) - return true; - - const QString fileName = fileNameForContext(context); - if (fileName.isEmpty()) - return true; - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "generating: " << fileName; - - QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls) - + QLatin1Char('/') + fileName; - FileOut fileOut(filePath); - - generateClass(fileOut.stream, context); - - FileOut::State state = fileOut.done(); - switch (state) { - case FileOut::Failure: - return false; - case FileOut::Unchanged: - // Even if contents is unchanged, the last file modification time should be updated, - // so that the build system can rely on the fact the generated file is up-to-date. - touchFile(filePath); - break; - case FileOut::Success: - break; - } - - ++m_d->numGenerated; - return true; -} - -QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType, - const AbstractMetaClass *smartPointerClass) const -{ - const AbstractMetaType *innerType = smartPointerType->getSmartPointerInnerType(); - QString fileName = smartPointerClass->qualifiedCppName().toLower(); - fileName.replace(QLatin1String("::"), QLatin1String("_")); - fileName.append(QLatin1String("_")); - fileName.append(innerType->name().toLower()); - - return fileName; -} - -bool Generator::generate() -{ - const AbstractMetaClassList &classList = m_d->apiextractor->classes(); - for (AbstractMetaClass *cls : classList) { - GeneratorContext context(cls); - if (!generateFileForContext(context)) - return false; - } - - for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) { - AbstractMetaClass *smartPointerClass = - AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->name()); - GeneratorContext context(smartPointerClass, type, true); - if (!generateFileForContext(context)) - return false; - } - return finishGeneration(); -} - -bool Generator::shouldGenerateTypeEntry(const TypeEntry* type) const -{ - return type->codeGeneration() & TypeEntry::GenerateTargetLang; -} - -bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const -{ - return shouldGenerateTypeEntry(metaClass->typeEntry()); -} - -void verifyDirectoryFor(const QFile &file) -{ - QDir dir = QFileInfo(file).dir(); - if (!dir.exists()) { - if (!dir.mkpath(dir.absolutePath())) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("unable to create directory '%1'").arg(dir.absolutePath()); - } - } -} - -void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func) -{ - const AbstractMetaClass *cpp_class = func->ownerClass(); - if (cpp_class) - code.replace(QLatin1String("%TYPE"), cpp_class->name()); - - const AbstractMetaArgumentList &argument = func->arguments(); - for (AbstractMetaArgument *arg : argument) - code.replace(QLatin1Char('%') + QString::number(arg->argumentIndex() + 1), arg->name()); - - //template values - code.replace(QLatin1String("%RETURN_TYPE"), translateType(func->type(), cpp_class)); - code.replace(QLatin1String("%FUNCTION_NAME"), func->originalName()); - - if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) { - QString str; - QTextStream aux_stream(&str); - writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments); - code.replace(QLatin1String("%ARGUMENT_NAMES"), str); - } - - if (code.contains(QLatin1String("%ARGUMENTS"))) { - QString str; - QTextStream aux_stream(&str); - writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments); - code.replace(QLatin1String("%ARGUMENTS"), str); - } -} - -QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor) -{ - // detect number of spaces before the first character - const QStringList lst(code.split(QLatin1Char('\n'))); - static const QRegularExpression nonSpaceRegex(QStringLiteral("[^\\s]")); - Q_ASSERT(nonSpaceRegex.isValid()); - int spacesToRemove = 0; - for (const QString &line : lst) { - if (!line.trimmed().isEmpty()) { - spacesToRemove = line.indexOf(nonSpaceRegex); - if (spacesToRemove == -1) - spacesToRemove = 0; - break; - } - } - - static const QRegularExpression emptyLine(QStringLiteral("^\\s*[\\r]?[\\n]?\\s*$")); - Q_ASSERT(emptyLine.isValid()); - - for (QString line : lst) { - if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) { - while (line.end()->isSpace()) - line.chop(1); - int limit = 0; - for(int i = 0; i < spacesToRemove; ++i) { - if (!line[i].isSpace()) - break; - limit++; - } - - s << indentor << line.remove(0, limit); - } - s << endl; - } - return s; -} - -AbstractMetaFunctionList Generator::implicitConversions(const TypeEntry* type) const -{ - if (type->isValue()) { - if (const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), type)) - return metaClass->implicitConversions(); - } - return AbstractMetaFunctionList(); -} - -AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType* metaType) const -{ - return implicitConversions(metaType->typeEntry()); -} - -bool Generator::isObjectType(const TypeEntry* type) -{ - if (type->isComplex()) - return Generator::isObjectType((const ComplexTypeEntry*)type); - return type->isObject(); -} -bool Generator::isObjectType(const ComplexTypeEntry* type) -{ - return type->isObject() || type->isQObject(); -} -bool Generator::isObjectType(const AbstractMetaClass* metaClass) -{ - return Generator::isObjectType(metaClass->typeEntry()); -} -bool Generator::isObjectType(const AbstractMetaType* metaType) -{ - return isObjectType(metaType->typeEntry()); -} - -bool Generator::isPointer(const AbstractMetaType* type) -{ - return type->indirections() > 0 - || type->isNativePointer() - || type->isValuePointer(); -} - -bool Generator::isCString(const AbstractMetaType* type) -{ - return type->isNativePointer() - && type->indirections() == 1 - && type->name() == QLatin1String("char"); -} - -bool Generator::isVoidPointer(const AbstractMetaType* type) -{ - return type->isNativePointer() - && type->indirections() == 1 - && type->name() == QLatin1String("void"); -} - -QString Generator::getFullTypeName(const TypeEntry* type) const -{ - return type->isCppPrimitive() - ? type->qualifiedCppName() - : (QLatin1String("::") + type->qualifiedCppName()); -} - -QString Generator::getFullTypeName(const AbstractMetaType* type) const -{ - if (isCString(type)) - return QLatin1String("const char*"); - if (isVoidPointer(type)) - return QLatin1String("void*"); - if (type->typeEntry()->isContainer()) - return QLatin1String("::") + type->cppSignature(); - QString typeName; - if (type->typeEntry()->isComplex() && type->hasInstantiations()) - typeName = getFullTypeNameWithoutModifiers(type); - else - typeName = getFullTypeName(type->typeEntry()); - return typeName + QString::fromLatin1("*").repeated(type->indirections()); -} - -QString Generator::getFullTypeName(const AbstractMetaClass* metaClass) const -{ - return QLatin1String("::") + metaClass->qualifiedCppName(); -} - -QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const -{ - if (isCString(type)) - return QLatin1String("const char*"); - if (isVoidPointer(type)) - return QLatin1String("void*"); - if (!type->hasInstantiations()) - return getFullTypeName(type->typeEntry()); - QString typeName = type->cppSignature(); - if (type->isConstant()) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - switch (type->referenceType()) { - case NoReference: - break; - case LValueReference: - typeName.chop(1); - break; - case RValueReference: - typeName.chop(2); - break; - } - while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' '))) - typeName.chop(1); - return QLatin1String("::") + typeName; -} - -QString Generator::minimalConstructor(const AbstractMetaType* type) const -{ - if (!type || (type->referenceType() == LValueReference && Generator::isObjectType(type))) - return QString(); - - if (type->isContainer()) { - QString ctor = type->cppSignature(); - if (ctor.endsWith(QLatin1Char('*'))) - return QLatin1String("0"); - if (ctor.startsWith(QLatin1String("const "))) - ctor.remove(0, sizeof("const ") / sizeof(char) - 1); - if (ctor.endsWith(QLatin1Char('&'))) { - ctor.chop(1); - ctor = ctor.trimmed(); - } - return QLatin1String("::") + ctor + QLatin1String("()"); - } - - if (type->isNativePointer()) - return QLatin1String("static_cast<") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)"); - if (Generator::isPointer(type)) - return QLatin1String("static_cast< ::") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)"); - - if (type->typeEntry()->isComplex()) { - const ComplexTypeEntry* cType = reinterpret_cast(type->typeEntry()); - QString ctor = cType->defaultConstructor(); - if (!ctor.isEmpty()) - return ctor; - ctor = minimalConstructor(AbstractMetaClass::findClass(classes(), cType)); - if (type->hasInstantiations()) - ctor = ctor.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type)); - return ctor; - } - - return minimalConstructor(type->typeEntry()); -} - -QString Generator::minimalConstructor(const TypeEntry* type) const -{ - if (!type) - return QString(); - - if (type->isCppPrimitive()) { - const QString &name = type->qualifiedCppName(); - return name == QLatin1String("bool") - ? QLatin1String("false") : name + QLatin1String("(0)"); - } - - if (type->isEnum()) - return QLatin1String("static_cast< ::") + type->qualifiedCppName() + QLatin1String(">(0)"); - - if (type->isFlags()) - return type->qualifiedCppName() + QLatin1String("(0)"); - - if (type->isPrimitive()) { - QString ctor = reinterpret_cast(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 - // bindings will tell. - return ctor.isEmpty() - ? (QLatin1String("::") + type->qualifiedCppName() + QLatin1String("()")) - : ctor; - } - - if (type->isComplex()) - return minimalConstructor(AbstractMetaClass::findClass(classes(), type)); - - return QString(); -} - -QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const -{ - if (!metaClass) - return QString(); - - const ComplexTypeEntry* cType = reinterpret_cast(metaClass->typeEntry()); - if (cType->hasDefaultConstructor()) - return cType->defaultConstructor(); - - const AbstractMetaFunctionList &constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors); - int maxArgs = 0; - for (const AbstractMetaFunction *ctor : constructors) { - if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) - continue; - - int numArgs = ctor->arguments().size(); - if (numArgs == 0) { - maxArgs = 0; - break; - } - if (numArgs > maxArgs) - maxArgs = numArgs; - } - - QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName(); - QStringList templateTypes; - const QVector &templateArguments = metaClass->templateArguments(); - for (TypeEntry *templateType : templateArguments) - templateTypes << templateType->qualifiedCppName(); - - // Empty constructor. - if (maxArgs == 0) - return QLatin1String("::") + qualifiedCppName + QLatin1String("()"); - - QVector candidates; - - // Constructors with C++ primitive types, enums or pointers only. - // Start with the ones with fewer arguments. - for (int i = 1; i <= maxArgs; ++i) { - for (const AbstractMetaFunction *ctor : constructors) { - if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) - continue; - - const AbstractMetaArgumentList &arguments = ctor->arguments(); - if (arguments.size() != i) - continue; - - QStringList args; - for (const AbstractMetaArgument *arg : arguments) { - const TypeEntry* type = arg->type()->typeEntry(); - if (type == metaClass->typeEntry()) { - args.clear(); - break; - } - - if (!arg->originalDefaultValueExpression().isEmpty()) { - if (!arg->defaultValueExpression().isEmpty() - && arg->defaultValueExpression() != arg->originalDefaultValueExpression()) { - args << arg->defaultValueExpression(); - } - break; - } - - if (type->isCppPrimitive() || type->isEnum() || isPointer(arg->type())) { - QString argValue = minimalConstructor(arg->type()); - if (argValue.isEmpty()) { - args.clear(); - break; - } - args << argValue; - } else { - args.clear(); - break; - } - } - - if (!args.isEmpty()) - return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", "))); - - candidates << ctor; - } - } - - // Constructors with C++ primitive types, enums, pointers, value types, - // and user defined primitive types. - // Builds the minimal constructor recursively. - for (const AbstractMetaFunction *ctor : qAsConst(candidates)) { - QStringList args; - const AbstractMetaArgumentList &arguments = ctor->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (arg->type()->typeEntry() == metaClass->typeEntry()) { - args.clear(); - break; - } - QString argValue = minimalConstructor(arg->type()); - if (argValue.isEmpty()) { - args.clear(); - break; - } - args << argValue; - } - if (!args.isEmpty()) { - return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", "))); - } - } - - return QString(); -} - -QString Generator::translateType(const AbstractMetaType *cType, - const AbstractMetaClass *context, - Options options) const -{ - QString s; - static int constLen = strlen("const"); - - if (context && cType && - context->typeEntry()->isGenericClass() && - cType->originalTemplateType()) { - cType = cType->originalTemplateType(); - } - - if (!cType) { - s = QLatin1String("void"); - } else if (cType->isArray()) { - s = translateType(cType->arrayElementType(), context, options) + QLatin1String("[]"); - } else if (options & Generator::EnumAsInts && (cType->isEnum() || cType->isFlags())) { - s = QLatin1String("int"); - } else { - if (options & Generator::OriginalName) { - s = cType->originalTypeDescription().trimmed(); - if ((options & Generator::ExcludeReference) && s.endsWith(QLatin1Char('&'))) - s.chop(1); - - // remove only the last const (avoid remove template const) - if (options & Generator::ExcludeConst) { - int index = s.lastIndexOf(QLatin1String("const")); - - if (index >= (s.size() - (constLen + 1))) // (VarType const) or (VarType const[*|&]) - s = s.remove(index, constLen); - } - } else if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) { - AbstractMetaType* copyType = cType->copy(); - - 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(QLatin1String("::")); - delete copyType; - } else { - s = cType->cppSignature(); - } - } - - return s; -} - - -QString Generator::subDirectoryForClass(const AbstractMetaClass* clazz) const -{ - return subDirectoryForPackage(clazz->package()); -} - -QString Generator::subDirectoryForPackage(QString packageName) const -{ - if (packageName.isEmpty()) - packageName = m_d->packageName; - return QString(packageName).replace(QLatin1Char('.'), QDir::separator()); -} - -template -static QString getClassTargetFullName_(const T* t, bool includePackageName) -{ - QString name = t->name(); - const AbstractMetaClass* context = t->enclosingClass(); - while (context) { - name.prepend(QLatin1Char('.')); - name.prepend(context->name()); - context = context->enclosingClass(); - } - if (includePackageName) { - name.prepend(QLatin1Char('.')); - name.prepend(t->package()); - } - return name; -} - -QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName) -{ - return getClassTargetFullName_(metaClass, includePackageName); -} - -QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName) -{ - return getClassTargetFullName_(metaEnum, includePackageName); -} - -QString getClassTargetFullName(const AbstractMetaType *metaType, bool includePackageName) -{ - QString name = metaType->cppSignature(); - name.replace(QLatin1String("::"), QLatin1String("_")); - name.replace(QLatin1Char('<'), QLatin1Char('_')); - name.remove(QLatin1Char('>')); - name.remove(QLatin1Char(' ')); - if (includePackageName) { - name.prepend(QLatin1Char('.')); - name.prepend(metaType->package()); - } - return name; -} - -QString getFilteredCppSignatureString(QString signature) -{ - signature.replace(QLatin1String("::"), QLatin1String("_")); - signature.replace(QLatin1Char('<'), QLatin1Char('_')); - signature.replace(QLatin1Char('>'), QLatin1Char('_')); - signature.replace(QLatin1Char(' '), QLatin1Char('_')); - return signature; -} diff --git a/generator/generator.h b/generator/generator.h deleted file mode 100644 index 5ff5d6ae5..000000000 --- a/generator/generator.h +++ /dev/null @@ -1,448 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef GENERATOR_H -#define GENERATOR_H - -#include -#include -#include -#include -#include -#include -#include - -class ApiExtractor; -class AbstractMetaBuilder; -class AbstractMetaFunction; -class AbstractMetaClass; -class AbstractMetaEnum; -class TypeEntry; -class ComplexTypeEntry; -class AbstractMetaType; -class EnumTypeEntry; -class FlagsTypeEntry; - -QT_BEGIN_NAMESPACE -class QFile; -QT_END_NAMESPACE - -class PrimitiveTypeEntry; -class ContainerTypeEntry; -class Indentor; - -QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor); -void verifyDirectoryFor(const QFile &file); - -QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true); -QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true); -QString getClassTargetFullName(const AbstractMetaType *metaType, 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 - -/** - * 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. 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 { -public: - GeneratorContext() : m_metaClass(0), m_preciseClassType(0), m_forSmartPointer(false) {} - GeneratorContext(AbstractMetaClass *metaClass, - const AbstractMetaType *preciseType = 0, - bool forSmartPointer = false) - : m_metaClass(metaClass), - m_preciseClassType(preciseType), - m_forSmartPointer(forSmartPointer) {} - - - AbstractMetaClass *metaClass() const { return m_metaClass; } - bool forSmartPointer() const { return m_forSmartPointer; } - const AbstractMetaType *preciseType() const { return m_preciseClassType; } - -private: - AbstractMetaClass *m_metaClass; - const AbstractMetaType *m_preciseClassType; - bool m_forSmartPointer; -}; - -/** - * Base class for all generators. The default implementations does nothing, - * you must subclass this to create your own generators. - */ -class Generator -{ -public: - /// Optiosn used around the generator code - enum Option { - NoOption = 0x00000000, - BoxedPrimitive = 0x00000001, - ExcludeConst = 0x00000002, - ExcludeReference = 0x00000004, - UseNativeIds = 0x00000008, - - EnumAsInts = 0x00000010, - SkipName = 0x00000020, - NoCasts = 0x00000040, - SkipReturnType = 0x00000080, - OriginalName = 0x00000100, - ShowStatic = 0x00000200, - UnderscoreSpaces = 0x00000400, - ForceEnumCast = 0x00000800, - ArrayAsPointer = 0x00001000, - VirtualCall = 0x00002000, - SkipTemplateParameters = 0x00004000, - SkipAttributes = 0x00008000, - OriginalTypeDescription = 0x00010000, - SkipRemovedArguments = 0x00020000, - IncludeDefaultExpression = 0x00040000, - NoReturnStatement = 0x00080000, - NoBlockedSlot = 0x00100000, - - SuperCall = 0x00200000, - - GlobalRefJObject = 0x00100000, - - SkipDefaultValues = 0x00400000, - - WriteSelf = 0x00800000, - ExcludeMethodConst = 0x01000000, - - ForceValueType = ExcludeReference | ExcludeConst - }; - Q_DECLARE_FLAGS(Options, Option) - - Generator(); - virtual ~Generator(); - - bool setup(const ApiExtractor& extractor, const QMap args); - - virtual QMap options() const; - - /// Returns the classes used to generate the binding code. - AbstractMetaClassList classes() const; - - /// Returns the classes, topologically ordered, used to generate the binding code. - /// - /// The classes are ordered such that derived classes appear later in the list than - /// their parent classes. - AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const; - - /// Returns all global functions found by APIExtractor - AbstractMetaFunctionList globalFunctions() const; - - /// Returns all global enums found by APIExtractor - AbstractMetaEnumList globalEnums() const; - - /// Returns all primitive types found by APIExtractor - PrimitiveTypeEntryList primitiveTypes() const; - - /// Returns all container types found by APIExtractor - ContainerTypeEntryList containerTypes() const; - - /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found. - const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const; - - /// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found. - const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const; - - /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found. - const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const; - - /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found. - const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const; - - /// Returns the output directory - QString outputDirectory() const; - - /// Set the output directory - void setOutputDirectory(const QString &outDir); - - /** - * Start the code generation, be sure to call setClasses before callign this method. - * For each class it creates a QTextStream, call the write method with the current - * class and the associated text stream, then write the text stream contents if needed. - * \see #write - */ - bool generate(); - - - /// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case). - bool generateFileForContext(GeneratorContext &context); - - /// Returns the file base name for a smart pointer. - QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType, - const AbstractMetaClass *smartPointerClass) const; - - /// Returns the number of generated items - int numGenerated() const; - - /// Returns the generator's name. Used for cosmetic purposes. - virtual const char* name() const = 0; - - /// Returns true if the generator should generate any code for the TypeEntry. - bool shouldGenerateTypeEntry(const TypeEntry*) const; - - /// Returns true if the generator should generate any code for the AbstractMetaClass. - virtual bool shouldGenerate(const AbstractMetaClass *) const; - - /// Returns the subdirectory used to write the binding code of an AbstractMetaClass. - virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const; - - /** - * Translate metatypes to binding source format. - * \param metatype a pointer to metatype - * \param context the current meta class - * \param option some extra options - * \return the metatype translated to binding source format - */ - QString translateType(const AbstractMetaType *metatype, - const AbstractMetaClass *context, - Options options = NoOption) const; - - /** - * Function used to write the fucntion arguments on the class buffer. - * \param s the class output buffer - * \param metafunction the pointer to metafunction information - * \param count the number of function arguments - * \param options some extra options used during the parser - */ - virtual void writeFunctionArguments(QTextStream &s, - const AbstractMetaFunction *metafunction, - Options options = NoOption) const = 0; - - virtual void writeArgumentNames(QTextStream &s, - const AbstractMetaFunction *metafunction, - Options options = NoOption) const = 0; - - void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func); - - // QtScript - QSet qtMetaTypeDeclaredTypeNames() const; - - /** - * Returns the license comment to be prepended to each source file generated. - */ - QString licenseComment() const; - - /** - * Sets the license comment to be prepended to each source file generated. - */ - void setLicenseComment(const QString &licenseComment); - - /** - * Returns the package name. - */ - QString packageName() const; - - /** - * Retrieves the name of the currently processed module. - * While package name is a complete package idetification, e.g. 'PySide.QtCore', - * a module name represents the last part of the package, e.g. 'QtCore'. - * If the target language separates the modules with characters other than - * dots ('.') the generator subclass must overload this method. - * \return a string representing the last part of a package name - */ - virtual QString moduleName() 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 - */ - AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const; - - /// Convenience function for implicitConversions(const TypeEntry* type). - AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const; - - /// Check if type is a pointer. - static bool isPointer(const AbstractMetaType* type); - - /// Tells if the type or class is an Object (or QObject) Type. - static bool isObjectType(const TypeEntry* type); - static bool isObjectType(const ComplexTypeEntry* type); - static bool isObjectType(const AbstractMetaType* metaType); - static bool isObjectType(const AbstractMetaClass* metaClass); - - /// Returns true if the type is a C string (const char*). - static bool isCString(const AbstractMetaType* type); - /// Returns true if the type is a void pointer. - static bool isVoidPointer(const AbstractMetaType* type); - - // Returns the full name of the type. - QString getFullTypeName(const TypeEntry* type) const; - QString getFullTypeName(const AbstractMetaType* type) const; - QString getFullTypeName(const AbstractMetaClass* metaClass) const; - - /** - * Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers - * as 'const', '&', and '*' (except if the class is not derived from a template). - * This is useful for instantiated templates. - */ - QString getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const; - - /** - * Tries to build a minimal constructor for the type. - * It will check first for a user defined default constructor. - * Returns a null string if it fails. - */ - QString minimalConstructor(const TypeEntry* type) const; - QString minimalConstructor(const AbstractMetaType* type) const; - QString minimalConstructor(const AbstractMetaClass* metaClass) const; - -protected: - /** - * Returns the file name used to write the binding code of an AbstractMetaClass/Type. - * \param context the GeneratorContext which contains an AbstractMetaClass or AbstractMetaType - * for which the file name must be returned - * \return the file name used to write the binding code for the class - */ - virtual QString fileNamePrefix() const = 0; - virtual QString fileNameForContext(GeneratorContext &context) const = 0; - - - virtual bool doSetup(const QMap& args) = 0; - - /** - * Write the bindding code for an AbstractMetaClass. - * This is called by generate method. - * \param s text stream to write the generated output - * \param metaClass the class that should be generated - */ - virtual void generateClass(QTextStream& s, GeneratorContext &classContext) = 0; - virtual bool finishGeneration() = 0; - - /** - * Returns the subdirectory path for a given package - * (aka module, aka library) name. - * If the target language separates the package modules with characters other - * than dots ('.') the generator subclass must overload this method. - * /param packageName complete package name for which to return the subdirectory path - * or nothing the use the name of the currently processed package - * /return a string representing the subdirectory path for the given package - */ - virtual QString subDirectoryForPackage(QString packageName = QString()) const; - - QVector instantiatedContainers() const; - QVector instantiatedSmartPointers() const; - - static QString getSimplifiedContainerTypeName(const AbstractMetaType *type); - void addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, - const QString &context); - -private: - struct GeneratorPrivate; - GeneratorPrivate* m_d; - void collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction* func); - void collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass); - void collectInstantiatedContainersAndSmartPointers(); -}; - -Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options) -typedef QSharedPointer GeneratorPtr; -typedef QVector Generators; - -/** -* Utility class to store the identation level, use it in a QTextStream. -*/ -class Indentor -{ -public: - Indentor() : indent(0) {} - int indent; -}; - -/** -* Class that use the RAII idiom to set and unset the identation level. -*/ -class Indentation -{ -public: - Indentation(Indentor &indentor) : indentor(indentor) - { - indentor.indent++; - } - ~Indentation() - { - indentor.indent--; - } - -private: - Indentor &indentor; -}; - -inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor) -{ - for (int i = 0; i < indentor.indent; ++i) - s << " "; - return s; -} - -#endif // GENERATOR_H - diff --git a/generator/main.cpp b/generator/main.cpp deleted file mode 100644 index 25b50b04e..000000000 --- a/generator/main.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "generator.h" -#include "shibokenconfig.h" -#include "cppgenerator.h" -#include "headergenerator.h" -#include "qtdocgenerator.h" - -#ifdef _WINDOWS - #define PATH_SPLITTER ";" -#else - #define PATH_SPLITTER ":" -#endif - -namespace { - -class ArgsHandler -{ -public: - explicit ArgsHandler(const QMap& other); - virtual ~ArgsHandler(); - - inline QMap& args() const - { - return *m_args; - } - - inline bool argExists(const QString& s) const - { - return m_args->contains(s); - } - - QString removeArg(const QString& s); - bool argExistsRemove(const QString& s); - - inline QString argValue(const QString& s) const - { - return m_args->value(s); - } - - inline bool noArgs() const - { - return m_args->isEmpty(); - } - - QString errorMessage() const; - -private: - QMap* m_args; -}; - -ArgsHandler::ArgsHandler(const QMap& other) - : m_args(new QMap(other)) -{ -} - -ArgsHandler::~ArgsHandler() -{ - delete m_args; -} - -QString ArgsHandler::removeArg(const QString& s) -{ - QString retval; - - if (argExists(s)) { - retval = argValue(s); - m_args->remove(s); - } - - return retval; -} - -bool ArgsHandler::argExistsRemove(const QString& s) -{ - bool retval = false; - - if (argExists(s)) { - retval = true; - m_args->remove(s); - } - - return retval; -} - -QString ArgsHandler::errorMessage() const -{ - typedef QMap::ConstIterator StringMapConstIt; - - QString message; - QTextStream str(&message); - str << "shiboken: Called with wrong arguments:"; - for (StringMapConstIt it = m_args->cbegin(), end = m_args->cend(); it != end; ++it) { - str << ' ' << it.key(); - if (!it.value().isEmpty()) - str << ' ' << it.value(); - } - str << "\nCommand line: " << QCoreApplication::arguments().join(QLatin1Char(' ')); - return message; -} -} - -static void printOptions(QTextStream& s, const QMap& options) -{ - QMap::const_iterator it = options.constBegin(); - s.setFieldAlignment(QTextStream::AlignLeft); - for (; it != options.constEnd(); ++it) { - s << " --"; - s.setFieldWidth(38); - s << it.key() << it.value(); - s.setFieldWidth(0); - s << endl; - } -} - -typedef void (*getGeneratorsFunc)(QLinkedList*); - -static bool processProjectFile(QFile& projectFile, QMap& args) -{ - QByteArray line = projectFile.readLine().trimmed(); - if (line.isEmpty() || line != "[generator-project]") - return false; - - QStringList includePaths; - QStringList frameworkIncludePaths; - QStringList typesystemPaths; - QStringList apiVersions; - - 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 - 1).trimmed(); - value = QString::fromUtf8(line.mid(split + 1).trimmed()); - } else { - key = line; - } - - if (key == "include-path") - includePaths << QDir::toNativeSeparators(value); - else if (key == "framework-include-path") - frameworkIncludePaths << QDir::toNativeSeparators(value); - else if (key == "typesystem-path") - typesystemPaths << QDir::toNativeSeparators(value); - else if (key == "api-version") - apiVersions << value; - else if (key == "header-file") - args.insert(QLatin1String("arg-1"), value); - else if (key == "typesystem-file") - args.insert(QLatin1String("arg-2"), value); - else - args.insert(QString::fromUtf8(key), value); - } - - if (!includePaths.isEmpty()) - args.insert(QLatin1String("include-paths"), includePaths.join(QLatin1String(PATH_SPLITTER))); - - if (!frameworkIncludePaths.isEmpty()) - args.insert(QLatin1String("framework-include-paths"), - frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER))); - - if (!typesystemPaths.isEmpty()) - args.insert(QLatin1String("typesystem-paths"), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); - if (!apiVersions.isEmpty()) - args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); - return true; -} - -static QMap getInitializedArguments() -{ - QMap args; - QStringList arguments = QCoreApplication::arguments(); - QString appName = arguments.first(); - arguments.removeFirst(); - - QString projectFileName; - for (const QString &arg : qAsConst(arguments)) { - if (arg.startsWith(QLatin1String("--project-file"))) { - int split = arg.indexOf(QLatin1Char('=')); - if (split > 0) - projectFileName = arg.mid(split + 1).trimmed(); - break; - } - } - - if (projectFileName.isNull()) - return args; - - if (!QFile::exists(projectFileName)) { - std::cerr << qPrintable(appName) << ": Project file \""; - std::cerr << qPrintable(projectFileName) << "\" not found."; - std::cerr << std::endl; - return args; - } - - QFile projectFile(projectFileName); - if (!projectFile.open(QIODevice::ReadOnly)) - return args; - - if (!processProjectFile(projectFile, args)) { - std::cerr << qPrintable(appName) << ": first line of project file \""; - std::cerr << qPrintable(projectFileName) << "\" must be the string \"[generator-project]\""; - std::cerr << std::endl; - return args; - } - - return args; -} - -static QMap getCommandLineArgs() -{ - QMap args = getInitializedArguments(); - QStringList arguments = QCoreApplication::arguments(); - arguments.removeFirst(); - - int argNum = 0; - for (const QString &carg : qAsConst(arguments)) { - const QString &arg = carg.trimmed(); - if (arg.startsWith(QLatin1String("--"))) { - int split = arg.indexOf(QLatin1Char('=')); - if (split > 0) - args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed(); - else - args[arg.mid(2)] = QString(); - } else if (arg.startsWith(QLatin1Char('-'))) { - args[arg.mid(1)] = QString(); - } else { - argNum++; - args[QString::fromLatin1("arg-%1").arg(argNum)] = arg; - } - } - return args; -} - -static inline Generators docGenerators() -{ - Generators result; -#ifdef DOCSTRINGS_ENABLED - result.append(GeneratorPtr(new QtDocGenerator)); -#endif - return result; -} - -static inline Generators shibokenGenerators() -{ - Generators result; - result << GeneratorPtr(new CppGenerator) << GeneratorPtr(new HeaderGenerator); - return result; -} - -void printUsage() -{ - QTextStream s(stdout); - s << "Usage:\n " - << "shiboken [options] header-file typesystem-file\n\n" - << "General options:\n"; - QMap generalOptions; - generalOptions.insert(QLatin1String("project-file="), - QLatin1String("text file containing a description of the binding project. Replaces and overrides command line arguments")); - generalOptions.insert(QLatin1String("debug-level=[sparse|medium|full]"), - QLatin1String("Set the debug level")); - generalOptions.insert(QLatin1String("silent"), - QLatin1String("Avoid printing any message")); - generalOptions.insert(QLatin1String("help"), - QLatin1String("Display this help and exit")); - generalOptions.insert(QLatin1String("no-suppress-warnings"), - QLatin1String("Show all warnings")); - generalOptions.insert(QLatin1String("output-directory="), - QLatin1String("The directory where the generated files will be written")); - generalOptions.insert(QLatin1String("include-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), - QLatin1String("Include paths used by the C++ parser")); - generalOptions.insert(QLatin1String("framework-include-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), - QLatin1String("Framework include paths used by the C++ parser")); - generalOptions.insert(QLatin1String("typesystem-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), - QLatin1String("Paths used when searching for typesystems")); - generalOptions.insert(QLatin1String("documentation-only"), - QLatin1String("Do not generates any code, just the documentation")); - generalOptions.insert(QLatin1String("license-file="), - QLatin1String("File used for copyright headers of generated files")); - generalOptions.insert(QLatin1String("version"), - QLatin1String("Output version information and exit")); - generalOptions.insert(QLatin1String("generator-set=<\"generator module\">"), - QLatin1String("generator-set to be used. e.g. qtdoc")); - generalOptions.insert(QLatin1String("api-version=<\"package mask\">,<\"version\">"), - QLatin1String("Specify the supported api version used to generate the bindings")); - generalOptions.insert(QLatin1String("drop-type-entries=\"[;TypeEntry1;...]\""), - QLatin1String("Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.")); - printOptions(s, generalOptions); - - const Generators generators = shibokenGenerators() + docGenerators(); - for (const GeneratorPtr &generator : generators) { - QMap options = generator->options(); - if (!options.isEmpty()) { - s << endl << generator->name() << " options:\n"; - printOptions(s, generator->options()); - } - } -} - -static inline void printVerAndBanner() -{ - std::cout << "shiboken v" SHIBOKEN_VERSION << std::endl; - std::cout << "Copyright (C) 2016 The Qt Company Ltd." << std::endl; -} - -static inline void errorPrint(const QString& s) -{ - QStringList arguments = QCoreApplication::arguments(); - arguments.pop_front(); - std::cerr << "shiboken: " << qPrintable(s) - << "\nCommand line: " << qPrintable(arguments.join(QLatin1Char(' '))) << '\n'; -} - -static QString msgInvalidVersion(const QString &package, const QString &version) -{ - return QLatin1String("Invalid version \"") + version - + QLatin1String("\" specified for package ") + package + QLatin1Char('.'); -} - -int main(int argc, char *argv[]) -{ - QElapsedTimer timer; - timer.start(); - // needed by qxmlpatterns - QCoreApplication app(argc, argv); - ReportHandler::install(); - qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); - - // Store command arguments in a map - QMap args = getCommandLineArgs(); - ArgsHandler argsHandler(args); - Generators generators; - - if (argsHandler.argExistsRemove(QLatin1String("version"))) { - printVerAndBanner(); - return EXIT_SUCCESS; - } - - QString generatorSet = argsHandler.removeArg(QLatin1String("generator-set")); - // Also check QLatin1String("generatorSet") command line argument for backward compatibility. - if (generatorSet.isEmpty()) - generatorSet = argsHandler.removeArg(QLatin1String("generatorSet")); - - // Pre-defined generator sets. - if (generatorSet == QLatin1String("qtdoc")) { - generators = docGenerators(); - if (generators.isEmpty()) { - errorPrint(QLatin1String("Doc strings extractions was not enabled in this shiboken build.")); - return EXIT_FAILURE; - } - } else if (generatorSet.isEmpty() || generatorSet == QLatin1String("shiboken")) { - generators = shibokenGenerators(); - } else { - errorPrint(QLatin1String("Unknown generator set, try \"shiboken\" or \"qtdoc\".")); - return EXIT_FAILURE; - } - - if (argsHandler.argExistsRemove(QLatin1String("help"))) { - printUsage(); - return EXIT_SUCCESS; - } - - QString licenseComment; - QString licenseFileName = argsHandler.removeArg(QLatin1String("license-file")); - if (!licenseFileName.isEmpty()) { - if (QFile::exists(licenseFileName)) { - QFile licenseFile(licenseFileName); - if (licenseFile.open(QIODevice::ReadOnly)) - licenseComment = QString::fromUtf8(licenseFile.readAll()); - } else { - errorPrint(QStringLiteral("Couldn't find the file containing the license heading: %1"). - arg(licenseFileName)); - return EXIT_FAILURE; - } - } - - QString outputDirectory = argsHandler.removeArg(QLatin1String("output-directory")); - if (outputDirectory.isEmpty()) - outputDirectory = QLatin1String("out"); - - if (!QDir(outputDirectory).exists()) { - if (!QDir().mkpath(outputDirectory)) { - qCWarning(lcShiboken).noquote().nospace() - << "Can't create output directory: " << QDir::toNativeSeparators(outputDirectory); - return EXIT_FAILURE; - } - } - - // Create and set-up API Extractor - ApiExtractor extractor; - extractor.setLogDirectory(outputDirectory); - - if (argsHandler.argExistsRemove(QLatin1String("silent"))) { - extractor.setSilent(true); - } else { - QString level = argsHandler.removeArg(QLatin1String("debug-level")); - if (!level.isEmpty()) { - if (level == QLatin1String("sparse")) - extractor.setDebugLevel(ReportHandler::SparseDebug); - else if (level == QLatin1String("medium")) - extractor.setDebugLevel(ReportHandler::MediumDebug); - else if (level == QLatin1String("full")) - extractor.setDebugLevel(ReportHandler::FullDebug); - } - } - if (argsHandler.argExistsRemove(QLatin1String("no-suppress-warnings"))) - extractor.setSuppressWarnings(false); - - if (argsHandler.argExists(QLatin1String("api-version"))) { - const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); - for (const QString &fullVersion : versions) { - QStringList parts = fullVersion.split(QLatin1Char(',')); - QString package; - QString version; - // avoid constFirst to stay Qt 5.5 compatible - package = parts.count() == 1 ? QLatin1String("*") : parts.first(); - version = parts.last(); - if (!extractor.setApiVersion(package, version)) { - errorPrint(msgInvalidVersion(package, version)); - return EXIT_FAILURE; - } - } - } - - if (argsHandler.argExists(QLatin1String("drop-type-entries"))) - extractor.setDropTypeEntries(argsHandler.removeArg(QLatin1String("drop-type-entries"))); - - QString path = argsHandler.removeArg(QLatin1String("typesystem-paths")); - if (!path.isEmpty()) - extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER))); - - path = argsHandler.removeArg(QLatin1String("include-paths")); - if (!path.isEmpty()) { - const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER)); - for (const QString &s : qAsConst(includePathListList)) { - const bool isFramework = false; - extractor.addIncludePath(HeaderPath(s, isFramework)); - } - } - - path = argsHandler.removeArg(QLatin1String("framework-include-paths")); - if (!path.isEmpty()) { - const QStringList frameworkPathList = path.split(QLatin1String(PATH_SPLITTER)); - const bool isFramework = true; - for (const QString &s : qAsConst(frameworkPathList)) { - extractor.addIncludePath(HeaderPath(s, isFramework)); - } - } - - QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1")); - QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2")); - - /* 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. - */ - argsHandler.removeArg(QLatin1String("project-file")); - QMap projectFileArgs = getInitializedArguments(); - if (!projectFileArgs.isEmpty()) { - QMap::const_iterator it = - projectFileArgs.constBegin(); - for ( ; it != projectFileArgs.constEnd(); ++it) - argsHandler.removeArg(it.key()); - } - for (const GeneratorPtr &generator : qAsConst(generators)) { - QMap options = generator->options(); - if (!options.isEmpty()) { - QMap::const_iterator it = options.constBegin(); - for ( ; it != options.constEnd(); ++it) - argsHandler.removeArg(it.key()); - } - } - - if (!argsHandler.noArgs()) { - errorPrint(argsHandler.errorMessage()); - std::cout << "Note: use --help option for more information." << std::endl; - return EXIT_FAILURE; - } - - extractor.setCppFileName(cppFileName); - extractor.setTypeSystem(typeSystemFileName); - if (!extractor.run()) { - errorPrint(QLatin1String("Error running ApiExtractor.")); - return EXIT_FAILURE; - } - - if (!extractor.classCount()) - qCWarning(lcShiboken) << "No C++ classes found!"; - - qCDebug(lcShiboken) << extractor; - - for (const GeneratorPtr &g : qAsConst(generators)) { - g->setOutputDirectory(outputDirectory); - g->setLicenseComment(licenseComment); - if (g->setup(extractor, args)) { - if (!g->generate()) { - errorPrint(QLatin1String("Error running generator: ") - + QLatin1String(g->name()) + QLatin1Char('.')); - return EXIT_FAILURE; - } - } - } - - QByteArray doneMessage = "Done, " + QByteArray::number(timer.elapsed()) + "ms"; - if (const int w = ReportHandler::warningCount()) - doneMessage += ", " + QByteArray::number(w) + " warnings"; - if (const int sw = ReportHandler::suppressedCount()) - doneMessage += " (" + QByteArray::number(sw) + " known issues)"; - qCDebug(lcShiboken()).noquote().nospace() << doneMessage; - std::cout << doneMessage.constData() << std::endl; - - return EXIT_SUCCESS; -} diff --git a/generator/qtdoc/CMakeLists.txt b/generator/qtdoc/CMakeLists.txt deleted file mode 100644 index 1361ba8f1..000000000 --- a/generator/qtdoc/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -project(qtdoc_generator) - -set(qtdoc_generator_SRC -qtdocgenerator.cpp -) - -include_directories(${generators_SOURCE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ${APIEXTRACTOR_INCLUDE_DIR}) -add_executable(docgenerator main.cpp) -set_target_properties(docgenerator PROPERTIES OUTPUT_NAME docgenerator${generator_SUFFIX}) - -target_link_libraries(docgenerator ${Qt5Core_LIBRARES}) - -add_library(qtdoc_generator SHARED ${qtdoc_generator_SRC}) -target_link_libraries(qtdoc_generator ${APIEXTRACTOR_LIBRARY} ${Qt5Core_LIBRARES} genrunner) -set_property(TARGET qtdoc_generator PROPERTY PREFIX "") - -install(TARGETS qtdoc_generator DESTINATION ${generator_plugin_DIR}) -install(TARGETS docgenerator DESTINATION bin) - diff --git a/generator/qtdoc/qtdocgenerator.cpp b/generator/qtdoc/qtdocgenerator.cpp deleted file mode 100644 index 02fd40354..000000000 --- a/generator/qtdoc/qtdocgenerator.cpp +++ /dev/null @@ -1,1715 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtdocgenerator.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static Indentor INDENT; - -static bool shouldSkip(const AbstractMetaFunction* func) -{ - bool skipable = func->isConstructor() - || func->isModifiedRemoved() - || func->declaringClass() != func->ownerClass() - || func->isCastOperator() - || func->name() == QLatin1String("operator="); - - // Search a const clone - if (!skipable && !func->isConstant()) { - const AbstractMetaArgumentList funcArgs = func->arguments(); - const AbstractMetaFunctionList &ownerFunctions = func->ownerClass()->functions(); - for (AbstractMetaFunction *f : ownerFunctions) { - if (f != func - && f->isConstant() - && f->name() == func->name() - && f->arguments().count() == funcArgs.count()) { - // Compare each argument - bool cloneFound = true; - - const AbstractMetaArgumentList fargs = f->arguments(); - for (int i = 0, max = funcArgs.count(); i < max; ++i) { - if (funcArgs.at(i)->type()->typeEntry() != fargs.at(i)->type()->typeEntry()) { - cloneFound = false; - break; - } - } - if (cloneFound) - return true; - } - } - } - return skipable; -} - -static bool functionSort(const AbstractMetaFunction* func1, const AbstractMetaFunction* func2) -{ - return func1->name() < func2->name(); -} - -static QString createRepeatedChar(int i, char c) -{ - QString out; - for (int j = 0; j < i; ++j) - out += QLatin1Char(c); - - return out; -} - -static QString escape(QString str) -{ - str.replace(QLatin1Char('*'), QLatin1String("\\*")); - str.replace(QLatin1Char('_'), QLatin1String("\\_")); - return str; -} - -static QString escape(const QStringRef& strref) -{ - QString str = strref.toString(); - return escape(str); -} - - -QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context) - : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false) -{ - m_handlerMap.insert(QLatin1String("heading"), &QtXmlToSphinx::handleHeadingTag); - m_handlerMap.insert(QLatin1String("brief"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("para"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("italic"), &QtXmlToSphinx::handleItalicTag); - m_handlerMap.insert(QLatin1String("bold"), &QtXmlToSphinx::handleBoldTag); - m_handlerMap.insert(QLatin1String("see-also"), &QtXmlToSphinx::handleSeeAlsoTag); - m_handlerMap.insert(QLatin1String("snippet"), &QtXmlToSphinx::handleSnippetTag); - m_handlerMap.insert(QLatin1String("dots"), &QtXmlToSphinx::handleDotsTag); - m_handlerMap.insert(QLatin1String("codeline"), &QtXmlToSphinx::handleDotsTag); - m_handlerMap.insert(QLatin1String("table"), &QtXmlToSphinx::handleTableTag); - m_handlerMap.insert(QLatin1String("header"), &QtXmlToSphinx::handleRowTag); - m_handlerMap.insert(QLatin1String("row"), &QtXmlToSphinx::handleRowTag); - m_handlerMap.insert(QLatin1String("item"), &QtXmlToSphinx::handleItemTag); - m_handlerMap.insert(QLatin1String("argument"), &QtXmlToSphinx::handleArgumentTag); - m_handlerMap.insert(QLatin1String("teletype"), &QtXmlToSphinx::handleArgumentTag); - m_handlerMap.insert(QLatin1String("link"), &QtXmlToSphinx::handleLinkTag); - m_handlerMap.insert(QLatin1String("inlineimage"), &QtXmlToSphinx::handleImageTag); - m_handlerMap.insert(QLatin1String("image"), &QtXmlToSphinx::handleImageTag); - m_handlerMap.insert(QLatin1String("list"), &QtXmlToSphinx::handleListTag); - m_handlerMap.insert(QLatin1String("term"), &QtXmlToSphinx::handleTermTag); - m_handlerMap.insert(QLatin1String("raw"), &QtXmlToSphinx::handleRawTag); - m_handlerMap.insert(QLatin1String("underline"), &QtXmlToSphinx::handleItalicTag); - m_handlerMap.insert(QLatin1String("superscript"), &QtXmlToSphinx::handleSuperScriptTag); - m_handlerMap.insert(QLatin1String("code"), &QtXmlToSphinx::handleCodeTag); - m_handlerMap.insert(QLatin1String("badcode"), &QtXmlToSphinx::handleCodeTag); - m_handlerMap.insert(QLatin1String("legalese"), &QtXmlToSphinx::handleCodeTag); - m_handlerMap.insert(QLatin1String("section"), &QtXmlToSphinx::handleAnchorTag); - m_handlerMap.insert(QLatin1String("quotefile"), &QtXmlToSphinx::handleQuoteFileTag); - - // ignored tags - m_handlerMap.insert(QLatin1String("generatedlist"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("tableofcontents"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("quotefromfile"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("skipto"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("target"), &QtXmlToSphinx::handleIgnoredTag); - - // useless tags - m_handlerMap.insert(QLatin1String("description"), &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert(QLatin1String("definition"), &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert(QLatin1String("printuntil"), &QtXmlToSphinx::handleUselessTag); - m_handlerMap.insert(QLatin1String("relation"), &QtXmlToSphinx::handleUselessTag); - - // Doxygen tags - m_handlerMap.insert(QLatin1String("title"), &QtXmlToSphinx::handleHeadingTag); - m_handlerMap.insert(QLatin1String("ref"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("computeroutput"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("detaileddescription"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("name"), &QtXmlToSphinx::handleParaTag); - m_handlerMap.insert(QLatin1String("listitem"), &QtXmlToSphinx::handleItemTag); - m_handlerMap.insert(QLatin1String("parametername"), &QtXmlToSphinx::handleItemTag); - m_handlerMap.insert(QLatin1String("parameteritem"), &QtXmlToSphinx::handleItemTag); - m_handlerMap.insert(QLatin1String("ulink"), &QtXmlToSphinx::handleLinkTag); - m_handlerMap.insert(QLatin1String("itemizedlist"), &QtXmlToSphinx::handleListTag); - m_handlerMap.insert(QLatin1String("parameternamelist"), &QtXmlToSphinx::handleListTag); - m_handlerMap.insert(QLatin1String("parameterlist"), &QtXmlToSphinx::handleListTag); - - // Doxygen ignored tags - m_handlerMap.insert(QLatin1String("highlight"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("linebreak"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("programlisting"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("xreftitle"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("sp"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("entry"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("simplesect"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("verbatim"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("xrefsect"), &QtXmlToSphinx::handleIgnoredTag); - m_handlerMap.insert(QLatin1String("xrefdescription"), &QtXmlToSphinx::handleIgnoredTag); - - m_result = transform(doc); -} - -void QtXmlToSphinx::pushOutputBuffer() -{ - QString* buffer = new QString(); - m_buffers << buffer; - m_output.setString(buffer); -} - -QString QtXmlToSphinx::popOutputBuffer() -{ - Q_ASSERT(!m_buffers.isEmpty()); - QString* str = m_buffers.pop(); - QString strcpy(*str); - delete str; - m_output.setString(m_buffers.isEmpty() ? 0 : m_buffers.top()); - return strcpy; -} - -QString QtXmlToSphinx::expandFunction(const QString& function) -{ - QStringList functionSpec = function.split(QLatin1Char('.')); - QString className = functionSpec.first(); - const AbstractMetaClass* metaClass = 0; - const AbstractMetaClassList &classes = m_generator->classes(); - for (const AbstractMetaClass *cls : classes) { - if (cls->name() == className) { - metaClass = cls; - break; - } - } - - if (metaClass) { - functionSpec.removeFirst(); - return metaClass->typeEntry()->qualifiedTargetLangName() - + QLatin1Char('.') + functionSpec.join(QLatin1Char('.')); - } else { - return function; - } -} - -QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) -{ - // avoid constLast to stay Qt 5.5 compatible - QString currentClass = m_context.split(QLatin1Char('.')).last(); - - const AbstractMetaClass* metaClass = 0; - const AbstractMetaClassList &classes = m_generator->classes(); - for (const AbstractMetaClass *cls : classes) { - if (cls->name() == currentClass) { - metaClass = cls; - break; - } - } - - if (metaClass) { - QList funcList; - const AbstractMetaFunctionList &methods = metaClass->queryFunctionsByName(methodName); - for (const AbstractMetaFunction *func : methods) { - if (methodName == func->name()) - funcList.append(func); - } - - const AbstractMetaClass* implementingClass = 0; - for (const AbstractMetaFunction *func : qAsConst(funcList)) { - implementingClass = func->implementingClass(); - if (implementingClass->name() == currentClass) - break; - } - - if (implementingClass) - return implementingClass->typeEntry()->qualifiedTargetLangName(); - } - - return QLatin1Char('~') + m_context; -} - -QString QtXmlToSphinx::transform(const QString& doc) -{ - Q_ASSERT(m_buffers.isEmpty()); - Indentation indentation(INDENT); - if (doc.trimmed().isEmpty()) - return doc; - - pushOutputBuffer(); - - QXmlStreamReader reader(doc); - - while (!reader.atEnd()) { - QXmlStreamReader::TokenType token = reader.readNext(); - if (reader.hasError()) { - const QString message = QLatin1String("XML Error: ") + reader.errorString() - + QLatin1Char('\n') + doc; - m_output << INDENT << message; - qCWarning(lcShiboken).noquote().nospace() << message; - break; - } - - if (token == QXmlStreamReader::StartElement) { - QStringRef tagName = reader.name(); - TagHandler handler = m_handlerMap.value(tagName.toString(), &QtXmlToSphinx::handleUnknownTag); - if (!m_handlers.isEmpty() && ( (m_handlers.top() == &QtXmlToSphinx::handleIgnoredTag) || - (m_handlers.top() == &QtXmlToSphinx::handleRawTag)) ) - handler = &QtXmlToSphinx::handleIgnoredTag; - - m_handlers.push(handler); - } - if (!m_handlers.isEmpty()) - (this->*(m_handlers.top()))(reader); - - if (token == QXmlStreamReader::EndElement) { - m_handlers.pop(); - m_lastTagName = reader.name().toString(); - } - } - m_output.flush(); - QString retval = popOutputBuffer(); - Q_ASSERT(m_buffers.isEmpty()); - return retval; -} - -QString QtXmlToSphinx::readFromLocations(const QStringList& locations, const QString& path, const QString& identifier) -{ - QString result; - bool ok; - for (QString location : locations) { - location.append(QLatin1Char('/')); - location.append(path); - result = readFromLocation(location, identifier, &ok); - if (ok) - break; - } - if (!ok) { - qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: {" - << locations.join(QLatin1Char('|')) << '}' << path; - } - return result; - -} - -QString QtXmlToSphinx::readFromLocation(const QString& location, const QString& identifier, bool* ok) -{ - QFile inputFile; - inputFile.setFileName(location); - if (!inputFile.open(QIODevice::ReadOnly)) { - if (!ok) { - qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: " - << QDir::toNativeSeparators(inputFile.fileName()); - } else { - *ok = false; - } - return QString(); - } - - QRegExp searchString(QLatin1String("//!\\s*\\[") + identifier + QLatin1String("\\]")); - QRegExp codeSnippetCode(QLatin1String("//!\\s*\\[[\\w\\d\\s]+\\]")); - QString code; - - bool identifierIsEmpty = identifier.isEmpty(); - bool getCode = false; - - while (!inputFile.atEnd()) { - QString line = QString::fromUtf8(inputFile.readLine()); - if (identifierIsEmpty) { - code += line; - } else if (getCode && !line.contains(searchString)) { - line.remove(codeSnippetCode); - code += line; - } else if (line.contains(searchString)) { - if (getCode) - break; - else - getCode = true; - } - } - - if (!identifierIsEmpty && !getCode) { - qCDebug(lcShiboken).noquote().nospace() << "Code snippet file found (" - << location << "), but snippet " << identifier << " not found."; - } - - if (ok) - *ok = true; - return code; -} - -void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) -{ - static QString heading; - static char type; - static char types[] = { '-', '^' }; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - uint typeIdx = reader.attributes().value(QLatin1String("level")).toString().toInt(); - if (typeIdx >= sizeof(types)) - type = types[sizeof(types)-1]; - else - type = types[typeIdx]; - } else if (token == QXmlStreamReader::EndElement) { - m_output << createRepeatedChar(heading.length(), type) << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - heading = escape(reader.text()).trimmed(); - m_output << endl << endl << heading << endl; - } -} - -void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - pushOutputBuffer(); - } else if (token == QXmlStreamReader::EndElement) { - QString result = popOutputBuffer().simplified(); - if (result.startsWith(QLatin1String("**Warning:**"))) - result.replace(0, 12, QLatin1String(".. warning:: ")); - else if (result.startsWith(QLatin1String("**Note:**"))) - result.replace(0, 9, QLatin1String(".. note:: ")); - - m_output << INDENT << result << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - QString text = escape(reader.text()); - if (!m_output.string()->isEmpty()) { - QChar start = text[0]; - QChar end = m_output.string()->at(m_output.string()->length() - 1); - if ((end == QLatin1Char('*') || end == QLatin1Char('`')) && start != QLatin1Char(' ') && !start.isPunct()) - m_output << '\\'; - } - m_output << INDENT << text; - } -} - -void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { - m_insideItalic = !m_insideItalic; - m_output << '*'; - } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); - } -} - -void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { - m_insideBold = !m_insideBold; - m_output << "**"; - } else if (token == QXmlStreamReader::Characters) { - m_output << escape(reader.text()).trimmed(); - } -} - -void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) - m_output << "``"; - else if (token == QXmlStreamReader::Characters) - m_output << reader.text().toString().trimmed(); -} - -void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) - m_output << INDENT << ".. seealso:: "; - else if (token == QXmlStreamReader::EndElement) - m_output << endl; -} - -void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - const bool consecutiveSnippet = m_lastTagName == QLatin1String("snippet") - || m_lastTagName == QLatin1String("dots") || m_lastTagName == QLatin1String("codeline"); - if (consecutiveSnippet) { - m_output.flush(); - m_output.string()->chop(2); - } - QString location = reader.attributes().value(QLatin1String("location")).toString(); - QString identifier = reader.attributes().value(QLatin1String("identifier")).toString(); - QString code = readFromLocations(m_generator->codeSnippetDirs(), location, identifier); - if (!consecutiveSnippet) - m_output << INDENT << "::\n\n"; - - Indentation indentation(INDENT); - if (code.isEmpty()) { - m_output << INDENT << "" << endl; - } else { - const QStringList lines = code.split(QLatin1Char('\n')); - for (const QString &line : lines) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } - m_output << endl; - } -} -void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - const bool consecutiveSnippet = m_lastTagName == QLatin1String("snippet") - || m_lastTagName == QLatin1String("dots") || m_lastTagName == QLatin1String("codeline"); - if (consecutiveSnippet) { - m_output.flush(); - m_output.string()->chop(2); - } - Indentation indentation(INDENT); - pushOutputBuffer(); - m_output << INDENT; - int indent = reader.attributes().value(QLatin1String("indent")).toString().toInt(); - for (int i = 0; i < indent; ++i) - m_output << ' '; - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString(); - } else if (token == QXmlStreamReader::EndElement) { - m_output << popOutputBuffer() << "\n\n\n"; - } -} - -void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_currentTable.clear(); - m_tableHasHeader = false; - } else if (token == QXmlStreamReader::EndElement) { - // write the table on m_output - m_currentTable.enableHeader(m_tableHasHeader); - m_currentTable.normalize(); - m_output << m_currentTable; - m_currentTable.clear(); - } -} - -void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - pushOutputBuffer(); - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString().replace(QLatin1String("::"), QLatin1String(".")); - } else if (token == QXmlStreamReader::EndElement) { - TableCell cell; - cell.data = popOutputBuffer().trimmed(); - m_currentTable << (TableRow() << cell); - } -} - - -void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - if (m_currentTable.isEmpty()) - m_currentTable << TableRow(); - TableRow& row = m_currentTable.last(); - TableCell cell; - cell.colSpan = reader.attributes().value(QLatin1String("colspan")).toString().toShort(); - cell.rowSpan = reader.attributes().value(QLatin1String("rowspan")).toString().toShort(); - row << cell; - pushOutputBuffer(); - } else if (token == QXmlStreamReader::EndElement) { - QString data = popOutputBuffer().trimmed(); - if (!m_currentTable.isEmpty()) { - TableRow& row = m_currentTable.last(); - if (!row.isEmpty()) - row.last().data = data; - } - } -} - -void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_tableHasHeader = reader.name() == QLatin1String("header"); - m_currentTable << TableRow(); - } -} - -void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) -{ - // BUG We do not support a list inside a table cell - static QString listType; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - listType = reader.attributes().value(QLatin1String("type")).toString(); - if (listType == QLatin1String("enum")) { - m_currentTable << (TableRow() << "Constant" << "Description"); - m_tableHasHeader = true; - } - INDENT.indent--; - } else if (token == QXmlStreamReader::EndElement) { - INDENT.indent++; - if (!m_currentTable.isEmpty()) { - if (listType == QLatin1String("bullet")) { - m_output << endl; - for (const TableCell &cell : m_currentTable.constFirst()) { - QStringList itemLines = cell.data.split(QLatin1Char('\n')); - m_output << INDENT << "* " << itemLines.first() << endl; - for (int i = 1, max = itemLines.count(); i < max; ++i) - m_output << INDENT << " " << itemLines[i] << endl; - } - m_output << endl; - } else if (listType == QLatin1String("enum")) { - m_currentTable.enableHeader(m_tableHasHeader); - m_currentTable.normalize(); - m_output << m_currentTable; - } - } - m_currentTable.clear(); - } -} - -void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader) -{ - static QString l_linktag; - static QString l_linkref; - static QString l_linktext; - static QString l_linktagending; - static QString l_type; - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - l_linktagending = QLatin1String("` "); - if (m_insideBold) { - l_linktag.prepend(QLatin1String("**")); - l_linktagending.append(QLatin1String("**")); - } else if (m_insideItalic) { - l_linktag.prepend(QLatin1Char('*')); - l_linktagending.append(QLatin1Char('*')); - } - l_type = reader.attributes().value(QLatin1String("type")).toString(); - - // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties - // are recognized as such or not in the binding - if (l_type == QLatin1String("property")) - l_type = QLatin1String("function"); - - if (l_type == QLatin1String("typedef")) - l_type = QLatin1String("class"); - - QString linkSource; - if (l_type == QLatin1String("function") || l_type == QLatin1String("class")) { - linkSource = QLatin1String("raw"); - } else if (l_type == QLatin1String("enum")) { - linkSource = QLatin1String("enum"); - } else if (l_type == QLatin1String("page")) { - linkSource = QLatin1String("page"); - } else { - linkSource = QLatin1String("href"); - } - - l_linkref = reader.attributes().value(linkSource).toString(); - l_linkref.replace(QLatin1String("::"), QLatin1String(".")); - l_linkref.remove(QLatin1String("()")); - - if (l_type == QLatin1String("function") && !m_context.isEmpty()) { - l_linktag = QLatin1String(" :meth:`"); - QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); - if (rawlinklist.size() == 1 || rawlinklist.first() == m_context) { - QString context = resolveContextForMethod(rawlinklist.last()); - if (!l_linkref.startsWith(context)) - l_linkref.prepend(context + QLatin1Char('.')); - } else { - l_linkref = expandFunction(l_linkref); - } - } else if (l_type == QLatin1String("function") && m_context.isEmpty()) { - l_linktag = QLatin1String(" :func:`"); - } else if (l_type == QLatin1String("class")) { - l_linktag = QLatin1String(" :class:`"); - TypeEntry* type = TypeDatabase::instance()->findType(l_linkref); - if (type) { - l_linkref = type->qualifiedTargetLangName(); - } else { // fall back to the old heuristic if the type wasn't found. - QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); - QStringList splittedContext = m_context.split(QLatin1Char('.')); - if (rawlinklist.size() == 1 || rawlinklist.first() == splittedContext.last()) { - splittedContext.removeLast(); - l_linkref.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.')) - + QLatin1Char('.')); - } - } - } else if (l_type == QLatin1String("enum")) { - l_linktag = QLatin1String(" :attr:`"); - } else if (l_type == QLatin1String("page") && l_linkref == m_generator->moduleName()) { - l_linktag = QLatin1String(" :mod:`"); - } else { - l_linktag = QLatin1String(" :ref:`"); - } - - } else if (token == QXmlStreamReader::Characters) { - QString linktext = reader.text().toString(); - linktext.replace(QLatin1String("::"), QLatin1String(".")); - // avoid constLast to stay Qt 5.5 compatible - QString item = l_linkref.split(QLatin1Char('.')).last(); - if (l_linkref == linktext - || (l_linkref + QLatin1String("()")) == linktext - || item == linktext - || (item + QLatin1String("()")) == linktext) - l_linktext.clear(); - else - l_linktext = linktext + QLatin1Char('<'); - } else if (token == QXmlStreamReader::EndElement) { - if (!l_linktext.isEmpty()) - l_linktagending.prepend(QLatin1Char('>')); - m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending; - } -} - -void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString href = reader.attributes().value(QLatin1String("href")).toString(); - QString packageName = m_generator->packageName(); - packageName.replace(QLatin1Char('.'), QLatin1Char('/')); - QDir dir(m_generator->outputDirectory() + QLatin1Char('/') + packageName); - QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + QLatin1String("/doc/src/")) - + QLatin1Char('/') + href; - - if (reader.name() == QLatin1String("image")) - m_output << INDENT << ".. image:: " << imgPath << endl << endl; - else - m_output << ".. image:: " << imgPath << ' '; - } -} - -void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString format = reader.attributes().value(QLatin1String("format")).toString(); - m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; - } else if (token == QXmlStreamReader::Characters) { - const QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); - for (const QString &row : lst) - m_output << INDENT << INDENT << row << endl; - } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; - } -} - -void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString format = reader.attributes().value(QLatin1String("format")).toString(); - m_output << INDENT << "::" << endl << endl; - INDENT.indent++; - } else if (token == QXmlStreamReader::Characters) { - const QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); - for (const QString row : lst) - m_output << INDENT << INDENT << row << endl; - } else if (token == QXmlStreamReader::EndElement) { - m_output << endl << endl; - INDENT.indent--; - } -} - -void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) - qCDebug(lcShiboken).noquote().nospace() << "Unknown QtDoc tag: \"" << reader.name().toString() << "\"."; -} - -void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - m_output << " :sup:`"; - pushOutputBuffer(); - } else if (token == QXmlStreamReader::Characters) { - m_output << reader.text().toString(); - } else if (token == QXmlStreamReader::EndElement) { - m_output << popOutputBuffer(); - m_output << '`'; - } -} - -void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&) -{ -} - -void QtXmlToSphinx::handleUselessTag(QXmlStreamReader&) -{ - // Tag "description" just marks the init of "Detailed description" title. - // Tag "definition" just marks enums. We have a different way to process them. -} - -void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::StartElement) { - QString anchor; - if (reader.attributes().hasAttribute(QLatin1String("id"))) - anchor = reader.attributes().value(QLatin1String("id")).toString(); - else if (reader.attributes().hasAttribute(QLatin1String("name"))) - anchor = reader.attributes().value(QLatin1String("name")).toString(); - if (!anchor.isEmpty() && m_opened_anchor != anchor) { - m_opened_anchor = anchor; - m_output << INDENT << ".. _" << m_context << "_" << anchor.toLower() << ":" << endl << endl; - } - } else if (token == QXmlStreamReader::EndElement) { - m_opened_anchor.clear(); - } -} - -void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) -{ - QXmlStreamReader::TokenType token = reader.tokenType(); - if (token == QXmlStreamReader::Characters) { - QString location = reader.text().toString(); - QString identifier; - location.prepend(m_generator->libSourceDir() + QLatin1Char('/')); - QString code = readFromLocation(location, identifier); - - m_output << INDENT << "::\n\n"; - Indentation indentation(INDENT); - if (code.isEmpty()) { - m_output << INDENT << "" << endl; - } else { - const QStringList lines = code.split(QLatin1Char('\n')); - for (const QString &line : lines) { - if (!QString(line).trimmed().isEmpty()) - m_output << INDENT << line; - - m_output << endl; - } - } - m_output << endl; - } -} - -void QtXmlToSphinx::Table::normalize() -{ - if (m_normalized || isEmpty()) - return; - - int row; - int col; - QtXmlToSphinx::Table& self = *this; - - //QDoc3 generates tables with wrong number of columns. We have to - //check and if necessary, merge the last columns. - int maxCols = self.at(0).count(); - // add col spans - for (row = 0; row < count(); ++row) { - for (col = 0; col < at(row).count(); ++col) { - QtXmlToSphinx::TableCell& cell = self[row][col]; - bool mergeCols = (col >= maxCols); - if (cell.colSpan > 0) { - QtXmlToSphinx::TableCell newCell; - newCell.colSpan = -1; - for (int i = 0, max = cell.colSpan-1; i < max; ++i) { - self[row].insert(col+1, newCell); - } - cell.colSpan = 0; - col++; - } else if (mergeCols) { - self[row][maxCols - 1].data += QLatin1Char(' ') + cell.data; - } - } - } - - // row spans - const int numCols = first().count(); - for (col = 0; col < numCols; ++col) { - for (row = 0; row < count(); ++row) { - if (col < self[row].count()) { - QtXmlToSphinx::TableCell& cell = self[row][col]; - if (cell.rowSpan > 0) { - QtXmlToSphinx::TableCell newCell; - newCell.rowSpan = -1; - int max = std::min(cell.rowSpan - 1, count()); - cell.rowSpan = 0; - for (int i = 0; i < max; ++i) { - self[row+i+1].insert(col, newCell); - } - row++; - } - } - } - } - m_normalized = true; -} - -QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) -{ - if (table.isEmpty()) - return s; - - if (!table.isNormalized()) { - qCDebug(lcShiboken) << "Attempt to print an unnormalized table!"; - return s; - } - - // calc width and height of each column and row - QVector colWidths(table.first().count()); - QVector rowHeights(table.count()); - for (int i = 0, maxI = table.count(); i < maxI; ++i) { - const QtXmlToSphinx::TableRow& row = table[i]; - for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { - const QStringList rowLines = row[j].data.split(QLatin1Char('\n')); // cache this would be a good idea - for (const QString &str : rowLines) - colWidths[j] = std::max(colWidths[j], str.count()); - rowHeights[i] = std::max(rowHeights[i], row[j].data.count(QLatin1Char('\n')) + 1); - } - } - - if (!*std::max_element(colWidths.begin(), colWidths.end())) - return s; // empty table (table with empty cells) - - // create a horizontal line to be used later. - QString horizontalLine = QLatin1String("+"); - for (int i = 0, max = colWidths.count(); i < max; ++i) { - horizontalLine += createRepeatedChar(colWidths[i], '-'); - horizontalLine += QLatin1Char('+'); - } - - // write table rows - for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row - const QtXmlToSphinx::TableRow& row = table[i]; - - // print line - s << INDENT << '+'; - for (int col = 0, max = colWidths.count(); col < max; ++col) { - char c; - if (col >= row.length() || row[col].rowSpan == -1) - c = ' '; - else if (i == 1 && table.hasHeader()) - c = '='; - else - c = '-'; - s << createRepeatedChar(colWidths[col], c) << '+'; - } - s << endl; - - - // Print the table cells - for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row - for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { // for each column - const QtXmlToSphinx::TableCell& cell = row[j]; - QStringList rowLines = cell.data.split(QLatin1Char('\n')); // FIXME: Cache this!!! - if (!j) // First column, so we need print the identation - s << INDENT; - - if (!j || !cell.colSpan) - s << '|'; - else - s << ' '; - s << qSetFieldWidth(colWidths[j]) << left; - s << (rowLine < rowLines.count() ? rowLines[rowLine] : QString()); - s << qSetFieldWidth(0); - } - s << '|' << endl; - } - } - s << INDENT << horizontalLine << endl; - s << endl; - return s; -} - -static QString getFuncName(const AbstractMetaFunction* cppFunc) { - static bool hashInitialized = false; - static QHash operatorsHash; - if (!hashInitialized) { - operatorsHash.insert(QLatin1String("operator+"), QLatin1String("__add__")); - operatorsHash.insert(QLatin1String("operator+="), QLatin1String("__iadd__")); - operatorsHash.insert(QLatin1String("operator-"), QLatin1String("__sub__")); - operatorsHash.insert(QLatin1String("operator-="), QLatin1String("__isub__")); - operatorsHash.insert(QLatin1String("operator*"), QLatin1String("__mul__")); - operatorsHash.insert(QLatin1String("operator*="), QLatin1String("__imul__")); - operatorsHash.insert(QLatin1String("operator/"), QLatin1String("__div__")); - operatorsHash.insert(QLatin1String("operator/="), QLatin1String("__idiv__")); - operatorsHash.insert(QLatin1String("operator%"), QLatin1String("__mod__")); - operatorsHash.insert(QLatin1String("operator%="), QLatin1String("__imod__")); - operatorsHash.insert(QLatin1String("operator<<"), QLatin1String("__lshift__")); - operatorsHash.insert(QLatin1String("operator<<="), QLatin1String("__ilshift__")); - operatorsHash.insert(QLatin1String("operator>>"), QLatin1String("__rshift__")); - operatorsHash.insert(QLatin1String("operator>>="), QLatin1String("__irshift__")); - operatorsHash.insert(QLatin1String("operator&"), QLatin1String("__and__")); - operatorsHash.insert(QLatin1String("operator&="), QLatin1String("__iand__")); - operatorsHash.insert(QLatin1String("operator|"), QLatin1String("__or__")); - operatorsHash.insert(QLatin1String("operator|="), QLatin1String("__ior__")); - operatorsHash.insert(QLatin1String("operator^"), QLatin1String("__xor__")); - operatorsHash.insert(QLatin1String("operator^="), QLatin1String("__ixor__")); - operatorsHash.insert(QLatin1String("operator=="), QLatin1String("__eq__")); - operatorsHash.insert(QLatin1String("operator!="), QLatin1String("__ne__")); - operatorsHash.insert(QLatin1String("operator<"), QLatin1String("__lt__")); - operatorsHash.insert(QLatin1String("operator<="), QLatin1String("__le__")); - operatorsHash.insert(QLatin1String("operator>"), QLatin1String("__gt__")); - operatorsHash.insert(QLatin1String("operator>="), QLatin1String("__ge__")); - hashInitialized = true; - } - - QHash::const_iterator it = operatorsHash.find(cppFunc->name()); - QString result = it != operatorsHash.end() ? it.value() : cppFunc->name(); - result.replace(QLatin1String("::"), QLatin1String(".")); - return result; -} - -QtDocGenerator::QtDocGenerator() : m_docParser(0) -{ -} - -QtDocGenerator::~QtDocGenerator() -{ - delete m_docParser; -} - -QString QtDocGenerator::fileNamePrefix() const -{ - return QLatin1String(".rst"); -} - -QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const -{ - const AbstractMetaClass *metaClass = context.metaClass(); - if (!context.forSmartPointer()) { - return getClassTargetFullName(metaClass, false) + fileNamePrefix(); - } else { - const AbstractMetaType *smartPointerType = context.preciseType(); - QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); - } -} - -void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass) -{ - QString metaClassName; - - if (metaClass) - metaClassName = getClassTargetFullName(metaClass); - - if (doc.format() == Documentation::Native) { - QtXmlToSphinx x(this, doc.value(), metaClassName); - s << x; - } else { - const QStringList lines = doc.value().split(QLatin1Char('\n')); - QRegExp regex(QLatin1String("\\S")); // non-space character - int typesystemIndentation = std::numeric_limits().max(); - // check how many spaces must be removed from the begining of each line - for (const QString &line : lines) { - int idx = line.indexOf(regex); - if (idx >= 0) - typesystemIndentation = qMin(typesystemIndentation, idx); - } - for (QString line : lines) - s << INDENT << line.remove(0, typesystemIndentation) << endl; - } - - s << endl; -} - -static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) -{ - AbstractMetaClassList res; - for (AbstractMetaClass *c : allClasses) { - if (c != metaClass && c->inheritsFrom(metaClass)) - res << c; - } - - if (res.isEmpty()) - return; - - s << "**Inherited by:** "; - QStringList classes; - for (AbstractMetaClass *c : qAsConst(res)) - classes << QLatin1String(":ref:`") + getClassTargetFullName(c, false) + QLatin1Char('`'); - s << classes.join(QLatin1String(", ")) << endl << endl; -} - -void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) -{ - AbstractMetaClass *metaClass = classContext.metaClass(); - qCDebug(lcShiboken).noquote().nospace() << "Generating Documentation for " << metaClass->fullName(); - - m_packages[metaClass->package()] << fileNameForContext(classContext); - - m_docParser->setPackageName(metaClass->package()); - m_docParser->fillDocumentation(const_cast(metaClass)); - - s << ".. module:: " << metaClass->package() << endl; - QString className = getClassTargetFullName(metaClass, false); - s << ".. _" << className << ":" << endl << endl; - - s << className << endl; - s << createRepeatedChar(className.count(), '*') << endl << endl; - - s << ".. inheritance-diagram:: " << className << endl - << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future... - - - writeInheritedByList(s, metaClass, classes()); - - if (metaClass->typeEntry() && (metaClass->typeEntry()->version() != 0)) - s << ".. note:: This class was introduced in Qt " << metaClass->typeEntry()->version() << endl; - - writeFunctionList(s, metaClass); - - //Function list - AbstractMetaFunctionList functionList = metaClass->functions(); - qSort(functionList.begin(), functionList.end(), functionSort); - - s << "Detailed Description\n" - "--------------------\n\n"; - - writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, 0); - if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, 0)) - writeFormatedText(s, metaClass->documentation(), metaClass); - - if (!metaClass->isNamespace()) - writeConstructors(s, metaClass); - writeEnums(s, metaClass); - if (!metaClass->isNamespace()) - writeFields(s, metaClass); - - - for (AbstractMetaFunction *func : qAsConst(functionList)) { - if (shouldSkip(func)) - continue; - - if (func->isStatic()) - s << ".. staticmethod:: "; - else - s << ".. method:: "; - - writeFunction(s, true, metaClass, func); - } - - writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass, 0); -} - -void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass) -{ - QStringList functionList; - QStringList virtualList; - QStringList signalList; - QStringList slotList; - QStringList staticFunctionList; - - const AbstractMetaFunctionList &classFunctions = cppClass->functions(); - for (AbstractMetaFunction *func : classFunctions) { - if (shouldSkip(func)) - continue; - - QString className; - if (!func->isConstructor()) - className = getClassTargetFullName(cppClass) + QLatin1Char('.'); - else if (func->implementingClass() && func->implementingClass()->enclosingClass()) - className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + QLatin1Char('.'); - QString funcName = getFuncName(func); - - QString str = QLatin1String("def :meth:`"); - - str += funcName; - str += QLatin1Char('<'); - if (!funcName.startsWith(className)) - str += className; - str += funcName; - str += QLatin1String(">` ("); - str += parseArgDocStyle(cppClass, func); - str += QLatin1Char(')'); - - 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 ((functionList.size() > 0) || (staticFunctionList.size() > 0)) { - QtXmlToSphinx::Table functionTable; - QtXmlToSphinx::TableRow row; - - s << "Synopsis" << endl - << "--------" << endl << endl; - - writeFunctionBlock(s, QLatin1String("Functions"), functionList); - writeFunctionBlock(s, QLatin1String("Virtual functions"), virtualList); - writeFunctionBlock(s, QLatin1String("Slots"), slotList); - writeFunctionBlock(s, QLatin1String("Signals"), signalList); - writeFunctionBlock(s, QLatin1String("Static functions"), staticFunctionList); - } -} - -void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions) -{ - if (functions.size() > 0) { - s << title << endl - << QString(title.size(), QLatin1Char('^')) << endl; - - qSort(functions); - - s << ".. container:: function_list" << endl << endl; - Indentation indentation(INDENT); - for (const QString &func : qAsConst(functions)) - s << '*' << INDENT << func << endl; - - s << endl << endl; - } -} - -void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass) -{ - static const QString section_title = QLatin1String(".. attribute:: "); - - const AbstractMetaEnumList &enums = cppClass->enums(); - for (AbstractMetaEnum *en : enums) { - s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; - writeFormatedText(s, en->documentation(), cppClass); - - if (en->typeEntry() && (en->typeEntry()->version() != 0)) - s << ".. note:: This enum was introduced or modified in Qt " << en->typeEntry()->version() << endl; - } - -} - -void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppClass) -{ - static const QString section_title = QLatin1String(".. attribute:: "); - - const AbstractMetaFieldList &fields = cppClass->fields(); - for (AbstractMetaField *field : fields) { - s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl; - //TODO: request for member ‘documentation’ is ambiguous - writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass); - } -} - -void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* cppClass) -{ - static const QString sectionTitle = QLatin1String(".. class:: "); - static const QString sectionTitleSpace = QString(sectionTitle.size(), QLatin1Char(' ')); - - const AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible); - - bool first = true; - QHash arg_map; - - for (AbstractMetaFunction *func : lst) { - if (func->isModifiedRemoved()) - continue; - - if (first) { - first = false; - s << sectionTitle; - } else { - s << sectionTitleSpace; - } - writeFunction(s, false, cppClass, func); - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - if (!arg_map.contains(arg->name())) { - arg_map.insert(arg->name(), arg); - } - } - } - - s << endl; - - for (QHash::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { - Indentation indentation(INDENT); - writeParamerteType(s, cppClass, it.value()); - } - - s << endl; - - for (AbstractMetaFunction *func : lst) - writeFormatedText(s, func->documentation(), cppClass); -} - -QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) -{ - QString ret; - int optArgs = 0; - - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - bool thisIsoptional = !arg->defaultValueExpression().isEmpty(); - if (optArgs || thisIsoptional) { - ret += QLatin1Char('['); - optArgs++; - } - - if (arg->argumentIndex() > 0) - ret += QLatin1String(", "); - - ret += arg->name(); - - if (thisIsoptional) { - QString defValue = arg->defaultValueExpression(); - if (defValue == QLatin1String("QString()")) { - defValue = QLatin1String("\"\""); - } else if (defValue == QLatin1String("QStringList()") - || defValue.startsWith(QLatin1String("QVector")) - || defValue.startsWith(QLatin1String("QList"))) { - defValue = QLatin1String("list()"); - } else if (defValue == QLatin1String("QVariant()")) { - defValue = QLatin1String("None"); - } else { - defValue.replace(QLatin1String("::"), QLatin1String(".")); - if (defValue == QLatin1String("0") && (arg->type()->isQObject() || arg->type()->isObject())) - defValue = QLatin1String("None"); - } - ret += QLatin1Char('=') + defValue; - } - } - - ret += QString(optArgs, QLatin1Char(']')); - return ret; -} - -void QtDocGenerator::writeDocSnips(QTextStream &s, - const CodeSnipList &codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language) -{ - Indentation indentation(INDENT); - QStringList invalidStrings; - const static QString startMarkup = QLatin1String("[sphinx-begin]"); - const static QString endMarkup = QLatin1String("[sphinx-end]"); - - invalidStrings << QLatin1String("*") << QLatin1String("//") << QLatin1String("/*") << QLatin1String("*/"); - - for (const CodeSnip &snip : codeSnips) { - if ((snip.position != position) || - !(snip.language & language)) - continue; - - QString code = snip.code(); - while (code.contains(startMarkup) && code.contains(endMarkup)) { - int startBlock = code.indexOf(startMarkup) + startMarkup.size(); - int endBlock = code.indexOf(endMarkup); - - if ((startBlock == -1) || (endBlock == -1)) - break; - - QString codeBlock = code.mid(startBlock, endBlock - startBlock); - const QStringList rows = codeBlock.split(QLatin1Char('\n')); - int currenRow = 0; - int offset = 0; - - for (QString row : rows) { - for (const QString &invalidString : qAsConst(invalidStrings)) - row.remove(invalidString); - - if (row.trimmed().size() == 0) { - if (currenRow == 0) - continue; - else - s << endl; - } - - if (currenRow == 0) { - //find offset - for (int i=0, i_max = row.size(); i < i_max; i++) { - if (row[i] == QLatin1Char(' ')) - offset++; - else if (row[i] == QLatin1Char('\n')) - offset = 0; - else - break; - } - } - row = row.mid(offset); - s << row << endl; - currenRow++; - } - - code = code.mid(endBlock+endMarkup.size()); - } - } -} - -bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, - TypeSystem::DocModificationMode mode, - const AbstractMetaClass* cppClass, - const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - 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 doc; - Documentation::Format fmt; - - if (mod.format == TypeSystem::NativeCode) - fmt = Documentation::Native; - else if (mod.format == TypeSystem::TargetLangCode) - fmt = Documentation::Target; - else - continue; - - doc.setValue(mod.code() , fmt); - writeFormatedText(s, doc, cppClass); - didSomething = true; - } - } - } - - s << endl; - - // TODO: 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); - return didSomething; -} - -void QtDocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) -{ - QString className; - if (!func->isConstructor()) - className = getClassTargetFullName(cppClass) + QLatin1Char('.'); - else if (func->implementingClass() && func->implementingClass()->enclosingClass()) - className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + QLatin1Char('.'); - - QString funcName = getFuncName(func); - if (!funcName.startsWith(className)) - funcName = className + funcName; - - s << funcName << "(" << parseArgDocStyle(cppClass, func) << ")"; -} - -QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, const AbstractMetaClass* cppClass) -{ - QString strType; - if (type->name() == QLatin1String("QString")) { - strType = QLatin1String("unicode"); - } else if (type->name() == QLatin1String("QVariant")) { - strType = QLatin1String("object"); - } else if (type->name() == QLatin1String("QStringList")) { - strType = QLatin1String("list of strings"); - } else if (type->isConstant() && type->name() == QLatin1String("char") && type->indirections() == 1) { - strType = QLatin1String("str"); - } else if (type->name().startsWith(QLatin1String("unsigned short"))) { - strType = QLatin1String("int"); - } else if (type->name().startsWith(QLatin1String("unsigned "))) { // uint and ulong - strType = QLatin1String("long"); - } else if (type->isContainer()) { - QString strType = translateType(type, cppClass, Options(ExcludeConst) | ExcludeReference); - strType.remove(QLatin1Char('*')); - strType.remove(QLatin1Char('>')); - strType.remove(QLatin1Char('<')); - strType.replace(QLatin1String("::"), QLatin1String(".")); - if (strType.contains(QLatin1String("QList")) || strType.contains(QLatin1String("QVector"))) { - strType.replace(QLatin1String("QList"), QLatin1String("list of ")); - strType.replace(QLatin1String("QVector"), QLatin1String("list of ")); - } else if (strType.contains(QLatin1String("QHash")) || strType.contains(QLatin1String("QMap"))) { - strType.remove(QLatin1String("QHash")); - strType.remove(QLatin1String("QMap")); - QStringList types = strType.split(QLatin1Char(',')); - strType = QString::fromLatin1("Dictionary with keys of type %1 and values of type %2.") - .arg(types[0], types[1]); - } - } else { - QString refTag; - if (type->isEnum()) - refTag = QLatin1String("attr"); - else - refTag = QLatin1String("class"); - strType = QLatin1Char(':') + refTag + QLatin1String(":`") + type->fullName() + QLatin1Char('`'); - } - return strType; -} - -void QtDocGenerator::writeParamerteType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) -{ - s << INDENT << ":param " << arg->name() << ": " - << translateToPythonType(arg->type(), cppClass) << endl; -} - -void QtDocGenerator::writeFunctionParametersType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - - s << endl; - const AbstractMetaArgumentList &funcArgs = func->arguments(); - for (AbstractMetaArgument *arg : funcArgs) { - - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - writeParamerteType(s, cppClass, arg); - } - - if (!func->isConstructor() && func->type()) { - - QString retType; - // check if the return type was modified - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argMod : mod.argument_mods) { - if (argMod.index == 0) { - retType = argMod.modified_type; - break; - } - } - } - - if (retType.isEmpty()) - retType = translateToPythonType(func->type(), cppClass); - s << INDENT << ":rtype: " << retType << endl; - } - s << endl; -} - -void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) -{ - writeFunctionSignature(s, cppClass, func); - s << endl; - - if (func->typeEntry() && (func->typeEntry()->version() != 0)) - s << ".. note:: This method was introduced in Qt " << func->typeEntry()->version() << endl; - - if (writeDoc) { - s << endl; - writeFunctionParametersType(s, cppClass, func); - s << endl; - writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); - if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) - writeFormatedText(s, func->documentation(), cppClass); - writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); - } -} - -static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4) -{ - typedef QMap TocMap; - TocMap tocMap; - QChar Q = QLatin1Char('Q'); - QChar idx; - for (QString item : items) { - if (item.isEmpty()) - continue; - if (item.startsWith(Q) && item.length() > 1) - idx = item[1]; - item.chop(4); // Remove the .rst extension - tocMap[idx] << item; - } - QtXmlToSphinx::Table table; - QtXmlToSphinx::TableRow row; - - int itemsPerCol = (items.size() + tocMap.size()*2) / cols; - QString currentColData; - int i = 0; - QTextStream ss(¤tColData); - QMutableMapIterator it(tocMap); - while (it.hasNext()) { - it.next(); - qSort(it.value()); - - if (i) - ss << endl; - - ss << "**" << it.key() << "**" << endl << endl; - i += 2; // a letter title is equivalent to two entries in space - for (const QString &item : qAsConst(it.value())) { - ss << "* :doc:`" << item << "`" << endl; - ++i; - - // end of column detected! - if (i > itemsPerCol) { - ss.flush(); - QtXmlToSphinx::TableCell cell(currentColData); - row << cell; - currentColData.clear(); - i = 0; - } - } - } - if (i) { - ss.flush(); - QtXmlToSphinx::TableCell cell(currentColData); - row << cell; - currentColData.clear(); - i = 0; - } - table << row; - table.normalize(); - s << ".. container:: pysidetoc" << endl << endl; - s << table; -} - -bool QtDocGenerator::finishGeneration() -{ - if (classes().isEmpty()) - return true; - - QMap::iterator it = m_packages.begin(); - for (; it != m_packages.end(); ++it) { - QString key = it.key(); - key.replace(QLatin1Char('.'), QLatin1Char('/')); - QString outputDir = outputDirectory() + QLatin1Char('/') + key; - FileOut output(outputDir + QLatin1String("/index.rst")); - QTextStream& s = output.stream; - - s << ".. module:: " << it.key() << endl << endl; - - QString title = it.key(); - s << title << endl; - s << createRepeatedChar(title.length(), '*') << endl << endl; - - /* Avoid showing "Detailed Description for *every* class in toc tree */ - Indentation indentation(INDENT); - - // Search for extra-sections - if (!m_extraSectionDir.isEmpty()) { - QDir extraSectionDir(m_extraSectionDir); - QStringList fileList = extraSectionDir.entryList(QStringList() << (it.key() + QLatin1String("?*.rst")), QDir::Files); - QStringList::iterator it2 = fileList.begin(); - for (; it2 != fileList.end(); ++it2) { - QString origFileName(*it2); - it2->remove(0, it.key().count() + 1); - QString newFilePath = outputDir + QLatin1Char('/') + *it2; - if (QFile::exists(newFilePath)) - QFile::remove(newFilePath); - if (!QFile::copy(m_extraSectionDir + QLatin1Char('/') + origFileName, newFilePath)) { - qCDebug(lcShiboken).noquote().nospace() << "Error copying extra doc " - << QDir::toNativeSeparators(m_extraSectionDir + QLatin1Char('/') + origFileName) - << " to " << QDir::toNativeSeparators(newFilePath); - } - } - it.value().append(fileList); - } - - writeFancyToc(s, it.value()); - - s << INDENT << ".. container:: hide" << endl << endl; - { - Indentation indentation(INDENT); - s << INDENT << ".. toctree::" << endl; - Indentation deeperIndentation(INDENT); - s << INDENT << ":maxdepth: 1" << endl << endl; - for (const QString &className : qAsConst(it.value())) - s << INDENT << className << endl; - s << endl << endl; - } - - s << "Detailed Description" << endl; - s << "--------------------" << endl << endl; - - // module doc is always wrong and C++istic, so go straight to the extra directory! - QFile moduleDoc(m_extraSectionDir + QLatin1Char('/') + it.key() + QLatin1String(".rst")); - if (moduleDoc.open(QIODevice::ReadOnly | QIODevice::Text)) { - s << moduleDoc.readAll(); - moduleDoc.close(); - } else { - // try the normal way - Documentation moduleDoc = m_docParser->retrieveModuleDocumentation(it.key()); - if (moduleDoc.format() == Documentation::Native) { - QString context = it.key(); - context.remove(0, context.lastIndexOf(QLatin1Char('.')) + 1); - QtXmlToSphinx x(this, moduleDoc.value(), context); - s << x; - } else { - s << moduleDoc.value(); - } - } - } - return true; -} - -bool QtDocGenerator::doSetup(const QMap& args) -{ - m_libSourceDir = args.value(QLatin1String("library-source-dir")); - m_docDataDir = args.value(QLatin1String("documentation-data-dir")); -#ifdef __WIN32__ -# define PATH_SEP ';' -#else -# define PATH_SEP ':' -#endif - m_codeSnippetDirs = args.value(QLatin1String("documentation-code-snippets-dir"), m_libSourceDir).split(QLatin1Char(PATH_SEP)); - m_extraSectionDir = args.value(QLatin1String("documentation-extra-sections-dir")); - - m_docParser = args.value(QLatin1String("doc-parser")) == QLatin1String("doxygen") - ? static_cast(new DoxygenParser) - : static_cast(new QtDocParser); - qCDebug(lcShiboken).noquote().nospace() << "doc-parser: " << args.value(QLatin1String("doc-parser")); - - if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) { - qCWarning(lcShiboken) << "Documentation data dir and/or Qt source dir not informed, " - "documentation will not be extracted from Qt sources."; - return false; - } else { - m_docParser->setDocumentationDataDirectory(m_docDataDir); - m_docParser->setLibrarySourceDirectory(m_libSourceDir); - } - return true; -} - - -QMap QtDocGenerator::options() const -{ - QMap options; - options.insert(QLatin1String("doc-parser"), - QLatin1String("The documentation parser used to interpret the documentation input files (qdoc3|doxygen)")); - options.insert(QLatin1String("library-source-dir"), - QLatin1String("Directory where library source code is located")); - options.insert(QLatin1String("documentation-data-dir"), - QLatin1String("Directory with XML files generated by documentation tool (qdoc3 or Doxygen)")); - options.insert(QLatin1String("documentation-code-snippets-dir"), - QLatin1String("Directory used to search code snippets used by the documentation")); - options.insert(QLatin1String("documentation-extra-sections-dir"), - QLatin1String("Directory used to search for extra documentation sections")); - return options; -} - diff --git a/generator/qtdoc/qtdocgenerator.h b/generator/qtdoc/qtdocgenerator.h deleted file mode 100644 index fa8524b21..000000000 --- a/generator/qtdoc/qtdocgenerator.h +++ /dev/null @@ -1,235 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef DOCGENERATOR_H -#define DOCGENERATOR_H - -#include -#include -#include -#include -#include "generator.h" -#include "docparser.h" -#include "typesystem_enums.h" -#include "typesystem_typedefs.h" - -class QtDocParser; -class AbstractMetaFunction; -class AbstractMetaClass; -QT_BEGIN_NAMESPACE -class QXmlStreamReader; -QT_END_NAMESPACE -class QtDocGenerator; - -class QtXmlToSphinx -{ -public: - struct TableCell - { - short rowSpan; - short colSpan; - QString data; - - TableCell(const QString& text = QString()) : rowSpan(0), colSpan(0), data(text) {} - TableCell(const char* text) : rowSpan(0), colSpan(0), data(QLatin1String(text)) {} - }; - - typedef QList TableRow; - class Table : public QList - { - public: - Table() : m_hasHeader(false), m_normalized(false) - { - } - - void enableHeader(bool enable) - { - m_hasHeader = enable; - } - - bool hasHeader() const - { - return m_hasHeader; - } - - void normalize(); - - bool isNormalized() const - { - return m_normalized; - } - - void clear() { - m_normalized = false; - QList::clear(); - } - - private: - bool m_hasHeader; - bool m_normalized; - }; - - QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context = QString()); - - QString result() const - { - return m_result; - } - -private: - QString resolveContextForMethod(const QString& methodName); - QString expandFunction(const QString& function); - QString transform(const QString& doc); - - void handleHeadingTag(QXmlStreamReader& reader); - void handleParaTag(QXmlStreamReader& reader); - void handleItalicTag(QXmlStreamReader& reader); - void handleBoldTag(QXmlStreamReader& reader); - void handleArgumentTag(QXmlStreamReader& reader); - void handleSeeAlsoTag(QXmlStreamReader& reader); - void handleSnippetTag(QXmlStreamReader& reader); - void handleDotsTag(QXmlStreamReader& reader); - void handleLinkTag(QXmlStreamReader& reader); - void handleImageTag(QXmlStreamReader& reader); - void handleListTag(QXmlStreamReader& reader); - void handleTermTag(QXmlStreamReader& reader); - void handleSuperScriptTag(QXmlStreamReader& reader); - void handleQuoteFileTag(QXmlStreamReader& reader); - - // table tagsvoid QtXmlToSphinx::handleValueTag(QXmlStreamReader& reader) - - void handleTableTag(QXmlStreamReader& reader); - void handleRowTag(QXmlStreamReader& reader); - void handleItemTag(QXmlStreamReader& reader); - void handleRawTag(QXmlStreamReader& reader); - void handleCodeTag(QXmlStreamReader& reader); - - void handleIgnoredTag(QXmlStreamReader& reader); - void handleUnknownTag(QXmlStreamReader& reader); - void handleUselessTag(QXmlStreamReader& reader); - void handleAnchorTag(QXmlStreamReader& reader); - - typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&); - QHash m_handlerMap; - QStack m_handlers; - QTextStream m_output; - QString m_result; - - QStack m_buffers; - - - Table m_currentTable; - bool m_tableHasHeader; - QString m_context; - QtDocGenerator* m_generator; - bool m_insideBold; - bool m_insideItalic; - QString m_lastTagName; - QString m_opened_anchor; - - QString readFromLocations(const QStringList& locations, const QString& path, const QString& identifier); - QString readFromLocation(const QString& location, const QString& identifier, bool* ok = 0); - void pushOutputBuffer(); - QString popOutputBuffer(); - void writeTable(Table& table); -}; - -inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx) -{ - return s << xmlToSphinx.result(); -} - -QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table); - -/** -* The DocGenerator generates documentation from library being binded. -*/ -class QtDocGenerator : public Generator -{ -public: - QtDocGenerator(); - ~QtDocGenerator(); - - QString libSourceDir() const - { - return m_libSourceDir; - } - - bool doSetup(const QMap& args); - - const char* name() const - { - return "QtDocGenerator"; - } - - QMap options() const; - - QStringList codeSnippetDirs() const - { - return m_codeSnippetDirs; - } - -protected: - QString fileNamePrefix() const; - QString fileNameForContext(GeneratorContext &context) const; - void generateClass(QTextStream &s, GeneratorContext &classContext); - bool finishGeneration(); - - void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {} - void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {} - -private: - void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass); - - void writeFields(QTextStream &s, const AbstractMetaClass *cppClass); - void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func); - void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass); - void writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions); - void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg); - - void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass); - void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0); - bool writeInjectDocumentation(QTextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); - void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); - - - QString parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); - QString translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass); - - QString m_docDataDir; - QString m_libSourceDir; - QStringList m_codeSnippetDirs; - QString m_extraSectionDir; - QStringList m_functionList; - QMap m_packages; - DocParser* m_docParser; -}; - -#endif // DOCGENERATOR_H diff --git a/generator/shiboken2/CMakeLists.txt b/generator/shiboken2/CMakeLists.txt deleted file mode 100644 index 5c1b612dd..000000000 --- a/generator/shiboken2/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -project(shibokengenerator) - -set(shiboken_SRC -../generator.cpp -cppgenerator.cpp -headergenerator.cpp -overloaddata.cpp -shibokengenerator.cpp -main.cpp -) - -include_directories(${generators_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${APIEXTRACTOR_INCLUDE_DIR} - ${Qt5Core_INCLUDE_DIRS} - ) - -add_executable(shiboken2 ${shiboken_SRC}) -set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken_SUFFIX}) -target_link_libraries(shiboken2 - ${APIEXTRACTOR_LIBRARY} - ${Qt5Core_LIBRARIES} - ) - -configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) - -install(TARGETS shiboken2 DESTINATION bin) diff --git a/generator/shiboken2/cppgenerator.cpp b/generator/shiboken2/cppgenerator.cpp deleted file mode 100644 index 6aa2c83df..000000000 --- a/generator/shiboken2/cppgenerator.cpp +++ /dev/null @@ -1,5755 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include "cppgenerator.h" -#include "overloaddata.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -QHash CppGenerator::m_nbFuncs = QHash(); -QHash CppGenerator::m_sqFuncs = QHash(); -QHash CppGenerator::m_mpFuncs = QHash(); -QString CppGenerator::m_currentErrorCode(QLatin1String("0")); - -// utility functions -inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg) -{ - if (arg && arg->typeEntry()->isContainer()) { - AbstractMetaTypeList lst = arg->instantiations(); - // only support containers with 1 type - if (lst.size() == 1) - return lst[0]; - } - return arg; -} - -CppGenerator::CppGenerator() -{ - // Number protocol structure members names - m_nbFuncs.insert(QLatin1String("__add__"), QLatin1String("nb_add")); - m_nbFuncs.insert(QLatin1String("__sub__"), QLatin1String("nb_subtract")); - m_nbFuncs.insert(QLatin1String("__mul__"), QLatin1String("nb_multiply")); - m_nbFuncs.insert(QLatin1String("__div__"), QLatin1String("nb_divide")); - m_nbFuncs.insert(QLatin1String("__mod__"), QLatin1String("nb_remainder")); - m_nbFuncs.insert(QLatin1String("__neg__"), QLatin1String("nb_negative")); - m_nbFuncs.insert(QLatin1String("__pos__"), QLatin1String("nb_positive")); - m_nbFuncs.insert(QLatin1String("__invert__"), QLatin1String("nb_invert")); - m_nbFuncs.insert(QLatin1String("__lshift__"), QLatin1String("nb_lshift")); - m_nbFuncs.insert(QLatin1String("__rshift__"), QLatin1String("nb_rshift")); - m_nbFuncs.insert(QLatin1String("__and__"), QLatin1String("nb_and")); - m_nbFuncs.insert(QLatin1String("__xor__"), QLatin1String("nb_xor")); - m_nbFuncs.insert(QLatin1String("__or__"), QLatin1String("nb_or")); - m_nbFuncs.insert(QLatin1String("__iadd__"), QLatin1String("nb_inplace_add")); - m_nbFuncs.insert(QLatin1String("__isub__"), QLatin1String("nb_inplace_subtract")); - m_nbFuncs.insert(QLatin1String("__imul__"), QLatin1String("nb_inplace_multiply")); - m_nbFuncs.insert(QLatin1String("__idiv__"), QLatin1String("nb_inplace_divide")); - m_nbFuncs.insert(QLatin1String("__imod__"), QLatin1String("nb_inplace_remainder")); - m_nbFuncs.insert(QLatin1String("__ilshift__"), QLatin1String("nb_inplace_lshift")); - m_nbFuncs.insert(QLatin1String("__irshift__"), QLatin1String("nb_inplace_rshift")); - m_nbFuncs.insert(QLatin1String("__iand__"), QLatin1String("nb_inplace_and")); - m_nbFuncs.insert(QLatin1String("__ixor__"), QLatin1String("nb_inplace_xor")); - m_nbFuncs.insert(QLatin1String("__ior__"), QLatin1String("nb_inplace_or")); - m_nbFuncs.insert(QLatin1String("bool"), QLatin1String("nb_nonzero")); - - // sequence protocol functions - typedef QPair StrPair; - m_sequenceProtocol.insert(QLatin1String("__len__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR), QLatin1String("Py_ssize_t"))); - m_sequenceProtocol.insert(QLatin1String("__getitem__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i"), - QLatin1String("PyObject*"))); - m_sequenceProtocol.insert(QLatin1String("__setitem__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* _value"), - QLatin1String("int"))); - m_sequenceProtocol.insert(QLatin1String("__getslice__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2"), - QLatin1String("PyObject*"))); - m_sequenceProtocol.insert(QLatin1String("__setslice__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value"), - QLatin1String("int"))); - m_sequenceProtocol.insert(QLatin1String("__contains__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _value"), - QLatin1String("int"))); - m_sequenceProtocol.insert(QLatin1String("__concat__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _other"), - QLatin1String("PyObject*"))); - - // Sequence protocol structure members names - m_sqFuncs.insert(QLatin1String("__concat__"), QLatin1String("sq_concat")); - m_sqFuncs.insert(QLatin1String("__contains__"), QLatin1String("sq_contains")); - m_sqFuncs.insert(QLatin1String("__getitem__"), QLatin1String("sq_item")); - m_sqFuncs.insert(QLatin1String("__getslice__"), QLatin1String("sq_slice")); - m_sqFuncs.insert(QLatin1String("__len__"), QLatin1String("sq_length")); - m_sqFuncs.insert(QLatin1String("__setitem__"), QLatin1String("sq_ass_item")); - m_sqFuncs.insert(QLatin1String("__setslice__"), QLatin1String("sq_ass_slice")); - - // mapping protocol function - m_mappingProtocol.insert(QLatin1String("__mlen__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR), - QLatin1String("Py_ssize_t"))); - m_mappingProtocol.insert(QLatin1String("__mgetitem__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key"), - QLatin1String("PyObject*"))); - m_mappingProtocol.insert(QLatin1String("__msetitem__"), - StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key, PyObject* _value"), - QLatin1String("int"))); - - // Sequence protocol structure members names - m_mpFuncs.insert(QLatin1String("__mlen__"), QLatin1String("mp_length")); - m_mpFuncs.insert(QLatin1String("__mgetitem__"), QLatin1String("mp_subscript")); - m_mpFuncs.insert(QLatin1String("__msetitem__"), QLatin1String("mp_ass_subscript")); -} - -QString CppGenerator::fileNamePrefix() const -{ - return QLatin1String("_wrapper.cpp"); -} - -QString CppGenerator::fileNameForContext(GeneratorContext &context) const -{ - const AbstractMetaClass *metaClass = context.metaClass(); - if (!context.forSmartPointer()) { - QString fileNameBase = metaClass->qualifiedCppName().toLower(); - fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); - return fileNameBase + fileNamePrefix(); - } else { - const AbstractMetaType *smartPointerType = context.preciseType(); - QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); - } -} - -QVector CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, - uint queryIn) -{ - // ( func_name, num_args ) => func_list - typedef QMap, AbstractMetaFunctionList> ResultMap; - ResultMap results; - const AbstractMetaClass::OperatorQueryOptions query(queryIn); - const AbstractMetaFunctionList &funcs = metaClass->operatorOverloads(query); - for (AbstractMetaFunction *func : funcs) { - if (func->isModifiedRemoved() - || func->usesRValueReferences() - || func->name() == QLatin1String("operator[]") - || func->name() == QLatin1String("operator->") - || func->name() == QLatin1String("operator!")) { - continue; - } - int args; - if (func->isComparisonOperator()) { - args = -1; - } else { - args = func->arguments().size(); - } - QPair op(func->name(), args); - results[op].append(func); - } - QVector result; - result.reserve(results.size()); - for (ResultMap::const_iterator it = results.cbegin(), end = results.cend(); it != end; ++it) - result.append(it.value()); - return result; -} - -bool CppGenerator::hasBoolCast(const AbstractMetaClass* metaClass) const -{ - if (!useIsNullAsNbNonZero()) - return false; - // TODO: This could be configurable someday - const AbstractMetaFunction* func = metaClass->findFunction(QLatin1String("isNull")); - if (!func || !func->type() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic()) - return false; - const PrimitiveTypeEntry* pte = static_cast(func->type()->typeEntry()); - while (pte->referencedTypeEntry()) - pte = pte->referencedTypeEntry(); - return func && func->isConstant() && pte->name() == QLatin1String("bool") && func->arguments().isEmpty(); -} - -typedef QMap FunctionGroupMap; -typedef FunctionGroupMap::const_iterator FunctionGroupMapIt; - -// Prevent ELF symbol qt_version_tag from being generated into the source -static const char includeQDebug[] = -"#ifndef QT_NO_VERSION_TAGGING\n" -"# define QT_NO_VERSION_TAGGING\n" -"#endif\n" -"#include \n"; - -static QString chopType(QString s) -{ - if (s.endsWith(QLatin1String("_Type"))) - s.chop(5); - return s; -} - -/*! - Function used to write the class generated binding code on the buffer - \param s the output buffer - \param metaClass the pointer to metaclass information -*/ -void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) -{ - AbstractMetaClass *metaClass = classContext.metaClass(); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName(); - - // write license comment - s << licenseComment() << endl; - - if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { - s << "//workaround to access protected functions" << endl; - s << "#define protected public" << endl << endl; - } - - // headers - s << "// default includes" << endl; - s << "#include " << endl; - if (usePySideExtensions()) { - s << includeQDebug; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - } - - s << "#include " << endl; - s << "#include " << endl; - if (usePySideExtensions() && metaClass->isQObject()) { - s << "#include " << endl; - s << "#include " << endl; - } - - // The multiple inheritance initialization function - // needs the 'set' class from C++ STL. - if (hasMultipleInheritanceInAncestry(metaClass)) - s << "#include " << endl; - - s << endl << "// module include" << endl << "#include \"" << getModuleHeaderFileName() << '"' << endl; - - QString headerfile = fileNameForContext(classContext); - headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); - s << endl << "// main header" << endl << "#include \"" << headerfile << '"' << endl; - - // PYSIDE-500: Use also includes for inherited wrapper classes, because - // without the protected hack, we sometimes need to cast inherited wrappers. - s << endl << "// inherited wrapper classes" << endl; - AbstractMetaClass *basis = metaClass->baseClass(); - for (; basis; basis = basis->baseClass()) { - GeneratorContext basisContext(basis); - QString headerfile = fileNameForContext(basisContext); - headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); - s << "#include \"" << headerfile << '"' << endl; - } - - s << endl << "// inner classes" << endl; - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) { - GeneratorContext innerClassContext(innerClass); - if (shouldGenerate(innerClass)) { - QString headerfile = fileNameForContext(innerClassContext); - headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); - s << "#include \"" << headerfile << '"' << endl; - } - } - - AbstractMetaEnumList classEnums = metaClass->enums(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); - - //Extra includes - s << endl << "// Extra includes" << endl; - QVector includes = metaClass->typeEntry()->extraIncludes(); - for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) - includes.append(cppEnum->typeEntry()->extraIncludes()); - qSort(includes.begin(), includes.end()); - for (const Include &inc : qAsConst(includes)) - s << inc.toString() << endl; - s << endl; - - if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) - s << "#Deprecated" << endl; - - // Use class base namespace - { - const AbstractMetaClass *context = metaClass->enclosingClass(); - while (context) { - if (context->isNamespace() && !context->enclosingClass()) { - s << "using namespace " << context->qualifiedCppName() << ";" << endl; - break; - } - context = context->enclosingClass(); - } - } - - s << endl; - - // Create string literal for smart pointer getter method. - if (classContext.forSmartPointer()) { - const SmartPointerTypeEntry *typeEntry = - static_cast(classContext.preciseType() - ->typeEntry()); - QString rawGetter = typeEntry->getter(); - s << "static const char * " SMART_POINTER_GETTER " = \"" << rawGetter << "\";"; - } - - // class inject-code native/beginning - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass); - s << endl; - } - - // python conversion rules - if (metaClass->typeEntry()->hasTargetConversionRule()) { - s << "// Python Conversion" << endl; - s << metaClass->typeEntry()->conversionRule() << endl; - } - - if (shouldGenerateCppWrapper(metaClass)) { - s << "// Native ---------------------------------------------------------" << endl; - s << endl; - - if (avoidProtectedHack() && usePySideExtensions()) { - s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n"; - Indentation indent(INDENT); - writeInitQtMetaTypeFunctionBody(s, classContext); - s << "}\n\n"; - } - - const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); - for (const AbstractMetaFunction *func : funcs) { - if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) - || (func->isModifiedRemoved() && !func->isAbstract())) - continue; - if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) - writeConstructorNative(s, func); - else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) - && (func->isVirtual() || func->isAbstract())) - writeVirtualMethodNative(s, func); - } - - if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) { - if (usePySideExtensions() && metaClass->isQObject()) - writeMetaObjectMethod(s, metaClass); - writeDestructorNative(s, metaClass); - } - } - - Indentation indentation(INDENT); - - QString methodsDefinitions; - QTextStream md(&methodsDefinitions); - QString singleMethodDefinitions; - QTextStream smd(&singleMethodDefinitions); - - s << endl << "// Target ---------------------------------------------------------" << endl << endl; - s << "extern \"C\" {" << endl; - const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - AbstractMetaFunctionList overloads; - QSet seenSignatures; - for (AbstractMetaFunction *func : it.value()) { - if (!func->isAssignmentOperator() - && !func->usesRValueReferences() - && !func->isCastOperator() - && !func->isModifiedRemoved() - && (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction) - && func->ownerClass() == func->implementingClass() - && (func->name() != QLatin1String("qt_metacall"))) { - // PYSIDE-331: Inheritance works correctly when there are disjoint functions. - // But when a function is both in a class and inherited in a subclass, - // then we need to search through all subclasses and collect the new signatures. - overloads << getFunctionAndInheritedOverloads(func, &seenSignatures); - } - } - - if (overloads.isEmpty()) - continue; - - const AbstractMetaFunction* rfunc = overloads.first(); - if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name())) - continue; - - if (rfunc->isConstructor()) { - // @TODO: Implement constructor support for smart pointers, so that they can be - // instantiated in python code. - if (classContext.forSmartPointer()) - continue; - writeConstructorWrapper(s, overloads, classContext); - } - // call operators - else if (rfunc->name() == QLatin1String("operator()")) - writeMethodWrapper(s, overloads, classContext); - else if (!rfunc->isOperatorOverload()) { - - if (classContext.forSmartPointer()) { - const SmartPointerTypeEntry *smartPointerTypeEntry = - static_cast( - classContext.preciseType()->typeEntry()); - - if (smartPointerTypeEntry->getter() == rfunc->name()) { - // Replace the return type of the raw pointer getter method with the actual - // return type. - QString innerTypeName = - classContext.preciseType()->getSmartPointerInnerType()->name(); - QString pointerToInnerTypeName = innerTypeName + QLatin1Char('*'); - // @TODO: This possibly leaks, but there are a bunch of other places where this - // is done, so this will be fixed in bulk with all the other cases, because the - // ownership of the pointers is not clear at the moment. - AbstractMetaType *pointerToInnerType = - buildAbstractMetaTypeFromString(pointerToInnerTypeName); - - AbstractMetaFunction *mutableRfunc = overloads.first(); - mutableRfunc->replaceType(pointerToInnerType); - } else if (smartPointerTypeEntry->refCountMethodName().isEmpty() - || smartPointerTypeEntry->refCountMethodName() != rfunc->name()) { - // Skip all public methods of the smart pointer except for the raw getter and - // the ref count method. - continue; - } - } - - writeMethodWrapper(s, overloads, classContext); - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { - QString methDefName = cpythonMethodDefinitionName(rfunc); - smd << "static PyMethodDef " << methDefName << " = {" << endl; - smd << INDENT; - writeMethodDefinitionEntry(smd, overloads); - smd << endl << "};" << endl << endl; - } - writeMethodDefinition(md, overloads); - } - } - - const QString className = chopType(cpythonTypeName(metaClass)); - - if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) - writeCopyFunction(s, classContext); - - // Write single method definitions - s << singleMethodDefinitions; - - // Write methods definition - s << "static PyMethodDef " << className << "_methods[] = {" << endl; - s << methodsDefinitions << endl; - if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) - s << INDENT << "{\"__copy__\", (PyCFunction)" << className << "___copy__" << ", METH_NOARGS}," << endl; - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - - // Write tp_getattro function - if ((usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))) { - writeGetattroFunction(s, classContext); - s << endl; - writeSetattroFunction(s, classContext); - s << endl; - } else { - if (classNeedsGetattroFunction(metaClass)) { - writeGetattroFunction(s, classContext); - s << endl; - } - if (classNeedsSetattroFunction(metaClass)) { - writeSetattroFunction(s, classContext); - s << endl; - } - } - - if (hasBoolCast(metaClass)) { - ErrorCode errorCode(-1); - s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, classContext); - s << INDENT << "int result;" << endl; - s << INDENT << BEGIN_ALLOW_THREADS << endl; - s << INDENT << "result = !" CPP_SELF_VAR "->isNull();" << endl; - s << INDENT << END_ALLOW_THREADS << endl; - s << INDENT << "return result;" << endl; - s << '}' << endl << endl; - } - - if (supportsNumberProtocol(metaClass) && !metaClass->typeEntry()->isSmartPointer()) { - const QVector opOverloads = filterGroupedOperatorFunctions( - metaClass, - AbstractMetaClass::ArithmeticOp - | AbstractMetaClass::LogicalOp - | AbstractMetaClass::BitwiseOp); - - for (const AbstractMetaFunctionList &allOverloads : opOverloads) { - AbstractMetaFunctionList overloads; - for (AbstractMetaFunction *func : allOverloads) { - if (!func->isModifiedRemoved() - && !func->isPrivate() - && (func->ownerClass() == func->implementingClass() || func->isAbstract())) - overloads.append(func); - } - - if (overloads.isEmpty()) - continue; - - writeMethodWrapper(s, overloads, classContext); - } - } - - if (supportsSequenceProtocol(metaClass)) { - writeSequenceMethods(s, metaClass, classContext); - } - - if (supportsMappingProtocol(metaClass)) { - writeMappingMethods(s, metaClass, classContext); - } - - if (metaClass->hasComparisonOperatorOverload()) { - s << "// Rich comparison" << endl; - writeRichCompareFunction(s, classContext); - } - - if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) { - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField *metaField : fields) { - if (metaField->isStatic()) - continue; - writeGetterFunction(s, metaField, classContext); - if (!metaField->type()->isConstant()) - writeSetterFunction(s, metaField, classContext); - s << endl; - } - - s << "// Getters and Setters for " << metaClass->name() << endl; - s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl; - for (const AbstractMetaField *metaField : fields) { - if (metaField->isStatic()) - continue; - - bool hasSetter = !metaField->type()->isConstant(); - s << INDENT << "{const_cast(\"" << metaField->name() << "\"), "; - s << cpythonGetterFunctionName(metaField); - s << ", " << (hasSetter ? cpythonSetterFunctionName(metaField) : QLatin1String("0")); - s << "}," << endl; - } - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - } - - s << "} // extern \"C\"" << endl << endl; - - if (!metaClass->typeEntry()->hashFunction().isEmpty()) - writeHashFunction(s, classContext); - - // Write tp_traverse and tp_clear functions. - writeTpTraverseFunction(s, metaClass); - writeTpClearFunction(s, metaClass); - - writeClassDefinition(s, metaClass, classContext); - s << endl; - - if (metaClass->isPolymorphic() && metaClass->baseClass()) - writeTypeDiscoveryFunction(s, metaClass); - - - for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - - bool hasFlags = cppEnum->typeEntry()->flags(); - if (hasFlags) { - writeFlagsMethods(s, cppEnum); - writeFlagsNumberMethodsDefinition(s, cppEnum); - s << endl; - } - } - s << endl; - - writeConverterFunctions(s, metaClass, classContext); - writeClassRegister(s, metaClass, classContext); - - // class inject-code native/end - if (!metaClass->typeEntry()->codeSnips().isEmpty()) { - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, metaClass); - s << endl; - } -} - -void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func) -{ - Indentation indentation(INDENT); - s << functionSignature(func, wrapperName(func->ownerClass()) + QLatin1String("::"), QString(), - OriginalTypeDescription | SkipDefaultValues); - s << " : "; - writeFunctionCall(s, func); - s << " {" << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); - s << INDENT << "// ... middle" << endl; - writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); - s << '}' << endl << endl; -} - -void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass) -{ - Indentation indentation(INDENT); - s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; - // kill pyobject - s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "Shiboken::Object::destroy(wrapper, this);" << endl; - s << '}' << endl; -} - -static bool allArgumentsRemoved(const AbstractMetaFunction* func) -{ - if (func->arguments().isEmpty()) - return false; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (!func->argumentRemoved(arg->argumentIndex() + 1)) - return false; - } - return true; -} - -QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func) -{ - if (!func->type()) - return QLatin1String("\"\""); - - if (!func->typeReplaced(0).isEmpty()) - return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"'); - - // SbkType would return null when the type is a container. - if (func->type()->typeEntry()->isContainer()) { - return QLatin1Char('"') - + reinterpret_cast(func->type()->typeEntry())->typeName() - + QLatin1Char('"'); - } - - if (avoidProtectedHack()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); - if (metaEnum && metaEnum->isProtected()) - return QLatin1Char('"') + protectedEnumSurrogateName(metaEnum) + QLatin1Char('"'); - } - - if (func->type()->isPrimitive()) - return QLatin1Char('"') + func->type()->name() + QLatin1Char('"'); - - return QString::fromLatin1("Shiboken::SbkType< %1 >()->tp_name").arg(func->type()->typeEntry()->qualifiedCppName()); -} - -void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFunction* func) -{ - //skip metaObject function, this will be written manually ahead - if (usePySideExtensions() && func->ownerClass() && func->ownerClass()->isQObject() && - ((func->name() == QLatin1String("metaObject")) || (func->name() == QLatin1String("qt_metacall")))) - return; - - const TypeEntry* retType = func->type() ? func->type()->typeEntry() : 0; - const QString funcName = func->isOperatorOverload() ? pythonOperatorFunctionName(func) : func->name(); - - QString prefix = wrapperName(func->ownerClass()) + QLatin1String("::"); - s << functionSignature(func, prefix, QString(), Generator::SkipDefaultValues|Generator::OriginalTypeDescription) - << endl << '{' << endl; - - Indentation indentation(INDENT); - - QString defaultReturnExpr; - if (retType) { - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &mod : mods) { - for (const ArgumentModification &argMod : mod.argument_mods) { - if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { - static const QRegularExpression regex(QStringLiteral("%(\\d+)")); - Q_ASSERT(regex.isValid()); - defaultReturnExpr = argMod.replacedDefaultExpression; - for (int offset = 0; ; ) { - const QRegularExpressionMatch match = regex.match(defaultReturnExpr, offset); - if (!match.hasMatch()) - break; - const int argId = match.capturedRef(1).toInt() - 1; - if (argId < 0 || argId > func->arguments().count()) { - qCWarning(lcShiboken) << "The expression used in return value contains an invalid index."; - break; - } - defaultReturnExpr.replace(match.captured(0), func->arguments()[argId]->name()); - offset = match.capturedStart(1); - } - } - } - } - if (defaultReturnExpr.isEmpty()) - defaultReturnExpr = minimalConstructor(func->type()); - if (defaultReturnExpr.isEmpty()) { - QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": "); - if (const AbstractMetaClass *c = func->implementingClass()) - errorMsg += c->qualifiedCppName() + QLatin1String("::"); - errorMsg += func->signature(); - errorMsg = ShibokenGenerator::msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); - qCWarning(lcShiboken).noquote().nospace() << errorMsg; - s << endl << INDENT << "#error " << errorMsg << endl; - } - } - - if (func->isAbstract() && func->isModifiedRemoved()) { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\ - "completely removed on type system.") - .arg(func->ownerClass()->name(), func->minimalSignature()); - s << INDENT << "return " << defaultReturnExpr << ';' << endl; - s << '}' << endl << endl; - return; - } - - //Write declaration/native injected code - if (func->hasInjectedCode()) { - CodeSnipList snips = func->injectedCodeSnips(); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg); - s << endl; - } - - s << INDENT << "Shiboken::GilState gil;" << endl; - - // Get out of virtual method call if someone already threw an error. - s << INDENT << "if (PyErr_Occurred())" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "return " << defaultReturnExpr << ';' << endl; - } - - s << INDENT << "Shiboken::AutoDecRef " PYTHON_OVERRIDE_VAR "(Shiboken::BindingManager::instance().getOverride(this, \""; - s << funcName << "\"));" << endl; - - s << INDENT << "if (" PYTHON_OVERRIDE_VAR ".isNull()) {" << endl; - { - Indentation indentation(INDENT); - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg); - s << endl; - } - - if (func->isAbstract()) { - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; - s << func->ownerClass()->name() << '.' << funcName; - s << "()' not implemented.\");" << endl; - s << INDENT << "return " << (retType ? defaultReturnExpr : QString()); - } else { - s << INDENT << "gil.release();" << endl; - s << INDENT; - if (retType) - s << "return "; - s << "this->::" << func->implementingClass()->qualifiedCppName() << "::"; - writeFunctionCall(s, func, Generator::VirtualCall); - if (!retType) - s << ";\n" << INDENT << "return"; - } - } - s << ';' << endl; - s << INDENT << '}' << endl << endl; - - writeConversionRule(s, func, TypeSystem::TargetLangCode); - - s << INDENT << "Shiboken::AutoDecRef " PYTHON_ARGS "("; - - if (func->arguments().isEmpty() || allArgumentsRemoved(func)) { - s << "PyTuple_New(0));" << endl; - } else { - QStringList argConversions; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - QString argConv; - QTextStream ac(&argConv); - const PrimitiveTypeEntry* argType = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); - bool convert = argType->isObject() - || arg->type()->isQObject() - || argType->isValue() - || arg->type()->isValuePointer() - || arg->type()->isNativePointer() - || argType->isFlags() - || argType->isEnum() - || argType->isContainer() - || arg->type()->referenceType() == LValueReference; - - if (!convert && argType->isPrimitive()) { - if (argType->basicReferencedTypeEntry()) - argType = argType->basicReferencedTypeEntry(); - convert = !m_formatUnits.contains(argType->name()); - } - - Indentation indentation(INDENT); - ac << INDENT; - if (!func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty()) { - // Has conversion rule. - ac << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); - } else { - QString argName = arg->name(); - if (convert) - writeToPythonConversion(ac, arg->type(), func->ownerClass(), argName); - else - ac << argName; - } - - argConversions << argConv; - } - - s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\"," << endl; - s << argConversions.join(QLatin1String(",\n")) << endl; - s << INDENT << "));" << endl; - } - - bool invalidateReturn = false; - QSet invalidateArgs; - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &funcMod : mods) { - for (const ArgumentModification &argMod : funcMod.argument_mods) { - if (argMod.resetAfterUse && !invalidateArgs.contains(argMod.index)) { - invalidateArgs.insert(argMod.index); - s << INDENT << "bool invalidateArg" << argMod.index; - s << " = PyTuple_GET_ITEM(" PYTHON_ARGS ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl; - } else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) { - invalidateReturn = true; - } - } - } - s << endl; - - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - - if (injectedCodeUsesPySelf(func)) - s << INDENT << "PyObject* pySelf = BindingManager::instance().retrieveWrapper(this);" << endl; - - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); - s << endl; - } - - if (!injectedCodeCallsPythonOverride(func)) { - s << INDENT; - s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(" PYTHON_OVERRIDE_VAR ", " PYTHON_ARGS ", NULL));" << endl; - - s << INDENT << "// An error happened in python code!" << endl; - s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "return " << defaultReturnExpr << ';' << endl; - } - s << INDENT << '}' << endl; - - if (retType) { - if (invalidateReturn) - s << INDENT << "bool invalidateArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl; - - if (func->typeReplaced(0) != QLatin1String("PyObject")) { - - s << INDENT << "// Check return type" << endl; - s << INDENT; - if (func->typeReplaced(0).isEmpty()) { - s << "PythonToCppFunc " PYTHON_TO_CPP_VAR " = " << cpythonIsConvertibleFunction(func->type()); - s << PYTHON_RETURN_VAR ");" << endl; - s << INDENT << "if (!" PYTHON_TO_CPP_VAR ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\ - "\"Invalid return value in function %s, expected %s, got %s.\", \""; - s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); - s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; - s << INDENT << "return " << defaultReturnExpr << ';' << endl; - } - s << INDENT << '}' << endl; - - } else { - - s << INDENT << "// Check return type" << endl; - s << INDENT << "bool typeIsValid = "; - writeTypeCheck(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), - isNumber(func->type()->typeEntry()), func->typeReplaced(0)); - s << ';' << endl; - s << INDENT << "if (!typeIsValid"; - s << (isPointerToWrapperType(func->type()) ? " && " PYTHON_RETURN_VAR " != Py_None" : ""); - s << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\ - "\"Invalid return value in function %s, expected %s, got %s.\", \""; - s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); - s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; - s << INDENT << "return " << defaultReturnExpr << ';' << endl; - } - s << INDENT << '}' << endl; - - } - } - - if (!func->conversionRule(TypeSystem::NativeCode, 0).isEmpty()) { - // Has conversion rule. - writeConversionRule(s, func, TypeSystem::NativeCode, QLatin1String(CPP_RETURN_VAR)); - } else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) { - writePythonToCppTypeConversion(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), - QLatin1String(CPP_RETURN_VAR), func->implementingClass()); - } - } - } - - if (invalidateReturn) { - s << INDENT << "if (invalidateArg0)" << endl; - Indentation indentation(INDENT); - s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR ".object());" << endl; - } - for (int argIndex : qAsConst(invalidateArgs)) { - s << INDENT << "if (invalidateArg" << argIndex << ')' << endl; - Indentation indentation(INDENT); - s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", "; - s << (argIndex - 1) << "));" << endl; - } - - - const FunctionModificationList &funcMods = func->modifications(); - for (const FunctionModification &funcMod : funcMods) { - for (const ArgumentModification &argMod : funcMod.argument_mods) { - if (argMod.ownerships.contains(TypeSystem::NativeCode) - && argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) { - s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl; - Indentation indent(INDENT); - s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl; - } - } - } - - if (func->hasInjectedCode()) { - s << endl; - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); - } - - if (retType) { - s << INDENT << "return "; - if (avoidProtectedHack() && retType->isEnum()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(retType); - bool isProtectedEnum = metaEnum && metaEnum->isProtected(); - if (isProtectedEnum) { - QString typeCast; - if (metaEnum->enclosingClass()) - typeCast += QLatin1String("::") + metaEnum->enclosingClass()->qualifiedCppName(); - typeCast += QLatin1String("::") + metaEnum->name(); - s << '(' << typeCast << ')'; - } - } - if (func->type()->referenceType() == LValueReference && !isPointer(func->type())) - s << '*'; - s << CPP_RETURN_VAR ";" << endl; - } - - s << '}' << endl << endl; -} - -void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass) -{ - Indentation indentation(INDENT); - QString wrapperClassName = wrapperName(metaClass); - s << "const QMetaObject* " << wrapperClassName << "::metaObject() const" << endl; - s << '{' << endl; - s << INDENT << "if (QObject::d_ptr->metaObject)" << endl - << INDENT << INDENT << "return QObject::d_ptr->dynamicMetaObject();" << endl; - s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "if (pySelf == NULL)" << endl; - s << INDENT << INDENT << "return " << metaClass->qualifiedCppName() << "::metaObject();" << endl; - s << INDENT << "return PySide::SignalManager::retriveMetaObject(reinterpret_cast(pySelf));" << endl; - s << '}' << endl << endl; - - // qt_metacall function - s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void** args)" << endl; - s << "{" << endl; - - AbstractMetaFunction *func = NULL; - AbstractMetaFunctionList list = metaClass->queryFunctionsByName(QLatin1String("qt_metacall")); - if (list.size() == 1) - func = list[0]; - - CodeSnipList snips; - if (func) { - snips = func->injectedCodeSnips(); - if (func->isUserAdded()) { - CodeSnipList snips = func->injectedCodeSnips(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode, func); - } - } - - s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);" << endl; - s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);" << endl; - s << "}" << endl << endl; - - // qt_metacast function - writeMetaCast(s, metaClass); -} - -void CppGenerator::writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass) -{ - Indentation indentation(INDENT); - QString wrapperClassName = wrapperName(metaClass); - s << "void* " << wrapperClassName << "::qt_metacast(const char* _clname)" << endl; - s << '{' << endl; - s << INDENT << "if (!_clname) return 0;" << endl; - s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))" << endl; - s << INDENT << INDENT << "return static_cast(const_cast< " << wrapperClassName << "* >(this));" << endl; - s << INDENT << "return " << metaClass->qualifiedCppName() << "::qt_metacast(_clname);" << endl; - s << "}" << endl << endl; -} - -void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum) -{ - if (metaEnum->isPrivate() || metaEnum->isAnonymous()) - return; - writeEnumConverterFunctions(s, metaEnum->typeEntry()); -} - -void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType) -{ - if (!enumType) - return; - QString enumFlagName = enumType->isFlags() ? QLatin1String("flag") : QLatin1String("enum"); - QString typeName = fixedCppTypeName(enumType); - QString enumPythonType = cpythonTypeNameExt(enumType); - QString cppTypeName = getFullTypeName(enumType).trimmed(); - if (avoidProtectedHack()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(enumType); - if (metaEnum && metaEnum->isProtected()) - cppTypeName = protectedEnumSurrogateName(metaEnum); - } - QString code; - QTextStream c(&code); - c << INDENT << "*((" << cppTypeName << "*)cppOut) = "; - if (enumType->isFlags()) - c << cppTypeName << "(QFlag((int)PySide::QFlags::getValue(reinterpret_cast(pyIn))))"; - else - c << "(" << cppTypeName << ") Shiboken::Enum::getValue(pyIn)"; - c << ';' << endl; - writePythonToCppFunction(s, code, typeName, typeName); - - QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, %1)").arg(enumPythonType); - writeIsPythonConvertibleToCppFunction(s, typeName, typeName, pyTypeCheck); - - code.clear(); - - c << INDENT << "int castCppIn = *((" << cppTypeName << "*)cppIn);" << endl; - c << INDENT; - c << "return "; - if (enumType->isFlags()) - c << "reinterpret_cast(PySide::QFlags::newObject(castCppIn, " << enumPythonType << "))"; - - else - c << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn)"; - c << ';' << endl; - writeCppToPythonFunction(s, code, typeName, typeName); - s << endl; - - if (enumType->isFlags()) - return; - - const FlagsTypeEntry* flags = reinterpret_cast(enumType)->flags(); - if (!flags) - return; - - // QFlags part. - - writeEnumConverterFunctions(s, flags); - - code.clear(); - cppTypeName = getFullTypeName(flags).trimmed(); - c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName; - c << "(QFlag((int)Shiboken::Enum::getValue(pyIn)));" << endl; - - QString flagsTypeName = fixedCppTypeName(flags); - writePythonToCppFunction(s, code, typeName, flagsTypeName); - writeIsPythonConvertibleToCppFunction(s, typeName, flagsTypeName, pyTypeCheck); - - code.clear(); - c << INDENT << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));" << endl; - c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName; - c << "(QFlag((int)PyLong_AsLong(pyLong.object())));" << endl; - writePythonToCppFunction(s, code, QLatin1String("number"), flagsTypeName); - writeIsPythonConvertibleToCppFunction(s, QLatin1String("number"), flagsTypeName, - QLatin1String("PyNumber_Check(pyIn)")); -} - -void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext) -{ - s << "// Type conversion functions." << endl << endl; - - AbstractMetaEnumList classEnums = metaClass->enums(); - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); - if (!classEnums.isEmpty()) - s << "// Python to C++ enum conversion." << endl; - for (const AbstractMetaEnum *metaEnum : qAsConst(classEnums)) - writeEnumConverterFunctions(s, metaEnum); - - if (metaClass->isNamespace()) - return; - - QString typeName; - if (!classContext.forSmartPointer()) - typeName = getFullTypeName(metaClass); - else - typeName = getFullTypeName(classContext.preciseType()); - - QString cpythonType = cpythonTypeName(metaClass); - - // Returns the C++ pointer of the Python wrapper. - s << "// Python to C++ pointer conversion - returns the C++ object of the Python wrapper (keeps object identity)." << endl; - - QString sourceTypeName = metaClass->name(); - QString targetTypeName = metaClass->name() + QLatin1String("_PTR"); - QString code; - QTextStream c(&code); - c << INDENT << "Shiboken::Conversions::pythonToCppPointer(&" << cpythonType << ", pyIn, cppOut);"; - writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); - - // "Is convertible" function for the Python object to C++ pointer conversion. - QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, (PyTypeObject*)&%1)").arg(cpythonType); - writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true); - s << endl; - - // 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)." << endl; - code.clear(); - if (usePySideExtensions() && metaClass->isQObject()) - { - c << INDENT << "return PySide::getWrapperForQObject((" << typeName << "*)cppIn, &" << cpythonType << ");" << endl; - } else { - c << INDENT << "PyObject* pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppIn);" << endl; - c << INDENT << "if (pyOut) {" << endl; - { - Indentation indent(INDENT); - c << INDENT << "Py_INCREF(pyOut);" << endl; - c << INDENT << "return pyOut;" << endl; - } - c << INDENT << '}' << endl; - c << INDENT << "const char* typeName = typeid(*((" << typeName << "*)cppIn)).name();" << endl; - c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType; - c << ", const_cast(cppIn), false, false, typeName);"; - } - std::swap(targetTypeName, sourceTypeName); - writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); - - // The conversions for an Object Type end here. - if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) { - s << endl; - return; - } - - // Always copies C++ value (not pointer, and not reference) to a new Python wrapper. - s << endl << "// C++ to Python copy conversion." << endl; - if (!classContext.forSmartPointer()) - targetTypeName = metaClass->name(); - else - targetTypeName = classContext.preciseType()->name(); - - sourceTypeName = targetTypeName + QLatin1String("_COPY"); - - code.clear(); - - QString computedWrapperName; - if (!classContext.forSmartPointer()) - computedWrapperName = wrapperName(metaClass); - else - computedWrapperName = wrapperName(classContext.preciseType()); - - c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << computedWrapperName; - c << "(*((" << typeName << "*)cppIn)), true, true);"; - writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); - s << endl; - - // Python to C++ copy conversion. - s << "// Python to C++ copy conversion." << endl; - if (!classContext.forSmartPointer()) - sourceTypeName = metaClass->name(); - else - sourceTypeName = classContext.preciseType()->name(); - - targetTypeName = QStringLiteral("%1_COPY").arg(sourceTypeName); - code.clear(); - - QString pyInVariable = QLatin1String("pyIn"); - QString wrappedCPtrExpression; - if (!classContext.forSmartPointer()) - wrappedCPtrExpression = cpythonWrapperCPtr(metaClass->typeEntry(), pyInVariable); - else - wrappedCPtrExpression = cpythonWrapperCPtr(classContext.preciseType(), pyInVariable); - - c << INDENT << "*((" << typeName << "*)cppOut) = *" - << wrappedCPtrExpression << ';'; - writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); - - // "Is convertible" function for the Python object to C++ value copy conversion. - writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck); - s << endl; - - // User provided implicit conversions. - CustomConversion* customConversion = metaClass->typeEntry()->customConversion(); - - // Implicit conversions. - AbstractMetaFunctionList implicitConvs; - if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { - const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); - for (AbstractMetaFunction *func : allImplicitConvs) { - if (!func->isUserAdded()) - implicitConvs << func; - } - } - - if (!implicitConvs.isEmpty()) - s << "// Implicit conversions." << endl; - - AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); - for (const AbstractMetaFunction* conv : qAsConst(implicitConvs)) { - if (conv->isModifiedRemoved()) - continue; - - QString typeCheck; - QString toCppConv; - QString toCppPreConv; - if (conv->isConversionOperator()) { - const AbstractMetaClass* sourceClass = conv->ownerClass(); - typeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, %1)").arg(cpythonTypeNameExt(sourceClass->typeEntry())); - toCppConv = QLatin1Char('*') + cpythonWrapperCPtr(sourceClass->typeEntry(), QLatin1String("pyIn")); - } else { - // Constructor that does implicit conversion. - if (!conv->typeReplaced(1).isEmpty()) - continue; - const AbstractMetaType* sourceType = conv->arguments().first()->type(); - typeCheck = cpythonCheckFunction(sourceType); - bool isUserPrimitiveWithoutTargetLangName = isUserPrimitive(sourceType) - && sourceType->typeEntry()->targetLangApiName() == sourceType->typeEntry()->name(); - if (!isWrapperType(sourceType) - && !isUserPrimitiveWithoutTargetLangName - && !sourceType->typeEntry()->isEnum() - && !sourceType->typeEntry()->isFlags() - && !sourceType->typeEntry()->isContainer()) { - typeCheck += QLatin1Char('('); - } - if (isWrapperType(sourceType)) { - typeCheck += QLatin1String("pyIn)"); - toCppConv = (sourceType->referenceType() == LValueReference || !isPointerToWrapperType(sourceType)) - ? QLatin1String("*") : QString(); - toCppConv += cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); - } else if (typeCheck.contains(QLatin1String("%in"))) { - typeCheck.replace(QLatin1String("%in"), QLatin1String("pyIn")); - typeCheck.append(QLatin1Char(')')); - } else { - typeCheck += QLatin1String("pyIn)"); - } - - if (isUserPrimitive(sourceType) - || isCppPrimitive(sourceType) - || sourceType->typeEntry()->isContainer() - || sourceType->typeEntry()->isEnum() - || sourceType->typeEntry()->isFlags()) { - QTextStream pc(&toCppPreConv); - pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn"; - writeMinimalConstructorExpression(pc, sourceType); - pc << ';' << endl; - writeToCppConversion(pc, sourceType, 0, QLatin1String("pyIn"), QLatin1String("cppIn")); - pc << ';'; - toCppConv.append(QLatin1String("cppIn")); - } else if (!isWrapperType(sourceType)) { - QTextStream tcc(&toCppConv); - writeToCppConversion(tcc, sourceType, metaClass, QLatin1String("pyIn"), QLatin1String("/*BOZO-1061*/")); - } - - - } - const AbstractMetaType* sourceType = conv->isConversionOperator() - ? buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass()) - : conv->arguments().first()->type(); - writePythonToCppConversionFunctions(s, sourceType, targetType, typeCheck, toCppConv, toCppPreConv); - } - - writeCustomConverterFunctions(s, customConversion); -} - -void CppGenerator::writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion) -{ - if (!customConversion) - return; - const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); - if (toCppConversions.isEmpty()) - return; - s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'." << endl; - for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) - writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType()); - s << endl; -} - -void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext) -{ - if (metaClass->isNamespace()) - return; - s << INDENT << "// Register Converter" << endl; - s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(&"; - s << cpythonTypeName(metaClass) << ',' << endl; - { - Indentation indent(INDENT); - QString sourceTypeName = metaClass->name(); - QString targetTypeName = sourceTypeName + QLatin1String("_PTR"); - s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; - s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; - std::swap(targetTypeName, sourceTypeName); - s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); - if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { - s << ',' << endl; - sourceTypeName = metaClass->name() + QLatin1String("_COPY"); - s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); - } - } - s << ");" << endl; - - s << endl; - - QStringList cppSignature; - if (!classContext.forSmartPointer()) { - cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"), - QString::SkipEmptyParts); - } else { - cppSignature = classContext.preciseType()->cppSignature().split(QLatin1String("::"), - QString::SkipEmptyParts); - } - while (!cppSignature.isEmpty()) { - QString signature = cppSignature.join(QLatin1String("::")); - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");" << endl; - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");" << endl; - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");" << endl; - cppSignature.removeFirst(); - } - - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::"; - QString qualifiedCppNameInvocation; - if (!classContext.forSmartPointer()) - qualifiedCppNameInvocation = metaClass->qualifiedCppName(); - else - qualifiedCppNameInvocation = classContext.preciseType()->cppSignature(); - - s << qualifiedCppNameInvocation << ").name());" << endl; - - if (shouldGenerateCppWrapper(metaClass)) { - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::"; - s << wrapperName(metaClass) << ").name());" << endl; - } - - s << endl; - - if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) - return; - - // Python to C++ copy (value, not pointer neither reference) conversion. - s << INDENT << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter." << endl; - QString sourceTypeName = metaClass->name(); - QString targetTypeName = sourceTypeName + QLatin1String("_COPY"); - QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName); - QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName); - writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); - - // User provided implicit conversions. - CustomConversion* customConversion = metaClass->typeEntry()->customConversion(); - - // Add implicit conversions. - AbstractMetaFunctionList implicitConvs; - if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { - const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); - for (AbstractMetaFunction *func : allImplicitConvs) { - if (!func->isUserAdded()) - implicitConvs << func; - } - } - - if (!implicitConvs.isEmpty()) - s << INDENT << "// Add implicit conversions to type converter." << endl; - - AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); - for (const AbstractMetaFunction *conv : qAsConst(implicitConvs)) { - if (conv->isModifiedRemoved()) - continue; - const AbstractMetaType* sourceType; - if (conv->isConversionOperator()) { - sourceType = buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass()); - } else { - // Constructor that does implicit conversion. - if (!conv->typeReplaced(1).isEmpty()) - continue; - sourceType = conv->arguments().first()->type(); - } - QString toCpp = pythonToCppFunctionName(sourceType, targetType); - QString isConv = convertibleToCppFunctionName(sourceType, targetType); - writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); - } - - writeCustomConverterRegister(s, customConversion, QLatin1String("converter")); -} - -void CppGenerator::writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar) -{ - if (!customConversion) - return; - const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); - if (toCppConversions.isEmpty()) - return; - s << INDENT << "// Add user defined implicit conversions to type converter." << endl; - for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) { - QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType()); - QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType()); - writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); - } -} - -void CppGenerator::writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar) -{ - s << INDENT << "// Add user defined container conversion to type converter." << endl; - QString typeName = fixedCppTypeName(container); - QString toCpp = pythonToCppFunctionName(typeName, typeName); - QString isConv = convertibleToCppFunctionName(typeName, typeName); - writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); -} - -void CppGenerator::writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType) -{ - writeCppToPythonFunction(s, containerType); - writePythonToCppConversionFunctions(s, containerType); -} - -void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, - GeneratorContext &context) -{ - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - const AbstractMetaClass* ownerClass = rfunc->ownerClass(); - int minArgs = overloadData.minArgs(); - int maxArgs = overloadData.maxArgs(); - bool initPythonArguments; - bool usesNamedArguments; - - // If method is a constructor... - if (rfunc->isConstructor()) { - // Check if the right constructor was called. - if (!ownerClass->hasPrivateDestructor()) { - s << INDENT; - s << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ") && !Shiboken::ObjectType::canCallConstructor(" PYTHON_SELF_VAR "->ob_type, Shiboken::SbkType< ::"; - QString qualifiedCppName; - if (!context.forSmartPointer()) - qualifiedCppName = ownerClass->qualifiedCppName(); - else - qualifiedCppName = context.preciseType()->cppSignature(); - - s << qualifiedCppName << " >()))" << endl; - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; - } - // Declare pointer for the underlying C++ object. - s << INDENT << "::"; - if (!context.forSmartPointer()) { - s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass) - : ownerClass->qualifiedCppName()); - } else { - s << context.preciseType()->cppSignature(); - } - s << "* cptr = 0;" << endl; - - initPythonArguments = maxArgs > 0; - usesNamedArguments = !ownerClass->isQObject() && overloadData.hasArgumentWithDefaultValue(); - - } else { - if (rfunc->implementingClass() && - (!rfunc->implementingClass()->isNamespace() && overloadData.hasInstanceFunction())) { - writeCppSelfDefinition(s, rfunc, context, overloadData.hasStaticFunction()); - } - if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType()) - s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; - - initPythonArguments = minArgs != maxArgs || maxArgs > 1; - usesNamedArguments = rfunc->isCallOperator() || overloadData.hasArgumentWithDefaultValue(); - } - - if (maxArgs > 0) { - s << INDENT << "int overloadId = -1;" << endl; - s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR; - if (pythonFunctionWrapperUsesListOfArguments(overloadData)) - s << "[] = { 0" << QString::fromLatin1(", 0").repeated(maxArgs-1) << " }"; - s << ';' << endl; - writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); - } - - if (usesNamedArguments && !rfunc->isCallOperator()) - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; - - if (initPythonArguments) { - s << INDENT << "int numArgs = "; - if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData)) - s << "(" PYTHON_ARG " == 0 ? 0 : 1);" << endl; - else - writeArgumentsInitializer(s, overloadData); - } -} - -void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, - GeneratorContext &classContext) -{ - ErrorCode errorCode(-1); - OverloadData overloadData(overloads, this); - - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - const AbstractMetaClass* metaClass = rfunc->ownerClass(); - - s << "static int" << endl; - s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* args, PyObject* kwds)" << endl; - s << '{' << endl; - - QSet argNamesSet; - if (usePySideExtensions() && metaClass->isQObject()) { - // Write argNames variable with all known argument names. - const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); - for (const AbstractMetaFunction *func : overloads) { - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - argNamesSet << arg->name(); - } - } - QStringList argNamesList = argNamesSet.toList(); - qSort(argNamesList.begin(), argNamesList.end()); - if (argNamesList.isEmpty()) { - s << INDENT << "const char** argNames = 0;" << endl; - } else { - s << INDENT << "const char* argNames[] = {\"" - << argNamesList.join(QLatin1String("\", \"")) << "\"};" << endl; - } - s << INDENT << "const QMetaObject* metaObject;" << endl; - } - - s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(" PYTHON_SELF_VAR ");" << endl; - - if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { - s << INDENT << "SbkObjectType* type = reinterpret_cast(" PYTHON_SELF_VAR "->ob_type);" << endl; - s << INDENT << "SbkObjectType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; - } - - if (metaClass->isAbstract()) { - s << INDENT << "if (type == myType) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl; - { - Indentation indentation(INDENT); - s << INDENT << "\"'" << metaClass->qualifiedCppName(); - } - s << "' represents a C++ abstract class and cannot be instantiated\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl << endl; - } - - if (metaClass->baseClassNames().size() > 1) { - if (!metaClass->isAbstract()) { - s << INDENT << "if (type != myType) {" << endl; - } - { - Indentation indentation(INDENT); - s << INDENT << "Shiboken::ObjectType::copyMultimpleheritance(type, myType);" << endl; - } - if (!metaClass->isAbstract()) - s << INDENT << '}' << endl << endl; - } - - writeMethodWrapperPreamble(s, overloadData, classContext); - - s << endl; - - if (overloadData.maxArgs() > 0) - writeOverloadedFunctionDecisor(s, overloadData); - - writeFunctionCalls(s, overloadData, classContext); - s << endl; - - s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "delete cptr;" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; - if (overloadData.maxArgs() > 0) { - s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;" << endl; - s << endl; - } - - s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);" << endl; - // If the created C++ object has a C++ wrapper the ownership is assigned to Python - // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper - // is marked as true (the second "1"). Otherwise the default values apply: - // Python owns it and C++ wrapper is false. - if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) - s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl; - // 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 << INDENT << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Shiboken::BindingManager::instance().releaseWrapper(Shiboken::BindingManager::instance().retrieveWrapper(cptr));" << endl; - } - s << INDENT << "}" << endl; - s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; - - // Create metaObject and register signal/slot - if (metaClass->isQObject() && usePySideExtensions()) { - s << endl << INDENT << "// QObject setup" << endl; - s << INDENT << "PySide::Signal::updateSourceObject(" PYTHON_SELF_VAR ");" << endl; - s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl; - s << INDENT << "if (kwds && !PySide::fillQtProperties(" PYTHON_SELF_VAR ", metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - - // Constructor code injections, position=end - bool hasCodeInjectionsAtEnd = false; - for (AbstractMetaFunction *func : overloads) { - const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); - for (const CodeSnip &cs : injectedCodeSnips) { - if (cs.position == TypeSystem::CodeSnipPositionEnd) { - hasCodeInjectionsAtEnd = true; - break; - } - } - } - if (hasCodeInjectionsAtEnd) { - // FIXME: C++ arguments are not available in code injection on constructor when position = end. - s << INDENT << "switch(overloadId) {" << endl; - for (AbstractMetaFunction *func : overloads) { - Indentation indent(INDENT); - const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); - for (const CodeSnip &cs : injectedCodeSnips) { - if (cs.position == TypeSystem::CodeSnipPositionEnd) { - s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func); - } - s << INDENT << '}' << endl; - break; - } - } - } - s << '}' << endl; - } - - s << endl; - s << endl << INDENT << "return 1;" << endl; - if (overloadData.maxArgs() > 0) - writeErrorSection(s, overloadData); - s << '}' << endl << endl; -} - -void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, - GeneratorContext &classContext) -{ - OverloadData overloadData(overloads, this); - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - - int maxArgs = overloadData.maxArgs(); - - s << "static PyObject* "; - s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR; - if (maxArgs > 0) { - s << ", PyObject* " << (pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : PYTHON_ARG); - if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator()) - s << ", PyObject* kwds"; - } - s << ')' << endl << '{' << endl; - - writeMethodWrapperPreamble(s, overloadData, classContext); - - s << endl; - - /* - * 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(); - if (callExtendedReverseOperator) { - QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, QLatin1Char('r')); - if (rfunc->isBinaryOperator()) { - s << INDENT << "if (!isReverse" << endl; - { - Indentation indent(INDENT); - s << INDENT << "&& Shiboken::Object::checkType(" PYTHON_ARG ")" << endl; - s << INDENT << "&& !PyObject_TypeCheck(" PYTHON_ARG ", " PYTHON_SELF_VAR "->ob_type)" << endl; - s << INDENT << "&& PyObject_HasAttrString(" PYTHON_ARG ", const_cast(\"" << revOpName << "\"))) {" << endl; - - // 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 << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(" PYTHON_ARG ", const_cast(\"" << revOpName << "\"));" << endl; - s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast(\"O\"), " PYTHON_SELF_VAR ");" << endl; - s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)"; - s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Clear();" << endl; - s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; - s << INDENT << PYTHON_RETURN_VAR " = 0;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << "}" << endl; - s << INDENT << "Py_XDECREF(revOpMethod);" << endl << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl; - s << INDENT << "if (!" PYTHON_RETURN_VAR ") {" << endl << endl; - } - - if (maxArgs > 0) - writeOverloadedFunctionDecisor(s, overloadData); - - writeFunctionCalls(s, overloadData, classContext); - - if (callExtendedReverseOperator) - s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl; - - s << endl; - - writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator()); - - if (hasReturnValue) { - if (rfunc->isInplaceOperator()) { - s << INDENT << "Py_INCREF(" PYTHON_SELF_VAR ");\n"; - s << INDENT << "return " PYTHON_SELF_VAR ";\n"; - } else { - s << INDENT << "return " PYTHON_RETURN_VAR ";\n"; - } - } else { - s << INDENT << "Py_RETURN_NONE;" << endl; - } - - if (maxArgs > 0) - writeErrorSection(s, overloadData); - - s << '}' << endl << endl; -} - -void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData) -{ - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - s << "PyTuple_GET_SIZE(args);" << endl; - - int minArgs = overloadData.minArgs(); - int maxArgs = overloadData.maxArgs(); - - s << INDENT << "PyObject* "; - s << PYTHON_ARGS "[] = {" - << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), QString::SkipEmptyParts).join(QLatin1String(", ")) - << "};" << endl; - s << endl; - - if (overloadData.hasVarargs()) { - maxArgs--; - if (minArgs > maxArgs) - minArgs = maxArgs; - - s << INDENT << "PyObject* nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl; - s << INDENT << PYTHON_ARGS "[" << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_varargs(" PYTHON_ARGS "[" << maxArgs << "]);" << endl; - s << endl; - } - - bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); - - s << INDENT << "// invalid argument lengths" << endl; - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (usesNamedArguments) { - if (!ownerClassIsQObject) { - s << INDENT << "if (numArgs" << (overloadData.hasArgumentWithDefaultValue() ? " + numNamedArgs" : "") << " > " << maxArgs << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}'; - } - if (minArgs > 0) { - if (ownerClassIsQObject) - s << INDENT; - else - s << " else "; - s << "if (numArgs < " << minArgs << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}'; - } - } - const QVector invalidArgsLength = overloadData.invalidArgumentLengths(); - if (!invalidArgsLength.isEmpty()) { - QStringList invArgsLen; - for (int i : qAsConst(invalidArgsLength)) - invArgsLen << QStringLiteral("numArgs == %1").arg(i); - if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0)) - s << " else "; - else - s << INDENT; - s << "if (" << invArgsLen.join(QLatin1String(" || ")) << ")" << endl; - Indentation indent(INDENT); - s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; - } - s << endl << endl; - - QString funcName; - if (rfunc->isOperatorOverload()) - funcName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); - else - funcName = rfunc->name(); - - QString argsVar = overloadData.hasVarargs() ? QLatin1String("nonvarargs") : QLatin1String("args"); - s << INDENT << "if (!"; - if (usesNamedArguments) - s << "PyArg_ParseTuple(" << argsVar << ", \"|" << QByteArray(maxArgs, 'O') << ':' << funcName << '"'; - else - s << "PyArg_UnpackTuple(" << argsVar << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs; - QStringList palist; - for (int i = 0; i < maxArgs; i++) - palist << QString::fromLatin1("&(" PYTHON_ARGS "[%1])").arg(i); - s << ", " << palist.join(QLatin1String(", ")) << "))" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << endl; -} - -void CppGenerator::writeCppSelfDefinition(QTextStream &s, - GeneratorContext &context, - bool hasStaticOverload, - bool cppSelfAsReference) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers(); - QString className; - if (!context.forSmartPointer()) { - className = useWrapperClass - ? wrapperName(metaClass) - : (QLatin1String("::") + metaClass->qualifiedCppName()); - } else { - className = context.preciseType()->cppSignature(); - } - - QString cppSelfAttribution; - QString pythonSelfVar = QLatin1String(PYTHON_SELF_VAR); - QString cpythonWrapperCPtrResult; - if (!context.forSmartPointer()) - cpythonWrapperCPtrResult = cpythonWrapperCPtr(metaClass, pythonSelfVar); - else - cpythonWrapperCPtrResult = cpythonWrapperCPtr(context.preciseType(), pythonSelfVar); - - if (cppSelfAsReference) { - QString cast = useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString(); - cppSelfAttribution = QString::fromLatin1("%1& %2 = *(%3%4)") - .arg(className, QLatin1String(CPP_SELF_VAR), cast, - cpythonWrapperCPtrResult); - } else { - s << INDENT << className << "* " CPP_SELF_VAR " = 0;" << endl; - writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); - cppSelfAttribution = QString::fromLatin1("%1 = %2%3") - .arg(QLatin1String(CPP_SELF_VAR), - (useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString()), - cpythonWrapperCPtrResult); - } - - // Checks if the underlying C++ object is valid. - if (hasStaticOverload && !cppSelfAsReference) { - s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl; - { - Indentation indent(INDENT); - writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); - s << INDENT << cppSelfAttribution << ';' << endl; - } - s << INDENT << '}' << endl; - return; - } - - writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); - s << INDENT << cppSelfAttribution << ';' << endl; -} - -void CppGenerator::writeCppSelfDefinition(QTextStream &s, - const AbstractMetaFunction *func, - GeneratorContext &context, - bool hasStaticOverload) -{ - if (!func->ownerClass() || func->isConstructor()) - return; - - if (func->isOperatorOverload() && func->isBinaryOperator()) { - QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry()); - s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG ")" << endl; - { - Indentation indent1(INDENT); - Indentation indent2(INDENT); - Indentation indent3(INDENT); - Indentation indent4(INDENT); - s << INDENT << "&& !" << checkFunc << PYTHON_SELF_VAR ");" << endl; - } - s << INDENT << "if (isReverse)" << endl; - Indentation indent(INDENT); - s << INDENT << "std::swap(" PYTHON_SELF_VAR ", " PYTHON_ARG ");" << endl; - } - - writeCppSelfDefinition(s, context, hasStaticOverload); -} - -void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) -{ - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:" << endl; - Indentation indentation(INDENT); - QString funcName = fullPythonFunctionName(rfunc); - - QString argsVar = pythonFunctionWrapperUsesListOfArguments(overloadData) - ? QLatin1String("args") : QLatin1String(PYTHON_ARG); - if (verboseErrorMessagesDisabled()) { - s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl; - } else { - QStringList overloadSignatures; - const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); - for (const AbstractMetaFunction *f : overloads) { - QStringList args; - const AbstractMetaArgumentList &arguments = f->arguments(); - for (AbstractMetaArgument *arg : arguments) { - QString strArg; - AbstractMetaType* argType = arg->type(); - if (isCString(argType)) { - strArg = QLatin1String("\" SBK_STR_NAME \""); - } else if (argType->isPrimitive()) { - const PrimitiveTypeEntry* ptp = reinterpret_cast(argType->typeEntry()); - while (ptp->referencedTypeEntry()) - ptp = ptp->referencedTypeEntry(); - strArg = ptp->name(); - if (strArg == QLatin1String("QString")) { - strArg = QLatin1String("unicode"); - } else if (strArg == QLatin1String("QChar")) { - strArg = QLatin1String("1-unicode"); - } else { - strArg = ptp->name(); - static const QRegularExpression regex(QStringLiteral("^signed\\s+")); - Q_ASSERT(regex.isValid()); - strArg.remove(regex); - if (strArg == QLatin1String("double")) - strArg = QLatin1String("float"); - } - } else if (argType->typeEntry()->isContainer()) { - strArg = argType->fullName(); - if (strArg == QLatin1String("QList") || strArg == QLatin1String("QVector") - || strArg == QLatin1String("QLinkedList") || strArg == QLatin1String("QStack") - || strArg == QLatin1String("QQueue")) { - strArg = QLatin1String("list"); - } else if (strArg == QLatin1String("QMap") || strArg == QLatin1String("QHash") - || strArg == QLatin1String("QMultiMap") || strArg == QLatin1String("QMultiHash")) { - strArg = QLatin1String("dict"); - } else if (strArg == QLatin1String("QPair")) { - strArg = QLatin1String("2-tuple"); - } - } else { - strArg = argType->fullName(); - if (strArg == QLatin1String("PyUnicode")) - strArg = QLatin1String("unicode"); - else if (strArg == QLatin1String("PyString")) - strArg = QLatin1String("str"); - else if (strArg == QLatin1String("PyBytes")) - strArg = QLatin1String("\" SBK_STR_NAME \""); - else if (strArg == QLatin1String("PySequece")) - strArg = QLatin1String("list"); - else if (strArg == QLatin1String("PyTuple")) - strArg = QLatin1String("tuple"); - else if (strArg == QLatin1String("PyDict")) - strArg = QLatin1String("dict"); - else if (strArg == QLatin1String("PyObject")) - strArg = QLatin1String("object"); - else if (strArg == QLatin1String("PyCallable")) - strArg = QLatin1String("callable"); - else if (strArg == QLatin1String("uchar")) - strArg = QLatin1String("buffer"); // This depends on an inject code to be true, but if it's not true - // the function wont work at all, so it must be true. - } - if (!arg->defaultValueExpression().isEmpty()) { - strArg += QLatin1String(" = "); - if ((isCString(argType) || isPointerToWrapperType(argType)) - && arg->defaultValueExpression() == QLatin1String("0")) { - strArg += QLatin1String("None"); - } else { - QString e = arg->defaultValueExpression(); - e.replace(QLatin1String("::"), QLatin1String(".")); - e.replace(QLatin1String("\""), QLatin1String("\\\"")); - strArg += e; - } - } - args << strArg; - } - overloadSignatures << QLatin1Char('"') + args.join(QLatin1String(", ")) + QLatin1Char('"'); - } - s << INDENT << "const char* overloads[] = {" << overloadSignatures.join(QLatin1String(", ")) - << ", 0};" << endl; - s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", overloads);" << endl; - } - s << INDENT << "return " << m_currentErrorCode << ';' << endl; -} - -void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue) -{ - s << INDENT << "if (PyErr_Occurred()" << (hasReturnValue ? " || !" PYTHON_RETURN_VAR : "") << ") {" << endl; - { - Indentation indent(INDENT); - if (hasReturnValue) - s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; -} - -void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj) -{ - s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))" << endl; - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; -} - -static QString pythonToCppConverterForArgumentName(const QString& argumentName) -{ - static const QRegularExpression pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])")); - Q_ASSERT(pyArgsRegex.isValid()); - const QRegularExpressionMatch match = pyArgsRegex.match(argumentName); - QString result = QLatin1String(PYTHON_TO_CPP_VAR); - if (match.hasMatch()) - result += match.captured(1); - return result; -} - -void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType, bool rejectNull) -{ - QString customCheck; - if (!customType.isEmpty()) { - AbstractMetaType* metaType; - customCheck = guessCPythonCheckFunction(customType, &metaType); - if (metaType) - argType = metaType; - } - - // TODO-CONVERTER: merge this with the code below. - QString typeCheck; - if (customCheck.isEmpty()) - typeCheck = cpythonIsConvertibleFunction(argType, argType->isEnum() ? false : isNumber); - else - typeCheck = customCheck; - typeCheck.append(QString::fromLatin1("(%1)").arg(argumentName)); - - // TODO-CONVERTER ----------------------------------------------------------------------- - if (customCheck.isEmpty() && !argType->typeEntry()->isCustom()) { - typeCheck = QString::fromLatin1("(%1 = %2))").arg(pythonToCppConverterForArgumentName(argumentName), typeCheck); - if (!isNumber && argType->typeEntry()->isCppPrimitive()) - typeCheck.prepend(QString::fromLatin1("%1(%2) && ").arg(cpythonCheckFunction(argType), argumentName)); - } - // TODO-CONVERTER ----------------------------------------------------------------------- - - if (rejectNull) - typeCheck = QString::fromLatin1("(%1 != Py_None && %2)").arg(argumentName, typeCheck); - - s << typeCheck; -} - -static void checkTypeViability(const AbstractMetaFunction* func, const AbstractMetaType* type, int argIdx) -{ - if (!type - || !type->typeEntry()->isPrimitive() - || type->indirections() == 0 - || ShibokenGenerator::isCString(type) - || func->argumentRemoved(argIdx) - || !func->typeReplaced(argIdx).isEmpty() - || !func->conversionRule(TypeSystem::All, argIdx).isEmpty() - || func->hasInjectedCode()) - return; - QString prefix; - if (func->ownerClass()) - prefix = func->ownerClass()->qualifiedCppName() + QLatin1String("::"); - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("There's no user provided way (conversion rule, argument removal, custom code, etc) " - "to handle the primitive %1 type '%2' in function '%3%4'.") - .arg(argIdx == 0 ? QStringLiteral("return") : QStringLiteral("argument"), - type->cppSignature(), prefix, func->signature()); -} - -static void checkTypeViability(const AbstractMetaFunction* func) -{ - if (func->isUserAdded()) - return; - const AbstractMetaType* type = func->type(); - checkTypeViability(func, type, 0); - for (int i = 0; i < func->arguments().count(); ++i) - checkTypeViability(func, func->arguments().at(i)->type(), i + 1); -} - -void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName) -{ - QSet numericTypes; - const OverloadDataList &overloads = overloadData->previousOverloadData()->nextOverloadData(); - for (OverloadData *od : overloads) { - const OverloadData::MetaFunctionList &odOverloads = od->overloads(); - for (const AbstractMetaFunction *func : odOverloads) { - checkTypeViability(func); - const AbstractMetaType* argType = od->argument(func)->type(); - if (!argType->isPrimitive()) - continue; - if (ShibokenGenerator::isNumber(argType->typeEntry())) - numericTypes << argType->typeEntry(); - } - } - - // This condition trusts that the OverloadData object will arrange for - // PyInt type to come after the more precise numeric types (e.g. float and bool) - const AbstractMetaType* argType = overloadData->argType(); - bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType); - QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : QString()); - bool rejectNull = shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos()); - writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull); -} - -void CppGenerator::writeArgumentConversion(QTextStream& s, - const AbstractMetaType* argType, - const QString& argName, const QString& pyArgName, - const AbstractMetaClass* context, - const QString& defaultValue, - bool castArgumentAsUnused) -{ - if (argType->typeEntry()->isCustom() || argType->typeEntry()->isVarargs()) - return; - if (isWrapperType(argType)) - writeInvalidPyObjectCheck(s, pyArgName); - writePythonToCppTypeConversion(s, argType, pyArgName, argName, context, defaultValue); - if (castArgumentAsUnused) - writeUnusedVariableCast(s, argName); -} - -const AbstractMetaType* CppGenerator::getArgumentType(const AbstractMetaFunction* func, int argPos) -{ - if (argPos < 0 || argPos > func->arguments().size()) { - qCWarning(lcShiboken).noquote().nospace() - << QStringLiteral("Argument index for function '%1' out of range.").arg(func->signature()); - return 0; - } - - const AbstractMetaType* argType = 0; - QString typeReplaced = func->typeReplaced(argPos); - if (typeReplaced.isEmpty()) - argType = (argPos == 0) ? func->type() : func->arguments().at(argPos-1)->type(); - else - argType = buildAbstractMetaTypeFromString(typeReplaced); - if (!argType && !m_knownPythonTypes.contains(typeReplaced)) { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("Unknown type '%1' used as argument type replacement "\ - "in function '%2', the generated code may be broken.") - .arg(typeReplaced, func->signature()); - } - return argType; -} - -void CppGenerator::writePythonToCppTypeConversion(QTextStream& s, - const AbstractMetaType* type, - const QString& pyIn, - const QString& cppOut, - const AbstractMetaClass* /* context */, - const QString& defaultValue) -{ - const TypeEntry* typeEntry = type->typeEntry(); - if (typeEntry->isCustom() || typeEntry->isVarargs()) - return; - - QString cppOutAux = cppOut + QLatin1String("_local"); - - bool treatAsPointer = isValueTypeWithCopyConstructorOnly(type); - bool isPointerOrObjectType = (isObjectType(type) || isPointer(type)) && !isUserPrimitive(type) && !isCppPrimitive(type); - bool isNotContainerEnumOrFlags = !typeEntry->isContainer() && !typeEntry->isEnum() && !typeEntry->isFlags(); - bool mayHaveImplicitConversion = type->referenceType() == LValueReference - && !isUserPrimitive(type) - && !isCppPrimitive(type) - && isNotContainerEnumOrFlags - && !(treatAsPointer || isPointerOrObjectType); - QString typeName = getFullTypeNameWithoutModifiers(type); - - bool isProtectedEnum = false; - - if (mayHaveImplicitConversion) { - s << INDENT << typeName << ' ' << cppOutAux; - writeMinimalConstructorExpression(s, type, defaultValue); - s << ';' << endl; - } else if (avoidProtectedHack() && type->typeEntry()->isEnum()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type); - if (metaEnum && metaEnum->isProtected()) { - typeName = QLatin1String("long"); - isProtectedEnum = true; - } - } - - s << INDENT << typeName; - if (treatAsPointer || isPointerOrObjectType) { - s << "* " << cppOut; - if (!defaultValue.isEmpty()) - s << " = " << defaultValue; - } else if (type->referenceType() == LValueReference && !typeEntry->isPrimitive() && isNotContainerEnumOrFlags) { - s << "* " << cppOut << " = &" << cppOutAux; - } else { - s << ' ' << cppOut; - if (isProtectedEnum && avoidProtectedHack()) { - s << " = "; - if (defaultValue.isEmpty()) - s << "0"; - else - s << "(long)" << defaultValue; - } else if (isUserPrimitive(type) || typeEntry->isEnum() || typeEntry->isFlags()) { - writeMinimalConstructorExpression(s, typeEntry, defaultValue); - } else if (!type->isContainer() && !type->isSmartPointer()) { - writeMinimalConstructorExpression(s, type, defaultValue); - } - } - s << ';' << endl; - - QString pythonToCppFunc = pythonToCppConverterForArgumentName(pyIn); - - s << INDENT; - if (!defaultValue.isEmpty()) - s << "if (" << pythonToCppFunc << ") "; - - QString pythonToCppCall = QString::fromLatin1("%1(%2, &%3)").arg(pythonToCppFunc, pyIn, cppOut); - if (!mayHaveImplicitConversion) { - s << pythonToCppCall << ';' << endl; - return; - } - - if (!defaultValue.isEmpty()) - s << '{' << endl << INDENT; - - s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast(" - << cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))" << endl; - { - Indentation indent(INDENT); - s << INDENT << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");" << endl; - } - s << INDENT << "else" << endl; - { - Indentation indent(INDENT); - s << INDENT << pythonToCppCall << ';' << endl; - } - - if (!defaultValue.isEmpty()) - s << INDENT << '}'; - s << endl; -} - -static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rule, - TypeSystem::Language /* conversionLanguage */, - TypeSystem::Language snippetLanguage, - QString outputName = QString(), - QString inputName = QString()) -{ - if (rule.isEmpty()) - return; - if (snippetLanguage == TypeSystem::TargetLangCode) { - rule.replace(QLatin1String("%in"), inputName); - rule.replace(QLatin1String("%out"), outputName + QLatin1String("_out")); - } else { - rule.replace(QLatin1String("%out"), outputName); - } - CodeSnip snip(0, snippetLanguage); - snip.position = (snippetLanguage == TypeSystem::NativeCode) ? TypeSystem::CodeSnipPositionAny : TypeSystem::CodeSnipPositionBeginning; - snip.addCode(rule); - snippetList << snip; -} - -void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language) -{ - CodeSnipList snippets; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - QString rule = func->conversionRule(language, arg->argumentIndex() + 1); - addConversionRuleCodeSnippet(snippets, rule, language, TypeSystem::TargetLangCode, - arg->name(), arg->name()); - } - writeCodeSnips(s, snippets, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func); -} - -void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar) -{ - CodeSnipList snippets; - QString rule = func->conversionRule(language, 0); - addConversionRuleCodeSnippet(snippets, rule, language, language, outputVar); - writeCodeSnips(s, snippets, TypeSystem::CodeSnipPositionAny, language, func); -} - -void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue) -{ - if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) { - s << INDENT << PYTHON_RETURN_VAR " = Py_None;" << endl; - s << INDENT << "Py_INCREF(Py_None);" << endl; - } -} - -void CppGenerator::writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData) -{ - s << INDENT << "// Overloaded function decisor" << endl; - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - const OverloadData::MetaFunctionList &functionOverloads = overloadData.overloadsWithoutRepetition(); - for (int i = 0; i < functionOverloads.count(); i++) - s << INDENT << "// " << i << ": " << functionOverloads.at(i)->minimalSignature() << endl; - writeOverloadedFunctionDecisorEngine(s, &overloadData); - s << endl; - - // Ensure that the direct overload that called this reverse - // is called. - if (rfunc->isOperatorOverload() && !rfunc->isCallOperator()) { - s << INDENT << "if (isReverse && overloadId == -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"reverse operator not implemented.\");" << endl; - s << INDENT << "return 0;" << endl; - } - s << INDENT << "}" << endl << endl; - } - - s << INDENT << "// Function signature not found." << endl; - s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;" << endl; - s << endl; -} - -void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData) -{ - bool hasDefaultCall = parentOverloadData->nextArgumentHasDefaultValue(); - const AbstractMetaFunction* referenceFunction = parentOverloadData->referenceFunction(); - - // If the next argument has not an argument with a default value, it is still possible - // that one of the overloads for the current overload data has its final occurrence here. - // If found, the final occurrence of a method is attributed to the referenceFunction - // variable to be used further on this method on the conditional that identifies default - // method calls. - if (!hasDefaultCall) { - const OverloadData::MetaFunctionList &overloads = parentOverloadData->overloads(); - for (const AbstractMetaFunction *func : overloads) { - if (parentOverloadData->isFinalOccurrence(func)) { - referenceFunction = func; - hasDefaultCall = true; - break; - } - } - } - - int maxArgs = parentOverloadData->maxArgs(); - // Python constructors always receive multiple arguments. - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(*parentOverloadData); - - // Functions without arguments are identified right away. - if (maxArgs == 0) { - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction); - s << "; // " << referenceFunction->minimalSignature() << endl; - return; - - // To decide if a method call is possible at this point the current overload - // data object cannot be the head, since it is just an entry point, or a root, - // for the tree of arguments and it does not represent a valid method call. - } else if (!parentOverloadData->isHeadOverloadData()) { - bool isLastArgument = parentOverloadData->nextOverloadData().isEmpty(); - bool signatureFound = parentOverloadData->overloads().size() == 1; - - // The current overload data describes the last argument of a signature, - // so the method can be identified right now. - if (isLastArgument || (signatureFound && !hasDefaultCall)) { - const AbstractMetaFunction* func = parentOverloadData->referenceFunction(); - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; - return; - } - } - - bool isFirst = true; - - // If the next argument has a default value the decisor can perform a method call; - // it just need to check if the number of arguments received from Python are equal - // to the number of parameters preceding the argument with the default value. - const OverloadDataList &overloads = parentOverloadData->nextOverloadData(); - if (hasDefaultCall) { - isFirst = false; - int numArgs = parentOverloadData->argPos() + 1; - s << INDENT << "if (numArgs == " << numArgs << ") {" << endl; - { - Indentation indent(INDENT); - const AbstractMetaFunction* func = referenceFunction; - for (OverloadData *overloadData : overloads) { - const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue(); - if (defValFunc) { - func = defValFunc; - break; - } - } - s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); - s << "; // " << func->minimalSignature() << endl; - } - s << INDENT << '}'; - } - - for (OverloadData *overloadData : overloads) { - bool signatureFound = overloadData->overloads().size() == 1 - && !overloadData->getFunctionWithDefaultValue() - && !overloadData->findNextArgWithDefault(); - - const AbstractMetaFunction* refFunc = overloadData->referenceFunction(); - - QStringList typeChecks; - QString pyArgName = (usePyArgs && maxArgs > 1) - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(overloadData->argPos()) - : QLatin1String(PYTHON_ARG); - OverloadData* od = overloadData; - int startArg = od->argPos(); - int sequenceArgCount = 0; - while (od && !od->argType()->isVarargs()) { - bool typeReplacedByPyObject = od->argumentTypeReplaced() == QLatin1String("PyObject"); - if (!typeReplacedByPyObject) { - if (usePyArgs) - pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(od->argPos()); - QString typeCheck; - QTextStream tck(&typeCheck); - const AbstractMetaFunction* func = od->referenceFunction(); - - if (func->isConstructor() && func->arguments().count() == 1) { - const AbstractMetaClass* ownerClass = func->ownerClass(); - const ComplexTypeEntry* baseContainerType = ownerClass->typeEntry()->baseContainerType(); - if (baseContainerType && baseContainerType == func->arguments().first()->type()->typeEntry() && isCopyable(ownerClass)) { - tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ')' << endl; - Indentation indent(INDENT); - tck << INDENT << "&& "; - } - } - writeTypeCheck(tck, od, pyArgName); - typeChecks << typeCheck; - } - - sequenceArgCount++; - - if (od->nextOverloadData().isEmpty() - || od->nextArgumentHasDefaultValue() - || od->nextOverloadData().size() != 1 - || od->overloads().size() != od->nextOverloadData().first()->overloads().size()) { - overloadData = od; - od = 0; - } else { - od = od->nextOverloadData().first(); - } - } - - if (usePyArgs && signatureFound) { - AbstractMetaArgumentList args = refFunc->arguments(); - int lastArgIsVarargs = (int) (args.size() > 1 && args.last()->type()->isVarargs()); - int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; - typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); - } else if (sequenceArgCount > 1) { - typeChecks.prepend(QString::fromLatin1("numArgs >= %1").arg(startArg + sequenceArgCount)); - } else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) { - typeChecks.prepend(QString::fromLatin1("%1isReverse").arg(refFunc->isReverseOperator() ? QString() : QLatin1String("!"))); - } - - if (isFirst) { - isFirst = false; - s << INDENT; - } else { - s << " else "; - } - s << "if ("; - if (typeChecks.isEmpty()) { - s << "true"; - } else { - Indentation indent(INDENT); - QString separator; - QTextStream sep(&separator); - sep << endl << INDENT << "&& "; - s << typeChecks.join(separator); - } - s << ") {" << endl; - { - Indentation indent(INDENT); - writeOverloadedFunctionDecisorEngine(s, overloadData); - } - s << INDENT << "}"; - } - s << endl; -} - -void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, - GeneratorContext &context) -{ - const OverloadData::MetaFunctionList &overloads = overloadData.overloadsWithoutRepetition(); - s << INDENT << "// Call function/method" << endl; - s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl; - { - Indentation indent(INDENT); - if (overloads.count() == 1) { - writeSingleFunctionCall(s, overloadData, overloads.first(), context); - } else { - for (int i = 0; i < overloads.count(); i++) { - const AbstractMetaFunction* func = overloads.at(i); - s << INDENT << "case " << i << ": // " << func->signature() << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - writeSingleFunctionCall(s, overloadData, func, context); - s << INDENT << "break;" << endl; - } - s << INDENT << '}' << endl; - } - } - } - s << INDENT << '}' << endl; -} - -void CppGenerator::writeSingleFunctionCall(QTextStream &s, - const OverloadData &overloadData, - const AbstractMetaFunction *func, - GeneratorContext &context) -{ - if (func->isDeprecated()) { - s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '" - << func->signature().replace(QLatin1String("::"), QLatin1String(".")) - << "' is marked as deprecated, please check the documentation for more information.\");" << endl; - } - - if (func->functionType() == AbstractMetaFunction::EmptyFunction) { - s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" - << func->signature().replace(QLatin1String("::"), QLatin1String(".")) - << "\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - return; - } - - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); - - // Handle named arguments. - writeNamedArgumentResolution(s, func, usePyArgs); - - bool injectCodeCallsFunc = injectedCodeCallsCppFunction(func); - bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc; - int removedArgs = 0; - for (int argIdx = 0; argIdx < func->arguments().count(); ++argIdx) { - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, argIdx + 1).isEmpty(); - const AbstractMetaArgument* arg = func->arguments().at(argIdx); - if (func->argumentRemoved(argIdx + 1)) { - if (!arg->defaultValueExpression().isEmpty()) { - QString cppArgRemoved = QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(argIdx); - s << INDENT << getFullTypeName(arg->type()) << ' ' << cppArgRemoved; - s << " = " << guessScopeForDefaultValue(func, arg) << ';' << endl; - writeUnusedVariableCast(s, 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. - qFatal(qPrintable(QString::fromLatin1("No way to call '%1::%2' with the modifications described in the type system.") - .arg(func->ownerClass()->name(), func->signature())), NULL); - } - removedArgs++; - continue; - } - if (hasConversionRule) - continue; - const AbstractMetaType* argType = getArgumentType(func, argIdx + 1); - if (!argType || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx))) - continue; - int argPos = argIdx - removedArgs; - QString argName = QString::fromLatin1(CPP_ARG"%1").arg(argPos); - QString pyArgName = usePyArgs ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) : QLatin1String(PYTHON_ARG); - QString defaultValue = guessScopeForDefaultValue(func, arg); - writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded()); - } - - s << endl; - - int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); - - s << INDENT << "if (!PyErr_Occurred()) {" << endl; - { - Indentation indentation(INDENT); - writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs); - if (!func->isConstructor()) - writeNoneReturn(s, func, overloadData.hasNonVoidReturnType()); - } - s << INDENT << '}' << endl; -} - -QString CppGenerator::cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName) -{ - if (targetTypeName.isEmpty()) - targetTypeName = sourceTypeName; - return QString::fromLatin1("%1_CppToPython_%2").arg(sourceTypeName, targetTypeName); -} - -QString CppGenerator::pythonToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName) -{ - return QString::fromLatin1("%1_PythonToCpp_%2").arg(sourceTypeName, targetTypeName); -} -QString CppGenerator::pythonToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType) -{ - return pythonToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType)); -} -QString CppGenerator::pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, - const TypeEntry* targetType) -{ - return pythonToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType)); -} - -QString CppGenerator::convertibleToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName) -{ - return QString::fromLatin1("is_%1_PythonToCpp_%2_Convertible").arg(sourceTypeName, targetTypeName); -} -QString CppGenerator::convertibleToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType) -{ - return convertibleToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType)); -} -QString CppGenerator::convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, - const TypeEntry* targetType) -{ - return convertibleToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType)); -} - -void CppGenerator::writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName) -{ - QString prettyCode; - QTextStream c(&prettyCode); - formatCode(c, code, INDENT); - processCodeSnip(prettyCode); - - s << "static PyObject* " << cppToPythonFunctionName(sourceTypeName, targetTypeName); - s << "(const void* cppIn) {" << endl; - s << prettyCode; - s << '}' << endl; -} - -static void replaceCppToPythonVariables(QString& code, const QString& typeName) -{ - code.prepend(QString::fromLatin1("%1& cppInRef = *((%1*)cppIn);\n").arg(typeName)); - code.replace(QLatin1String("%INTYPE"), typeName); - code.replace(QLatin1String("%OUTTYPE"), QLatin1String("PyObject*")); - code.replace(QLatin1String("%in"), QLatin1String("cppInRef")); - code.replace(QLatin1String("%out"), QLatin1String("pyOut")); -} -void CppGenerator::writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion) -{ - QString code = customConversion->nativeToTargetConversion(); - replaceCppToPythonVariables(code, getFullTypeName(customConversion->ownerType())); - writeCppToPythonFunction(s, code, fixedCppTypeName(customConversion->ownerType())); -} -void CppGenerator::writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType) -{ - const CustomConversion* customConversion = containerType->typeEntry()->customConversion(); - if (!customConversion) { - qFatal(qPrintable(QString::fromLatin1("Can't write the C++ to Python conversion function for container type '%1' - "\ - "no conversion rule was defined for it in the type system.") - .arg(containerType->typeEntry()->qualifiedCppName())), NULL); - } - if (!containerType->typeEntry()->isContainer()) { - writeCppToPythonFunction(s, customConversion); - return; - } - QString code = customConversion->nativeToTargetConversion(); - for (int i = 0; i < containerType->instantiations().count(); ++i) { - AbstractMetaType* type = containerType->instantiations().at(i); - QString typeName = getFullTypeName(type); - if (type->isConstant()) - typeName = QLatin1String("const ") + typeName; - code.replace(QString::fromLatin1("%INTYPE_%1").arg(i), typeName); - } - replaceCppToPythonVariables(code, getFullTypeNameWithoutModifiers(containerType)); - processCodeSnip(code); - writeCppToPythonFunction(s, code, fixedCppTypeName(containerType)); -} - -void CppGenerator::writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName) -{ - QString prettyCode; - QTextStream c(&prettyCode); - formatCode(c, code, INDENT); - processCodeSnip(prettyCode); - s << "static void " << pythonToCppFunctionName(sourceTypeName, targetTypeName); - s << "(PyObject* pyIn, void* cppOut) {" << endl; - s << prettyCode; - s << '}' << endl; -} - -void CppGenerator::writeIsPythonConvertibleToCppFunction(QTextStream& s, - const QString& sourceTypeName, - const QString& targetTypeName, - const QString& condition, - QString pythonToCppFuncName, - bool acceptNoneAsCppNull) -{ - if (pythonToCppFuncName.isEmpty()) - pythonToCppFuncName = pythonToCppFunctionName(sourceTypeName, targetTypeName); - - s << "static PythonToCppFunc " << convertibleToCppFunctionName(sourceTypeName, targetTypeName); - s << "(PyObject* pyIn) {" << endl; - if (acceptNoneAsCppNull) { - s << INDENT << "if (pyIn == Py_None)" << endl; - Indentation indent(INDENT); - s << INDENT << "return Shiboken::Conversions::nonePythonToCppNullPtr;" << endl; - } - s << INDENT << "if (" << condition << ')' << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " << pythonToCppFuncName << ';' << endl; - } - s << INDENT << "return 0;" << endl; - s << '}' << endl; -} - -void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, - const AbstractMetaType* sourceType, - const AbstractMetaType* targetType, - QString typeCheck, - QString conversion, - QString preConversion) -{ - QString sourcePyType = cpythonTypeNameExt(sourceType); - - // Python to C++ conversion function. - QString code; - QTextStream c(&code); - if (conversion.isEmpty()) - conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); - if (!preConversion.isEmpty()) - c << INDENT << preConversion << endl; - c << INDENT << QString::fromLatin1("*((%1*)cppOut) = %1(%2);") - .arg(getFullTypeName(targetType->typeEntry()), conversion); - QString sourceTypeName = fixedCppTypeName(sourceType); - QString targetTypeName = fixedCppTypeName(targetType); - writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); - - // Python to C++ convertible check function. - if (typeCheck.isEmpty()) - typeCheck = QString::fromLatin1("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType); - writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); - s << endl; -} - -void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, - const CustomConversion::TargetToNativeConversion* toNative, - const TypeEntry* targetType) -{ - // Python to C++ conversion function. - QString code = toNative->conversion(); - QString inType; - if (toNative->sourceType()) - inType = cpythonTypeNameExt(toNative->sourceType()); - else - inType = QString::fromLatin1("(&%1_Type)").arg(toNative->sourceTypeName()); - code.replace(QLatin1String("%INTYPE"), inType); - code.replace(QLatin1String("%OUTTYPE"), targetType->qualifiedCppName()); - code.replace(QLatin1String("%in"), QLatin1String("pyIn")); - code.replace(QLatin1String("%out"), QString::fromLatin1("*((%1*)cppOut)").arg(getFullTypeName(targetType))); - - QString sourceTypeName = fixedCppTypeName(toNative); - QString targetTypeName = fixedCppTypeName(targetType); - writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); - - // Python to C++ convertible check function. - QString typeCheck = toNative->sourceTypeCheck(); - if (typeCheck.isEmpty()) { - QString pyTypeName = toNative->sourceTypeName(); - if (pyTypeName == QLatin1String("Py_None") || pyTypeName == QLatin1String("PyNone")) - typeCheck = QLatin1String("%in == Py_None"); - else if (pyTypeName == QLatin1String("SbkEnumType")) - typeCheck = QLatin1String("Shiboken::isShibokenEnum(%in)"); - else if (pyTypeName == QLatin1String("SbkObject")) - typeCheck = QLatin1String("Shiboken::Object::checkType(%in)"); - else if (pyTypeName == QLatin1String("PyTypeObject")) - typeCheck = QLatin1String("PyType_Check(%in)"); - else if (pyTypeName == QLatin1String("PyObject")) - typeCheck = QLatin1String("PyObject_TypeCheck(%in, &PyBaseObject_Type)"); - else if (pyTypeName.startsWith(QLatin1String("Py"))) - typeCheck = pyTypeName + QLatin1String("_Check(%in)"); - } - if (typeCheck.isEmpty()) { - if (!toNative->sourceType() || toNative->sourceType()->isPrimitive()) { - qFatal(qPrintable(QString::fromLatin1("User added implicit conversion for C++ type '%1' must provide either an input "\ - "type check function or a non primitive type entry.") - .arg(targetType->qualifiedCppName())), NULL); - - } - typeCheck = QString::fromLatin1("PyObject_TypeCheck(%in, %1)").arg(cpythonTypeNameExt(toNative->sourceType())); - } - typeCheck.replace(QLatin1String("%in"), QLatin1String("pyIn")); - processCodeSnip(typeCheck); - writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); -} - -void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType) -{ - const CustomConversion* customConversion = containerType->typeEntry()->customConversion(); - if (!customConversion) { - //qFatal - return; - } - const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); - if (toCppConversions.isEmpty()) { - //qFatal - return; - } - // Python to C++ conversion function. - QString cppTypeName = getFullTypeNameWithoutModifiers(containerType); - QString code; - QTextStream c(&code); - c << INDENT << QString::fromLatin1("%1& cppOutRef = *((%1*)cppOut);").arg(cppTypeName) << endl; - code.append(toCppConversions.first()->conversion()); - for (int i = 0; i < containerType->instantiations().count(); ++i) { - const AbstractMetaType* type = containerType->instantiations().at(i); - QString typeName = getFullTypeName(type); - if (type->isValue() && isValueTypeWithCopyConstructorOnly(type)) { - static const QRegularExpression regex(QLatin1String(CONVERTTOCPP_REGEX)); - Q_ASSERT(regex.isValid()); - for (int pos = 0; ; ) { - const QRegularExpressionMatch match = regex.match(code, pos); - if (!match.hasMatch()) - break; - pos = match.capturedEnd(); - const QString varName = match.captured(1); - QString rightCode = code.mid(pos); - rightCode.replace(varName, QLatin1Char('*') + varName); - code.replace(pos, code.size() - pos, rightCode); - } - typeName.append(QLatin1Char('*')); - } - code.replace(QString::fromLatin1("%OUTTYPE_%1").arg(i), typeName); - } - code.replace(QLatin1String("%OUTTYPE"), cppTypeName); - code.replace(QLatin1String("%in"), QLatin1String("pyIn")); - code.replace(QLatin1String("%out"), QLatin1String("cppOutRef")); - QString typeName = fixedCppTypeName(containerType); - writePythonToCppFunction(s, code, typeName, typeName); - - // Python to C++ convertible check function. - QString typeCheck = cpythonCheckFunction(containerType); - if (typeCheck.isEmpty()) - typeCheck = QLatin1String("false"); - else - typeCheck = QString::fromLatin1("%1pyIn)").arg(typeCheck); - writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck); - s << endl; -} - -void CppGenerator::writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc) -{ - s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl; - { - Indentation indent(INDENT); - s << INDENT << pythonToCppFunc << ',' << endl; - s << INDENT << isConvertibleFunc; - } - s << ");" << endl; -} - -void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs) -{ - const AbstractMetaArgumentList &args = OverloadData::getArgumentsWithDefaultValues(func); - if (args.isEmpty()) - return; - - QString pyErrString(QLatin1String("PyErr_SetString(PyExc_TypeError, \"") + fullPythonFunctionName(func) - + QLatin1String("(): got multiple values for keyword argument '%1'.\");")); - - s << INDENT << "if (kwds) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* "; - for (const AbstractMetaArgument *arg : args) { - int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex()); - QString pyArgName = usePyArgs - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(pyArgIndex) - : QLatin1String(PYTHON_ARG); - s << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl; - s << INDENT << "if (value && " << pyArgName << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << pyErrString.arg(arg->name()) << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << "} else if (value) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << pyArgName << " = value;" << endl; - s << INDENT << "if (!"; - writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1)); - s << ')' << endl; - { - Indentation indent(INDENT); - s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl; - } - } - s << INDENT << '}' << endl; - if (arg != args.last()) - s << INDENT; - } - } - s << INDENT << '}' << endl; -} - -QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass) -{ - *wrappedClass = 0; - QString pyArgName; - if (argIndex == -1) { - pyArgName = QLatin1String(PYTHON_SELF_VAR); - *wrappedClass = func->implementingClass(); - } else if (argIndex == 0) { - AbstractMetaType *funcType = func->type(); - AbstractMetaType *returnType = getTypeWithoutContainer(funcType); - if (returnType) { - pyArgName = QLatin1String(PYTHON_RETURN_VAR); - *wrappedClass = AbstractMetaClass::findClass(classes(), returnType->typeEntry()->name()); - } else { - QString message = QLatin1String("Invalid Argument index (0, return value) on function modification: ") - + (funcType ? funcType->name() : QLatin1String("void")) + QLatin1Char(' '); - if (const AbstractMetaClass *declaringClass = func->declaringClass()) - message += declaringClass->name() + QLatin1String("::"); - message += func->name() + QLatin1String("()"); - qCWarning(lcShiboken).noquote().nospace() << message; - } - } else { - int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); - AbstractMetaType* argType = getTypeWithoutContainer(func->arguments().at(realIndex)->type()); - - if (argType) { - *wrappedClass = AbstractMetaClass::findClass(classes(), argType->typeEntry()->name()); - if (argIndex == 1 - && !func->isConstructor() - && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) - pyArgName = QLatin1String(PYTHON_ARG); - else - pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argIndex - 1); - } - } - return pyArgName; -} - -void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, - GeneratorContext &context, int maxArgs) -{ - s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; - if (func->isConstructor()) { - const CodeSnipList &snips = func->injectedCodeSnips(); - for (const CodeSnip &cs : snips) { - if (cs.position == TypeSystem::CodeSnipPositionEnd) { - s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast(func)) << ';' << endl; - break; - } - } - } - - if (func->isAbstract()) { - s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast(" PYTHON_SELF_VAR "))) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; - s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << "}\n"; - } - - // Used to provide contextual information to custom code writer function. - const AbstractMetaArgument* lastArg = 0; - - CodeSnipList snips; - if (func->hasInjectedCode()) { - snips = func->injectedCodeSnips(); - - // Find the last argument available in the method call to provide - // the injected code writer with information to avoid invalid replacements - // on the %# variable. - if (maxArgs > 0 && maxArgs < func->arguments().size() - OverloadData::numberOfRemovedArguments(func)) { - int removedArgs = 0; - for (int i = 0; i < maxArgs + removedArgs; i++) { - lastArg = func->arguments().at(i); - if (func->argumentRemoved(i + 1)) - removedArgs++; - } - } else if (maxArgs != 0 && !func->arguments().isEmpty()) { - lastArg = func->arguments().last(); - } - - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg); - s << endl; - } - - writeConversionRule(s, func, TypeSystem::NativeCode); - - if (!func->isUserAdded()) { - QStringList userArgs; - if (func->functionType() != AbstractMetaFunction::CopyConstructorFunction) { - int removedArgs = 0; - for (int i = 0; i < maxArgs + removedArgs; i++) { - const AbstractMetaArgument* arg = func->arguments().at(i); - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); - if (func->argumentRemoved(i + 1)) { - // If some argument with default value is removed from a - // method signature, the said value must be explicitly - // added to the method call. - removedArgs++; - - // If have conversion rules I will use this for removed args - if (hasConversionRule) - userArgs << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); - else if (!arg->defaultValueExpression().isEmpty()) - userArgs << QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i); - } else { - int idx = arg->argumentIndex() - removedArgs; - bool deRef = isValueTypeWithCopyConstructorOnly(arg->type()) - || isObjectTypeUsedAsValueType(arg->type()) - || (arg->type()->referenceType() == LValueReference && isWrapperType(arg->type()) && !isPointer(arg->type())); - QString argName = hasConversionRule - ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX) - : QString::fromLatin1("%1" CPP_ARG "%2").arg(deRef ? QLatin1String("*") : QString()).arg(idx); - userArgs << argName; - } - } - - // If any argument's default value was modified the method must be called - // with this new value whenever the user doesn't pass an explicit value to it. - // Also, any unmodified default value coming after the last user specified - // argument and before the modified argument must be explicitly stated. - QStringList otherArgs; - bool otherArgsModified = false; - bool argsClear = true; - for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) { - const AbstractMetaArgument* arg = func->arguments().at(i); - bool defValModified = arg->defaultValueExpression() != arg->originalDefaultValueExpression(); - bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); - if (argsClear && !defValModified && !hasConversionRule) - continue; - else - argsClear = false; - otherArgsModified |= defValModified || hasConversionRule || func->argumentRemoved(i + 1); - if (hasConversionRule) - otherArgs.prepend(arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)); - else - otherArgs.prepend(QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i)); - } - if (otherArgsModified) - userArgs << otherArgs; - } - - bool isCtor = false; - QString methodCall; - QTextStream mc(&methodCall); - QString useVAddr; - QTextStream uva(&useVAddr); - if (func->isOperatorOverload() && !func->isCallOperator()) { - QString firstArg = QLatin1String("(*" CPP_SELF_VAR ")"); - if (func->isPointerOperator()) - firstArg.remove(1, 1); // remove the de-reference operator - - QString secondArg = QLatin1String(CPP_ARG0); - if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { - secondArg.prepend(QLatin1String("(*")); - secondArg.append(QLatin1Char(')')); - } - - if (func->isUnaryOperator()) - std::swap(firstArg, secondArg); - - QString op = func->originalName(); - op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1)); - - if (func->isBinaryOperator()) { - if (func->isReverseOperator()) - std::swap(firstArg, secondArg); - - if (((op == QLatin1String("++")) || (op == QLatin1String("--"))) && !func->isReverseOperator()) { - s << endl << INDENT << "for(int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");" << endl; - mc << firstArg; - } else { - mc << firstArg << ' ' << op << ' ' << secondArg; - } - } else { - mc << op << ' ' << secondArg; - } - } else if (!injectedCodeCallsCppFunction(func)) { - if (func->isConstructor()) { - isCtor = true; - QString className = wrapperName(func->ownerClass()); - - if (func->functionType() == AbstractMetaFunction::CopyConstructorFunction && maxArgs == 1) { - mc << "new ::" << className << "(*" << CPP_ARG0 << ')'; - } else { - QString ctorCall = className + QLatin1Char('(') + userArgs.join(QLatin1String(", ")) + QLatin1Char(')'); - if (usePySideExtensions() && func->ownerClass()->isQObject()) { - s << INDENT << "void* addr = PySide::nextQObjectMemoryAddr();" << endl; - uva << "if (addr) {" << endl; - { - Indentation indent(INDENT); - - uva << INDENT << "cptr = " << "new (addr) ::" - << ctorCall << ';' << endl - << INDENT - << "PySide::setNextQObjectMemoryAddr(0);" - << endl; - } - uva << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - - uva << INDENT << "cptr = " << "new ::" - << ctorCall << ';' << endl; - } - uva << INDENT << "}" << endl; - } else { - mc << "new ::" << ctorCall; - } - } - } else { - QString methodCallClassName; - if (context.forSmartPointer()) - methodCallClassName = context.preciseType()->cppSignature(); - else if (func->ownerClass()) - methodCallClassName = func->ownerClass()->qualifiedCppName(); - - if (func->ownerClass()) { - if (!avoidProtectedHack() || !func->isProtected()) { - if (func->isStatic()) { - mc << "::" << methodCallClassName << "::"; - } else { - const QString selfVarCast = func->ownerClass() == func->implementingClass() - ? QLatin1String(CPP_SELF_VAR) - : QLatin1String("reinterpret_cast<") + methodCallClassName + QLatin1String(" *>(" CPP_SELF_VAR ")"); - if (func->isConstant()) { - if (avoidProtectedHack()) { - mc << "const_castownerClass()->hasProtectedMembers()) { - // PYSIDE-500: Need a special wrapper cast when inherited - const QString selfWrapCast = func->ownerClass() == func->implementingClass() - ? QLatin1String(CPP_SELF_VAR) - : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass()) + QLatin1String(" *>(" CPP_SELF_VAR ")"); - mc << wrapperName(func->ownerClass()); - mc << "*>(" << selfWrapCast << ")->"; - } - else { - mc << methodCallClassName; - mc << "*>(" << selfVarCast << ")->"; - } - } else { - mc << "const_cast(" << selfVarCast << ")->"; - } - } else { - mc << selfVarCast << "->"; - } - } - - if (!func->isAbstract() && func->isVirtual()) - mc << "::%CLASS_NAME::"; - - mc << func->originalName(); - } else { - if (!func->isStatic()) - mc << "((::" << wrapperName(func->ownerClass()) << "*) " << CPP_SELF_VAR << ")->"; - - if (!func->isAbstract()) - mc << (func->isProtected() ? wrapperName(func->ownerClass()) : - QLatin1String("::") - + methodCallClassName) << "::"; - mc << func->originalName() << "_protected"; - } - } else { - mc << func->originalName(); - } - mc << '(' << userArgs.join(QLatin1String(", ")) << ')'; - if (!func->isAbstract() && func->isVirtual()) { - mc.flush(); - if (!avoidProtectedHack() || !func->isProtected()) { - QString virtualCall(methodCall); - QString normalCall(methodCall); - virtualCall = virtualCall.replace(QLatin1String("%CLASS_NAME"), - methodCallClassName); - normalCall.remove(QLatin1String("::%CLASS_NAME::")); - methodCall.clear(); - mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast(" PYTHON_SELF_VAR ")) ? "; - mc << virtualCall << " : " << normalCall; - } - } - } - } - - if (!injectedCodeCallsCppFunction(func)) { - s << INDENT << BEGIN_ALLOW_THREADS << endl << INDENT; - if (isCtor) { - s << (useVAddr.isEmpty() ? - QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl; - } else if (func->type() && !func->isInplaceOperator()) { - bool writeReturnType = true; - if (avoidProtectedHack()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); - if (metaEnum) { - QString enumName; - if (metaEnum->isProtected()) - enumName = protectedEnumSurrogateName(metaEnum); - else - enumName = func->type()->cppSignature(); - methodCall.prepend(enumName + QLatin1Char('(')); - methodCall.append(QLatin1Char(')')); - s << enumName; - writeReturnType = false; - } - } - if (writeReturnType) { - s << func->type()->cppSignature(); - if (isObjectTypeUsedAsValueType(func->type())) { - s << '*'; - methodCall.prepend(QString::fromLatin1("new %1(").arg(func->type()->typeEntry()->qualifiedCppName())); - methodCall.append(QLatin1Char(')')); - } - } - s << " " CPP_RETURN_VAR " = "; - s << methodCall << ';' << endl; - } else { - s << methodCall << ';' << endl; - } - s << INDENT << END_ALLOW_THREADS << endl; - - if (!func->conversionRule(TypeSystem::TargetLangCode, 0).isEmpty()) { - writeConversionRule(s, func, TypeSystem::TargetLangCode, QLatin1String(PYTHON_RETURN_VAR)); - } else if (!isCtor && !func->isInplaceOperator() && func->type() - && !injectedCodeHasReturnValueAttribution(func, TypeSystem::TargetLangCode)) { - s << INDENT << PYTHON_RETURN_VAR " = "; - if (isObjectTypeUsedAsValueType(func->type())) { - s << "Shiboken::Object::newObject(reinterpret_cast(" << cpythonTypeNameExt(func->type()->typeEntry()) - << "), " << CPP_RETURN_VAR << ", true, true)"; - } else { - writeToPythonConversion(s, func->type(), func->ownerClass(), QLatin1String(CPP_RETURN_VAR)); - } - s << ';' << endl; - } - } - } - - if (func->hasInjectedCode() && !func->isConstructor()) { - s << endl; - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func, lastArg); - } - - bool hasReturnPolicy = false; - - // Ownership transference between C++ and Python. - QVector ownership_mods; - // Python object reference management. - QVector refcount_mods; - const FunctionModificationList &funcMods = func->modifications(); - for (const FunctionModification &func_mod : funcMods) { - for (const ArgumentModification &arg_mod : func_mod.argument_mods) { - if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode)) - ownership_mods.append(arg_mod); - else if (!arg_mod.referenceCounts.isEmpty()) - refcount_mods.append(arg_mod); - } - } - - // If there's already a setParent(return, me), don't use the return heuristic! - if (func->argumentOwner(func->ownerClass(), -1).index == 0) - hasReturnPolicy = true; - - if (!ownership_mods.isEmpty()) { - s << endl << INDENT << "// Ownership transferences." << endl; - for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) { - const AbstractMetaClass* wrappedClass = 0; - QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); - if (!wrappedClass) { - s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl; - break; - } - - if (arg_mod.index == 0 || arg_mod.owner.index == 0) - hasReturnPolicy = true; - - // The default ownership does nothing. This is useful to avoid automatic heuristically - // based generation of code defining parenting. - if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership) - continue; - - s << INDENT << "Shiboken::Object::"; - if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "getOwnership(" << pyArgName << ");"; - } else if (wrappedClass->hasVirtualDestructor()) { - if (arg_mod.index == 0) - s << "releaseOwnership(" PYTHON_RETURN_VAR ");"; - else - s << "releaseOwnership(" << pyArgName << ");"; - } else { - s << "invalidate(" << pyArgName << ");"; - } - s << endl; - } - - } else if (!refcount_mods.isEmpty()) { - for (const ArgumentModification &arg_mod : qAsConst(refcount_mods)) { - ReferenceCount refCount = arg_mod.referenceCounts.first(); - if (refCount.action != ReferenceCount::Set - && refCount.action != ReferenceCount::Remove - && refCount.action != ReferenceCount::Add) { - qCWarning(lcShiboken) << "\"set\", \"add\" and \"remove\" are the only values supported by Shiboken for action attribute of reference-count tag."; - continue; - } - const AbstractMetaClass* wrappedClass = 0; - - QString pyArgName; - if (refCount.action == ReferenceCount::Remove) { - pyArgName = QLatin1String("Py_None"); - } else { - pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); - if (pyArgName.isEmpty()) { - s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl; - break; - } - } - - if (refCount.action == ReferenceCount::Add || refCount.action == ReferenceCount::Set) - s << INDENT << "Shiboken::Object::keepReference("; - else - s << INDENT << "Shiboken::Object::removeReference("; - - s << "reinterpret_cast(" PYTHON_SELF_VAR "), \""; - QString varName = arg_mod.referenceCounts.first().varName; - if (varName.isEmpty()) - varName = func->minimalSignature() + QString().number(arg_mod.index); - - s << varName << "\", " << pyArgName - << (refCount.action == ReferenceCount::Add ? ", true" : "") - << ");" << endl; - - if (arg_mod.index == 0) - hasReturnPolicy = true; - } - } - writeParentChildManagement(s, func, !hasReturnPolicy); -} - -QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass) -{ - QStringList result; - const AbstractMetaClassList &baseClases = getBaseClasses(metaClass); - if (!baseClases.isEmpty()) { - for (const AbstractMetaClass *baseClass : baseClases) { - result.append(QString::fromLatin1("((size_t) static_cast(class_ptr)) - base") - .arg(baseClass->qualifiedCppName())); - result.append(QString::fromLatin1("((size_t) static_cast((%2*)((void*)class_ptr))) - base") - .arg(baseClass->qualifiedCppName(), metaClass->qualifiedCppName())); - } - for (const AbstractMetaClass *baseClass : baseClases) - result.append(getAncestorMultipleInheritance(baseClass)); - } - return result; -} - -void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* 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 };" << endl; - s << "int*" << endl; - s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void* cptr)" << endl; - s << '{' << endl; - s << INDENT << "if (mi_offsets[0] == -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "std::set offsets;" << endl; - s << INDENT << "std::set::iterator it;" << endl; - s << INDENT << "const " << className << "* class_ptr = reinterpret_cast(cptr);" << endl; - s << INDENT << "size_t base = (size_t) class_ptr;" << endl; - - for (const QString &ancestor : ancestors) - s << INDENT << "offsets.insert(" << ancestor << ");" << endl; - - s << endl; - s << INDENT << "offsets.erase(0);" << endl; - s << endl; - - s << INDENT << "int i = 0;" << endl; - s << INDENT << "for (it = offsets.begin(); it != offsets.end(); it++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "mi_offsets[i] = *it;" << endl; - s << INDENT << "i++;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "return mi_offsets;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n"; - s << "{\n"; - s << INDENT << className << "* me = reinterpret_cast< ::" << className << "*>(obj);\n"; - bool firstClass = true; - const AbstractMetaClassList &allAncestors = getAllAncestors(metaClass); - for (const AbstractMetaClass *baseClass : allAncestors) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; - Indentation indent(INDENT); - s << INDENT << "return static_cast< ::" << baseClass->qualifiedCppName() << "*>(me);\n"; - firstClass = false; - } - s << INDENT << "return me;\n"; - s << "}\n\n"; -} - -void CppGenerator::writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion) -{ - const TypeEntry* type = customConversion->ownerType(); - QString converter = converterObject(type); - s << INDENT << "// Register converter for type '" << type->qualifiedTargetLangName() << "'." << endl; - s << INDENT << converter << " = Shiboken::Conversions::createConverter("; - if (type->targetLangApiName() == type->name()) - s << '0'; - else if (type->targetLangApiName() == QLatin1String("PyObject")) - s << "&PyBaseObject_Type"; - else - s << '&' << type->targetLangApiName() << "_Type"; - QString typeName = fixedCppTypeName(type); - s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl; - s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << type->qualifiedCppName() << "\");" << endl; - writeCustomConverterRegister(s, customConversion, converter); -} - -void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum) -{ - if (metaEnum->isPrivate() || metaEnum->isAnonymous()) - return; - writeEnumConverterInitialization(s, metaEnum->typeEntry()); -} - -void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType) -{ - if (!enumType) - return; - QString enumFlagName = enumType->isFlags() ? QLatin1String("flag") : QLatin1String("enum"); - QString enumPythonType = cpythonTypeNameExt(enumType); - - const FlagsTypeEntry* flags = 0; - if (enumType->isFlags()) - flags = reinterpret_cast(enumType); - - s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'." << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - QString typeName = fixedCppTypeName(enumType); - s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl; - { - Indentation indent(INDENT); - s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");" << endl; - } - - if (flags) { - QString enumTypeName = fixedCppTypeName(flags->originator()); - QString toCpp = pythonToCppFunctionName(enumTypeName, typeName); - QString isConv = convertibleToCppFunctionName(enumTypeName, typeName); - writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); - } - - QString toCpp = pythonToCppFunctionName(typeName, typeName); - QString isConv = convertibleToCppFunctionName(typeName, typeName); - writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); - - if (flags) { - QString toCpp = pythonToCppFunctionName(QLatin1String("number"), typeName); - QString isConv = convertibleToCppFunctionName(QLatin1String("number"), typeName); - writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); - } - - s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; - s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; - QStringList cppSignature = enumType->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); - while (!cppSignature.isEmpty()) { - QString signature = cppSignature.join(QLatin1String("::")); - s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \""; - if (flags) - s << "QFlags<"; - s << signature << "\");" << endl; - cppSignature.removeFirst(); - } - } - s << INDENT << '}' << endl; - - if (!flags) - writeEnumConverterInitialization(s, reinterpret_cast(enumType)->flags()); -} - -void CppGenerator::writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type) -{ - QByteArray cppSignature = QMetaObject::normalizedSignature(type->cppSignature().toUtf8()); - s << INDENT << "// Register converter for type '" << cppSignature << "'." << endl; - QString converter = converterObject(type); - s << INDENT << converter << " = Shiboken::Conversions::createConverter("; - if (type->typeEntry()->targetLangApiName() == QLatin1String("PyObject")) { - s << "&PyBaseObject_Type"; - } else { - QString baseName = cpythonBaseName(type->typeEntry()); - if (baseName == QLatin1String("PySequence")) - baseName = QLatin1String("PyList"); - s << '&' << baseName << "_Type"; - } - QString typeName = fixedCppTypeName(type); - s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl; - QString toCpp = pythonToCppFunctionName(typeName, typeName); - QString isConv = convertibleToCppFunctionName(typeName, typeName); - s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl; - if (usePySideExtensions() && cppSignature.startsWith("const ") && cppSignature.endsWith("&")) { - cppSignature.chop(1); - cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1); - s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl; - } - writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv); -} - -void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, - const QVector& conversions) -{ - s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; - for (const AbstractMetaClass *sourceClass : conversions) { - const QString converterVar = QLatin1String("reinterpret_cast(") - + cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[') - + getTypeIndexVariableName(externalType) + QLatin1String("])"); - QString sourceTypeName = fixedCppTypeName(sourceClass->typeEntry()); - QString targetTypeName = fixedCppTypeName(externalType); - QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName); - QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName); - writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); - } -} - -QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass) -{ - if (!hasMultipleInheritanceInAncestry(metaClass)) - return QString(); - return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("_mi_init"); -} - -typedef QHash >::const_iterator ProtocolIt; - -bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass* metaClass) -{ - for (ProtocolIt it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { - if (metaClass->hasFunction(it.key())) - return true; - } - - return false; -} - -bool CppGenerator::supportsNumberProtocol(const AbstractMetaClass* metaClass) -{ - return metaClass->hasArithmeticOperatorOverload() - || metaClass->hasLogicalOperatorOverload() - || metaClass->hasBitwiseOperatorOverload() - || hasBoolCast(metaClass); -} - -bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) -{ - for (ProtocolIt it = m_sequenceProtocol.cbegin(), end = m_sequenceProtocol.cend(); it != end; ++it) { - if (metaClass->hasFunction(it.key())) - return true; - } - - const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType(); - if (baseType && baseType->isContainer()) - return true; - - return false; -} - -bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass) -{ - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField *f : fields) { - if (!f->isStatic()) - return true; - } - return false; -} - -void CppGenerator::writeClassDefinition(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &classContext) -{ - QString tp_flags; - QString tp_init; - QString tp_new; - QString tp_dealloc; - QString tp_hash(QLatin1Char('0')); - QString tp_call = tp_hash; - QString cppClassName = metaClass->qualifiedCppName(); - const QString className = chopType(cpythonTypeName(metaClass)); - QString baseClassName(QLatin1Char('0')); - AbstractMetaFunctionList ctors; - const AbstractMetaFunctionList &allCtors = metaClass->queryFunctions(AbstractMetaClass::Constructors); - for (AbstractMetaFunction *f : allCtors) { - if (!f->isPrivate() && !f->isModifiedRemoved() && !classContext.forSmartPointer()) - ctors.append(f); - } - - if (!metaClass->baseClass()) - baseClassName = QLatin1String("reinterpret_cast(&SbkObject_Type)"); - - bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor(); - - if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { - tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); - tp_dealloc = metaClass->hasPrivateDestructor() ? - QLatin1String("SbkDeallocWrapperWithPrivateDtor") : QLatin1String("0"); - tp_init = QLatin1String("0"); - } else { - if (onlyPrivCtor) - tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); - else - tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); - - QString deallocClassName; - if (shouldGenerateCppWrapper(metaClass)) - deallocClassName = wrapperName(metaClass); - else - deallocClassName = cppClassName; - tp_dealloc = QLatin1String("&SbkDeallocWrapper"); - // avoid constFirst to stay Qt 5.5 compatible - tp_init = (onlyPrivCtor || ctors.isEmpty()) ? QLatin1String("0") : cpythonFunctionName(ctors.first()); - } - - QString tp_getattro(QLatin1Char('0')); - QString tp_setattro = tp_getattro; - if (usePySideExtensions() && (metaClass->qualifiedCppName() == QLatin1String("QObject"))) { - tp_getattro = cpythonGetattroFunctionName(metaClass); - tp_setattro = cpythonSetattroFunctionName(metaClass); - } else { - if (classNeedsGetattroFunction(metaClass)) - tp_getattro = cpythonGetattroFunctionName(metaClass); - if (classNeedsSetattroFunction(metaClass)) - tp_setattro = cpythonSetattroFunctionName(metaClass); - } - - if (metaClass->hasPrivateDestructor() || onlyPrivCtor) - tp_new = QLatin1String("0"); - else - tp_new = QLatin1String("SbkObjectTpNew"); - - QString tp_richcompare = QString(QLatin1Char('0')); - if (metaClass->hasComparisonOperatorOverload()) - tp_richcompare = cpythonBaseName(metaClass) + QLatin1String("_richcompare"); - - QString tp_getset = QString(QLatin1Char('0')); - if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) - tp_getset = cpythonGettersSettersDefinitionName(metaClass); - - // search for special functions - ShibokenGenerator::clearTpFuncs(); - const AbstractMetaFunctionList &funcs = metaClass->functions(); - for (AbstractMetaFunction *func : funcs) { - if (m_tpFuncs.contains(func->name())) - m_tpFuncs[func->name()] = cpythonFunctionName(func); - } - if (m_tpFuncs[QLatin1String("__repr__")] == QLatin1String("0") - && !metaClass->isQObject() - && metaClass->hasToStringCapability()) { - m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, classContext); - } - - // class or some ancestor has multiple inheritance - const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); - if (miClass) { - if (metaClass == miClass) - writeMultipleInheritanceInitializerFunction(s, metaClass); - writeSpecialCastFunction(s, metaClass); - s << endl; - } - - if (!metaClass->typeEntry()->hashFunction().isEmpty()) - tp_hash = QLatin1Char('&') + cpythonBaseName(metaClass) + QLatin1String("_HashFunc"); - - const AbstractMetaFunction* callOp = metaClass->findFunction(QLatin1String("operator()")); - if (callOp && !callOp->isModifiedRemoved()) - tp_call = QLatin1Char('&') + cpythonFunctionName(callOp); - - s << "// Class Definition -----------------------------------------------" << endl; - s << "extern \"C\" {" << endl; - - if (supportsNumberProtocol(metaClass)) { - s << "static PyNumberMethods " << className + QLatin1String("_TypeAsNumber") << ";" << endl; - s << endl; - } - - if (supportsSequenceProtocol(metaClass)) { - s << "static PySequenceMethods " << className + QLatin1String("_TypeAsSequence") << ";" << endl; - s << endl; - } - - if (supportsMappingProtocol(metaClass)) { - s << "static PyMappingMethods " << className + QLatin1String("_TypeAsMapping") << ";" << endl; - s << endl; - } - - s << "static SbkObjectType " << className + QLatin1String("_Type") << " = { { {" << endl; - s << INDENT << "PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)" << endl; - QString computedClassTargetFullName; - if (!classContext.forSmartPointer()) - computedClassTargetFullName = getClassTargetFullName(metaClass); - else - computedClassTargetFullName = getClassTargetFullName(classContext.preciseType()); - - s << INDENT << "/*tp_name*/ \"" << computedClassTargetFullName << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ " << m_tpFuncs[QLatin1String("__repr__")] << "," << endl; - s << INDENT << "/*tp_as_number*/ 0," << endl; - s << INDENT << "/*tp_as_sequence*/ 0," << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl; - s << INDENT << "/*tp_call*/ " << tp_call << ',' << endl; - s << INDENT << "/*tp_str*/ " << m_tpFuncs[QLatin1String("__str__")] << ',' << endl; - s << INDENT << "/*tp_getattro*/ " << tp_getattro << ',' << endl; - s << INDENT << "/*tp_setattro*/ " << tp_setattro << ',' << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ " << tp_flags << ',' << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ " << className << "_traverse," << endl; - s << INDENT << "/*tp_clear*/ " << className << "_clear," << endl; - s << INDENT << "/*tp_richcompare*/ " << tp_richcompare << ',' << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ " << m_tpFuncs[QLatin1String("__iter__")] << ',' << endl; - s << INDENT << "/*tp_iternext*/ " << m_tpFuncs[QLatin1String("__next__")] << ',' << endl; - s << INDENT << "/*tp_methods*/ " << className << "_methods," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ " << tp_getset << ',' << endl; - s << INDENT << "/*tp_base*/ " << baseClassName << ',' << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ " << tp_init << ',' << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ " << tp_new << ',' << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "}, }," << endl; - s << INDENT << "/*priv_data*/ 0" << endl; - s << "};" << endl; - QString suffix; - if (isObjectType(metaClass)) - suffix = QLatin1String("*"); - s << "} //extern" << endl; -} - -void CppGenerator::writeMappingMethods(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &context) -{ - - QMap funcs; - - QHash< QString, QPair< QString, QString > >::const_iterator it = m_mappingProtocol.begin(); - for (; it != m_mappingProtocol.end(); ++it) { - const AbstractMetaFunction* func = metaClass->findFunction(it.key()); - if (!func) - continue; - QString funcName = cpythonFunctionName(func); - QString funcArgs = it.value().first; - QString funcRetVal = it.value().second; - - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; - writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); - - writeCppSelfDefinition(s, func, context); - - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); - s << '}' << endl << endl; - } -} - -void CppGenerator::writeSequenceMethods(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &context) -{ - - QMap funcs; - bool injectedCode = false; - - QHash< QString, QPair< QString, QString > >::const_iterator it = m_sequenceProtocol.begin(); - for (; it != m_sequenceProtocol.end(); ++it) { - const AbstractMetaFunction* func = metaClass->findFunction(it.key()); - if (!func) - continue; - injectedCode = true; - QString funcName = cpythonFunctionName(func); - QString funcArgs = it.value().first; - QString funcRetVal = it.value().second; - - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; - writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); - - writeCppSelfDefinition(s, func, context); - - const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); - writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); - s << '}' << endl << endl; - } - - if (!injectedCode) - writeStdListWrapperMethods(s, context); -} - -void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - bool hasFunctions = false; - QMap funcs; - for (ProtocolIt it = m_sequenceProtocol.cbegin(), end = m_sequenceProtocol.cend(); it != end; ++it) { - const QString &funcName = it.key(); - const AbstractMetaFunction* func = metaClass->findFunction(funcName); - funcs[funcName] = func ? cpythonFunctionName(func).prepend(QLatin1Char('&')) : QString(); - if (!hasFunctions && func) - hasFunctions = true; - } - - QString baseName = cpythonBaseName(metaClass); - - //use default implementation - if (!hasFunctions) { - funcs[QLatin1String("__len__")] = baseName + QLatin1String("__len__"); - funcs[QLatin1String("__getitem__")] = baseName + QLatin1String("__getitem__"); - funcs[QLatin1String("__setitem__")] = baseName + QLatin1String("__setitem__"); - } - - s << INDENT << "memset(&" << baseName << "_TypeAsSequence, 0, sizeof(PySequenceMethods));" << endl; - for (QHash::const_iterator it = m_sqFuncs.cbegin(), end = m_sqFuncs.cend(); it != end; ++it) { - const QString& sqName = it.key(); - if (funcs[sqName].isEmpty()) - continue; - if (it.value() == QLatin1String("sq_slice")) - s << "#ifndef IS_PY3K" << endl; - s << INDENT << baseName << "_TypeAsSequence." << it.value() << " = " << funcs[sqName] << ';' << endl; - if (it.value() == QLatin1String("sq_slice")) - s << "#endif" << endl; - } -} - -void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - bool hasFunctions = false; - QMap funcs; - for (ProtocolIt it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { - const QString &funcName = it.key(); - const AbstractMetaFunction* func = metaClass->findFunction(funcName); - funcs[funcName] = func ? cpythonFunctionName(func).prepend(QLatin1Char('&')) : QLatin1String("0"); - if (!hasFunctions && func) - hasFunctions = true; - } - - //use default implementation - if (!hasFunctions) { - funcs.insert(QLatin1String("__mlen__"), QString()); - funcs.insert(QLatin1String("__mgetitem__"), QString()); - funcs.insert(QLatin1String("__msetitem__"), QString()); - } - - QString baseName = cpythonBaseName(metaClass); - s << INDENT << "memset(&" << baseName << "_TypeAsMapping, 0, sizeof(PyMappingMethods));" << endl; - for (QHash::const_iterator it = m_mpFuncs.cbegin(), end = m_mpFuncs.end(); it != end; ++it) { - const QString &mpName = it.key(); - if (funcs[mpName].isEmpty()) - continue; - s << INDENT << baseName << "_TypeAsMapping." << it.value() << " = " << funcs[mpName] << ';' << endl; - } -} - -void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QMap nb; - - nb.insert(QLatin1String("__add__"), QString()); - nb.insert(QLatin1String("__sub__"), QString()); - nb.insert(QLatin1String("__mul__"), QString()); - nb.insert(QLatin1String("__div__"), QString()); - nb.insert(QLatin1String("__mod__"), QString()); - nb.insert(QLatin1String("__neg__"), QString()); - nb.insert(QLatin1String("__pos__"), QString()); - nb.insert(QLatin1String("__invert__"), QString()); - nb.insert(QLatin1String("__lshift__"), QString()); - nb.insert(QLatin1String("__rshift__"), QString()); - nb.insert(QLatin1String("__and__"), QString()); - nb.insert(QLatin1String("__xor__"), QString()); - nb.insert(QLatin1String("__or__"), QString()); - nb.insert(QLatin1String("__iadd__"), QString()); - nb.insert(QLatin1String("__isub__"), QString()); - nb.insert(QLatin1String("__imul__"), QString()); - nb.insert(QLatin1String("__idiv__"), QString()); - nb.insert(QLatin1String("__imod__"), QString()); - nb.insert(QLatin1String("__ilshift__"), QString()); - nb.insert(QLatin1String("__irshift__"), QString()); - nb.insert(QLatin1String("__iand__"), QString()); - nb.insert(QLatin1String("__ixor__"), QString()); - nb.insert(QLatin1String("__ior__"), QString()); - - const QVector opOverloads = - filterGroupedOperatorFunctions(metaClass, - AbstractMetaClass::ArithmeticOp - | AbstractMetaClass::LogicalOp - | AbstractMetaClass::BitwiseOp); - - for (const AbstractMetaFunctionList &opOverload : opOverloads) { - const AbstractMetaFunction* rfunc = opOverload[0]; - QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); - nb[opName] = cpythonFunctionName(rfunc); - } - - QString baseName = cpythonBaseName(metaClass); - - nb[QLatin1String("bool")] = hasBoolCast(metaClass) ? baseName + QLatin1String("___nb_bool") : QString(); - - s << INDENT << "memset(&" << baseName << "_TypeAsNumber, 0, sizeof(PyNumberMethods));" << endl; - for (QHash::const_iterator it = m_nbFuncs.cbegin(), end = m_nbFuncs.cend(); it != end; ++it) { - const QString &nbName = it.key(); - if (nb[nbName].isEmpty()) - continue; - - // bool is special because the field name differs on Python 2 and 3 (nb_nonzero vs nb_bool) - // so a shiboken macro is used. - if (nbName == QLatin1String("bool")) { - s << INDENT << "SBK_NB_BOOL(" << baseName << "_TypeAsNumber) = " << nb[nbName] << ';' << endl; - } else { - bool excludeFromPy3K = nbName == QLatin1String("__div__") || nbName == QLatin1String("__idiv__"); - if (excludeFromPy3K) { - s << "#ifdef IS_PY3K" << endl; - s << INDENT << "SBK_UNUSED(&" << nb[nbName] << ");" << endl; - s << "#else" << endl; - } - s << INDENT << baseName << "_TypeAsNumber." << it.value() << " = " << nb[nbName] << ';' << endl; - if (excludeFromPy3K) - s << "#endif" << endl; - } - } - if (!nb[QLatin1String("__div__")].isEmpty()) - s << INDENT << baseName << "_TypeAsNumber.nb_true_divide = " << nb[QLatin1String("__div__")] << ';' << endl; -} - -void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString baseName = cpythonBaseName(metaClass); - s << "static int "; - s << baseName << "_traverse(PyObject* " PYTHON_SELF_VAR ", visitproc visit, void* arg)" << endl; - s << '{' << endl; - s << INDENT << "return reinterpret_cast(&SbkObject_Type)->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl; - s << '}' << endl; -} - -void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString baseName = cpythonBaseName(metaClass); - s << "static int "; - s << baseName << "_clear(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << '{' << endl; - s << INDENT << "return reinterpret_cast(&SbkObject_Type)->tp_clear(" PYTHON_SELF_VAR ");" << endl; - s << '}' << endl; -} - -void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - const QString className = chopType(cpythonTypeName(metaClass)); - s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << "{" << endl; - writeCppSelfDefinition(s, context, false, true); - QString conversionCode; - if (!context.forSmartPointer()) - conversionCode = cpythonToPythonConversionFunction(metaClass); - else - conversionCode = cpythonToPythonConversionFunction(context.preciseType()); - - s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << conversionCode; - s << CPP_SELF_VAR ");" << endl; - writeFunctionReturnErrorCheckSection(s); - s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; - s << "}" << endl; - s << endl; -} - -void CppGenerator::writeGetterFunction(QTextStream &s, - const AbstractMetaField *metaField, - GeneratorContext &context) -{ - ErrorCode errorCode(0); - s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", void*)" << endl; - s << '{' << endl; - - writeCppSelfDefinition(s, context); - - AbstractMetaType* fieldType = metaField->type(); - // Force use of pointer to return internal variable memory - bool newWrapperSameObject = !fieldType->isConstant() && isWrapperType(fieldType) && !isPointer(fieldType); - - QString cppField; - if (avoidProtectedHack() && metaField->isProtected()) { - cppField = QString::fromLatin1("((%1*)%2)->%3()") - .arg(wrapperName(metaField->enclosingClass()), QLatin1String(CPP_SELF_VAR), - protectedFieldGetterName(metaField)); - } else { - cppField = QLatin1String(CPP_SELF_VAR) + QLatin1String("->") + metaField->name(); - if (newWrapperSameObject) { - cppField.prepend(QLatin1String("&(")); - cppField.append(QLatin1Char(')')); - } - } - if (isCppIntegralPrimitive(fieldType) || fieldType->isEnum()) { - s << INDENT << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl; - cppField = QLatin1String("cppOut_local"); - } else if (avoidProtectedHack() && metaField->isProtected()) { - s << INDENT << getFullTypeNameWithoutModifiers(fieldType); - if (fieldType->isContainer() || fieldType->isFlags() || fieldType->isSmartPointer()) { - s << '&'; - cppField.prepend(QLatin1Char('*')); - } else if ((!fieldType->isConstant() && !fieldType->isEnum() && !fieldType->isPrimitive()) || fieldType->indirections() == 1) { - s << '*'; - } - s << " fieldValue = " << cppField << ';' << endl; - cppField = QLatin1String("fieldValue"); - } - - s << INDENT << "PyObject* pyOut = 0;\n"; - if (newWrapperSameObject) { - // Special case colocated field with same address (first field in a struct) - s << INDENT << "if (reinterpret_cast(" - << cppField - << ") == reinterpret_cast(" - << CPP_SELF_VAR << ")) {\n"; - { - Indentation indent(INDENT); - s << INDENT << "pyOut = reinterpret_cast(Shiboken::Object::findColocatedChild(" - << "reinterpret_cast(self), reinterpret_cast(" - << cpythonTypeNameExt(fieldType) - << ")));\n"; - s << INDENT << "if (pyOut) {Py_IncRef(pyOut); return pyOut;}\n"; - } - s << INDENT << "}\n"; - // Check if field wrapper has already been created. - s << INDENT << "else if (Shiboken::BindingManager::instance().hasWrapper(" << cppField << ")) {" << "\n"; - { - Indentation indent(INDENT); - s << INDENT << "pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(" << cppField << ");" << "\n"; - s << INDENT << "Py_IncRef(pyOut);" << "\n"; - s << INDENT << "return pyOut;" << "\n"; - } - s << INDENT << "}\n"; - // Create and register new wrapper - s << INDENT << "pyOut = "; - s << "Shiboken::Object::newObject(reinterpret_cast(" << cpythonTypeNameExt(fieldType) - << "), " << cppField << ", false, true);" << endl; - s << INDENT << "Shiboken::Object::setParent(" PYTHON_SELF_VAR ", pyOut)"; - } else { - s << INDENT << "pyOut = "; - writeToPythonConversion(s, fieldType, metaField->enclosingClass(), cppField); - } - s << ';' << endl; - - s << INDENT << "return pyOut;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeSetterFunction(QTextStream &s, - const AbstractMetaField *metaField, - GeneratorContext &context) -{ - ErrorCode errorCode(0); - s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* pyIn, void*)" << endl; - s << '{' << endl; - - writeCppSelfDefinition(s, context); - - s << INDENT << "if (pyIn == 0) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"; - s << metaField->name() << "' may not be deleted\");" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << '}' << endl; - - AbstractMetaType* fieldType = metaField->type(); - - s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl; - s << INDENT << "if (!"; - writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry())); - s << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"; - s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << '}' << endl << endl; - - QString cppField = QString::fromLatin1("%1->%2").arg(QLatin1String(CPP_SELF_VAR), metaField->name()); - s << INDENT; - if (avoidProtectedHack() && metaField->isProtected()) { - s << getFullTypeNameWithoutModifiers(fieldType); - s << (fieldType->indirections() == 1 ? "*" : "") << " cppOut;" << endl; - s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);" << endl; - s << INDENT << QString::fromLatin1("((%1*)%2)->%3(cppOut)") - .arg(wrapperName(metaField->enclosingClass()), - QLatin1String(CPP_SELF_VAR), protectedFieldSetterName(metaField)); - } else if (isCppIntegralPrimitive(fieldType) || fieldType->typeEntry()->isEnum() || fieldType->typeEntry()->isFlags()) { - s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl; - s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl; - s << INDENT << cppField << " = cppOut_local"; - } else { - s << getFullTypeNameWithoutModifiers(fieldType); - s << QString::fromLatin1("*").repeated(fieldType->indirections()) << "& cppOut_ptr = "; - s << cppField << ';' << endl; - s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)"; - } - s << ';' << endl << endl; - - if (isPointerToWrapperType(fieldType)) { - s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast(" PYTHON_SELF_VAR "), \""; - s << metaField->name() << "\", pyIn);" << endl; - } - - s << INDENT << "return 0;" << endl; - s << '}' << endl; -} - -void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - QString baseName = cpythonBaseName(metaClass); - s << "static PyObject* "; - s << baseName << "_richcompare(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ", int op)" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, context, false, true); - writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); - s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; - s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR << ';' << endl; - writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); - s << endl; - - s << INDENT << "switch (op) {" << endl; - { - Indentation indent(INDENT); - const QVector &groupedFuncs = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); - for (const AbstractMetaFunctionList &overloads : groupedFuncs) { - const AbstractMetaFunction* rfunc = overloads[0]; - - QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc); - s << INDENT << "case " << operatorId << ':' << endl; - - Indentation indent(INDENT); - - QString op = rfunc->originalName(); - op = op.right(op.size() - QLatin1String("operator").size()); - - int alternativeNumericTypes = 0; - for (const AbstractMetaFunction *func : overloads) { - if (!func->isStatic() && - ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry())) - alternativeNumericTypes++; - } - - bool first = true; - OverloadData overloadData(overloads, this); - const OverloadDataList &nextOverloads = overloadData.nextOverloadData(); - for (OverloadData *od : nextOverloads) { - const AbstractMetaFunction* func = od->referenceFunction(); - if (func->isStatic()) - continue; - const AbstractMetaType* argType = getArgumentType(func, 1); - if (!argType) - continue; - if (!first) { - s << " else "; - } else { - first = false; - s << INDENT; - } - s << "if ("; - writeTypeCheck(s, argType, QLatin1String(PYTHON_ARG), alternativeNumericTypes == 1 || isPyInt(argType)); - s << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "// " << func->signature() << endl; - writeArgumentConversion(s, argType, QLatin1String(CPP_ARG0), - QLatin1String(PYTHON_ARG), metaClass, - QString(), func->isUserAdded()); - - // If the function is user added, use the inject code - if (func->isUserAdded()) { - CodeSnipList snips = func->injectedCodeSnips(); - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().last()); - } else { - QString expression = QString::fromLatin1("%1%2 %3 (%4" CPP_ARG0 ")") - .arg(func->isPointerOperator() ? QLatin1String("&") : QString(), - QLatin1String(CPP_SELF_VAR), op, - shouldDereferenceAbstractMetaTypePointer(argType) ? QLatin1String("*") : QString()); - s << INDENT; - if (func->type()) - s << func->type()->cppSignature() << " " CPP_RETURN_VAR " = "; - s << expression << ';' << endl; - s << INDENT << PYTHON_RETURN_VAR " = "; - if (func->type()) - writeToPythonConversion(s, func->type(), metaClass, QLatin1String(CPP_RETURN_VAR)); - else - s << "Py_None;" << endl << INDENT << "Py_INCREF(Py_None)"; - s << ';' << endl; - } - } - s << INDENT << '}'; - } - - s << " else {" << endl; - if (operatorId == QLatin1String("Py_EQ") || operatorId == QLatin1String("Py_NE")) { - Indentation indent(INDENT); - s << INDENT << PYTHON_RETURN_VAR " = " - << (operatorId == QLatin1String("Py_EQ") ? "Py_False" : "Py_True") << ';' << endl; - s << INDENT << "Py_INCREF(" PYTHON_RETURN_VAR ");" << endl; - } else { - Indentation indent(INDENT); - s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl; - } - s << INDENT << '}' << endl << endl; - - s << INDENT << "break;" << endl; - } - s << INDENT << "default:" << endl; - { - Indentation indent(INDENT); - s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl; - } - } - s << INDENT << '}' << endl << endl; - - s << INDENT << "if (" PYTHON_RETURN_VAR " && !PyErr_Occurred())" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; - } - s << INDENT << baseName << "_RichComparison_TypeError:" << endl; - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - Q_ASSERT(!overloads.isEmpty()); - OverloadData overloadData(overloads, this); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); - const AbstractMetaFunction* func = overloadData.referenceFunction(); - int min = overloadData.minArgs(); - int max = overloadData.maxArgs(); - - s << '"' << func->name() << "\", (PyCFunction)" << cpythonFunctionName(func) << ", "; - if ((min == max) && (max < 2) && !usePyArgs) { - if (max == 0) - s << "METH_NOARGS"; - else - s << "METH_O"; - } else { - s << "METH_VARARGS"; - if (overloadData.hasArgumentWithDefaultValue()) - s << "|METH_KEYWORDS"; - } - if (func->ownerClass() && overloadData.hasStaticFunction()) - s << "|METH_STATIC"; -} - -void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads) -{ - Q_ASSERT(!overloads.isEmpty()); - const AbstractMetaFunction* func = overloads.first(); - if (m_tpFuncs.contains(func->name())) - return; - - s << INDENT; - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { - s << cpythonMethodDefinitionName(func); - } else { - s << '{'; - writeMethodDefinitionEntry(s, overloads); - s << '}'; - } - s << ',' << endl; -} - -void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums) -{ - if (enums.isEmpty()) - return; - s << INDENT << "// Initialization of enums." << endl << endl; - for (const AbstractMetaEnum *cppEnum : qAsConst(enums)) { - if (cppEnum->isPrivate()) - continue; - writeEnumInitialization(s, cppEnum); - } -} - -void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum); - const AbstractMetaClass* upper = enclosingClass ? enclosingClass->enclosingClass() : 0; - bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; - QString enclosingObjectVariable; - if (enclosingClass) - enclosingObjectVariable = QLatin1Char('&') + cpythonTypeName(enclosingClass); - else if (hasUpperEnclosingClass) - enclosingObjectVariable = QLatin1String("enclosingClass"); - else - enclosingObjectVariable = QLatin1String("module"); - - s << INDENT << "// Initialization of "; - s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum"); - s << " '" << cppEnum->name() << "'." << endl; - - if (!cppEnum->isAnonymous()) { - FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); - if (flags) { - s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", &" - << cpythonEnumName(cppEnum) << "_as_number);" << endl; - } - - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = Shiboken::Enum::"; - s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); - s << '(' << enclosingObjectVariable << ',' << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << cppEnum->name() << "\"," << endl; - s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\"," << endl; - s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString()); - s << cppEnum->name() << '"'; - if (flags) - s << ',' << endl << INDENT << cpythonTypeNameExt(flags); - s << ");" << endl; - } - s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; - } - } - - const AbstractMetaEnumValueList &enumValues = cppEnum->values(); - for (const AbstractMetaEnumValue *enumValue : enumValues) { - if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) - continue; - - QString enumValueText; - if (!avoidProtectedHack() || !cppEnum->isProtected()) { - enumValueText = QLatin1String("(long) "); - if (cppEnum->enclosingClass()) - enumValueText += cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::"); - enumValueText += enumValue->name(); - } else { - enumValueText += QString::number(enumValue->value()); - } - - if (cppEnum->isAnonymous()) { - if (enclosingClass || hasUpperEnclosingClass) { - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl; - s << INDENT << "if (PyDict_SetItemString(reinterpret_cast(" << enclosingObjectVariable - << ")->super.ht_type.tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << "Py_DECREF(anonEnumItem);" << endl; - } - s << INDENT << '}' << endl; - } else { - s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", "; - s << enumValueText << ") < 0)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - } else { - s << INDENT << "if (!Shiboken::Enum::"; - s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); - s << '(' << cpythonTypeNameExt(cppEnum->typeEntry()) << ',' << endl; - Indentation indent(INDENT); - s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", "; - s << enumValueText << "))" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - - writeEnumConverterInitialization(s, cppEnum); - - s << INDENT << "// End of '" << cppEnum->name() << "' enum"; - if (cppEnum->typeEntry()->flags()) - s << "/flags"; - s << '.' << endl << endl; -} - -void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) -{ - // Try to check something and print some warnings - const AbstractMetaFunctionList &signalFuncs = metaClass->cppSignalFunctions(); - for (const AbstractMetaFunction *cppSignal : signalFuncs) { - if (cppSignal->declaringClass() != metaClass) - continue; - const AbstractMetaArgumentList &arguments = cppSignal->arguments(); - for (AbstractMetaArgument *arg : arguments) { - AbstractMetaType* metaType = arg->type(); - const QByteArray origType = - QMetaObject::normalizedType(qPrintable(metaType->originalTypeDescription())); - const QByteArray cppSig = - QMetaObject::normalizedType(qPrintable(metaType->cppSignature())); - if ((origType != cppSig) && (!metaType->isFlags())) { - qCWarning(lcShiboken).noquote().nospace() - << "Typedef used on signal " << metaClass->qualifiedCppName() << "::" - << cppSignal->signature(); - } - } - } - - s << INDENT << "PySide::Signal::registerSignals(&" << cpythonTypeName(metaClass) << ", &::" - << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl; -} - -void CppGenerator::writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - if (!flagsEntry) - return; - s << "static PyObject* " << cpythonEnumName(cppEnum) << "_long(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << "{" << endl; - s << INDENT << "int val;" << endl; - AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); - s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl; - s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &val);" << endl; - s << "}" << endl; -} - -void CppGenerator::writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - if (!flagsEntry) - return; - s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << "{" << endl; - - s << INDENT << "int val;" << endl; - AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); - s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl; - s << INDENT << "return val != 0;" << endl; - s << "}" << endl; -} - -void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - writeFlagsBinaryOperator(s, cppEnum, QLatin1String("and"), QLatin1String("&")); - writeFlagsBinaryOperator(s, cppEnum, QLatin1String("or"), QLatin1String("|")); - writeFlagsBinaryOperator(s, cppEnum, QLatin1String("xor"), QLatin1String("^")); - - writeFlagsUnaryOperator(s, cppEnum, QLatin1String("invert"), QLatin1String("~")); - writeFlagsToLong(s, cppEnum); - writeFlagsNonZero(s, cppEnum); - - s << endl; -} - -void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - - s << "static PyNumberMethods " << cpythonName << "_as_number = {" << endl; - s << INDENT << "/*nb_add*/ 0," << endl; - s << INDENT << "/*nb_subtract*/ 0," << endl; - s << INDENT << "/*nb_multiply*/ 0," << endl; - s << INDENT << "#ifndef IS_PY3K" << endl; - s << INDENT << "/* nb_divide */ 0," << endl; - s << INDENT << "#endif" << endl; - s << INDENT << "/*nb_remainder*/ 0," << endl; - s << INDENT << "/*nb_divmod*/ 0," << endl; - s << INDENT << "/*nb_power*/ 0," << endl; - s << INDENT << "/*nb_negative*/ 0," << endl; - s << INDENT << "/*nb_positive*/ 0," << endl; - s << INDENT << "/*nb_absolute*/ 0," << endl; - s << INDENT << "/*nb_nonzero*/ " << cpythonName << "__nonzero," << endl; - s << INDENT << "/*nb_invert*/ (unaryfunc)" << cpythonName << "___invert__," << endl; - s << INDENT << "/*nb_lshift*/ 0," << endl; - s << INDENT << "/*nb_rshift*/ 0," << endl; - s << INDENT << "/*nb_and*/ (binaryfunc)" << cpythonName << "___and__," << endl; - s << INDENT << "/*nb_xor*/ (binaryfunc)" << cpythonName << "___xor__," << endl; - s << INDENT << "/*nb_or*/ (binaryfunc)" << cpythonName << "___or__," << endl; - s << INDENT << "#ifndef IS_PY3K" << endl; - s << INDENT << "/* nb_coerce */ 0," << endl; - s << INDENT << "#endif" << endl; - s << INDENT << "/*nb_int*/ " << cpythonName << "_long," << endl; - s << INDENT << "#ifdef IS_PY3K" << endl; - s << INDENT << "/*nb_reserved*/ 0," << endl; - s << INDENT << "/*nb_float*/ 0," << endl; - s << INDENT << "#else" << endl; - s << INDENT << "/*nb_long*/ " << cpythonName << "_long," << endl; - s << INDENT << "/*nb_float*/ 0," << endl; - s << INDENT << "/*nb_oct*/ 0," << endl; - s << INDENT << "/*nb_hex*/ 0," << endl; - s << INDENT << "#endif" << endl; - s << INDENT << "/*nb_inplace_add*/ 0," << endl; - s << INDENT << "/*nb_inplace_subtract*/ 0," << endl; - s << INDENT << "/*nb_inplace_multiply*/ 0," << endl; - s << INDENT << "#ifndef IS_PY3K" << endl; - s << INDENT << "/*nb_inplace_divide*/ 0," << endl; - s << INDENT << "#endif" << endl; - s << INDENT << "/*nb_inplace_remainder*/ 0," << endl; - s << INDENT << "/*nb_inplace_power*/ 0," << endl; - s << INDENT << "/*nb_inplace_lshift*/ 0," << endl; - s << INDENT << "/*nb_inplace_rshift*/ 0," << endl; - s << INDENT << "/*nb_inplace_and*/ 0," << endl; - s << INDENT << "/*nb_inplace_xor*/ 0," << endl; - s << INDENT << "/*nb_inplace_or*/ 0," << endl; - s << INDENT << "/*nb_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_true_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl; - s << INDENT << "/*nb_index*/ 0" << endl; - s << "};" << endl << endl; -} - -void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - Q_ASSERT(flagsEntry); - - s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl; - s << '{' << endl; - - AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); - s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " CPP_SELF_VAR ", cppArg;" << endl; - s << "#ifdef IS_PY3K" << endl; - s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_SELF_VAR ");" << endl; - s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_ARG ");" << endl; - s << "#else" << endl; - s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_SELF_VAR ");" << endl; - s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_ARG ");" << endl; - s << "#endif" << endl << endl; - s << INDENT << "cppResult = " CPP_SELF_VAR " " << cppOpName << " cppArg;" << endl; - s << INDENT << "return "; - writeToPythonConversion(s, flagsType, 0, QLatin1String("cppResult")); - s << ';' << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName, bool boolResult) -{ - FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); - Q_ASSERT(flagsEntry); - - s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl; - s << '{' << endl; - - AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); - s << INDENT << "::" << flagsEntry->originalName() << " " CPP_SELF_VAR ";" << endl; - s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &" CPP_SELF_VAR ");" << endl; - s << INDENT; - if (boolResult) - s << "bool"; - else - s << "::" << flagsEntry->originalName(); - s << " cppResult = " << cppOpName << CPP_SELF_VAR ";" << endl; - s << INDENT << "return "; - if (boolResult) - s << "PyBool_FromLong(cppResult)"; - else - writeToPythonConversion(s, flagsType, 0, QLatin1String("cppResult")); - s << ';' << endl; - s << '}' << endl << endl; -} - -QString CppGenerator::getInitFunctionName(GeneratorContext &context) const -{ - QString initFunctionName; - if (!context.forSmartPointer()) { - initFunctionName = context.metaClass()->qualifiedCppName(); - initFunctionName.replace(QLatin1String("::"), QLatin1String("_")); - } else { - initFunctionName = getFilteredCppSignatureString(context.preciseType()->cppSignature()); - } - return initFunctionName; -} - -void CppGenerator::writeClassRegister(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &classContext) -{ - const ComplexTypeEntry* classTypeEntry = metaClass->typeEntry(); - - const AbstractMetaClass* enc = metaClass->enclosingClass(); - bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; - QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module"); - - QString pyTypeName = cpythonTypeName(metaClass); - QString initFunctionName = getInitFunctionName(classContext); - s << "void init_" << initFunctionName; - s << "(PyObject* " << enclosingObjectVariable << ")" << endl; - s << '{' << endl; - - if (supportsNumberProtocol(metaClass)) { - s << INDENT << "// type has number operators" << endl; - writeTypeAsNumberDefinition(s, metaClass); - s << INDENT << pyTypeName << ".super.ht_type.tp_as_number = &" << pyTypeName << "AsNumber;" << endl; - s << endl; - } - - if (supportsSequenceProtocol(metaClass)) { - s << INDENT << "// type supports sequence protocol" << endl; - writeTypeAsSequenceDefinition(s, metaClass); - s << INDENT << pyTypeName << ".super.ht_type.tp_as_sequence = &" << pyTypeName << "AsSequence;" << endl; - s << endl; - } - - if (supportsMappingProtocol(metaClass)) { - s << INDENT << "// type supports mapping protocol" << endl; - writeTypeAsMappingDefinition(s, metaClass); - s << INDENT << pyTypeName << ".super.ht_type.tp_as_mapping = &" << pyTypeName << "AsMapping;" << endl; - s << endl; - } - - if (!classContext.forSmartPointer()) - s << INDENT << cpythonTypeNameExt(classTypeEntry); - else - s << INDENT << cpythonTypeNameExt(classContext.preciseType()); - - s << " = reinterpret_cast(&" << pyTypeName << ");" << endl; - s << endl; - - // Multiple inheritance - QString pyTypeBasesVariable = pyTypeName + QLatin1String("_bases"); - const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); - if (metaClass->baseClassNames().size() > 1) { - s << INDENT << "PyObject* " << pyTypeBasesVariable << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl; - QStringList bases; - for (const AbstractMetaClass *base : baseClasses) - bases << QLatin1String("(PyObject*)") + cpythonTypeNameExt(base->typeEntry()); - Indentation indent(INDENT); - QString separator; - QTextStream sep(&separator); - sep << "," << endl << INDENT; - s << INDENT << bases.join(separator) << ");" << endl << endl; - } - - // Create type and insert it in the module or enclosing class. - s << INDENT << "if (!Shiboken::ObjectType::introduceWrapperType(" << enclosingObjectVariable; - QString typeName; - if (!classContext.forSmartPointer()) - typeName = metaClass->name(); - else - typeName = classContext.preciseType()->cppSignature(); - - s << ", \"" << typeName << "\", \""; - - // Original name - if (!classContext.forSmartPointer()) - s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : ""); - else - s << classContext.preciseType()->cppSignature(); - - s << "\"," << endl; - { - Indentation indent(INDENT); - s << INDENT << "&" << pyTypeName; - - // Set destructor function - if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { - QString dtorClassName = metaClass->qualifiedCppName(); - if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue()) - dtorClassName = wrapperName(metaClass); - if (classContext.forSmartPointer()) - dtorClassName = wrapperName(classContext.preciseType()); - - s << ", &Shiboken::callCppDestructor< ::" << dtorClassName << " >"; - } else if (metaClass->baseClass() || hasEnclosingClass) { - s << ", 0"; - } - - // Base type - if (metaClass->baseClass()) { - s << ", reinterpret_cast(" << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ')'; - // The other base types - if (metaClass->baseClassNames().size() > 1) - s << ", " << pyTypeBasesVariable; - else if (hasEnclosingClass) - s << ", 0"; - } else if (hasEnclosingClass) { - s << ", 0, 0"; - } - if (hasEnclosingClass) - s << ", true"; - s << ")) {" << endl; - s << INDENT << "return;" << endl; - } - s << INDENT << '}' << endl << endl; - - // Register conversions for the type. - writeConverterRegister(s, metaClass, classContext); - s << endl; - - // class inject-code target/beginning - if (!classTypeEntry->codeSnips().isEmpty()) { - writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, metaClass); - s << endl; - } - - // Fill multiple inheritance data, if needed. - const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); - if (miClass) { - s << INDENT << "MultipleInheritanceInitFunction func = "; - if (miClass == metaClass) { - s << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl; - } else { - s << "Shiboken::ObjectType::getMultipleIheritanceFunction(reinterpret_cast("; - s << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; - } - s << INDENT << "Shiboken::ObjectType::setMultipleIheritanceFunction(&"; - s << cpythonTypeName(metaClass) << ", func);" << endl; - s << INDENT << "Shiboken::ObjectType::setCastFunction(&" << cpythonTypeName(metaClass); - s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; - } - - // Set typediscovery struct or fill the struct of another one - if (metaClass->isPolymorphic() && metaClass->baseClass()) { - s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(&" << cpythonTypeName(metaClass); - s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl << endl; - } - - AbstractMetaEnumList classEnums = metaClass->enums(); - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); - - ErrorCode errorCode(QString::null); - writeEnumsInitialization(s, classEnums); - - if (metaClass->hasSignals()) - writeSignalInitialization(s, metaClass); - - // Write static fields - const AbstractMetaFieldList &fields = metaClass->fields(); - for (const AbstractMetaField *field : fields) { - if (!field->isStatic()) - continue; - s << INDENT << QLatin1String("PyDict_SetItemString(") + cpythonTypeName(metaClass) + QLatin1String(".super.ht_type.tp_dict, \""); - s << field->name() << "\", "; - writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name()); - s << ");" << endl; - } - s << endl; - - // class inject-code target/end - if (!classTypeEntry->codeSnips().isEmpty()) { - s << endl; - writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, metaClass); - } - - if (usePySideExtensions()) { - if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass)) - s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n"; - else - writeInitQtMetaTypeFunctionBody(s, classContext); - } - - if (usePySideExtensions() && metaClass->isQObject()) { - s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(&" << pyTypeName << ", &PySide::initQObjectSubType);" << endl; - s << INDENT << "PySide::initDynamicMetaObject(&" << pyTypeName << ", &::" << metaClass->qualifiedCppName() - << "::staticMetaObject, sizeof(::" << metaClass->qualifiedCppName() << "));" << endl; - } - - s << '}' << endl; -} - -void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const -{ - const AbstractMetaClass* metaClass = context.metaClass(); - // Gets all class name variants used on different possible scopes - QStringList nameVariants; - if (!context.forSmartPointer()) - nameVariants << metaClass->name(); - else - nameVariants << context.preciseType()->cppSignature(); - - const AbstractMetaClass* enclosingClass = metaClass->enclosingClass(); - while (enclosingClass) { - if (enclosingClass->typeEntry()->generateCode()) - nameVariants << (enclosingClass->name() + QLatin1String("::") + nameVariants.last()); - enclosingClass = enclosingClass->enclosingClass(); - } - - QString className; - if (!context.forSmartPointer()) - className = metaClass->qualifiedCppName(); - else - className = context.preciseType()->cppSignature(); - - if (!metaClass->isNamespace() && !metaClass->isAbstract()) { - // Qt metatypes are registered only on their first use, so we do this now. - bool canBeValue = false; - if (!isObjectType(metaClass)) { - // check if there's a empty ctor - const AbstractMetaFunctionList &funcs = metaClass->functions(); - for (AbstractMetaFunction *func : funcs) { - if (func->isConstructor() && !func->arguments().count()) { - canBeValue = true; - break; - } - } - } - - if (canBeValue) { - for (const QString &name : qAsConst(nameVariants)) { - if (name == QLatin1String("iterator")) { - qCWarning(lcShiboken).noquote().nospace() - << QString::fromLatin1("%1:%2 FIXME:\n" - " The code tried to qRegisterMetaType the unqualified name " - "'iterator'. This is currently fixed by a hack(ct) and needs improvement!") - .arg(QFile::decodeName(__FILE__)).arg(__LINE__); - continue; - } - s << INDENT << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");" << endl; - } - } - } - - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum *metaEnum : enums) { - if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) { - for (const QString &name : qAsConst(nameVariants)) - s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");" << endl; - - if (metaEnum->typeEntry()->flags()) { - QString n = metaEnum->typeEntry()->flags()->originalName(); - s << INDENT << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");" << endl; - } - } - } -} - -void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); - - s << "static void* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl; - - if (!polymorphicExpr.isEmpty()) { - polymorphicExpr = polymorphicExpr.replace(QLatin1String("%1"), - QLatin1String(" reinterpret_cast< ::") - + metaClass->qualifiedCppName() - + QLatin1String("*>(cptr)")); - s << INDENT << " if (" << polymorphicExpr << ")" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return cptr;" << endl; - } - } else if (metaClass->isPolymorphic()) { - const AbstractMetaClassList &ancestors = getAllAncestors(metaClass); - for (AbstractMetaClass *ancestor : ancestors) { - if (ancestor->baseClass()) - continue; - if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType< ::" - << ancestor->qualifiedCppName() << " >()))" << endl; - Indentation indent(INDENT); - s << INDENT << "return dynamic_cast< ::" << metaClass->qualifiedCppName() - << "*>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << "*>(cptr));" << endl; - } else { - qCWarning(lcShiboken).noquote().nospace() - << metaClass->qualifiedCppName() << " inherits from a non polymorphic type (" - << ancestor->qualifiedCppName() << "), type discovery based on RTTI is " - "impossible, write a polymorphic-id-expression for this type."; - } - - } - } - s << INDENT << "return 0;" << endl; - s << "}\n\n"; -} - -QString CppGenerator::writeSmartPointerGetterCast() { - return QLatin1String("const_cast(" SMART_POINTER_GETTER ")"); -} - -void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass* metaClass = context.metaClass(); - s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name, PyObject* value)" << endl; - s << '{' << endl; - if (usePySideExtensions()) { - s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast(PySide::Property::getObject(" PYTHON_SELF_VAR ", name)));" << endl; - s << INDENT << "if (!pp.isNull())" << endl; - Indentation indent(INDENT); - s << INDENT << "return PySide::Property::setValue(reinterpret_cast(pp.object()), " PYTHON_SELF_VAR ", value);" << endl; - } - - if (context.forSmartPointer()) { - s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer." << endl; - s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", " - << writeSmartPointerGetterCast() << ", 0);" << endl; - s << INDENT << "if (rawObj) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "int hasAttribute = PyObject_HasAttr(rawObj, name);" << endl; - s << INDENT << "if (hasAttribute) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return PyObject_GenericSetAttr(rawObj, name, value);" << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "Py_DECREF(rawObj);" << endl; - } - s << INDENT << '}' << endl; - - } - - s << INDENT << "return PyObject_GenericSetAttr(" PYTHON_SELF_VAR ", name, value);" << endl; - s << '}' << endl; -} - -static inline QString qObjectClassName() { return QStringLiteral("QObject"); } -static inline QString qMetaObjectClassName() { return QStringLiteral("QMetaObject"); } - -void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &context) -{ - const AbstractMetaClass* metaClass = context.metaClass(); - s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name)" << endl; - s << '{' << endl; - - QString getattrFunc; - if (usePySideExtensions() && metaClass->isQObject()) { - AbstractMetaClass *qobjectClass = AbstractMetaClass::findClass(classes(), qObjectClassName()); - getattrFunc = QString::fromLatin1("PySide::getMetaDataFromQObject(%1, " PYTHON_SELF_VAR ", name)") - .arg(cpythonWrapperCPtr(qobjectClass, QLatin1String(PYTHON_SELF_VAR))); - } else { - getattrFunc = QLatin1String("PyObject_GenericGetAttr(" PYTHON_SELF_VAR ", name)"); - } - - if (classNeedsGetattroFunction(metaClass)) { - s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "// Search the method in the instance dict" << endl; - s << INDENT << "if (reinterpret_cast(" PYTHON_SELF_VAR ")->ob_dict) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast(" PYTHON_SELF_VAR ")->ob_dict, name);" << endl; - s << INDENT << "if (meth) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "Py_INCREF(meth);" << endl; - s << INDENT << "return meth;" << endl; - } - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "// Search the method in the type dict" << endl; - s << INDENT << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ")) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* meth = PyDict_GetItem(" PYTHON_SELF_VAR "->ob_type->tp_dict, name);" << endl; - s << INDENT << "if (meth)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, " PYTHON_SELF_VAR ") : " << getattrFunc << ';' << endl; - } - } - s << INDENT << '}' << endl; - - const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass); - for (const AbstractMetaFunction *func : funcs) { - QString defName = cpythonMethodDefinitionName(func); - s << INDENT << "static PyMethodDef non_static_" << defName << " = {" << endl; - { - Indentation indent(INDENT); - s << INDENT << defName << ".ml_name," << endl; - s << INDENT << defName << ".ml_meth," << endl; - s << INDENT << defName << ".ml_flags & (~METH_STATIC)," << endl; - s << INDENT << defName << ".ml_doc," << endl; - } - s << INDENT << "};" << endl; - s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)" << endl; - Indentation indent(INDENT); - s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", " PYTHON_SELF_VAR ", 0);" << endl; - } - } - s << INDENT << '}' << endl; - } - - if (context.forSmartPointer()) { - s << INDENT << "PyObject *tmp = " << getattrFunc << ';' << endl; - s << INDENT << "if (tmp) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return tmp;" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL;" << endl; - s << INDENT << "PyErr_Clear();" << endl; - - s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for " - "the corresponding C++ object held by the smart pointer." << endl; - s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", " - << writeSmartPointerGetterCast() << ", 0);" << endl; - s << INDENT << "if (rawObj) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject *attribute = PyObject_GetAttr(rawObj, name);" << endl; - s << INDENT << "if (attribute) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "tmp = attribute;" << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "Py_DECREF(rawObj);" << endl; - } - s << INDENT << '}' << endl; - s << INDENT << "if (!tmp) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl; - s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl; - s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl; - s << INDENT << " tp->tp_name, PyBytes_AS_STRING(name));" << endl; - s << INDENT << "return NULL;" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return tmp;" << endl; - } - s << INDENT << '}' << endl; - - } - s << INDENT << '}' << endl; - - } else { - s << INDENT << "return " << getattrFunc << ';' << endl; - } - s << '}' << endl; -} - -bool CppGenerator::finishGeneration() -{ - //Generate CPython wrapper file - QString classInitDecl; - QTextStream s_classInitDecl(&classInitDecl); - QString classPythonDefines; - QTextStream s_classPythonDefines(&classPythonDefines); - - QSet includes; - QString globalFunctionImpl; - QTextStream s_globalFunctionImpl(&globalFunctionImpl); - QString globalFunctionDecl; - QTextStream s_globalFunctionDef(&globalFunctionDecl); - - Indentation indent(INDENT); - - const FunctionGroupMap &functionGroups = getFunctionGroups(); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - AbstractMetaFunctionList overloads; - for (AbstractMetaFunction *func : it.value()) { - if (!func->isModifiedRemoved()) { - overloads.append(func); - if (func->typeEntry()) - includes << func->typeEntry()->include(); - } - } - - if (overloads.isEmpty()) - continue; - - // Dummy context to satisfy the API. - GeneratorContext classContext; - writeMethodWrapper(s_globalFunctionImpl, overloads, classContext); - writeMethodDefinition(s_globalFunctionDef, overloads); - } - - //this is a temporary solution before new type revison implementation - //We need move QMetaObject register before QObject - Dependencies additionalDependencies; - const AbstractMetaClassList &allClasses = classes(); - if (AbstractMetaClass::findClass(allClasses, qObjectClassName()) != Q_NULLPTR - && AbstractMetaClass::findClass(allClasses, qMetaObjectClassName()) != Q_NULLPTR) { - Dependency dependency; - dependency.parent = qMetaObjectClassName(); - dependency.child = qObjectClassName(); - additionalDependencies.append(dependency); - } - const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); - - for (const AbstractMetaClass *cls : lst){ - if (!shouldGenerate(cls)) - continue; - - s_classInitDecl << "void init_" << cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")) << "(PyObject* module);" << endl; - - QString defineStr = QLatin1String("init_") + cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")); - - if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) - defineStr += QLatin1Char('(') + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) + QLatin1String("->tp_dict);"); - else - defineStr += QLatin1String("(module);"); - s_classPythonDefines << INDENT << defineStr << endl; - } - - // Initialize smart pointer types. - const QVector &smartPtrs = instantiatedSmartPointers(); - for (const AbstractMetaType *metaType : smartPtrs) { - GeneratorContext context(0, metaType, true); - QString initFunctionName = getInitFunctionName(context); - s_classInitDecl << "void init_" << initFunctionName << "(PyObject* module);" << endl; - QString defineStr = QLatin1String("init_") + initFunctionName; - defineStr += QLatin1String("(module);"); - s_classPythonDefines << INDENT << defineStr << endl; - } - - QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName())); - moduleFileName += QLatin1Char('/') + moduleName().toLower() + QLatin1String("_module_wrapper.cpp"); - - QFile file(moduleFileName); - verifyDirectoryFor(file); - if (!file.open(QFile::WriteOnly)) { - qCWarning(lcShiboken).noquote().nospace() - << "Error writing file: " << QDir::toNativeSeparators(moduleFileName); - return false; - } - - QTextStream s(&file); - - // write license comment - s << licenseComment() << endl; - - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - if (usePySideExtensions()) { - s << includeQDebug; - s << "#include " << endl; - } - - s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; - for (const Include &include : qAsConst(includes)) - s << include; - s << endl; - - // Global enums - AbstractMetaEnumList globalEnums = this->globalEnums(); - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) { - const AbstractMetaClass* encClass = metaClass->enclosingClass(); - if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - continue; - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); - } - - TypeDatabase* typeDb = TypeDatabase::instance(); - TypeSystemTypeEntry* moduleEntry = reinterpret_cast(typeDb->findType(packageName())); - - //Extra includes - s << endl << "// Extra includes" << endl; - QVector extraIncludes; - if (moduleEntry) - extraIncludes = moduleEntry->extraIncludes(); - for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) - extraIncludes.append(cppEnum->typeEntry()->extraIncludes()); - qSort(extraIncludes.begin(), extraIncludes.end()); - for (const Include &inc : qAsConst(extraIncludes)) - s << inc; - s << endl; - - s << "// Current module's type array." << endl; - s << "PyTypeObject** " << cppApiVariableName() << ';' << endl; - - s << "// Current module's converter array." << endl; - s << "SbkConverter** " << convertersVariableName() << ';' << endl; - - CodeSnipList snips; - if (moduleEntry) - snips = moduleEntry->codeSnips(); - - // module inject-code native/beginning - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode); - s << endl; - } - - // cleanup staticMetaObject attribute - if (usePySideExtensions()) { - s << "void cleanTypesAttributes(void) {" << endl; - s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "PyObject *pyType = reinterpret_cast(" << cppApiVariableName() << "[i]);" << endl; - s << INDENT << "if (pyType && PyObject_HasAttrString(pyType, \"staticMetaObject\"))"<< endl; - { - Indentation indentation(INDENT); - s << INDENT << "PyObject_SetAttrString(pyType, \"staticMetaObject\", Py_None);" << endl; - } - } - s << INDENT << "}" << endl; - s << "}" << endl; - } - - s << "// Global functions "; - s << "------------------------------------------------------------" << endl; - s << globalFunctionImpl << endl; - - s << "static PyMethodDef " << moduleName() << "_methods[] = {" << endl; - s << globalFunctionDecl; - s << INDENT << "{0} // Sentinel" << endl << "};" << endl << endl; - - s << "// Classes initialization functions "; - s << "------------------------------------------------------------" << endl; - s << classInitDecl << endl; - - if (!globalEnums.isEmpty()) { - QString converterImpl; - QTextStream convImpl(&converterImpl); - - s << "// Enum definitions "; - s << "------------------------------------------------------------" << endl; - for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - writeEnumConverterFunctions(s, cppEnum); - s << endl; - } - - if (!converterImpl.isEmpty()) { - s << "// Enum converters "; - s << "------------------------------------------------------------" << endl; - s << "namespace Shiboken" << endl << '{' << endl; - s << converterImpl << endl; - s << "} // namespace Shiboken" << endl << endl; - } - } - - const QStringList &requiredModules = typeDb->requiredTargetImports(); - if (!requiredModules.isEmpty()) - s << "// Required modules' type and converter arrays." << endl; - for (const QString &requiredModule : requiredModules) { - s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ';' << endl; - s << "SbkConverter** " << convertersVariableName(requiredModule) << ';' << endl; - } - s << endl; - - s << "// Module initialization "; - s << "------------------------------------------------------------" << endl; - ExtendedConverterData extendedConverters = getExtendedConverters(); - if (!extendedConverters.isEmpty()) { - s << endl << "// Extended Converters." << endl << endl; - for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { - const TypeEntry *externalType = it.key(); - s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; - for (const AbstractMetaClass *sourceClass : it.value()) { - AbstractMetaType* sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass); - AbstractMetaType* targetType = buildAbstractMetaTypeFromTypeEntry(externalType); - writePythonToCppConversionFunctions(s, sourceType, targetType); - } - } - } - - const QVector &typeConversions = getPrimitiveCustomConversions(); - if (!typeConversions.isEmpty()) { - s << endl << "// Primitive Type converters." << endl << endl; - for (const CustomConversion *conversion : typeConversions) { - s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl; - writeCppToPythonFunction(s, conversion); - writeCustomConverterFunctions(s, conversion); - } - s << endl; - } - - const QVector &containers = instantiatedContainers(); - if (!containers.isEmpty()) { - s << "// Container Type converters." << endl << endl; - for (const AbstractMetaType *container : containers) { - s << "// C++ to Python conversion for type '" << container->cppSignature() << "'." << endl; - writeContainerConverterFunctions(s, container); - } - s << endl; - } - - s << "#if defined _WIN32 || defined __CYGWIN__" << endl; - s << " #define SBK_EXPORT_MODULE __declspec(dllexport)" << endl; - s << "#elif __GNUC__ >= 4" << endl; - s << " #define SBK_EXPORT_MODULE __attribute__ ((visibility(\"default\")))" << endl; - s << "#else" << endl; - s << " #define SBK_EXPORT_MODULE" << endl; - s << "#endif" << endl << endl; - - s << "#ifdef IS_PY3K" << endl; - s << "static struct PyModuleDef moduledef = {" << endl; - s << " /* m_base */ PyModuleDef_HEAD_INIT," << endl; - s << " /* m_name */ \"" << moduleName() << "\"," << endl; - s << " /* m_doc */ 0," << endl; - s << " /* m_size */ -1," << endl; - s << " /* m_methods */ " << moduleName() << "_methods," << endl; - s << " /* m_reload */ 0," << endl; - s << " /* m_traverse */ 0," << endl; - s << " /* m_clear */ 0," << endl; - s << " /* m_free */ 0" << endl; - s << "};" << endl << endl; - s << "#endif" << endl; - s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")" << endl; - - ErrorCode errorCode(QLatin1String("SBK_MODULE_INIT_ERROR")); - // module inject-code target/beginning - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode); - s << endl; - } - - for (const QString& requiredModule : requiredModules) { - s << INDENT << "{" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));" << endl; - s << INDENT << "if (requiredModule.isNull())" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "return SBK_MODULE_INIT_ERROR;" << endl; - } - s << INDENT << cppApiVariableName(requiredModule) << " = Shiboken::Module::getTypes(requiredModule);" << endl; - s << INDENT << convertersVariableName(requiredModule) << " = Shiboken::Module::getTypeConverters(requiredModule);" << endl; - } - s << INDENT << "}" << endl << endl; - } - - int maxTypeIndex = getMaxTypeIndex() + instantiatedSmartPointers().size(); - if (maxTypeIndex) { - s << INDENT << "// Create an array of wrapper types for the current module." << endl; - s << INDENT << "static PyTypeObject* cppApi[SBK_" << moduleName() << "_IDX_COUNT];" << endl; - s << INDENT << cppApiVariableName() << " = cppApi;" << endl << endl; - } - - s << INDENT << "// Create an array of primitive type converters for the current module." << endl; - s << INDENT << "static SbkConverter* sbkConverters[SBK_" << moduleName() << "_CONVERTERS_IDX_COUNT" << "];" << endl; - s << INDENT << convertersVariableName() << " = sbkConverters;" << endl << endl; - - s << "#ifdef IS_PY3K" << endl; - s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", &moduledef);" << endl; - s << "#else" << endl; - s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", "; - s << moduleName() << "_methods);" << endl; - s << "#endif" << endl << endl; - - //s << INDENT << "// Initialize converters for primitive types." << endl; - //s << INDENT << "initConverters();" << endl << endl; - - s << INDENT << "// Initialize classes in the type system" << endl; - s << classPythonDefines; - - if (!typeConversions.isEmpty()) { - s << endl; - for (const CustomConversion *conversion : typeConversions) { - writePrimitiveConverterInitialization(s, conversion); - s << endl; - } - } - - if (!containers.isEmpty()) { - s << endl; - for (const AbstractMetaType *container : containers) { - writeContainerConverterInitialization(s, container); - s << endl; - } - } - - if (!extendedConverters.isEmpty()) { - s << endl; - for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { - writeExtendedConverterInitialization(s, it.key(), it.value()); - s << endl; - } - } - - writeEnumsInitialization(s, globalEnums); - - s << INDENT << "// Register primitive types converters." << endl; - const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); - for (const PrimitiveTypeEntry *pte : primitiveTypeList) { - if (!pte->generateCode() || !pte->isCppPrimitive()) - continue; - const TypeEntry *referencedType = pte->basicReferencedTypeEntry(); - if (!referencedType) - continue; - QString converter = converterObject(referencedType); - QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); - while (!cppSignature.isEmpty()) { - QString signature = cppSignature.join(QLatin1String("::")); - s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");" << endl; - cppSignature.removeFirst(); - } - } - // Register type resolver for all containers found in signals. - QSet typeResolvers; - - for (AbstractMetaClass *metaClass : classList) { - if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode()) - continue; - const AbstractMetaFunctionList &functions = metaClass->functions(); - for (AbstractMetaFunction *func : functions) { - if (func->isSignal()) { - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - if (arg->type()->isContainer()) { - QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference); - if (value.startsWith(QLatin1String("::"))) - value.remove(0, 2); - typeResolvers << QMetaObject::normalizedType(value.toUtf8().constData()); - } - } - } - } - } - - s << endl; - if (maxTypeIndex) - s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");" << endl; - s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");" << endl; - - s << endl << INDENT << "if (PyErr_Occurred()) {" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");" << endl; - } - s << INDENT << '}' << endl; - - // module inject-code target/end - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode); - s << endl; - } - - // module inject-code native/end - if (!snips.isEmpty()) { - writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode); - s << endl; - } - - if (usePySideExtensions()) { - for (AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) - if (!metaEnum->isAnonymous()) { - s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");" << endl; - } - - // cleanup staticMetaObject attribute - s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl; - } - - s << "SBK_MODULE_INIT_FUNCTION_END" << endl; - - return true; -} - -static ArgumentOwner getArgumentOwner(const AbstractMetaFunction* func, int argIndex) -{ - ArgumentOwner argOwner = func->argumentOwner(func->ownerClass(), argIndex); - if (argOwner.index == ArgumentOwner::InvalidIndex) - argOwner = func->argumentOwner(func->declaringClass(), argIndex); - return argOwner; -} - -bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy) -{ - const int numArgs = func->arguments().count(); - bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy; - - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this)); - - ArgumentOwner argOwner = getArgumentOwner(func, argIndex); - ArgumentOwner::Action action = argOwner.action; - int parentIndex = argOwner.index; - int childIndex = argIndex; - if (ctorHeuristicEnabled && argIndex > 0 && numArgs) { - AbstractMetaArgument* arg = func->arguments().at(argIndex-1); - if (arg->name() == QLatin1String("parent") && isObjectType(arg->type())) { - action = ArgumentOwner::Add; - parentIndex = argIndex; - childIndex = -1; - } - } - - QString parentVariable; - QString childVariable; - if (action != ArgumentOwner::Invalid) { - if (!usePyArgs && argIndex > 1) - qCWarning(lcShiboken).noquote().nospace() - << "Argument index for parent tag out of bounds: " << func->signature(); - - if (action == ArgumentOwner::Remove) { - parentVariable = QLatin1String("Py_None"); - } else { - if (parentIndex == 0) { - parentVariable = QLatin1String(PYTHON_RETURN_VAR); - } else if (parentIndex == -1) { - parentVariable = QLatin1String(PYTHON_SELF_VAR); - } else { - parentVariable = usePyArgs - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(parentIndex - 1) - : QLatin1String(PYTHON_ARG); - } - } - - if (childIndex == 0) { - childVariable = QLatin1String(PYTHON_RETURN_VAR); - } else if (childIndex == -1) { - childVariable = QLatin1String(PYTHON_SELF_VAR); - } else { - childVariable = usePyArgs - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(childIndex - 1) - : QLatin1String(PYTHON_ARG); - } - - s << INDENT << "Shiboken::Object::setParent(" << parentVariable << ", " << childVariable << ");\n"; - return true; - } - - return false; -} - -void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn) -{ - const int numArgs = func->arguments().count(); - - // -1 = return value - // 0 = self - // 1..n = func. args. - for (int i = -1; i <= numArgs; ++i) - writeParentChildManagement(s, func, i, useHeuristicForReturn); - - if (useHeuristicForReturn) - writeReturnValueHeuristics(s, func); -} - -void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self) -{ - AbstractMetaType *type = func->type(); - if (!useReturnValueHeuristic() - || !func->ownerClass() - || !type - || func->isStatic() - || func->isConstructor() - || !func->typeReplaced(0).isEmpty()) { - return; - } - - ArgumentOwner argOwner = getArgumentOwner(func, ArgumentOwner::ReturnIndex); - if (argOwner.action == ArgumentOwner::Invalid || argOwner.index != ArgumentOwner::ThisIndex) { - if (isPointerToWrapperType(type)) - s << INDENT << "Shiboken::Object::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; - } -} - -void CppGenerator::writeHashFunction(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject* self) {" << endl; - writeCppSelfDefinition(s, context); - s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '('; - s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");" << endl; - s << '}' << endl << endl; -} - -void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - ErrorCode errorCode(0); - - // __len__ - s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* " PYTHON_SELF_VAR ")" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, context); - s << INDENT << "return " CPP_SELF_VAR "->size();" << endl; - s << '}' << endl; - - // __getitem__ - s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i)" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, context); - writeIndexError(s, QLatin1String("index out of bounds")); - - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl; - s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl; - - const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().first(); - - s << INDENT << "return "; - writeToPythonConversion(s, itemType, metaClass, QLatin1String("*_item")); - s << ';' << endl; - s << '}' << endl; - - // __setitem__ - ErrorCode errorCode2(-1); - s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* pyArg)" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, context); - writeIndexError(s, QLatin1String("list assignment index out of range")); - - s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl; - s << INDENT << "if (!"; - writeTypeCheck(s, itemType, QLatin1String("pyArg"), isNumber(itemType->typeEntry())); - s << ") {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_TypeError, \"attributed value with wrong type, '"; - s << itemType->name() << "' or other convertible type expected\");" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << '}' << endl; - writeArgumentConversion(s, itemType, QLatin1String("cppValue"), QLatin1String("pyArg"), metaClass); - - s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl; - s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl; - s << INDENT << "*_item = cppValue;" << endl; - s << INDENT << "return 0;" << endl; - s << '}' << endl; -} -void CppGenerator::writeIndexError(QTextStream& s, const QString& errorMsg) -{ - s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " CPP_SELF_VAR "->size()) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << '}' << endl; -} - -QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &context) -{ - const AbstractMetaClass *metaClass = context.metaClass(); - QString funcName = cpythonBaseName(metaClass) + QLatin1String("__repr__"); - s << "extern \"C\"" << endl; - s << '{' << endl; - s << "static PyObject* " << funcName << "(PyObject* self)" << endl; - s << '{' << endl; - writeCppSelfDefinition(s, context); - s << INDENT << "QBuffer buffer;" << endl; - s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl; - s << INDENT << "QDebug dbg(&buffer);" << endl; - s << INDENT << "dbg << " << (metaClass->typeEntry()->isValue() ? "*" : "") << CPP_SELF_VAR ";" << endl; - s << INDENT << "buffer.close();" << endl; - s << INDENT << "QByteArray str = buffer.data();" << endl; - s << INDENT << "int idx = str.indexOf('(');" << endl; - s << INDENT << "if (idx >= 0)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl; - } - s << INDENT << "PyObject* mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl; - s << INDENT << "if (mod)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);" << endl; - } - s << INDENT << "else" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);" << endl; - } - s << '}' << endl; - s << "} // extern C" << endl << endl;; - return funcName; -} diff --git a/generator/shiboken2/cppgenerator.h b/generator/shiboken2/cppgenerator.h deleted file mode 100644 index c3ca48307..000000000 --- a/generator/shiboken2/cppgenerator.h +++ /dev/null @@ -1,370 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CPPGENERATOR_H -#define CPPGENERATOR_H - -#include "shibokengenerator.h" - -/** - * The CppGenerator generate the implementations of C++ bindings classes. - */ -class CppGenerator : public ShibokenGenerator -{ -public: - CppGenerator(); -protected: - QString fileNamePrefix() const override; - QString fileNameForContext(GeneratorContext &context) const override; - QVector filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, - uint query); - void generateClass(QTextStream& s, GeneratorContext &classContext) override; - bool finishGeneration() override; - -private: - void writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func); - void writeDestructorNative(QTextStream& s, const AbstractMetaClass* metaClass); - - QString getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func); - void writeVirtualMethodNative(QTextStream& s, const AbstractMetaFunction* func); - - void writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType); - void writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum); - void writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext); - void writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion); - void writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, - GeneratorContext &classContext); - void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar); - void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar); - - void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType); - - void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, - GeneratorContext &context); - void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, GeneratorContext &classContext); - void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, - GeneratorContext &classContext); - void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData); - void writeCppSelfDefinition(QTextStream &s, - const AbstractMetaFunction *func, - GeneratorContext &context, - bool hasStaticOverload = false); - void writeCppSelfDefinition(QTextStream &s, - GeneratorContext &context, - bool hasStaticOverload = false, - bool cppSelfAsReference = false); - - void writeErrorSection(QTextStream& s, OverloadData& overloadData); - void writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue = true); - - /// Writes the check section for the validity of wrapped C++ objects. - void writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj); - - void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = QString(), bool rejectNull = false); - void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName); - - void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeSetattroFunction(QTextStream &s, GeneratorContext &context); - void writeGetattroFunction(QTextStream &s, GeneratorContext &context); - QString writeSmartPointerGetterCast(); - - /** - * Writes Python to C++ conversions for arguments on Python wrappers. - * If implicit conversions, and thus new object allocation, are needed, - * code to deallocate a possible new instance is also generated. - * \param s text stream to write - * \param argType a pointer to the argument type to be converted - * \param argName C++ argument name - * \param pyArgName Python argument name - * \param context the current meta class - * \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(QTextStream& s, const AbstractMetaType* argType, - const QString& argName, const QString& pyArgName, - const AbstractMetaClass* context = 0, - const QString& defaultValue = QString(), - bool castArgumentAsUnused = false); - - /** - * Returns the AbstractMetaType for a function argument. - * If the argument type was modified in the type system, this method will - * try to build a new type based on the type name defined in the type system. - * \param func The function which owns the argument. - * \param argPos Argument position in the function signature. - * Note that the position 0 represents the return value, and the function - * parameters start counting on 1. - * \param newType It is set to true if the type returned is a new object that must be deallocated. - * \return The type of the argument indicated by \p argPos. - */ - const AbstractMetaType* getArgumentType(const AbstractMetaFunction* func, int argPos); - - void writePythonToCppTypeConversion(QTextStream& s, - const AbstractMetaType* type, - const QString& pyIn, - const QString& cppOut, - const AbstractMetaClass* context = 0, - const QString& defaultValue = QString()); - - /// Writes the conversion rule for arguments of regular and virtual methods. - void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language); - /// Writes the conversion rule for the return value of a method. - void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar); - - /** - * Set the Python method wrapper return value variable to Py_None if - * there are return types different from void in any of the other overloads - * for the function passed as parameter. - * \param s text stream to write - * \param func a pointer to the function that will possibly return Py_None - * \param thereIsReturnValue indicates if the return type of any of the other overloads - * for this function is different from 'void' - */ - void writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue); - - /** - * Writes the Python function wrapper overload decisor that selects which C++ - * method/function to call with the received Python arguments. - * \param s text stream to write - * \param overloadData the overload data describing all the possible overloads for the function/method - */ - void writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData); - /// Recursive auxiliar method to the other writeOverloadedFunctionDecisor. - void writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData); - - /// Writes calls to all the possible method/function overloads. - void writeFunctionCalls(QTextStream &s, - const OverloadData &overloadData, - GeneratorContext &context); - - /// Writes the call to a single function usually from a collection of overloads. - void writeSingleFunctionCall(QTextStream &s, - const OverloadData &overloadData, - const AbstractMetaFunction *func, - GeneratorContext &context); - - /// Returns the name of a C++ to Python conversion function. - static QString cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName = QString()); - - /// 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); - - /// 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); - - /// Writes a C++ to Python conversion function. - void writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName = QString()); - void writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion); - void writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType); - - /// Writes a Python to C++ conversion function. - void writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName); - - /// Writes a Python to C++ convertible check function. - void writeIsPythonConvertibleToCppFunction(QTextStream& s, - const QString& sourceTypeName, - const QString& targetTypeName, - const QString& condition, - QString pythonToCppFuncName = QString(), - bool acceptNoneAsCppNull = false); - - /// Writes a pair of Python to C++ conversion and check functions. - void writePythonToCppConversionFunctions(QTextStream& s, - const AbstractMetaType* sourceType, - const AbstractMetaType* targetType, - QString typeCheck = QString(), - QString conversion = QString(), - QString preConversion = QString()); - /// Writes a pair of Python to C++ conversion and check functions for implicit conversions. - void writePythonToCppConversionFunctions(QTextStream& s, - const CustomConversion::TargetToNativeConversion* toNative, - const TypeEntry* targetType); - - /// Writes a pair of Python to C++ conversion and check functions for instantiated container types. - void writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType); - - void writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc); - - void writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs); - - /// Returns a string containing the name of an argument for the given function and argument index. - QString argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass); - void writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, - GeneratorContext &context, int maxArgs = 0); - - QString getInitFunctionName(GeneratorContext &context) const; - - void writeClassRegister(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &classContext); - void writeClassDefinition(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &classContext); - void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads); - void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads); - - /// Writes the implementation of all methods part of python sequence protocol - void writeSequenceMethods(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &context); - void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - - /// Writes the PyMappingMethods structure for types that supports the python mapping protocol. - void writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - void writeMappingMethods(QTextStream &s, - const AbstractMetaClass *metaClass, - GeneratorContext &context); - - void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeCopyFunction(QTextStream &s, GeneratorContext &context); - - void writeGetterFunction(QTextStream &s, - const AbstractMetaField *metaField, - GeneratorContext &context); - void writeSetterFunction(QTextStream &s, - const AbstractMetaField *metaField, - GeneratorContext &context); - - void writeRichCompareFunction(QTextStream &s, GeneratorContext &context); - void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums); - void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); - - void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass); - - void writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName); - void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, - QString pyOpName, QString cppOpName, bool boolResult = false); - - /// Writes the function that registers the multiple inheritance information for the classes that need it. - void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass); - /// Writes the implementation of special cast functions, used when we need to cast a class with multiple inheritance. - void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass); - - void writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion); - void writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType); - void writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); - void writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type); - void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QVector& conversions); - - void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn); - bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy); - void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = QLatin1String(PYTHON_SELF_VAR)); - void writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const; - - /** - * Returns the multiple inheritance initializer function for the given class. - * \param metaClass the class for whom the function name must be generated. - * \return name of the multiple inheritance information initializer function or - * an empty string if there is no multiple inheritance in its ancestry. - */ - QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass); - - /// Returns a list of all classes to which the given class could be cast. - QStringList getAncestorMultipleInheritance(const AbstractMetaClass* metaClass); - - /// Returns true if the given class supports the python number protocol - bool supportsNumberProtocol(const AbstractMetaClass* metaClass); - - /// Returns true if the given class supports the python sequence protocol - bool supportsSequenceProtocol(const AbstractMetaClass* metaClass); - - /// Returns true if the given class supports the python mapping protocol - bool supportsMappingProtocol(const AbstractMetaClass* metaClass); - - /// Returns true if generator should produce getters and setters for the given class. - bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); - - void writeHashFunction(QTextStream &s, GeneratorContext &context); - - /// Write default implementations for sequence protocol - void writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context); - /// Helper function for writeStdListWrapperMethods. - void writeIndexError(QTextStream& s, const QString& errorMsg); - - QString writeReprFunction(QTextStream &s, GeneratorContext &context); - - bool hasBoolCast(const AbstractMetaClass* metaClass) const; - - // Number protocol structure members names. - static QHash m_nbFuncs; - - // Maps special function names to function parameters and return types - // used by CPython API in the sequence protocol. - QHash > m_sequenceProtocol; - // Sequence protocol structure members names. - static QHash m_sqFuncs; - - // Maps special function names to function parameters and return types - // used by CPython API in the mapping protocol. - QHash > m_mappingProtocol; - // Mapping protocol structure members names. - static QHash m_mpFuncs; - - static QString m_currentErrorCode; - - /// Helper class to set and restore the current error code. - class ErrorCode { - public: - explicit ErrorCode(QString errorCode) { - m_savedErrorCode = CppGenerator::m_currentErrorCode; - CppGenerator::m_currentErrorCode = errorCode; - } - explicit ErrorCode(int errorCode) { - m_savedErrorCode = CppGenerator::m_currentErrorCode; - CppGenerator::m_currentErrorCode = QString::number(errorCode); - } - ~ErrorCode() { - CppGenerator::m_currentErrorCode = m_savedErrorCode; - } - private: - QString m_savedErrorCode; - }; -}; - -#endif // CPPGENERATOR_H diff --git a/generator/shiboken2/headergenerator.cpp b/generator/shiboken2/headergenerator.cpp deleted file mode 100644 index 6b8185dc9..000000000 --- a/generator/shiboken2/headergenerator.cpp +++ /dev/null @@ -1,569 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "headergenerator.h" -#include -#include -#include -#include - -#include -#include -#include -#include - -QString HeaderGenerator::fileNamePrefix() const -{ - return QLatin1String("_wrapper.h"); -} - -QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const -{ - const AbstractMetaClass *metaClass = context.metaClass(); - if (!context.forSmartPointer()) { - QString fileNameBase = metaClass->qualifiedCppName().toLower(); - fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); - return fileNameBase + fileNamePrefix(); - } else { - const AbstractMetaType *smartPointerType = context.preciseType(); - QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); - return fileNameBase + fileNamePrefix(); - } -} - -void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* metaClass) const -{ - s << INDENT << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName() << "& self)"; - s << " : " << metaClass->qualifiedCppName() << "(self)" << endl; - s << INDENT << "{" << endl; - s << INDENT << "}" << endl << endl; -} - -void HeaderGenerator::writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const -{ - AbstractMetaType *metaType = field->type(); - QString fieldType = metaType->cppSignature(); - QString fieldName = field->enclosingClass()->qualifiedCppName() + QLatin1String("::") + field->name(); - - // Force use of pointer to return internal variable memory - bool useReference = (!metaType->isConstant() && - !metaType->isEnum() && - !metaType->isPrimitive() && - metaType->indirections() == 0); - - - // Get function - s << INDENT << "inline " << fieldType - << (useReference ? '*' : ' ') - << ' ' << protectedFieldGetterName(field) << "()" - << " { return " - << (useReference ? '&' : ' ') << "this->" << fieldName << "; }" << endl; - - // Set function - s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)" - << " { " << fieldName << " = value; }" << endl; -} - -void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) -{ - AbstractMetaClass *metaClass = classContext.metaClass(); - if (ReportHandler::isDebug(ReportHandler::SparseDebug)) - qCDebug(lcShiboken) << "Generating header for " << metaClass->fullName(); - m_inheritedOverloads.clear(); - Indentation indent(INDENT); - - // write license comment - s << licenseComment(); - - QString wrapperName; - if (!classContext.forSmartPointer()) { - wrapperName = HeaderGenerator::wrapperName(metaClass); - } else { - wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); - } - QString headerGuard = getFilteredCppSignatureString(wrapperName).toUpper(); - - // Header - s << "#ifndef SBK_" << headerGuard << "_H" << endl; - s << "#define SBK_" << headerGuard << "_H" << endl<< endl; - - if (!avoidProtectedHack()) - s << "#define protected public" << endl << endl; - - s << "#include " << endl << endl; - - //Includes - s << metaClass->typeEntry()->include() << endl; - - if (shouldGenerateCppWrapper(metaClass)) { - - if (usePySideExtensions() && metaClass->isQObject()) - s << "namespace PySide { class DynamicQMetaObject; }\n\n"; - - // Class - s << "class " << wrapperName; - s << " : public " << metaClass->qualifiedCppName(); - - s << endl << '{' << endl << "public:" << endl; - - bool hasVirtualFunction = false; - const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); - for (AbstractMetaFunction *func : funcs) { - if (func->isVirtual()) - hasVirtualFunction = true; - writeFunction(s, func); - } - - if (avoidProtectedHack() && metaClass->hasProtectedFields()) { - const AbstractMetaFieldList &fields = metaClass->fields(); - for (AbstractMetaField *field : fields) { - if (!field->isProtected()) - continue; - writeProtectedFieldAccessors(s, field); - } - } - - //destructor - // PYSIDE-504: When C++ 11 is used, then the destructor must always be written. - // See generator.h for further reference. - if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor() || alwaysGenerateDestructor) { - s << INDENT; - if (avoidProtectedHack() && metaClass->hasPrivateDestructor()) - s << "// C++11: need to declare (unimplemented) destructor because " - "the base class destructor is private." << endl; - if (metaClass->hasVirtualDestructor() || hasVirtualFunction) - s << "virtual "; - s << '~' << wrapperName << "();" << endl; - } - - writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode); - - if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) - && usePySideExtensions() && metaClass->isQObject()) { - s << "public:\n"; - s << INDENT << "virtual int qt_metacall(QMetaObject::Call call, int id, void** args);" << endl; - s << INDENT << "virtual void* qt_metacast(const char* _clname);" << endl; - } - - if (m_inheritedOverloads.size()) { - s << INDENT << "// Inherited overloads, because the using keyword sux" << endl; - writeInheritedOverloads(s); - } - - if (usePySideExtensions()) - s << INDENT << "static void pysideInitQtMetaTypes();" << endl; - - s << "};" << endl << endl; - } - - s << "#endif // SBK_" << headerGuard << "_H" << endl << endl; -} - -void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* func) -{ - - // do not write copy ctors here. - if (!func->isPrivate() && func->functionType() == AbstractMetaFunction::CopyConstructorFunction) { - writeCopyCtor(s, func->ownerClass()); - return; - } - if (func->isUserAdded()) - return; - - if (avoidProtectedHack() && func->isProtected() && !func->isConstructor() && !func->isOperatorOverload()) { - s << INDENT << "inline " << (func->isStatic() ? "static " : ""); - s << functionSignature(func, QString(), QLatin1String("_protected"), Generator::EnumAsInts|Generator::OriginalTypeDescription) - << " { "; - s << (func->type() ? "return " : ""); - if (!func->isAbstract()) - s << func->ownerClass()->qualifiedCppName() << "::"; - s << func->originalName() << '('; - QStringList args; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - QString argName = arg->name(); - const TypeEntry* enumTypeEntry = 0; - if (arg->type()->isFlags()) - enumTypeEntry = reinterpret_cast(arg->type()->typeEntry())->originator(); - else if (arg->type()->isEnum()) - enumTypeEntry = arg->type()->typeEntry(); - if (enumTypeEntry) - argName = QString::fromLatin1("%1(%2)").arg(arg->type()->cppSignature(), argName); - args << argName; - } - s << args.join(QLatin1String(", ")) << ')'; - s << "; }" << endl; - } - - // pure virtual functions need a default implementation - if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) - || (func->isModifiedRemoved() && !func->isAbstract())) - return; - - if (avoidProtectedHack() && func->ownerClass()->hasPrivateDestructor() - && (func->isAbstract() || func->isVirtual())) - return; - - if (func->isConstructor() || func->isAbstract() || func->isVirtual()) { - s << INDENT; - Options virtualOption = Generator::OriginalTypeDescription; - - if (func->isVirtual() || func->isAbstract()) - s << "virtual "; - else if (!func->hasSignatureModifications()) - virtualOption = Generator::NoOption; - - s << functionSignature(func, QString(), QString(), virtualOption) << ';' << endl; - - // Check if this method hide other methods in base classes - const AbstractMetaFunctionList &ownerFuncs = func->ownerClass()->functions(); - for (const AbstractMetaFunction *f : ownerFuncs) { - if (f != func - && !f->isConstructor() - && !f->isPrivate() - && !f->isVirtual() - && !f->isAbstract() - && !f->isStatic() - && f->name() == func->name()) { - m_inheritedOverloads << f; - } - } - - // TODO: when modified an abstract method ceases to be virtual but stays abstract - //if (func->isModifiedRemoved() && func->isAbstract()) { - //} - } -} - -static void _writeTypeIndexDefineLine(QTextStream& s, const QString& variableName, int typeIndex) -{ - s << "#define "; - s.setFieldWidth(60); - s << variableName; - s.setFieldWidth(0); - s << ' ' << typeIndex << endl; -} -void HeaderGenerator::writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry) -{ - if (!typeEntry || !typeEntry->generateCode()) - return; - s.setFieldAlignment(QTextStream::AlignLeft); - int typeIndex = getTypeIndex(typeEntry); - _writeTypeIndexDefineLine(s, getTypeIndexVariableName(typeEntry), typeIndex); - if (typeEntry->isComplex()) { - const ComplexTypeEntry* cType = reinterpret_cast(typeEntry); - if (cType->baseContainerType()) { - const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), cType); - if (metaClass->templateBaseClass()) - _writeTypeIndexDefineLine(s, getTypeIndexVariableName(metaClass, true), typeIndex); - } - } - if (typeEntry->isEnum()) { - const EnumTypeEntry* ete = reinterpret_cast(typeEntry); - if (ete->flags()) - writeTypeIndexDefineLine(s, ete->flags()); - } -} - -void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass) -{ - if (!metaClass->typeEntry()->generateCode()) - return; - writeTypeIndexDefineLine(s, metaClass->typeEntry()); - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->isPrivate()) - continue; - writeTypeIndexDefineLine(s, metaEnum->typeEntry()); - } -} - -bool HeaderGenerator::finishGeneration() -{ - // Generate the main header for this module. - // This header should be included by binding modules - // extendind on top of this one. - QSet includes; - QString macros; - QTextStream macrosStream(¯os); - QString sbkTypeFunctions; - QTextStream typeFunctions(&sbkTypeFunctions); - QString protectedEnumSurrogates; - QTextStream protEnumsSurrogates(&protectedEnumSurrogates); - - Indentation indent(INDENT); - - macrosStream << "// Type indices" << endl; - AbstractMetaEnumList globalEnums = this->globalEnums(); - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) { - writeTypeIndexDefine(macrosStream, metaClass); - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); - } - - for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) - writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry()); - - // Write the smart pointer define indexes. - int smartPointerCountIndex = getMaxTypeIndex(); - int smartPointerCount = 0; - const QVector &instantiatedSmartPtrs = instantiatedSmartPointers(); - for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - QString variableName = getTypeIndexVariableName(metaType); - macrosStream << "#define "; - macrosStream.setFieldWidth(60); - macrosStream << variableName; - macrosStream.setFieldWidth(0); - macrosStream << ' ' << smartPointerCountIndex << " // " << metaType->cppSignature() - << endl; - ++smartPointerCountIndex; - ++smartPointerCount; - } - - - macrosStream << "#define "; - macrosStream.setFieldWidth(60); - macrosStream << QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT"); - macrosStream.setFieldWidth(0); - macrosStream << ' ' << getMaxTypeIndex() + smartPointerCount << endl << endl; - macrosStream << "// This variable stores all Python types exported by this module." << endl; - macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl; - macrosStream << "// This variable stores all type converters exported by this module." << endl; - macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl; - - // TODO-CONVERTER ------------------------------------------------------------------------------ - // Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex(). - macrosStream << "// Converter indices" << endl; - 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; - - _writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount++); - } - - const QVector &containers = instantiatedContainers(); - for (const AbstractMetaType *container : containers) { - //_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount); - // DEBUG - QString variableName = getTypeIndexVariableName(container); - macrosStream << "#define "; - macrosStream.setFieldWidth(60); - macrosStream << variableName; - macrosStream.setFieldWidth(0); - macrosStream << ' ' << pCount << " // " << container->cppSignature() << endl; - // DEBUG - pCount++; - } - - // Because on win32 the compiler will not accept a zero length array. - if (pCount == 0) - pCount++; - _writeTypeIndexDefineLine(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT").arg(moduleName()), pCount); - macrosStream << endl; - // TODO-CONVERTER ------------------------------------------------------------------------------ - - macrosStream << "// Macros for type check" << endl; - for (const AbstractMetaEnum *cppEnum : globalEnums) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - includes << cppEnum->typeEntry()->include(); - writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); - writeSbkTypeFunction(typeFunctions, cppEnum); - } - - for (AbstractMetaClass *metaClass : classList) { - if (!shouldGenerate(metaClass)) - continue; - - //Includes - const TypeEntry* classType = metaClass->typeEntry(); - includes << classType->include(); - - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *cppEnum : enums) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - EnumTypeEntry* enumType = cppEnum->typeEntry(); - includes << enumType->include(); - writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); - writeSbkTypeFunction(typeFunctions, cppEnum); - } - - if (!metaClass->isNamespace()) - writeSbkTypeFunction(typeFunctions, metaClass); - } - - for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { - const TypeEntry *classType = metaType->typeEntry(); - includes << classType->include(); - writeSbkTypeFunction(typeFunctions, metaType); - } - - QString moduleHeaderFileName(outputDirectory() - + QDir::separator() + subDirectoryForPackage(packageName()) - + QDir::separator() + getModuleHeaderFileName()); - - QString includeShield(QLatin1String("SBK_") + moduleName().toUpper() + QLatin1String("_PYTHON_H")); - - FileOut file(moduleHeaderFileName); - QTextStream& s = file.stream; - // write license comment - s << licenseComment() << endl << endl; - - s << "#ifndef " << includeShield << endl; - s << "#define " << includeShield << endl<< endl; - if (!avoidProtectedHack()) { - s << "//workaround to access protected functions" << endl; - s << "#define protected public" << endl << endl; - } - - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl << endl; - if (usePySideExtensions()) - s << "#include " << endl; - - QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports(); - if (!requiredTargetImports.isEmpty()) { - s << "// Module Includes" << endl; - for (const QString &requiredModule : qAsConst(requiredTargetImports)) - s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl; - s << endl; - } - - s << "// Binded library includes" << endl; - for (const Include &include : qAsConst(includes)) - s << include; - - if (!primitiveTypes().isEmpty()) { - s << "// Conversion Includes - Primitive Types" << endl; - const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); - for (const PrimitiveTypeEntry *ptype : primitiveTypeList) - s << ptype->include(); - s << endl; - } - - if (!containerTypes().isEmpty()) { - s << "// Conversion Includes - Container Types" << endl; - const ContainerTypeEntryList &containerTypeList = containerTypes(); - for (const ContainerTypeEntry *ctype : containerTypeList) - s << ctype->include(); - s << endl; - } - - s << macros << endl; - - if (!protectedEnumSurrogates.isEmpty()) { - s << "// Protected enum surrogates" << endl; - s << protectedEnumSurrogates << endl; - } - - s << "namespace Shiboken" << endl << '{' << endl << endl; - - s << "// PyType functions, to get the PyObjectType for a type T\n"; - s << sbkTypeFunctions << endl; - - s << "} // namespace Shiboken" << endl << endl; - - s << "#endif // " << includeShield << endl << endl; - - return file.done() != FileOut::Failure; -} - -void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - if (avoidProtectedHack() && cppEnum->isProtected()) - s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};" << endl; -} - -void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString enumName; - if (avoidProtectedHack() && cppEnum->isProtected()) { - enumName = protectedEnumSurrogateName(cppEnum); - } else { - enumName = cppEnum->name(); - if (cppEnum->enclosingClass()) - enumName = cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::") + enumName; - } - - s << "template<> inline PyTypeObject* SbkType< ::" << enumName << " >() "; - s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n"; - - FlagsTypeEntry* flag = cppEnum->typeEntry()->flags(); - if (flag) { - s << "template<> inline PyTypeObject* SbkType< ::" << flag->name() << " >() " - << "{ return " << cpythonTypeNameExt(flag) << "; }\n"; - } -} - -void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass) -{ - s << "template<> inline PyTypeObject* SbkType< ::" << cppClass->qualifiedCppName() << " >() " - << "{ return reinterpret_cast(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n"; -} - -void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType) -{ - s << "template<> inline PyTypeObject* SbkType< ::" << metaType->cppSignature() << " >() " - << "{ return reinterpret_cast(" << cpythonTypeNameExt(metaType) << "); }\n"; -} - -void HeaderGenerator::writeInheritedOverloads(QTextStream& s) -{ - for (const AbstractMetaFunction *func : qAsConst(m_inheritedOverloads)) { - s << INDENT << "inline "; - s << functionSignature(func, QString(), QString(), Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { "; - s << (func->type() ? "return " : ""); - s << func->ownerClass()->qualifiedCppName() << "::" << func->originalName() << '('; - QStringList args; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - QString argName = arg->name(); - const TypeEntry* enumTypeEntry = 0; - if (arg->type()->isFlags()) - enumTypeEntry = reinterpret_cast(arg->type()->typeEntry())->originator(); - else if (arg->type()->isEnum()) - enumTypeEntry = arg->type()->typeEntry(); - if (enumTypeEntry) - argName = arg->type()->cppSignature() + QLatin1Char('(') + argName + QLatin1Char(')'); - args << argName; - } - s << args.join(QLatin1String(", ")) << ')'; - s << "; }" << endl; - } -} diff --git a/generator/shiboken2/headergenerator.h b/generator/shiboken2/headergenerator.h deleted file mode 100644 index 5c1ffec35..000000000 --- a/generator/shiboken2/headergenerator.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HEADERGENERATOR_H -#define HEADERGENERATOR_H - -#include "shibokengenerator.h" - -#include - -class AbstractMetaFunction; - -/** - * The HeaderGenerator generate the declarations of C++ bindings classes. - */ -class HeaderGenerator : public ShibokenGenerator -{ -public: - QMap options() const override { return QMap(); } -protected: - QString fileNamePrefix() const override; - QString fileNameForContext(GeneratorContext &context) const override; - void generateClass(QTextStream& s, GeneratorContext &classContext) override; - bool finishGeneration() override; - -private: - void writeCopyCtor(QTextStream &s, const AbstractMetaClass* metaClass) const; - void writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const; - void writeFunction(QTextStream& s, const AbstractMetaFunction* func); - void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass); - void writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType); - void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry); - void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass); - void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeInheritedOverloads(QTextStream& s); - - QSet m_inheritedOverloads; -}; - -#endif // HEADERGENERATOR_H - diff --git a/generator/shiboken2/overloaddata.cpp b/generator/shiboken2/overloaddata.cpp deleted file mode 100644 index 876185cbe..000000000 --- a/generator/shiboken2/overloaddata.cpp +++ /dev/null @@ -1,1092 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "overloaddata.h" -#include "shibokengenerator.h" - -#include -#include -#include - -static const TypeEntry *getReferencedTypeEntry(const TypeEntry *typeEntry) -{ - if (typeEntry->isPrimitive()) { - const PrimitiveTypeEntry* pte = dynamic_cast(typeEntry); - while (pte->referencedTypeEntry()) - pte = pte->referencedTypeEntry(); - typeEntry = pte; - } - return typeEntry; -} - -static QString getTypeName(const AbstractMetaType* type) -{ - const TypeEntry* typeEntry = getReferencedTypeEntry(type->typeEntry()); - QString typeName = typeEntry->name(); - if (typeEntry->isContainer()) { - QStringList types; - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *cType : instantiations) { - const TypeEntry *typeEntry = getReferencedTypeEntry(cType->typeEntry()); - types << typeEntry->name(); - } - typeName += QLatin1Char('<') + types.join(QLatin1Char(',')) + QLatin1String(" >"); - } - return typeName; -} - -static QString getTypeName(const OverloadData* ov) -{ - return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType()); -} - -static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* typeB) -{ - if (typeA->typeEntry() == typeB->typeEntry()) { - if (typeA->isContainer() || typeA->isSmartPointer()) { - if (typeA->instantiations().size() != typeB->instantiations().size()) - return false; - - for (int i = 0; i < typeA->instantiations().size(); ++i) { - if (!typesAreEqual(typeA->instantiations().at(i), typeB->instantiations().at(i))) - return false; - } - return true; - } - - return !(ShibokenGenerator::isCString(typeA) ^ ShibokenGenerator::isCString(typeB)); - } - return false; -} - - -/** - * OverloadSortData just helps writing clearer code in the - * OverloadData::sortNextOverloads method. - */ -struct OverloadSortData -{ - OverloadSortData() : counter(0) {}; - - /** - * Adds a typeName into the type map without associating it with - * a OverloadData. This is done to express type dependencies that could - * or could not appear in overloaded signatures not processed yet. - */ - void mapType(const QString& typeName) - { - if (map.contains(typeName)) - return; - map[typeName] = counter; - if (!reverseMap.contains(counter)) - reverseMap[counter] = 0; - counter++; - } - - void mapType(OverloadData* overloadData) - { - QString typeName = getTypeName(overloadData); - map[typeName] = counter; - reverseMap[counter] = overloadData; - counter++; - } - - int lastProcessedItemId() { return counter - 1; } - - int counter; - QHash map; // typeName -> id - QHash reverseMap; // id -> OverloadData; -}; - -/** - * Helper function that returns the name of a container get from containerType argument and - * an instantiation taken either from an implicit conversion expressed by the function argument, - * or from the string argument implicitConvTypeName. - */ -static QString getImplicitConversionTypeName(const AbstractMetaType* containerType, - const AbstractMetaType* instantiation, - const AbstractMetaFunction* function, - const QString& implicitConvTypeName = QString()) -{ - QString impConv; - if (!implicitConvTypeName.isEmpty()) - impConv = implicitConvTypeName; - else if (function->isConversionOperator()) - impConv = function->ownerClass()->typeEntry()->name(); - else - impConv = getTypeName(function->arguments().first()->type()); - - QStringList types; - const AbstractMetaTypeList &instantiations = containerType->instantiations(); - for (const AbstractMetaType *otherType : instantiations) - types << (otherType == instantiation ? impConv : getTypeName(otherType)); - - const ContainerTypeEntry* containerTypeEntry = dynamic_cast(containerType->typeEntry()); - return containerTypeEntry->qualifiedCppName() + QLatin1Char('<') - + types.join(QLatin1String(", ")) + QLatin1String(" >"); -} - -static QString msgCyclicDependency(const QString &funcName, const QString &graphName, - const OverloadData::MetaFunctionList &involvedConversions) -{ - QString result; - QTextStream str(&result); - str << "Cyclic dependency found on overloaddata for \"" << funcName - << "\" method! The graph boy saved the graph at \"" << QDir::toNativeSeparators(graphName) - << "\"."; - if (const int count = involvedConversions.size()) { - str << " Implicit conversions (" << count << "): "; - for (int i = 0; i < count; ++i) { - if (i) - str << ", \""; - str << involvedConversions.at(i)->signature() << '"'; - if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass()) - str << '(' << c->name() << ')'; - } - } - return result; -} - -/** - * Topologically sort the overloads by implicit convertion order - * - * This avoids using an implicit conversion if there's an explicit - * overload for the convertible type. So, if there's an implicit convert - * like TargetType(ConvertibleType foo) and both are in the overload list, - * ConvertibleType is checked before TargetType. - * - * Side effects: Modifies m_nextOverloadData - */ -void OverloadData::sortNextOverloads() -{ - OverloadSortData sortData; - bool checkPyObject = false; - int pyobjectIndex = 0; - bool checkPySequence = false; - int pySeqIndex = 0; - bool checkQString = false; - int qstringIndex = 0; - bool checkQVariant = false; - int qvariantIndex = 0; - bool checkPyBuffer = false; - int pyBufferIndex = 0; - - // Primitive types that are not int, long, short, - // char and their respective unsigned counterparts. - QStringList nonIntegerPrimitives; - nonIntegerPrimitives << QLatin1String("float") << QLatin1String("double") - << QLatin1String("bool"); - - // Signed integer primitive types. - QStringList signedIntegerPrimitives; - signedIntegerPrimitives << QLatin1String("int") << QLatin1String("short") - << QLatin1String("long"); - - // sort the children overloads - for (OverloadData *ov : m_nextOverloadData) - ov->sortNextOverloads(); - - if (m_nextOverloadData.size() <= 1) - return; - - // Populates the OverloadSortData object containing map and reverseMap, to map type names to ids, - // these ids will be used by the topological sort algorithm, because is easier and faster to work - // with graph sorting using integers. - for (OverloadData *ov : m_nextOverloadData) { - sortData.mapType(ov); - - const QString typeName(getTypeName(ov)); - - if (!checkPyObject && typeName.contains(QLatin1String("PyObject"))) { - checkPyObject = true; - pyobjectIndex = sortData.lastProcessedItemId(); - } else if (!checkPySequence && typeName == QLatin1String("PySequence")) { - checkPySequence = true; - pySeqIndex = sortData.lastProcessedItemId(); - } else if (!checkPyBuffer && typeName == QLatin1String("PyBuffer")) { - checkPyBuffer = true; - pyBufferIndex = sortData.lastProcessedItemId(); - } else if (!checkQVariant && typeName == QLatin1String("QVariant")) { - checkQVariant = true; - qvariantIndex = sortData.lastProcessedItemId(); - } else if (!checkQString && typeName == QLatin1String("QString")) { - checkQString = true; - qstringIndex = sortData.lastProcessedItemId(); - } - - const AbstractMetaTypeList &instantiations = ov->argType()->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) { - // Add dependencies for type instantiation of container. - QString typeName = getTypeName(instantiation); - sortData.mapType(typeName); - - // Build dependency for implicit conversion types instantiations for base container. - // For example, considering signatures "method(list)" and "method(list)", - // and being PointF implicitly convertible from Point, an list instantiation with T - // as Point must come before the PointF instantiation, or else list will never - // be called. In the case of primitive types, list must come before list. - if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { - for (const QString &primitive : qAsConst(nonIntegerPrimitives)) - sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive)); - } else { - const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); - for (const AbstractMetaFunction *function : funcs) - sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, function)); - } - } - } - - - // Create the graph of type dependencies based on implicit conversions. - Graph graph(sortData.reverseMap.count()); - // All C++ primitive types, add any forgotten type AT THE END OF THIS LIST! - const char* primitiveTypes[] = {"int", - "unsigned int", - "long", - "unsigned long", - "short", - "unsigned short", - "bool", - "unsigned char", - "char", - "float", - "double", - "const char*" - }; - const int numPrimitives = sizeof(primitiveTypes)/sizeof(const char*); - bool hasPrimitive[numPrimitives]; - for (int i = 0; i < numPrimitives; ++i) - hasPrimitive[i] = sortData.map.contains(QLatin1String(primitiveTypes[i])); - - if (checkPySequence && checkPyObject) - graph.addEdge(pySeqIndex, pyobjectIndex); - - QStringList classesWithIntegerImplicitConversion; - - MetaFunctionList involvedConversions; - - for (OverloadData *ov : m_nextOverloadData) { - const AbstractMetaType* targetType = ov->argType(); - const QString targetTypeEntryName(getTypeName(ov)); - int targetTypeId = sortData.map[targetTypeEntryName]; - - // Process implicit conversions - const AbstractMetaFunctionList &functions = m_generator->implicitConversions(targetType); - for (AbstractMetaFunction *function : functions) { - QString convertibleType; - if (function->isConversionOperator()) - convertibleType = function->ownerClass()->typeEntry()->name(); - else - convertibleType = getTypeName(function->arguments().first()->type()); - - if (convertibleType == QLatin1String("int") || convertibleType == QLatin1String("unsigned int")) - classesWithIntegerImplicitConversion << targetTypeEntryName; - - if (!sortData.map.contains(convertibleType)) - continue; - - int convertibleTypeId = sortData.map[convertibleType]; - - // If a reverse pair already exists, remove it. Probably due to the - // container check (This happened to QVariant and QHash) - graph.removeEdge(targetTypeId, convertibleTypeId); - graph.addEdge(convertibleTypeId, targetTypeId); - involvedConversions.append(function); - } - - // Process inheritance relationships - if (targetType->isValue() || targetType->isObject()) { - const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_generator->classes(), targetType->typeEntry()); - const AbstractMetaClassList &ancestors = m_generator->getAllAncestors(metaClass); - for (const AbstractMetaClass *ancestor : ancestors) { - QString ancestorTypeName = ancestor->typeEntry()->name(); - if (!sortData.map.contains(ancestorTypeName)) - continue; - int ancestorTypeId = sortData.map[ancestorTypeName]; - graph.removeEdge(ancestorTypeId, targetTypeId); - graph.addEdge(targetTypeId, ancestorTypeId); - } - } - - // Process template instantiations - const AbstractMetaTypeList &instantiations = targetType->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) { - if (sortData.map.contains(getTypeName(instantiation))) { - int convertible = sortData.map[getTypeName(instantiation)]; - - if (!graph.containsEdge(targetTypeId, convertible)) // Avoid cyclic dependency. - graph.addEdge(convertible, targetTypeId); - - if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { - for (const QString &primitive : qAsConst(nonIntegerPrimitives)) { - QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive); - if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) // Avoid cyclic dependency. - graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); - } - - } else { - const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); - for (const AbstractMetaFunction *function : funcs) { - QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, function); - if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) { // Avoid cyclic dependency. - graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); - involvedConversions.append(function); - } - } - } - } - } - - - if ((checkPySequence || checkPyObject || checkPyBuffer) - && !targetTypeEntryName.contains(QLatin1String("PyObject")) - && !targetTypeEntryName.contains(QLatin1String("PyBuffer")) - && !targetTypeEntryName.contains(QLatin1String("PySequence"))) { - if (checkPySequence) { - // PySequence will be checked after all more specific types, but before PyObject. - graph.addEdge(targetTypeId, pySeqIndex); - } else if (checkPyBuffer) { - // PySequence will be checked after all more specific types, but before PyObject. - graph.addEdge(targetTypeId, pyBufferIndex); - } else { - // Add dependency on PyObject, so its check is the last one (too generic). - graph.addEdge(targetTypeId, pyobjectIndex); - } - } else if (checkQVariant && targetTypeEntryName != QLatin1String("QVariant")) { - if (!graph.containsEdge(qvariantIndex, targetTypeId)) // Avoid cyclic dependency. - graph.addEdge(targetTypeId, qvariantIndex); - } else if (checkQString && ShibokenGenerator::isPointer(ov->argType()) - && targetTypeEntryName != QLatin1String("QString") - && targetTypeEntryName != QLatin1String("QByteArray") - && (!checkPyObject || targetTypeId != pyobjectIndex)) { - if (!graph.containsEdge(qstringIndex, targetTypeId)) // Avoid cyclic dependency. - graph.addEdge(targetTypeId, qstringIndex); - } - - if (targetType->isEnum()) { - // Enum values must precede primitive types. - for (int i = 0; i < numPrimitives; ++i) { - if (hasPrimitive[i]) - graph.addEdge(targetTypeId, sortData.map[QLatin1String(primitiveTypes[i])]); - } - } - } - - // QByteArray args need to be checked after QString args - if (sortData.map.contains(QLatin1String("QString")) && sortData.map.contains(QLatin1String("QByteArray"))) - graph.addEdge(sortData.map[QLatin1String("QString")], sortData.map[QLatin1String("QByteArray")]); - - for (OverloadData *ov : m_nextOverloadData) { - 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)) - graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]); - } - - - // Special case for double(int i) (not tracked by m_generator->implicitConversions - for (const QString &signedIntegerName : qAsConst(signedIntegerPrimitives)) { - if (sortData.map.contains(signedIntegerName)) { - for (const QString &nonIntegerName : qAsConst(nonIntegerPrimitives)) { - if (sortData.map.contains(nonIntegerName)) - graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]); - } - } - } - - // sort the overloads topologically based on the dependency graph. - const QLinkedList unmappedResult = graph.topologicalSort(); - if (unmappedResult.isEmpty()) { - QString funcName = referenceFunction()->name(); - if (referenceFunction()->ownerClass()) - funcName.prepend(referenceFunction()->ownerClass()->name() + QLatin1Char('.')); - - // Dump overload graph - QString graphName = QDir::tempPath() + QLatin1Char('/') + funcName + QLatin1String(".dot"); - QHash::const_iterator it = sortData.map.begin(); - QHash nodeNames; - for (; it != sortData.map.end(); ++it) - nodeNames.insert(it.value(), it.key()); - graph.dumpDot(nodeNames, graphName); - qCWarning(lcShiboken).noquote() << qPrintable(msgCyclicDependency(funcName, graphName, involvedConversions)); - } - - m_nextOverloadData.clear(); - for (int i : unmappedResult) { - if (!sortData.reverseMap[i]) - continue; - m_nextOverloadData << sortData.reverseMap[i]; - } -} - -/** - * Root constructor for OverloadData - * - * This constructor receives the list of overloads for a given function and iterates generating - * the graph of OverloadData instances. Each OverloadData instance references an argument/type - * combination. - * - * Example: - * addStuff(double, PyObject *) - * addStuff(double, int) - * - * Given these two overloads, there will be the following graph: - * - * addStuff - double - PyObject* - * \- int - * - */ -OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator) - : m_minArgs(256), m_maxArgs(0), m_argPos(-1), m_argType(0), - m_headOverloadData(this), m_previousOverloadData(0), m_generator(generator) -{ - for (const AbstractMetaFunction *func : overloads) { - m_overloads.append(func); - int argSize = func->arguments().size() - numberOfRemovedArguments(func); - if (m_minArgs > argSize) - m_minArgs = argSize; - else if (m_maxArgs < argSize) - m_maxArgs = argSize; - OverloadData* currentOverloadData = this; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - currentOverloadData = currentOverloadData->addOverloadData(func, arg); - } - } - - // Sort the overload possibilities so that the overload decisor code goes for the most - // important cases first, based on the topological order of the implicit conversions - sortNextOverloads(); - - // Fix minArgs - if (minArgs() > maxArgs()) - m_headOverloadData->m_minArgs = maxArgs(); -} - -OverloadData::OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func, - const AbstractMetaType* argType, int argPos) - : m_minArgs(256), m_maxArgs(0), m_argPos(argPos), m_argType(argType), - m_headOverloadData(headOverloadData), m_previousOverloadData(0) -{ - if (func) - this->addOverload(func); -} - -void OverloadData::addOverload(const AbstractMetaFunction* func) -{ - int origNumArgs = func->arguments().size(); - int removed = numberOfRemovedArguments(func); - int numArgs = origNumArgs - removed; - - if (numArgs > m_headOverloadData->m_maxArgs) - m_headOverloadData->m_maxArgs = numArgs; - - if (numArgs < m_headOverloadData->m_minArgs) - m_headOverloadData->m_minArgs = numArgs; - - for (int i = 0; m_headOverloadData->m_minArgs > 0 && i < origNumArgs; i++) { - if (func->argumentRemoved(i + 1)) - continue; - if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[i]).isEmpty()) { - int fixedArgIndex = i - removed; - if (fixedArgIndex < m_headOverloadData->m_minArgs) - m_headOverloadData->m_minArgs = fixedArgIndex; - } - } - - m_overloads.append(func); -} - -OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func, - const AbstractMetaArgument* arg) -{ - const AbstractMetaType* argType = arg->type(); - OverloadData* overloadData = 0; - if (!func->isOperatorOverload()) { - for (OverloadData *tmp : qAsConst(m_nextOverloadData)) { - // 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 - // for it, unless the next argument also have a identical type replacement. - QString replacedArg = func->typeReplaced(tmp->m_argPos + 1); - bool argsReplaced = !replacedArg.isEmpty() || !tmp->m_argTypeReplaced.isEmpty(); - if ((!argsReplaced && typesAreEqual(tmp->m_argType, argType)) - || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) { - tmp->addOverload(func); - overloadData = tmp; - } - } - } - - if (!overloadData) { - overloadData = new OverloadData(m_headOverloadData, func, argType, m_argPos + 1); - overloadData->m_previousOverloadData = this; - overloadData->m_generator = this->m_generator; - QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); - - if (!typeReplaced.isEmpty()) - overloadData->m_argTypeReplaced = typeReplaced; - m_nextOverloadData.append(overloadData); - } - - return overloadData; -} - -QStringList OverloadData::returnTypes() const -{ - QSet retTypes; - for (const AbstractMetaFunction *func : m_overloads) { - if (!func->typeReplaced(0).isEmpty()) - retTypes << func->typeReplaced(0); - else if (func->type() && !func->argumentRemoved(0)) - retTypes << func->type()->cppSignature(); - else - retTypes << QLatin1String("void"); - } - return QStringList(retTypes.toList()); -} - -bool OverloadData::hasNonVoidReturnType() const -{ - QStringList retTypes = returnTypes(); - return !retTypes.contains(QLatin1String("void")) || retTypes.size() > 1; -} - -bool OverloadData::hasVarargs() const -{ - for (const AbstractMetaFunction *func : m_overloads) { - AbstractMetaArgumentList args = func->arguments(); - if (args.size() > 1 && args.last()->type()->isVarargs()) - return true; - } - return false; -} - -bool OverloadData::hasAllowThread() const -{ - for (const AbstractMetaFunction *func : m_overloads) { - if (func->allowThread()) - return true; - } - return false; -} - -bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads) -{ - for (const AbstractMetaFunction *func : qAsConst(overloads)) { - if (func->isStatic()) - return true; - } - return false; -} - -bool OverloadData::hasStaticFunction() const -{ - for (const AbstractMetaFunction *func : m_overloads) { - if (func->isStatic()) - return true; - } - return false; -} - -bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads) -{ - for (const AbstractMetaFunction *func : qAsConst(overloads)) { - if (!func->isStatic()) - return true; - } - return false; -} - -bool OverloadData::hasInstanceFunction() const -{ - for (const AbstractMetaFunction *func : m_overloads) { - if (!func->isStatic()) - return true; - } - return false; -} - -bool OverloadData::hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads) -{ - return OverloadData::hasStaticFunction(overloads) && OverloadData::hasInstanceFunction(overloads); -} - -bool OverloadData::hasStaticAndInstanceFunctions() const -{ - return OverloadData::hasStaticFunction() && OverloadData::hasInstanceFunction(); -} - -const AbstractMetaFunction* OverloadData::referenceFunction() const -{ - return m_overloads.first(); -} - -const AbstractMetaArgument* OverloadData::argument(const AbstractMetaFunction* func) const -{ - if (isHeadOverloadData() || !m_overloads.contains(func)) - return 0; - - int argPos = 0; - int removed = 0; - for (int i = 0; argPos <= m_argPos; i++) { - if (func->argumentRemoved(i + 1)) - removed++; - else - argPos++; - } - - return func->arguments()[m_argPos + removed]; -} - -OverloadDataList OverloadData::overloadDataOnPosition(OverloadData* overloadData, int argPos) const -{ - OverloadDataList overloadDataList; - if (overloadData->argPos() == argPos) { - overloadDataList.append(overloadData); - } else if (overloadData->argPos() < argPos) { - const OverloadDataList &data = overloadData->nextOverloadData(); - for (OverloadData *pd : data) - overloadDataList += overloadDataOnPosition(pd, argPos); - } - return overloadDataList; -} - -OverloadDataList OverloadData::overloadDataOnPosition(int argPos) const -{ - OverloadDataList overloadDataList; - overloadDataList += overloadDataOnPosition(m_headOverloadData, argPos); - return overloadDataList; -} - -bool OverloadData::nextArgumentHasDefaultValue() const -{ - for (OverloadData *overloadData : m_nextOverloadData) { - if (overloadData->getFunctionWithDefaultValue()) - return true; - } - return false; -} - -static OverloadData* _findNextArgWithDefault(OverloadData* overloadData) -{ - if (overloadData->getFunctionWithDefaultValue()) - return overloadData; - - OverloadData* result = 0; - const OverloadDataList &data = overloadData->nextOverloadData(); - for (OverloadData *odata : data) { - OverloadData* tmp = _findNextArgWithDefault(odata); - if (!result || (tmp && result->argPos() > tmp->argPos())) - result = tmp; - } - return result; -} - -OverloadData* OverloadData::findNextArgWithDefault() -{ - return _findNextArgWithDefault(this); -} - -bool OverloadData::isFinalOccurrence(const AbstractMetaFunction* func) const -{ - for (const OverloadData *pd : m_nextOverloadData) { - if (pd->overloads().contains(func)) - return false; - } - return true; -} - -OverloadData::MetaFunctionList OverloadData::overloadsWithoutRepetition() const -{ - MetaFunctionList overloads = m_overloads; - for (const AbstractMetaFunction *func : m_overloads) { - if (func->minimalSignature().endsWith(QLatin1String("const"))) - continue; - for (const AbstractMetaFunction *f : qAsConst(overloads)) { - if ((func->minimalSignature() + QLatin1String("const")) == f->minimalSignature()) { - overloads.removeOne(f); - break; - } - } - } - return overloads; -} - -const AbstractMetaFunction* OverloadData::getFunctionWithDefaultValue() const -{ - for (const AbstractMetaFunction *func : m_overloads) { - int removedArgs = 0; - for (int i = 0; i <= m_argPos + removedArgs; i++) { - if (func->argumentRemoved(i + 1)) - removedArgs++; - } - if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[m_argPos + removedArgs]).isEmpty()) - return func; - } - return 0; -} - -QVector OverloadData::invalidArgumentLengths() const -{ - QSet validArgLengths; - - for (const AbstractMetaFunction *func : qAsConst(m_headOverloadData->m_overloads)) { - const AbstractMetaArgumentList args = func->arguments(); - int offset = 0; - for (int i = 0; i < args.size(); ++i) { - if (func->argumentRemoved(i+1)) { - offset++; - } else { - if (!ShibokenGenerator::getDefaultValue(func, args[i]).isEmpty()) - validArgLengths << i-offset; - } - } - validArgLengths << args.size() - offset; - } - - QVector invalidArgLengths; - for (int i = minArgs() + 1; i < maxArgs(); i++) { - if (!validArgLengths.contains(i)) - invalidArgLengths.append(i); - } - - return invalidArgLengths; -} - -int OverloadData::numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos) -{ - int removed = 0; - if (finalArgPos < 0) { - for (int i = 0; i < func->arguments().size(); i++) { - if (func->argumentRemoved(i + 1)) - removed++; - } - } else { - for (int i = 0; i < finalArgPos + removed; i++) { - if (func->argumentRemoved(i + 1)) - removed++; - } - } - return removed; -} - -QPair OverloadData::getMinMaxArguments(const AbstractMetaFunctionList& overloads) -{ - int minArgs = 10000; - int maxArgs = 0; - for (int i = 0; i < overloads.size(); i++) { - const AbstractMetaFunction* func = overloads[i]; - int origNumArgs = func->arguments().size(); - int removed = numberOfRemovedArguments(func); - int numArgs = origNumArgs - removed; - if (maxArgs < numArgs) - maxArgs = numArgs; - if (minArgs > numArgs) - minArgs = numArgs; - for (int j = 0; j < origNumArgs; j++) { - if (func->argumentRemoved(j + 1)) - continue; - int fixedArgIndex = j - removed; - if (fixedArgIndex < minArgs && !ShibokenGenerator::getDefaultValue(func, func->arguments()[j]).isEmpty()) - minArgs = fixedArgIndex; - } - } - return QPair(minArgs, maxArgs); -} - -bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads) -{ - bool singleArgument = true; - for (const AbstractMetaFunction *func : overloads) { - if (func->arguments().size() - numberOfRemovedArguments(func) != 1) { - singleArgument = false; - break; - } - } - return singleArgument; -} - -void OverloadData::dumpGraph(QString filename) const -{ - QFile file(filename); - if (file.open(QFile::WriteOnly)) { - QTextStream s(&file); - s << m_headOverloadData->dumpGraph(); - } -} - -static inline QString toHtml(QString s) -{ - s.replace(QLatin1Char('<'), QLatin1String("<")); - s.replace(QLatin1Char('>'), QLatin1String(">")); - s.replace(QLatin1Char('&'), QLatin1String("&")); - return s; -} - -QString OverloadData::dumpGraph() const -{ - QString indent(4, QLatin1Char(' ')); - QString result; - QTextStream s(&result); - if (m_argPos == -1) { - const AbstractMetaFunction* rfunc = referenceFunction(); - s << "digraph OverloadedFunction {" << endl; - s << indent << "graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];" << endl; - - // Shows all function signatures - s << "legend [fontsize=9 fontname=freemono shape=rect label=\""; - for (const AbstractMetaFunction *func : m_overloads) { - s << "f" << functionNumber(func) << " : "; - if (func->type()) - s << toHtml(func->type()->cppSignature()); - else - s << "void"; - s << ' ' << toHtml(func->minimalSignature()) << "\\l"; - } - s << "\"];" << endl; - - // Function box title - s << indent << '"' << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 "; - s << "label=<"; - s << ""; - - // Function return type - s << ""; - - // Shows type changes for all function signatures - for (const AbstractMetaFunction *func : m_overloads) { - if (func->typeReplaced(0).isEmpty()) - continue; - s << ""; - } - - // Minimum and maximum number of arguments - s << ""; - s << ""; - - if (rfunc->ownerClass()) { - if (rfunc->implementingClass() != rfunc->ownerClass()) - s << ""; - if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass()) - s << ""; - } - - // Overloads for the signature to present point - s << ""; - - s << "
"; - if (rfunc->ownerClass()) - s << rfunc->ownerClass()->name() << "::"; - s << toHtml(rfunc->name()) << ""; - if (rfunc->isVirtual()) { - s << "
<<"; - if (rfunc->isAbstract()) - s << "pure "; - s << "virtual>>"; - } - s << "
original type"; - if (rfunc->type()) - s << toHtml(rfunc->type()->cppSignature()); - else - s << "void"; - s << "
f" << functionNumber(func); - s << "-type"; - s << toHtml(func->typeReplaced(0)) << "
minArgs"; - s << minArgs() << "
maxArgs"; - s << maxArgs() << "
implementor" << rfunc->implementingClass()->name() << "
declarator" << rfunc->declaringClass()->name() << "
overloads"; - for (const AbstractMetaFunction *func : m_overloads) - s << 'f' << functionNumber(func) << ' '; - s << "
> ];" << endl; - - for (const OverloadData *pd : m_nextOverloadData) - s << indent << '"' << rfunc->name() << "\" -> " << pd->dumpGraph(); - - s << "}" << endl; - } else { - QString argId = QLatin1String("arg_") + QString::number(quintptr(this)); - s << argId << ';' << endl; - - s << indent << '"' << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 "; - s << "label=<"; - - // Argument box title - s << ""; - - // Argument type information - QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType()->cppSignature(); - s << ""; - if (hasArgumentTypeReplace()) { - s << ""; - } - - // Overloads for the signature to present point - s << ""; - - // Show default values (original and modified) for various functions - for (const AbstractMetaFunction *func : m_overloads) { - const AbstractMetaArgument* arg = argument(func); - if (!arg) - continue; - QString argDefault = ShibokenGenerator::getDefaultValue(func, arg); - if (!argDefault.isEmpty() || - argDefault != arg->originalDefaultValueExpression()) { - s << ""; - } - if (argDefault != arg->originalDefaultValueExpression()) { - s << ""; - } - } - - s << "
"; - s << "arg #" << argPos() << "
type"; - s << toHtml(type) << "
orig. type"; - s << toHtml(argType()->cppSignature()) << "
overloads"; - for (const AbstractMetaFunction *func : m_overloads) - s << 'f' << functionNumber(func) << ' '; - s << "
f" << functionNumber(func); - s << "-default"; - s << argDefault << "
f" << functionNumber(func); - s << "-orig-default"; - s << arg->originalDefaultValueExpression() << "
>];" << endl; - - for (const OverloadData *pd : m_nextOverloadData) - s << indent << argId << " -> " << pd->dumpGraph(); - } - return result; -} - -int OverloadData::functionNumber(const AbstractMetaFunction* func) const -{ - return m_headOverloadData->m_overloads.indexOf(func); -} - -OverloadData::~OverloadData() -{ - while (!m_nextOverloadData.isEmpty()) - delete m_nextOverloadData.takeLast(); -} - -bool OverloadData::hasArgumentTypeReplace() const -{ - return !m_argTypeReplaced.isEmpty(); -} - -QString OverloadData::argumentTypeReplaced() const -{ - return m_argTypeReplaced; -} - -bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads) -{ - if (OverloadData::getMinMaxArguments(overloads).second == 0) - return false; - for (const AbstractMetaFunction *func : overloads) { - if (hasArgumentWithDefaultValue(func)) - return true; - } - return false; -} - -bool OverloadData::hasArgumentWithDefaultValue() const -{ - if (maxArgs() == 0) - return false; - for (const AbstractMetaFunction *func : m_overloads) { - if (hasArgumentWithDefaultValue(func)) - return true; - } - return false; -} - -bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func) -{ - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - if (!ShibokenGenerator::getDefaultValue(func, arg).isEmpty()) - return true; - } - return false; -} - -AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const AbstractMetaFunction* func) -{ - AbstractMetaArgumentList args; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (AbstractMetaArgument *arg : arguments) { - if (ShibokenGenerator::getDefaultValue(func, arg).isEmpty() - || func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - args << arg; - } - return args; -} - -#ifndef QT_NO_DEBUG_STREAM -void OverloadData::formatDebug(QDebug &d) const -{ - const int count = m_overloads.size(); - d << "argType=" << m_argType << ", minArgs=" << m_minArgs << ", maxArgs=" << m_maxArgs - << ", argPos=" << m_argPos << ", argTypeReplaced=\"" << m_argTypeReplaced - << "\", overloads[" << count << "]=("; - const int oldVerbosity = d.verbosity(); - d.setVerbosity(3); - for (int i = 0; i < count; ++i) { - if (i) - d << '\n'; - d << m_overloads.at(i); - } - d << ')'; - d.setVerbosity(oldVerbosity); -} - -QDebug operator<<(QDebug d, const OverloadData *od) -{ - QDebugStateSaver saver(d); - d.noquote(); - d.nospace(); - d << "OverloadData("; - if (od) - od->formatDebug(d); - else - d << '0'; - d << ')'; - return d; -} -#endif // !QT_NO_DEBUG_STREAM diff --git a/generator/shiboken2/overloaddata.h b/generator/shiboken2/overloaddata.h deleted file mode 100644 index 2d815f6bb..000000000 --- a/generator/shiboken2/overloaddata.h +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OVERLOADDATA_H -#define OVERLOADDATA_H - -#include -#include -#include - -QT_FORWARD_DECLARE_CLASS(QDebug) - -class ShibokenGenerator; - -class OverloadData; -typedef QVector OverloadDataList; - -class OverloadData -{ -public: - typedef QVector MetaFunctionList; - - OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator); - ~OverloadData(); - - int minArgs() const { return m_headOverloadData->m_minArgs; } - int maxArgs() const { return m_headOverloadData->m_maxArgs; } - int argPos() const { return m_argPos; } - - const AbstractMetaType* argType() const { return m_argType; } - - /// Returns a string list containing all the possible return types (including void) for the current OverloadData. - QStringList returnTypes() const; - - /// Returns true if any of the overloads for the current OverloadData has a return type different from void. - bool hasNonVoidReturnType() const; - - /// Returns true if any of the overloads for the current OverloadData has a varargs argument. - bool hasVarargs() const; - - /// Returns true if any of the overloads for the current OverloadData allows threads when called. - bool hasAllowThread() const; - - /// Returns true if any of the overloads for the current OverloadData is static. - bool hasStaticFunction() const; - - /// Returns true if any of the overloads passed as argument is static. - static bool hasStaticFunction(const AbstractMetaFunctionList& overloads); - - /// Returns true if any of the overloads for the current OverloadData is not static. - bool hasInstanceFunction() const; - - /// Returns true if any of the overloads passed as argument is not static. - static bool hasInstanceFunction(const AbstractMetaFunctionList& overloads); - - /// Returns true if among the overloads for the current OverloadData there are static and non-static methods altogether. - bool hasStaticAndInstanceFunctions() const; - - /// Returns true if among the overloads passed as argument there are static and non-static methods altogether. - static bool hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads); - - const AbstractMetaFunction* referenceFunction() const; - const AbstractMetaArgument* argument(const AbstractMetaFunction* func) const; - OverloadDataList overloadDataOnPosition(int argPos) const; - - bool isHeadOverloadData() const { return this == m_headOverloadData; } - - /// Returns the root OverloadData object that represents all the overloads. - OverloadData* headOverloadData() const { return m_headOverloadData; } - - /// Returns the function that has a default value at the current OverloadData argument position, otherwise returns null. - const AbstractMetaFunction* getFunctionWithDefaultValue() const; - - bool nextArgumentHasDefaultValue() const; - /// Returns the nearest occurrence, including this instance, of an argument with a default value. - OverloadData* findNextArgWithDefault(); - bool isFinalOccurrence(const AbstractMetaFunction* func) const; - - /// Returns the list of overloads removing repeated constant functions (ex.: "foo()" and "foo()const", the second is removed). - MetaFunctionList overloadsWithoutRepetition() const; - const MetaFunctionList& overloads() const { return m_overloads; } - OverloadDataList nextOverloadData() const { return m_nextOverloadData; } - OverloadData* previousOverloadData() const { return m_previousOverloadData; } - - QVector invalidArgumentLengths() const; - - static int numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos = -1); - static QPair getMinMaxArguments(const AbstractMetaFunctionList& overloads); - /// Returns true if all overloads have no more than one argument. - static bool isSingleArgument(const AbstractMetaFunctionList& overloads); - - void dumpGraph(QString filename) const; - QString dumpGraph() const; - - bool hasArgumentTypeReplace() const; - QString argumentTypeReplaced() const; - - bool hasArgumentWithDefaultValue() const; - static bool hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads); - static bool hasArgumentWithDefaultValue(const AbstractMetaFunction* func); - - /// Returns a list of function arguments which have default values and were not removed. - static AbstractMetaArgumentList getArgumentsWithDefaultValues(const AbstractMetaFunction* func); - -#ifndef QT_NO_DEBUG_STREAM - void formatDebug(QDebug &) const; -#endif - -private: - OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func, - const AbstractMetaType* argType, int argPos); - - void addOverload(const AbstractMetaFunction* func); - OverloadData* addOverloadData(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); - - void sortNextOverloads(); - - int functionNumber(const AbstractMetaFunction* func) const; - OverloadDataList overloadDataOnPosition(OverloadData* overloadData, int argPos) const; - - int m_minArgs; - int m_maxArgs; - int m_argPos; - const AbstractMetaType* m_argType; - QString m_argTypeReplaced; - MetaFunctionList m_overloads; - - OverloadData* m_headOverloadData; - OverloadDataList m_nextOverloadData; - OverloadData* m_previousOverloadData; - const ShibokenGenerator* m_generator; -}; - -#ifndef QT_NO_DEBUG_STREAM -QDebug operator<<(QDebug, const OverloadData *); -#endif - -#endif // OVERLOADDATA_H diff --git a/generator/shiboken2/shibokengenerator.cpp b/generator/shiboken2/shibokengenerator.cpp deleted file mode 100644 index 4768ddc88..000000000 --- a/generator/shiboken2/shibokengenerator.cpp +++ /dev/null @@ -1,2728 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "shibokengenerator.h" -#include -#include "overloaddata.h" -#include -#include -#include - -#include -#include -#include -#include -#include - -#define NULL_VALUE "NULL" -#define AVOID_PROTECTED_HACK "avoid-protected-hack" -#define PARENT_CTOR_HEURISTIC "enable-parent-ctor-heuristic" -#define RETURN_VALUE_HEURISTIC "enable-return-value-heuristic" -#define ENABLE_PYSIDE_EXTENSIONS "enable-pyside-extensions" -#define DISABLE_VERBOSE_ERROR_MESSAGES "disable-verbose-error-messages" -#define USE_ISNULL_AS_NB_NONZERO "use-isnull-as-nb_nonzero" - -//static void dumpFunction(AbstractMetaFunctionList lst); - -QHash ShibokenGenerator::m_pythonPrimitiveTypeName = QHash(); -QHash ShibokenGenerator::m_pythonOperators = QHash(); -QHash ShibokenGenerator::m_formatUnits = QHash(); -QHash ShibokenGenerator::m_tpFuncs = QHash(); -QStringList ShibokenGenerator::m_knownPythonTypes = QStringList(); - -static QRegularExpression placeHolderRegex(int index) -{ - return QRegularExpression(QLatin1Char('%') + QString::number(index) + QStringLiteral("\\b")); -} - -static QString resolveScopePrefix(const AbstractMetaClass* scope, const QString& value) -{ - if (!scope) - return QString(); - - QString name; - QStringList parts = scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); - for(int i = (parts.size() - 1) ; i >= 0; i--) { - if (!value.startsWith(parts[i] + QLatin1String("::"))) - name = parts[i] + QLatin1String("::") + name; - else - name.clear(); - } - - return name; -} -ShibokenGenerator::ShibokenGenerator() : Generator() -{ - if (m_pythonPrimitiveTypeName.isEmpty()) - ShibokenGenerator::initPrimitiveTypesCorrespondences(); - - if (m_tpFuncs.isEmpty()) - ShibokenGenerator::clearTpFuncs(); - - if (m_knownPythonTypes.isEmpty()) - ShibokenGenerator::initKnownPythonTypes(); - - m_metaTypeFromStringCache = AbstractMetaTypeCache(); - - m_typeSystemConvName[TypeSystemCheckFunction] = QLatin1String("checkType"); - m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible"); - m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp"); - m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython"); - m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX)); - m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX)); - m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX)); - m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX)); -} - -ShibokenGenerator::~ShibokenGenerator() -{ - // TODO-CONVERTER: it must be caching types that were not created here. - //qDeleteAll(m_metaTypeFromStringCache.values()); -} - -void ShibokenGenerator::clearTpFuncs() -{ - m_tpFuncs.insert(QLatin1String("__str__"), QLatin1String("0")); - m_tpFuncs.insert(QLatin1String("__repr__"), QLatin1String("0")); - m_tpFuncs.insert(QLatin1String("__iter__"), QLatin1String("0")); - m_tpFuncs.insert(QLatin1String("__next__"), QLatin1String("0")); -} - -void ShibokenGenerator::initPrimitiveTypesCorrespondences() -{ - // Python primitive types names - m_pythonPrimitiveTypeName.clear(); - - // PyBool - m_pythonPrimitiveTypeName.insert(QLatin1String("bool"), QLatin1String("PyBool")); - - // PyInt - m_pythonPrimitiveTypeName.insert(QLatin1String("char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned char"), QLatin1String("SbkChar")); - m_pythonPrimitiveTypeName.insert(QLatin1String("int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("uint"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ushort"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short int"), QLatin1String("PyInt")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long"), QLatin1String("PyInt")); - - // PyFloat - m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat")); - m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat")); - - // PyLong - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("signed long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("ulong"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long int"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("__int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long long"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned __int64"), QLatin1String("PyLong")); - m_pythonPrimitiveTypeName.insert(QLatin1String("size_t"), QLatin1String("PyLong")); - - // Python operators - m_pythonOperators.clear(); - - // call operator - m_pythonOperators.insert(QLatin1String("operator()"), QLatin1String("call")); - - // Arithmetic operators - m_pythonOperators.insert(QLatin1String("operator+"), QLatin1String("add")); - m_pythonOperators.insert(QLatin1String("operator-"), QLatin1String("sub")); - m_pythonOperators.insert(QLatin1String("operator*"), QLatin1String("mul")); - m_pythonOperators.insert(QLatin1String("operator/"), QLatin1String("div")); - m_pythonOperators.insert(QLatin1String("operator%"), QLatin1String("mod")); - - // Inplace arithmetic operators - m_pythonOperators.insert(QLatin1String("operator+="), QLatin1String("iadd")); - m_pythonOperators.insert(QLatin1String("operator-="), QLatin1String("isub")); - m_pythonOperators.insert(QLatin1String("operator++"), QLatin1String("iadd")); - m_pythonOperators.insert(QLatin1String("operator--"), QLatin1String("isub")); - m_pythonOperators.insert(QLatin1String("operator*="), QLatin1String("imul")); - m_pythonOperators.insert(QLatin1String("operator/="), QLatin1String("idiv")); - m_pythonOperators.insert(QLatin1String("operator%="), QLatin1String("imod")); - - // Bitwise operators - m_pythonOperators.insert(QLatin1String("operator&"), QLatin1String("and")); - m_pythonOperators.insert(QLatin1String("operator^"), QLatin1String("xor")); - m_pythonOperators.insert(QLatin1String("operator|"), QLatin1String("or")); - m_pythonOperators.insert(QLatin1String("operator<<"), QLatin1String("lshift")); - m_pythonOperators.insert(QLatin1String("operator>>"), QLatin1String("rshift")); - m_pythonOperators.insert(QLatin1String("operator~"), QLatin1String("invert")); - - // Inplace bitwise operators - m_pythonOperators.insert(QLatin1String("operator&="), QLatin1String("iand")); - m_pythonOperators.insert(QLatin1String("operator^="), QLatin1String("ixor")); - m_pythonOperators.insert(QLatin1String("operator|="), QLatin1String("ior")); - m_pythonOperators.insert(QLatin1String("operator<<="), QLatin1String("ilshift")); - m_pythonOperators.insert(QLatin1String("operator>>="), QLatin1String("irshift")); - - // Comparison operators - m_pythonOperators.insert(QLatin1String("operator=="), QLatin1String("eq")); - m_pythonOperators.insert(QLatin1String("operator!="), QLatin1String("ne")); - m_pythonOperators.insert(QLatin1String("operator<"), QLatin1String("lt")); - m_pythonOperators.insert(QLatin1String("operator>"), QLatin1String("gt")); - m_pythonOperators.insert(QLatin1String("operator<="), QLatin1String("le")); - m_pythonOperators.insert(QLatin1String("operator>="), QLatin1String("ge")); - - // Initialize format units for C++->Python->C++ conversion - m_formatUnits.clear(); - m_formatUnits.insert(QLatin1String("char"), QLatin1String("b")); - m_formatUnits.insert(QLatin1String("unsigned char"), QLatin1String("B")); - m_formatUnits.insert(QLatin1String("int"), QLatin1String("i")); - m_formatUnits.insert(QLatin1String("unsigned int"), QLatin1String("I")); - m_formatUnits.insert(QLatin1String("short"), QLatin1String("h")); - m_formatUnits.insert(QLatin1String("unsigned short"), QLatin1String("H")); - m_formatUnits.insert(QLatin1String("long"), QLatin1String("l")); - m_formatUnits.insert(QLatin1String("unsigned long"), QLatin1String("k")); - m_formatUnits.insert(QLatin1String("long long"), QLatin1String("L")); - m_formatUnits.insert(QLatin1String("__int64"), QLatin1String("L")); - m_formatUnits.insert(QLatin1String("unsigned long long"), QLatin1String("K")); - m_formatUnits.insert(QLatin1String("unsigned __int64"), QLatin1String("K")); - m_formatUnits.insert(QLatin1String("double"), QLatin1String("d")); - m_formatUnits.insert(QLatin1String("float"), QLatin1String("f")); -} - -void ShibokenGenerator::initKnownPythonTypes() -{ - m_knownPythonTypes.clear(); - m_knownPythonTypes << QLatin1String("PyBool") << QLatin1String("PyInt") - << QLatin1String("PyFloat") << QLatin1String("PyLong") << QLatin1String("PyObject") - << QLatin1String("PyString") << QLatin1String("PyBuffer") << QLatin1String("PySequence") - << QLatin1String("PyTuple") << QLatin1String("PyList") << QLatin1String("PyDict") - << QLatin1String("PyObject*") << QLatin1String("PyObject *") << QLatin1String("PyTupleObject*"); -} - -QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* cType, - const AbstractMetaClass* context, - Options options) const -{ - if (cType->isArray()) - return translateTypeForWrapperMethod(cType->arrayElementType(), context, options) + QLatin1String("[]"); - - if (avoidProtectedHack() && cType->isEnum()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(cType); - if (metaEnum && metaEnum->isProtected()) - return protectedEnumSurrogateName(metaEnum); - } - - return translateType(cType, context, options); -} - -bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const -{ - bool result = metaClass->isPolymorphic() || metaClass->hasVirtualDestructor(); - if (avoidProtectedHack()) { - result = result || metaClass->hasProtectedFields() || metaClass->hasProtectedDestructor(); - if (!result && metaClass->hasProtectedFunctions()) { - int protectedFunctions = 0; - int protectedOperators = 0; - const AbstractMetaFunctionList &funcs = metaClass->functions(); - for (const AbstractMetaFunction *func : funcs) { - if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved()) - continue; - else if (func->isOperatorOverload()) - protectedOperators++; - else - protectedFunctions++; - } - result = result || (protectedFunctions > protectedOperators); - } - } else { - result = result && !metaClass->hasPrivateDestructor(); - } - return result && !metaClass->isNamespace(); -} - -void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass) -{ - if (!metaClass) - return; - - if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum *metaEnum : enums) { - if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) - continue; - if (!enumList.contains(const_cast(metaEnum))) - enumList.append(const_cast(metaEnum)); - } - lookForEnumsInClassesNotToBeGenerated(enumList, metaClass->enclosingClass()); - } -} - -static const AbstractMetaClass* getProperEnclosingClass(const AbstractMetaClass* metaClass) -{ - if (!metaClass) - return 0; - - if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) - return metaClass; - - return getProperEnclosingClass(metaClass->enclosingClass()); -} - -const AbstractMetaClass* ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum) -{ - return getProperEnclosingClass(metaEnum->enclosingClass()); -} - -QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const -{ - if (shouldGenerateCppWrapper(metaClass)) { - QString result = metaClass->name(); - if (metaClass->enclosingClass()) // is a inner class - result.replace(QLatin1String("::"), QLatin1String("_")); - - result += QLatin1String("Wrapper"); - return result; - } else { - return metaClass->qualifiedCppName(); - } -} - -QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const -{ - return metaType->cppSignature(); -} - -QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func) -{ - QString funcName; - if (func->isOperatorOverload()) - funcName = ShibokenGenerator::pythonOperatorFunctionName(func); - else - funcName = func->name(); - if (func->ownerClass()) { - QString fullName = func->ownerClass()->fullName(); - if (func->isConstructor()) - funcName = fullName; - else - funcName.prepend(fullName + QLatin1Char('.')); - } - return funcName; -} - -QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum) -{ - return metaEnum->fullName().replace(QLatin1Char('.'), QLatin1Char('_')).replace(QLatin1String("::"), QLatin1String("_")) + QLatin1String("_Surrogate"); -} - -QString ShibokenGenerator::protectedFieldGetterName(const AbstractMetaField* field) -{ - return QStringLiteral("protected_%1_getter").arg(field->name()); -} - -QString ShibokenGenerator::protectedFieldSetterName(const AbstractMetaField* field) -{ - return QStringLiteral("protected_%1_setter").arg(field->name()); -} - -QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func) -{ - QString result; - - // PYSIDE-331: For inherited functions, we need to find the same labels. - // Therefore we use the implementing class. - if (func->implementingClass()) { - result = cpythonBaseName(func->implementingClass()->typeEntry()); - if (func->isConstructor()) { - result += QLatin1String("_Init"); - } else { - result += QLatin1String("Func_"); - if (func->isOperatorOverload()) - result += ShibokenGenerator::pythonOperatorFunctionName(func); - else - result += func->name(); - } - } else { - result = QLatin1String("Sbk") + moduleName() + QLatin1String("Module_") + func->name(); - } - - return result; -} - -QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunction* func) -{ - if (!func->ownerClass()) - return QString(); - return QStringLiteral("%1Method_%2").arg(cpythonBaseName(func->ownerClass()->typeEntry()), func->name()); -} - -QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass) -{ - return cpythonBaseName(metaClass) + QLatin1String("_getsetlist"); -} - -QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass* metaClass) -{ - return cpythonBaseName(metaClass) + QLatin1String("_setattro"); -} - - -QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass* metaClass) -{ - return cpythonBaseName(metaClass) + QLatin1String("_getattro"); -} - -QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField* metaField) -{ - return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); -} - -QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField* metaField) -{ - return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); -} - -static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName) -{ - QString result = QStringLiteral("Sbk%1_%2").arg(moduleName, qualifiedCppName); - result.replace(QLatin1String("::"), QLatin1String("_")); - return result; -} - -static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QString& value) -{ - QString enumValueName = value.trimmed(); - - if (!metaClass) - return QString(); - const AbstractMetaEnumList &enums = metaClass->enums(); - for (const AbstractMetaEnum* metaEnum : enums) { - const AbstractMetaEnumValueList &values = metaEnum->values(); - for (const AbstractMetaEnumValue *enumValue : values) { - if (enumValueName == enumValue->name()) - return metaClass->qualifiedCppName(); - } - } - // PYSIDE-331: We need to also search the base classes. - QString ret = searchForEnumScope(metaClass->enclosingClass(), enumValueName); - if (ret.isEmpty()) - ret = searchForEnumScope(metaClass->baseClass(), enumValueName); - return ret; -} - -/* - * This function uses some heuristics to find out the scope for a given - * argument default value. New situations may arise in the future and - * this method should be updated, do it with care. - */ -QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg) -{ - QString value = getDefaultValue(func, arg); - - if (value.isEmpty()) - return QString(); - - if (isPointer(arg->type())) - return value; - - static const QRegularExpression enumValueRegEx(QStringLiteral("^([A-Za-z_]\\w*)?$")); - Q_ASSERT(enumValueRegEx.isValid()); - // Do not qualify macros by class name, eg QSGGeometry(..., int t = GL_UNSIGNED_SHORT); - static const QRegularExpression macroRegEx(QStringLiteral("^[A-Z_][A-Z0-9_]*$")); - Q_ASSERT(macroRegEx.isValid()); - if (arg->type()->isPrimitive() && macroRegEx.match(value).hasMatch()) - return value; - - QString prefix; - QString suffix; - - if (arg->type()->isEnum()) { - const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type()); - if (metaEnum) - prefix = resolveScopePrefix(metaEnum->enclosingClass(), value); - } else if (arg->type()->isFlags()) { - static const QRegularExpression numberRegEx(QStringLiteral("^\\d+$")); // Numbers to flags - Q_ASSERT(numberRegEx.isValid()); - if (numberRegEx.match(value).hasMatch()) { - QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass()); - if (arg->type()->isConstant()) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - switch (arg->type()->referenceType()) { - case NoReference: - break; - case LValueReference: - typeName.chop(1); - break; - case RValueReference: - typeName.chop(2); - break; - } - prefix = typeName + QLatin1Char('('); - suffix = QLatin1Char(')'); - } - - static const QRegularExpression enumCombinationRegEx(QStringLiteral("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) - Q_ASSERT(enumCombinationRegEx.isValid()); - const QRegularExpressionMatch match = enumCombinationRegEx.match(value); - if (prefix.isEmpty() && match.hasMatch()) { - QString flagName = match.captured(1); - QStringList enumItems = match.captured(2).split(QLatin1Char('|')); - QString scope = searchForEnumScope(func->implementingClass(), enumItems.first()); - if (!scope.isEmpty()) - scope.append(QLatin1String("::")); - - QStringList fixedEnumItems; - for (const QString &enumItem : qAsConst(enumItems)) - fixedEnumItems << QString(scope + enumItem); - - if (!fixedEnumItems.isEmpty()) { - prefix = flagName + QLatin1Char('('); - value = fixedEnumItems.join(QLatin1Char('|')); - suffix = QLatin1Char(')'); - } - } - } else if (arg->type()->typeEntry()->isValue()) { - const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry()); - if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL")) - prefix = resolveScopePrefix(metaClass, value); - } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) { - if (enumValueRegEx.match(value).hasMatch() && func->implementingClass()) - prefix = resolveScopePrefix(func->implementingClass(), value); - } else if(arg->type()->isPrimitive()) { - static const QRegularExpression unknowArgumentRegEx(QStringLiteral("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] - Q_ASSERT(unknowArgumentRegEx.isValid()); - const QRegularExpressionMatch match = unknowArgumentRegEx.match(value); - if (match.hasMatch() && func->implementingClass()) { - const AbstractMetaFieldList &fields = func->implementingClass()->fields(); - for (const AbstractMetaField *field : fields) { - if (match.captured(1).trimmed() == field->name()) { - QString fieldName = field->name(); - if (field->isStatic()) { - prefix = resolveScopePrefix(func->implementingClass(), value); - fieldName.prepend(prefix); - prefix.clear(); - } else { - fieldName.prepend(QLatin1String(CPP_SELF_VAR "->")); - } - value.replace(match.captured(1), fieldName); - break; - } - } - } - } - - if (!prefix.isEmpty()) - value.prepend(prefix); - if (!suffix.isEmpty()) - value.append(suffix); - - return value; -} - -QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry* enumEntry) -{ - QString p = enumEntry->targetLangPackage(); - p.replace(QLatin1Char('.'), QLatin1Char('_')); - return cpythonEnumFlagsName(p, enumEntry->qualifiedCppName()); -} - -QString ShibokenGenerator::cpythonEnumName(const AbstractMetaEnum *metaEnum) -{ - return cpythonEnumName(metaEnum->typeEntry()); -} - -QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry* flagsEntry) -{ - QString p = flagsEntry->targetLangPackage(); - p.replace(QLatin1Char('.'), QLatin1Char('_')); - return cpythonEnumFlagsName(p, flagsEntry->originalName()); -} - -QString ShibokenGenerator::cpythonFlagsName(const AbstractMetaEnum *metaEnum) -{ - const FlagsTypeEntry *flags = metaEnum->typeEntry()->flags(); - if (!flags) - return QString(); - return cpythonFlagsName(flags); -} - -QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass) -{ - return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction"); -} - -QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName) -{ - return cpythonWrapperCPtr(metaClass->typeEntry(), argName); -} - -QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName) -{ - if (!ShibokenGenerator::isWrapperType(metaType->typeEntry())) - return QString(); - return QLatin1String("reinterpret_cast< ::") + metaType->cppSignature() - + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(metaType) - + QLatin1String(", reinterpret_cast(") + argName + QLatin1String(")))"); -} - -QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName) -{ - if (!ShibokenGenerator::isWrapperType(type)) - return QString(); - return QLatin1String("reinterpret_cast< ::") + type->qualifiedCppName() - + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(type) - + QLatin1String(", reinterpret_cast(") + argName + QLatin1String(")))"); -} - -QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func, Options) const -{ - if (func->ownerClass() && func->isConstructor()) - return func->ownerClass()->qualifiedCppName() + QLatin1Char('*'); - - return translateTypeForWrapperMethod(func->type(), func->implementingClass()); -} - -void ShibokenGenerator::writeToPythonConversion(QTextStream & s, const AbstractMetaType* type, - const AbstractMetaClass * /* context */, - const QString& argumentName) -{ - s << cpythonToPythonConversionFunction(type) << argumentName << ')'; -} - -void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, - const QString& inArgName, const QString& outArgName) -{ - s << cpythonToCppConversionFunction(metaClass) << inArgName << ", &" << outArgName << ')'; -} - -void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context, - const QString& inArgName, const QString& outArgName) -{ - s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')'; -} - -bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex) -{ - if (argIndex < 0 || argIndex >= func->arguments().count()) - return false; - - const AbstractMetaArgument* arg = func->arguments().at(argIndex); - if (isValueTypeWithCopyConstructorOnly(arg->type())) - return true; - - // Argument type is not a pointer, a None rejection should not be - // necessary because the type checking would handle that already. - if (!isPointer(arg->type())) - return false; - if (func->argumentRemoved(argIndex + 1)) - return false; - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &funcMod : mods) { - for (const ArgumentModification &argMod : funcMod.argument_mods) { - if (argMod.index == argIndex + 1 && argMod.noNullPointers) - return true; - } - } - return false; -} - -QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, bool incRef) const -{ - QString result; - const char objType = (incRef ? 'O' : 'N'); - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - - if (!func->typeReplaced(arg->argumentIndex() + 1).isEmpty()) { - result += QLatin1Char(objType); - } else if (arg->type()->isQObject() - || arg->type()->isObject() - || arg->type()->isValue() - || arg->type()->isValuePointer() - || arg->type()->isNativePointer() - || arg->type()->isEnum() - || arg->type()->isFlags() - || arg->type()->isContainer() - || arg->type()->isSmartPointer() - || arg->type()->referenceType() == LValueReference) { - result += QLatin1Char(objType); - } else if (arg->type()->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); - if (ptype->basicReferencedTypeEntry()) - ptype = ptype->basicReferencedTypeEntry(); - if (m_formatUnits.contains(ptype->name())) - result += m_formatUnits[ptype->name()]; - else - result += QLatin1Char(objType); - } else if (isCString(arg->type())) { - result += QLatin1Char('z'); - } else { - qCWarning(lcShiboken).noquote().nospace() - << "Method: " << func->ownerClass()->qualifiedCppName() - << "::" << func->signature() << " => Arg:" - << arg->name() << "index: " << arg->argumentIndex() - << " - cannot be handled properly. Use an inject-code to fix it!"; - result += QLatin1Char('?'); - } - } - return result; -} - -QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType* type) -{ - if (isCString(type)) - return QLatin1String("PyString"); - return cpythonBaseName(type->typeEntry()); -} - -QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClass* metaClass) -{ - return cpythonBaseName(metaClass->typeEntry()); -} - -QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) -{ - QString baseName; - if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && type->referenceType() == NoReference) { - baseName = QLatin1String("Sbk_") + type->name(); - } else if (type->isPrimitive()) { - const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type; - while (ptype->basicReferencedTypeEntry()) - ptype = ptype->basicReferencedTypeEntry(); - if (ptype->targetLangApiName() == ptype->name()) - baseName = pythonPrimitiveTypeName(ptype->name()); - else - baseName = ptype->targetLangApiName(); - } else if (type->isEnum()) { - baseName = cpythonEnumName((const EnumTypeEntry*) type); - } else if (type->isFlags()) { - baseName = cpythonFlagsName((const FlagsTypeEntry*) type); - } else if (type->isContainer()) { - const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type; - switch (ctype->type()) { - case ContainerTypeEntry::ListContainer: - case ContainerTypeEntry::StringListContainer: - case ContainerTypeEntry::LinkedListContainer: - case ContainerTypeEntry::VectorContainer: - case ContainerTypeEntry::StackContainer: - case ContainerTypeEntry::QueueContainer: - //baseName = "PyList"; - //break; - case ContainerTypeEntry::PairContainer: - //baseName = "PyTuple"; - baseName = QLatin1String("PySequence"); - break; - case ContainerTypeEntry::SetContainer: - baseName = QLatin1String("PySet"); - break; - case ContainerTypeEntry::MapContainer: - case ContainerTypeEntry::MultiMapContainer: - case ContainerTypeEntry::HashContainer: - case ContainerTypeEntry::MultiHashContainer: - baseName = QLatin1String("PyDict"); - break; - default: - Q_ASSERT(false); - } - } else { - baseName = QLatin1String("PyObject"); - } - return baseName.replace(QLatin1String("::"), QLatin1String("_")); -} - -QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass* metaClass) -{ - return cpythonTypeName(metaClass->typeEntry()); -} - -QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type) -{ - return cpythonBaseName(type) + QLatin1String("_Type"); -} - -QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type) -{ - return cppApiVariableName(type->targetLangPackage()) + QLatin1Char('[') - + getTypeIndexVariableName(type) + QLatin1Char(']'); -} - -QString ShibokenGenerator::converterObject(const AbstractMetaType* type) -{ - if (isCString(type)) - return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter()"); - if (isVoidPointer(type)) - return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter()"); - if (type->typeEntry()->isContainer()) { - return convertersVariableName(type->typeEntry()->targetLangPackage()) - + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); - } - return converterObject(type->typeEntry()); -} - -QString ShibokenGenerator::converterObject(const TypeEntry* type) -{ - if (isCppPrimitive(type)) - return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName()); - if (isWrapperType(type) || type->isEnum() || type->isFlags()) - return QString::fromLatin1("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type)); - - if (type->isArray()) { - qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName(); - return QString::null; - } - - /* the typedef'd primitive types case */ - const PrimitiveTypeEntry* pte = dynamic_cast(type); - if (!pte) { - qDebug() << "Warning: the Qt5 primitive type is unknown" << type->qualifiedCppName(); - return QString::null; - } - if (pte->basicReferencedTypeEntry()) - pte = pte->basicReferencedTypeEntry(); - if (pte->isPrimitive() && !pte->isCppPrimitive() && !pte->customConversion()) - return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(pte->qualifiedCppName()); - - return convertersVariableName(type->targetLangPackage()) - + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); -} - -QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type) -{ - return cppApiVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') - + getTypeIndexVariableName(type) + QLatin1Char(']'); -} - -static QString msgUnknownOperator(const AbstractMetaFunction* func) -{ - QString result = QLatin1String("Unknown operator: \"") + func->originalName() + QLatin1Char('"'); - if (const AbstractMetaClass *c = func->implementingClass()) - result += QLatin1String(" in class: ") + c->name(); - return result; -} - -static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); } - -QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func) -{ - if (!func->isOperatorOverload()) - return QString(); - const QString pythonOp = pythonOperatorFunctionName(func->originalName()); - if (pythonOp == unknownOperator()) - qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func); - return QLatin1String("Sbk") + func->ownerClass()->name() - + QLatin1Char('_') + pythonOp; -} - -QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative) -{ - if (toNative->sourceType()) - return fixedCppTypeName(toNative->sourceType()); - return toNative->sourceTypeName(); -} -QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType* type) -{ - return fixedCppTypeName(type->typeEntry(), type->cppSignature()); -} - -static QString _fixedCppTypeName(QString typeName) -{ - typeName.remove(QLatin1Char(' ')); - typeName.replace(QLatin1Char('.'), QLatin1Char('_')); - typeName.replace(QLatin1Char(','), QLatin1Char('_')); - typeName.replace(QLatin1Char('<'), QLatin1Char('_')); - typeName.replace(QLatin1Char('>'), QLatin1Char('_')); - typeName.replace(QLatin1String("::"), QLatin1String("_")); - typeName.replace(QLatin1String("*"), QLatin1String("PTR")); - typeName.replace(QLatin1String("&"), QLatin1String("REF")); - return typeName; -} -QString ShibokenGenerator::fixedCppTypeName(const TypeEntry* type, QString typeName) -{ - if (typeName.isEmpty()) - typeName = type->qualifiedCppName(); - if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang)) { - typeName.prepend(QLatin1Char('_')); - typeName.prepend(type->targetLangPackage()); - } - return _fixedCppTypeName(typeName); -} - -QString ShibokenGenerator::pythonPrimitiveTypeName(const QString& cppTypeName) -{ - QString rv = ShibokenGenerator::m_pythonPrimitiveTypeName.value(cppTypeName, QString()); - if (rv.isEmpty()) { - // activate this when some primitive types are missing, - // i.e. when shiboken itself fails to build. - // In general, this is valid while just called by isNumeric() - // used on Qt5, 2015-09-20 - if (false) { - std::cerr << "primitive type not found: " << qPrintable(cppTypeName) << std::endl; - abort(); - } - } - return rv; -} - -QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* type) -{ - while (type->basicReferencedTypeEntry()) - type = type->basicReferencedTypeEntry(); - return pythonPrimitiveTypeName(type->name()); -} - -QString ShibokenGenerator::pythonOperatorFunctionName(QString cppOpFuncName) -{ - QString value = m_pythonOperators.value(cppOpFuncName); - if (value.isEmpty()) - return unknownOperator(); - value.prepend(QLatin1String("__")); - value.append(QLatin1String("__")); - return value; -} - -QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction* func) -{ - QString op = pythonOperatorFunctionName(func->originalName()); - if (op == unknownOperator()) - qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func); - if (func->arguments().isEmpty()) { - if (op == QLatin1String("__sub__")) - op = QLatin1String("__neg__"); - else if (op == QLatin1String("__add__")) - op = QLatin1String("__pos__"); - } else if (func->isStatic() && func->arguments().size() == 2) { - // If a operator overload function has 2 arguments and - // is static we assume that it is a reverse operator. - op = op.insert(2, QLatin1Char('r')); - } - return op; -} - -QString ShibokenGenerator::pythonRichCompareOperatorId(QString cppOpFuncName) -{ - return QLatin1String("Py_") + m_pythonOperators.value(cppOpFuncName).toUpper(); -} - -QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunction* func) -{ - return pythonRichCompareOperatorId(func->originalName()); -} - -bool ShibokenGenerator::isNumber(QString cpythonApiName) -{ - return cpythonApiName == QLatin1String("PyInt") - || cpythonApiName == QLatin1String("PyFloat") - || cpythonApiName == QLatin1String("PyLong") - || cpythonApiName == QLatin1String("PyBool"); -} - -bool ShibokenGenerator::isNumber(const TypeEntry* type) -{ - if (!type->isPrimitive()) - return false; - return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type)); -} - -bool ShibokenGenerator::isNumber(const AbstractMetaType* type) -{ - return isNumber(type->typeEntry()); -} - -bool ShibokenGenerator::isPyInt(const TypeEntry* type) -{ - if (!type->isPrimitive()) - return false; - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == QLatin1String("PyInt"); -} - -bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) -{ - return isPyInt(type->typeEntry()); -} - -bool ShibokenGenerator::isPairContainer(const AbstractMetaType* type) -{ - return type->isContainer() - && static_cast(type->typeEntry())->type() == ContainerTypeEntry::PairContainer; -} - -bool ShibokenGenerator::isWrapperType(const TypeEntry* type) -{ - if (type->isComplex()) - return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type); - return type->isObject() || type->isValue() || type->isSmartPointer(); -} -bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type) -{ - return isObjectType(type) || type->isValue() || type->isSmartPointer(); -} -bool ShibokenGenerator::isWrapperType(const AbstractMetaType* metaType) -{ - return isObjectType(metaType) - || metaType->typeEntry()->isValue() - || metaType->typeEntry()->isSmartPointer(); -} - -bool ShibokenGenerator::isPointerToWrapperType(const AbstractMetaType* type) -{ - return (isObjectType(type) && type->indirections() == 1) || type->isValuePointer(); -} - -bool ShibokenGenerator::isObjectTypeUsedAsValueType(const AbstractMetaType* type) -{ - return type->typeEntry()->isObject() && type->referenceType() == NoReference && type->indirections() == 0; -} - -bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass) -{ - if (!metaClass || !metaClass->typeEntry()->isValue()) - return false; - AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); - if (ctors.count() != 1) - return false; - return ctors.first()->functionType() == AbstractMetaFunction::CopyConstructorFunction; -} - -bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const -{ - if (!type || !type->isValue()) - return false; - return isValueTypeWithCopyConstructorOnly(AbstractMetaClass::findClass(classes(), type)); -} - -bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const -{ - if (!type || !type->typeEntry()->isValue()) - return false; - return isValueTypeWithCopyConstructorOnly(type->typeEntry()); -} - -bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type) -{ - if (!type->isPrimitive()) - return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; - if (trueType->basicReferencedTypeEntry()) - trueType = trueType->basicReferencedTypeEntry(); - return trueType->isPrimitive() && !trueType->isCppPrimitive() - && trueType->qualifiedCppName() != QLatin1String("std::string"); -} - -bool ShibokenGenerator::isUserPrimitive(const AbstractMetaType* type) -{ - if (type->indirections() != 0) - return false; - return isUserPrimitive(type->typeEntry()); -} - -bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type) -{ - if (type->isCppPrimitive()) - return true; - if (!type->isPrimitive()) - return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; - if (trueType->basicReferencedTypeEntry()) - trueType = trueType->basicReferencedTypeEntry(); - return trueType->qualifiedCppName() == QLatin1String("std::string"); -} - -bool ShibokenGenerator::isCppPrimitive(const AbstractMetaType* type) -{ - if (isCString(type) || isVoidPointer(type)) - return true; - if (type->indirections() != 0) - return false; - return isCppPrimitive(type->typeEntry()); -} - -bool ShibokenGenerator::shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg) -{ - return shouldDereferenceAbstractMetaTypePointer(arg->type()); -} - -bool ShibokenGenerator::shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType) -{ - return metaType->referenceType() == LValueReference && isWrapperType(metaType) && !isPointer(metaType); -} - -bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction* func) -{ - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &mod : mods) { - if (mod.modifiers & Modification::Private) - return true; - } - return false; -} - -QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType) -{ - QString customCheck; - if (metaType->typeEntry()->isCustom()) { - AbstractMetaType* type; - customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type); - if (type) - metaType = type; - if (!customCheck.isEmpty()) - return customCheck; - } - - if (isCppPrimitive(metaType)) { - if (isCString(metaType)) - return QLatin1String("Shiboken::String::check"); - if (isVoidPointer(metaType)) - return QLatin1String("PyObject_Check"); - return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); - } else if (metaType->typeEntry()->isContainer()) { - QString typeCheck = QLatin1String("Shiboken::Conversions::"); - ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type(); - if (type == ContainerTypeEntry::ListContainer - || type == ContainerTypeEntry::StringListContainer - || type == ContainerTypeEntry::LinkedListContainer - || type == ContainerTypeEntry::VectorContainer - || type == ContainerTypeEntry::StackContainer - || type == ContainerTypeEntry::SetContainer - || type == ContainerTypeEntry::QueueContainer) { - const AbstractMetaType* type = metaType->instantiations().first(); - if (isPointerToWrapperType(type)) { - typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type)); - } else if (isWrapperType(type)) { - typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast("); - typeCheck += cpythonTypeNameExt(type); - typeCheck += QLatin1String("), "); - } else { - typeCheck += QString::fromLatin1("convertibleSequenceTypes(%1, ").arg(converterObject(type)); - } - } else if (type == ContainerTypeEntry::MapContainer - || type == ContainerTypeEntry::MultiMapContainer - || type == ContainerTypeEntry::HashContainer - || type == ContainerTypeEntry::MultiHashContainer - || type == ContainerTypeEntry::PairContainer) { - QString pyType = (type == ContainerTypeEntry::PairContainer) ? QLatin1String("Pair") : QLatin1String("Dict"); - const AbstractMetaType* firstType = metaType->instantiations().first(); - const AbstractMetaType* secondType = metaType->instantiations().last(); - if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) { - typeCheck += QString::fromLatin1("check%1Types(%2, %3, ").arg(pyType) - .arg(cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType)); - } else { - typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ") - .arg(pyType, converterObject(firstType), - isPointerToWrapperType(firstType) ? QLatin1String("true") : QLatin1String("false"), - converterObject(secondType), - isPointerToWrapperType(secondType) ? QLatin1String("true") : QLatin1String("false")); - } - } - return typeCheck; - } - return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); -} - -QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool genericNumberType) -{ - QString customCheck; - if (type->isCustom()) { - AbstractMetaType* metaType; - customCheck = guessCPythonCheckFunction(type->name(), &metaType); - if (metaType) - return cpythonCheckFunction(metaType, genericNumberType); - return customCheck; - } - - if (type->isEnum() || type->isFlags() || isWrapperType(type)) - return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type)); - else if (isCppPrimitive(type)) - return pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type) + QLatin1String("_Check"); - QString typeCheck; - if (type->targetLangApiName() == type->name()) - typeCheck = cpythonIsConvertibleFunction(type); - else if (type->targetLangApiName() == QLatin1String("PyUnicode")) - typeCheck = QLatin1String("Shiboken::String::check"); - else - typeCheck = type->targetLangApiName() + QLatin1String("_Check"); - return typeCheck; -} - -QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType) -{ - *metaType = 0; - if (type == QLatin1String("PyTypeObject")) - return QLatin1String("PyType_Check"); - - if (type == QLatin1String("PyBuffer")) - return QLatin1String("Shiboken::Buffer::checkType"); - - if (type == QLatin1String("str")) - return QLatin1String("Shiboken::String::check"); - - *metaType = buildAbstractMetaTypeFromString(type); - if (*metaType && !(*metaType)->typeEntry()->isCustom()) - return QString(); - - return type + QLatin1String("_Check"); -} - -QString ShibokenGenerator::guessCPythonIsConvertible(const QString& type) -{ - if (type == QLatin1String("PyTypeObject")) - return QLatin1String("PyType_Check"); - - AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type); - if (metaType && !metaType->typeEntry()->isCustom()) - return cpythonIsConvertibleFunction(metaType); - - return type + QLatin1String("_Check"); -} - -QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type, - bool /* genericNumberType */, - bool /* checkExact */) -{ - if (isWrapperType(type)) { - QString result = QLatin1String("Shiboken::Conversions::"); - result += (type->isValue() && !isValueTypeWithCopyConstructorOnly(type)) - ? QLatin1String("isPythonToCppValueConvertible") - : QLatin1String("isPythonToCppPointerConvertible"); - result += QLatin1String("(reinterpret_cast(") - + cpythonTypeNameExt(type) + QLatin1String("), "); - return result; - } - return QString::fromLatin1("Shiboken::Conversions::isPythonToCppConvertible(%1, ") - .arg(converterObject(type)); -} -QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* metaType, - bool /* genericNumberType */) -{ - QString customCheck; - if (metaType->typeEntry()->isCustom()) { - AbstractMetaType* type; - customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type); - if (type) - metaType = type; - if (!customCheck.isEmpty()) - return customCheck; - } - - if (isWrapperType(metaType)) { - QString result = QLatin1String("Shiboken::Conversions::"); - if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType)) - result += QLatin1String("isPythonToCppPointerConvertible"); - else if (metaType->referenceType() == LValueReference) - result += QLatin1String("isPythonToCppReferenceConvertible"); - else - result += QLatin1String("isPythonToCppValueConvertible"); - result += QLatin1String("(reinterpret_cast(") - + cpythonTypeNameExt(metaType) + QLatin1String("), "); - return result; - } - return QStringLiteral("Shiboken::Conversions::isPythonToCppConvertible(%1, ") - .arg(converterObject(metaType)); -} - -QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType) -{ - return cpythonIsConvertibleFunction(metaArg->type(), genericNumberType); -} - -QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass* metaClass) -{ - return QLatin1String("Shiboken::Conversions::pythonToCppPointer(reinterpret_cast(") - + cpythonTypeNameExt(metaClass->typeEntry()) + QLatin1String("), "); -} - -QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType *type, - const AbstractMetaClass * /* context */) -{ - if (isWrapperType(type)) { - return QLatin1String("Shiboken::Conversions::pythonToCpp") - + (isPointer(type) ? QLatin1String("Pointer") : QLatin1String("Copy")) - + QLatin1String("(reinterpret_cast(") - + cpythonTypeNameExt(type) + QLatin1String("), "); - } - return QStringLiteral("Shiboken::Conversions::pythonToCppCopy(%1, ") - .arg(converterObject(type)); -} - -QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType *type, - const AbstractMetaClass * /* context */) -{ - if (isWrapperType(type)) { - QString conversion; - if (type->referenceType() == LValueReference && !(type->isValue() && type->isConstant()) && !isPointer(type)) - conversion = QLatin1String("reference"); - else if (type->isValue() || type->isSmartPointer()) - conversion = QLatin1String("copy"); - else - conversion = QLatin1String("pointer"); - QString result = QLatin1String("Shiboken::Conversions::") + conversion - + QLatin1String("ToPython(reinterpret_cast(") - + cpythonTypeNameExt(type) + QLatin1String("), "); - if (conversion != QLatin1String("pointer")) - result += QLatin1Char('&'); - return result; - } - return QStringLiteral("Shiboken::Conversions::copyToPython(%1, %2") - .arg(converterObject(type), - (isCString(type) || isVoidPointer(type)) ? QString() : QLatin1String("&")); -} - -QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass) -{ - return cpythonToPythonConversionFunction(metaClass->typeEntry()); -} - -QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry* type) -{ - if (isWrapperType(type)) { - const QString conversion = type->isValue() ? QLatin1String("copy") : QLatin1String("pointer"); - QString result = QLatin1String("Shiboken::Conversions::") + conversion - + QLatin1String("ToPython(reinterpret_cast(") + cpythonTypeNameExt(type) - + QLatin1String("), "); - if (conversion != QLatin1String("pointer")) - result += QLatin1Char('&'); - return result; - } - - return QStringLiteral("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type)); -} - -QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, - const AbstractMetaArgument *argument, - Options options) const -{ - QString modified_type; - if (!(options & OriginalTypeDescription)) - modified_type = func->typeReplaced(argument->argumentIndex() + 1); - QString arg; - - if (modified_type.isEmpty()) - arg = translateType(argument->type(), func->implementingClass(), options); - else - arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.')); - - if (!(options & Generator::SkipName)) { - arg += QLatin1Char(' '); - arg += argument->name(); - } - - if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues && - !argument->originalDefaultValueExpression().isEmpty()) - { - QString default_value = argument->originalDefaultValueExpression(); - if (default_value == QLatin1String("NULL")) - default_value = QLatin1String(NULL_VALUE); - - //WORKAROUND: fix this please - if (default_value.startsWith(QLatin1String("new "))) - default_value.remove(0, 4); - - arg += QLatin1String(" = ") + default_value; - } - - return arg; -} - -void ShibokenGenerator::writeArgument(QTextStream &s, - const AbstractMetaFunction *func, - const AbstractMetaArgument *argument, - Options options) const -{ - s << argumentString(func, argument, options); -} - -void ShibokenGenerator::writeFunctionArguments(QTextStream &s, - const AbstractMetaFunction *func, - Options options) const -{ - AbstractMetaArgumentList arguments = func->arguments(); - - if (options & Generator::WriteSelf) { - s << func->implementingClass()->name() << '&'; - if (!(options & SkipName)) - s << " " PYTHON_SELF_VAR; - } - - int argUsed = 0; - for (int i = 0; i < arguments.size(); ++i) { - if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i+1)) - continue; - - if ((options & Generator::WriteSelf) || argUsed != 0) - s << ", "; - writeArgument(s, func, arguments[i], options); - argUsed++; - } -} - -QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, Options options) const -{ - QString modifiedReturnType = QString(func->typeReplaced(0)); - if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription)) - return modifiedReturnType; - else - return translateType(func->type(), func->implementingClass(), options); -} - -QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, - QString prepend, - QString append, - Options options, - int /* argCount */) const -{ - QString result; - QTextStream s(&result); - // The actual function - if (!(func->isEmptyFunction() || - func->isNormal() || - func->isSignal())) { - options |= Generator::SkipReturnType; - } else { - s << functionReturnType(func, options) << ' '; - } - - // name - QString name(func->originalName()); - if (func->isConstructor()) - name = wrapperName(func->ownerClass()); - - s << prepend << name << append << '('; - writeFunctionArguments(s, func, options); - s << ')'; - - if (func->isConstant() && !(options & Generator::ExcludeMethodConst)) - s << " const"; - - return result; -} - -void ShibokenGenerator::writeArgumentNames(QTextStream &s, - const AbstractMetaFunction *func, - Options options) const -{ - AbstractMetaArgumentList arguments = func->arguments(); - int argCount = 0; - for (int j = 0, max = arguments.size(); j < max; j++) { - - if ((options & Generator::SkipRemovedArguments) && (func->argumentRemoved(arguments.at(j)->argumentIndex()+1))) - continue; - - s << ((argCount > 0) ? ", " : "") << arguments.at(j)->name(); - - if (((options & Generator::VirtualCall) == 0) - && (!func->conversionRule(TypeSystem::NativeCode, arguments.at(j)->argumentIndex() + 1).isEmpty() - || !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty()) - && !func->isConstructor()) { - s << CONV_RULE_OUT_VAR_SUFFIX; - } - - argCount++; - } -} - -void ShibokenGenerator::writeFunctionCall(QTextStream& s, - const AbstractMetaFunction* func, - Options options) const -{ - if (!(options & Generator::SkipName)) - s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName()); - s << '('; - writeArgumentNames(s, func, options); - s << ')'; -} - -void ShibokenGenerator::writeUnusedVariableCast(QTextStream& s, const QString& variableName) -{ - s << INDENT << "SBK_UNUSED(" << variableName<< ')' << endl; -} - -AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass) -{ - AbstractMetaFunctionList result; - const AbstractMetaFunctionList &funcs = metaClass->functions(); - for (AbstractMetaFunction *func : funcs) { - if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() - || (func->isModifiedRemoved() && !func->isAbstract() - && (!avoidProtectedHack() || !func->isProtected()))) - continue; - result << func; - } - return result; -} - -ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const -{ - ExtendedConverterData extConvs; - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) { - // Use only the classes for the current module. - if (!shouldGenerate(metaClass)) - continue; - const AbstractMetaFunctionList &overloads = metaClass->operatorOverloads(AbstractMetaClass::ConversionOp); - for (AbstractMetaFunction *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(); - if ((convType->codeGeneration() & TypeEntry::GenerateTargetLang) - || !convType->isValue() - || convOp->isModifiedRemoved()) - continue; - extConvs[convType].append(convOp->ownerClass()); - } - } - return extConvs; -} - -QVector ShibokenGenerator::getPrimitiveCustomConversions() -{ - QVector conversions; - const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); - for (const PrimitiveTypeEntry *type : primitiveTypeList) { - if (!shouldGenerateTypeEntry(type) || !isUserPrimitive(type) || !type->customConversion()) - continue; - - conversions << type->customConversion(); - } - return conversions; -} - -static QString getArgumentsFromMethodCall(const QString& str) -{ - // It would be way nicer to be able to use a Perl like - // regular expression that accepts temporary variables - // to count the parenthesis. - // 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); - if (pos == -1) - return QString(); - pos = pos + funcCall.size(); - while (str.at(pos) == QLatin1Char(' ') || str.at(pos) == QLatin1Char('\t')) - ++pos; - if (str.at(pos) == QLatin1Char('(')) - ++pos; - int begin = pos; - int counter = 1; - while (counter != 0) { - if (str.at(pos) == QLatin1Char('(')) - ++counter; - else if (str.at(pos) == QLatin1Char(')')) - --counter; - ++pos; - } - return str.mid(begin, pos-begin-1); -} - -QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language) -{ - QString code; - QTextStream c(&code); - for (const CodeSnip &snip : codeSnips) { - if ((position != TypeSystem::CodeSnipPositionAny && snip.position != position) || !(snip.language & language)) - continue; - QString snipCode; - QTextStream sc(&snipCode); - formatCode(sc, snip.code(), INDENT); - c << snipCode; - } - return code; -} -void ShibokenGenerator::processCodeSnip(QString& code, const AbstractMetaClass* context) -{ - if (context) { - // Replace template variable by the Python Type object - // for the class context in which the variable is used. - code.replace(QLatin1String("%PYTHONTYPEOBJECT"), - cpythonTypeName(context) + QLatin1String(".super.ht_type")); - code.replace(QLatin1String("%TYPE"), wrapperName(context)); - code.replace(QLatin1String("%CPPTYPE"), context->name()); - } - - // replace "toPython" converters - replaceConvertToPythonTypeSystemVariable(code); - - // replace "toCpp" converters - replaceConvertToCppTypeSystemVariable(code); - - // replace "isConvertible" check - replaceIsConvertibleToCppTypeSystemVariable(code); - - // replace "checkType" check - replaceTypeCheckTypeSystemVariable(code); -} - -ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunction* func, - bool usePyArgs, TypeSystem::Language language, - const AbstractMetaArgument* lastArg) -{ - ArgumentVarReplacementList argReplacements; - TypeSystem::Language convLang = (language == TypeSystem::TargetLangCode) - ? TypeSystem::NativeCode : TypeSystem::TargetLangCode; - int removed = 0; - for (int i = 0; i < func->arguments().size(); ++i) { - const AbstractMetaArgument* arg = func->arguments().at(i); - QString argValue; - if (language == TypeSystem::TargetLangCode) { - bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty(); - bool argRemoved = func->argumentRemoved(i+1); - removed = removed + (int) argRemoved; - if (argRemoved && hasConversionRule) - argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); - else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex())) - argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(i); - if (!argRemoved && argValue.isEmpty()) { - int argPos = i - removed; - const AbstractMetaType* type = arg->type(); - QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); - if (!typeReplaced.isEmpty()) { - AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced); - if (builtType) - type = builtType; - } - if (type->typeEntry()->isCustom()) { - argValue = usePyArgs - ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) - : QLatin1String(PYTHON_ARG); - } else { - argValue = hasConversionRule - ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX) - : QLatin1String(CPP_ARG) + QString::number(argPos); - if (isWrapperType(type)) { - if (type->referenceType() == LValueReference && !isPointer(type)) - argValue.prepend(QLatin1Char('*')); - } - } - } - } else { - argValue = arg->name(); - } - if (!argValue.isEmpty()) - argReplacements << ArgumentVarReplacementPair(arg, argValue); - - } - return argReplacements; -} - -void ShibokenGenerator::writeCodeSnips(QTextStream& s, - const CodeSnipList& codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language, - const AbstractMetaClass* context) -{ - QString code = getCodeSnippets(codeSnips, position, language); - if (code.isEmpty()) - return; - processCodeSnip(code, context); - s << INDENT << "// Begin code injection" << endl; - s << code; - s << INDENT << "// End of code injection" << endl; -} - -static QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func) -{ - QString result; - QTextStream str(&result); - str << "Wrong index for " << varName << " variable (" << capture << ") on "; - if (const AbstractMetaClass *c = func->implementingClass()) - str << c->name() << "::"; - str << func->signature(); - return result; -} - -void ShibokenGenerator::writeCodeSnips(QTextStream& s, - const CodeSnipList& codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language, - const AbstractMetaFunction* func, - const AbstractMetaArgument* lastArg) -{ - QString code = getCodeSnippets(codeSnips, position, language); - if (code.isEmpty()) - return; - - // Calculate the real number of arguments. - int argsRemoved = 0; - for (int i = 0; i < func->arguments().size(); i++) { - if (func->argumentRemoved(i+1)) - argsRemoved++; - } - - OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od); - - // Replace %PYARG_# variables. - code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR)); - - static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)")); - Q_ASSERT(pyArgsRegex.isValid()); - if (language == TypeSystem::TargetLangCode) { - if (usePyArgs) { - code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]")); - } else { - static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)")); - Q_ASSERT(pyArgsRegexCheck.isValid()); - const QRegularExpressionMatch match = pyArgsRegexCheck.match(code); - if (match.hasMatch()) { - qCWarning(lcShiboken).noquote().nospace() - << msgWrongIndex("%PYARG", match.captured(1), func); - return; - } - code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG)); - } - } 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*([^;]+)")); - Q_ASSERT(pyArgsAttributionRegex.isValid()); - code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)")); - code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)")); - } - - // Replace %ARG#_TYPE variables. - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1); - QString argTypeVal = arg->type()->cppSignature(); - code.replace(argTypeVar, argTypeVal); - } - - static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE")); - 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); - } - - // Replace template variable for return variable name. - if (func->isConstructor()) { - code.replace(QLatin1String("%0."), QLatin1String("cptr->")); - code.replace(QLatin1String("%0"), QLatin1String("cptr")); - } else if (func->type()) { - QString returnValueOp = isPointerToWrapperType(func->type()) - ? QLatin1String("%1->") : QLatin1String("%1."); - if (ShibokenGenerator::isWrapperType(func->type())) - code.replace(QLatin1String("%0."), returnValueOp.arg(QLatin1String(CPP_RETURN_VAR))); - code.replace(QLatin1String("%0"), QLatin1String(CPP_RETURN_VAR)); - } - - // Replace template variable for self Python object. - QString pySelf = (language == TypeSystem::NativeCode) ? QLatin1String("pySelf") : QLatin1String(PYTHON_SELF_VAR); - code.replace(QLatin1String("%PYSELF"), pySelf); - - // Replace template variable for a pointer to C++ of this object. - if (func->implementingClass()) { - QString replacement = func->isStatic() ? QLatin1String("%1::") : QLatin1String("%1->"); - QString cppSelf; - if (func->isStatic()) - cppSelf = func->ownerClass()->qualifiedCppName(); - else if (language == TypeSystem::NativeCode) - cppSelf = QLatin1String("this"); - else - cppSelf = QLatin1String(CPP_SELF_VAR); - - // On comparison operator CPP_SELF_VAR is always a reference. - if (func->isComparisonOperator()) - replacement = QLatin1String("%1."); - - if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) { - QString methodCallArgs = getArgumentsFromMethodCall(code); - if (!methodCallArgs.isNull()) { - const QString pattern = QStringLiteral("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs); - if (func->name() == QLatin1String("metaObject")) { - QString wrapperClassName = wrapperName(func->ownerClass()); - QString cppSelfVar = avoidProtectedHack() - ? QLatin1String("%CPPSELF") - : QStringLiteral("reinterpret_cast<%1*>(%CPPSELF)").arg(wrapperClassName); - code.replace(pattern, - QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast(%1))" - " ? %2->::%3::%FUNCTION_NAME(%4)" - " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf, cppSelfVar, wrapperClassName, methodCallArgs)); - } else { - code.replace(pattern, - QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast(%1))" - " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)" - " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf, methodCallArgs)); - } - } - } - - code.replace(QLatin1String("%CPPSELF."), replacement.arg(cppSelf)); - code.replace(QLatin1String("%CPPSELF"), cppSelf); - - if (code.indexOf(QLatin1String("%BEGIN_ALLOW_THREADS")) > -1) { - if (code.count(QLatin1String("%BEGIN_ALLOW_THREADS")) == code.count(QLatin1String("%END_ALLOW_THREADS"))) { - code.replace(QLatin1String("%BEGIN_ALLOW_THREADS"), QLatin1String(BEGIN_ALLOW_THREADS)); - code.replace(QLatin1String("%END_ALLOW_THREADS"), QLatin1String(END_ALLOW_THREADS)); - } else { - qCWarning(lcShiboken) << "%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch"; - } - } - - // replace template variable for the Python Type object for the - // class implementing the method in which the code snip is written - if (func->isStatic()) { - code.replace(QLatin1String("%PYTHONTYPEOBJECT"), - cpythonTypeName(func->implementingClass()) + QLatin1String(".super.ht_type")); - } else { - code.replace(QLatin1String("%PYTHONTYPEOBJECT."), pySelf + QLatin1String("->ob_type->")); - code.replace(QLatin1String("%PYTHONTYPEOBJECT"), pySelf + QLatin1String("->ob_type")); - } - } - - // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values. - // Replaces template variables %# for individual arguments. - const ArgumentVarReplacementList &argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); - - QStringList args; - for (const ArgumentVarReplacementPair &pair : argReplacements) { - if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED))) - continue; - args << pair.second; - } - code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", "))); - - for (const ArgumentVarReplacementPair &pair : argReplacements) { - const AbstractMetaArgument* arg = pair.first; - int idx = arg->argumentIndex() + 1; - AbstractMetaType* type = arg->type(); - QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); - if (!typeReplaced.isEmpty()) { - AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced); - if (builtType) - type = builtType; - } - if (isWrapperType(type)) { - QString replacement = pair.second; - if (type->referenceType() == LValueReference && !isPointer(type)) - replacement.remove(0, 1); - if (type->referenceType() == LValueReference || isPointer(type)) - code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->")); - } - code.replace(placeHolderRegex(idx), pair.second); - } - - if (language == TypeSystem::NativeCode) { - // Replaces template %PYTHON_ARGUMENTS variable with a pointer to the Python tuple - // containing the converted virtual method arguments received from C++ to be passed - // to the Python override. - code.replace(QLatin1String("%PYTHON_ARGUMENTS"), QLatin1String(PYTHON_ARGS)); - - // replace variable %PYTHON_METHOD_OVERRIDE for a pointer to the Python method - // override for the C++ virtual method in which this piece of code was inserted - code.replace(QLatin1String("%PYTHON_METHOD_OVERRIDE"), QLatin1String(PYTHON_OVERRIDE_VAR)); - } - - if (avoidProtectedHack()) { - // If the function being processed was added by the user via type system, - // Shiboken needs to find out if there are other overloads for the same method - // name and if any of them is of the protected visibility. This is used to replace - // calls to %FUNCTION_NAME on user written custom code for calls to the protected - // dispatcher. - bool hasProtectedOverload = false; - if (func->isUserAdded()) { - const AbstractMetaFunctionList &funcs = getFunctionOverloads(func->ownerClass(), func->name()); - for (const AbstractMetaFunction *f : funcs) - hasProtectedOverload |= f->isProtected(); - } - - if (func->isProtected() || hasProtectedOverload) { - code.replace(QLatin1String("%TYPE::%FUNCTION_NAME"), - QStringLiteral("%1::%2_protected") - .arg(wrapperName(func->ownerClass()), func->originalName())); - code.replace(QLatin1String("%FUNCTION_NAME"), - func->originalName() + QLatin1String("_protected")); - } - } - - if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass())) - code.replace(QLatin1String("%TYPE"), wrapperName(func->ownerClass())); - - if (func->ownerClass()) - code.replace(QLatin1String("%CPPTYPE"), func->ownerClass()->name()); - - replaceTemplateVariables(code, func); - - processCodeSnip(code); - s << INDENT << "// Begin code injection" << endl; - s << code; - s << INDENT << "// End of code injection" << endl; -} - -// Returns true if the string is an expression, -// 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*(?:\\[[^\\[]+\\])*$")); - Q_ASSERT(expr.isValid()); - return expr.match(code.trimmed()).hasMatch(); -} - -// A miniature normalizer that puts a type string into a format -// suitable for comparison with AbstractMetaType::cppSignature() -// result. -static QString miniNormalizer(const QString& varType) -{ - QString normalized = varType.trimmed(); - if (normalized.isEmpty()) - return normalized; - if (normalized.startsWith(QLatin1String("::"))) - normalized.remove(0, 2); - QString suffix; - while (normalized.endsWith(QLatin1Char('*')) || normalized.endsWith(QLatin1Char('&'))) { - suffix.prepend(normalized.at(normalized.count() - 1)); - normalized.chop(1); - normalized = normalized.trimmed(); - } - const QString result = normalized + QLatin1Char(' ') + suffix; - return result.trimmed(); -} -// The position must indicate the first character after the opening '('. -// ATTENTION: do not modify this function to trim any resulting string! -// This must be done elsewhere. -static QString getConverterTypeSystemVariableArgument(const QString& code, int pos) -{ - QString arg; - int parenthesisDepth = 0; - int count = 0; - while (pos + count < code.count()) { - char c = code.at(pos+count).toLatin1(); // toAscii is gone - if (c == '(') { - ++parenthesisDepth; - } else if (c == ')') { - if (parenthesisDepth == 0) { - arg = code.mid(pos, count).trimmed(); - break; - } - --parenthesisDepth; - } - ++count; - } - if (parenthesisDepth != 0) - qFatal("Unbalanced parenthesis on type system converter variable call."); - return arg; -} -typedef QPair StringPair; -void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code) -{ - QVector replacements; - QRegularExpressionMatchIterator rit = m_typeSystemConvRegEx[converterVariable].globalMatch(code); - while (rit.hasNext()) { - const QRegularExpressionMatch match = rit.next(); - const QStringList list = match.capturedTexts(); - QString conversionString = list.first(); - QString conversionTypeName = list.last(); - const AbstractMetaType* conversionType = buildAbstractMetaTypeFromString(conversionTypeName); - if (!conversionType) { - qFatal(qPrintable(QString::fromLatin1("Could not find type '%1' for use in '%2' conversion. " - "Make sure to use the full C++ name, e.g. 'Namespace::Class'.") - .arg(conversionTypeName).arg(m_typeSystemConvName[converterVariable])), NULL); - - } - QString conversion; - QTextStream c(&conversion); - switch (converterVariable) { - case TypeSystemToCppFunction: { - int end = match.capturedStart(); - int start = end; - while (start > 0 && code.at(start) != QLatin1Char('\n')) - --start; - while (code.at(start).isSpace()) - ++start; - QString varType = code.mid(start, end - start); - conversionString = varType + list.first(); - varType = miniNormalizer(varType); - QString varName = list.at(1).trimmed(); - if (!varType.isEmpty()) { - if (varType != conversionType->cppSignature()) { - qFatal(qPrintable(QString::fromLatin1("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.") - .arg(varType, conversionType->cppSignature())), NULL); - } - c << getFullTypeName(conversionType) << ' ' << varName; - writeMinimalConstructorExpression(c, conversionType); - c << ';' << endl; - Indentation indent(INDENT); - c << INDENT; - } - c << cpythonToCppConversionFunction(conversionType); - QString prefix; - if (varName.startsWith(QLatin1Char('*'))) { - varName.remove(0, 1); - varName = varName.trimmed(); - } else { - prefix = QLatin1Char('&'); - } - QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); - conversionString += arg; - c << arg << ", " << prefix << '(' << varName << ')'; - break; - } - case TypeSystemCheckFunction: - conversion = cpythonCheckFunction(conversionType); - if (conversionType->typeEntry()->isPrimitive() - && (conversionType->typeEntry()->name() == QLatin1String("PyObject") - || !conversion.endsWith(QLatin1Char(' ')))) { - c << '('; - break; - } - case TypeSystemIsConvertibleFunction: - if (conversion.isEmpty()) - conversion = cpythonIsConvertibleFunction(conversionType); - case TypeSystemToPythonFunction: - if (conversion.isEmpty()) - conversion = cpythonToPythonConversionFunction(conversionType); - default: { - QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); - conversionString += arg; - if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) { - qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'") - .arg(code)), NULL); - } - if (conversion.contains(QLatin1String("%in"))) { - conversion.prepend(QLatin1Char('(')); - conversion.replace(QLatin1String("%in"), arg); - } else { - c << arg; - } - } - } - replacements.append(qMakePair(conversionString, conversion)); - } - for (const StringPair &rep : qAsConst(replacements)) - code.replace(rep.first, rep.second); -} - -bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func) -{ - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - for (const CodeSnip &snip : qAsConst(snips)) { - if (snip.code().contains(QLatin1String("%CPPSELF"))) - return true; - } - return false; -} - -bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func) -{ - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - for (const CodeSnip &snip : qAsConst(snips)) { - if (snip.code().contains(QLatin1String("%PYSELF"))) - return true; - } - return false; -} - -bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* func) -{ - QString funcCall = func->originalName() + QLatin1Char('('); - QString wrappedCtorCall; - if (func->isConstructor()) { - funcCall.prepend(QLatin1String("new ")); - wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); - } - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); - for (const CodeSnip &snip : qAsConst(snips)) { - if (snip.code().contains(QLatin1String("%FUNCTION_NAME(")) || snip.code().contains(funcCall) - || (func->isConstructor() - && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall)) - || snip.code().contains(QLatin1String("new %TYPE(")))) - ) - return true; - } - return false; -} - -bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction* func) -{ - static const QRegularExpression overrideCallRegexCheck(QStringLiteral("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); - Q_ASSERT(overrideCallRegexCheck.isValid()); - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); - for (const CodeSnip &snip : qAsConst(snips)) { - if (snip.code().contains(overrideCallRegexCheck)) - return true; - } - return false; -} - -bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language) -{ - static const QRegularExpression retValAttributionRegexCheck_native(QStringLiteral("%0\\s*=[^=]\\s*.+")); - Q_ASSERT(retValAttributionRegexCheck_native.isValid()); - static const QRegularExpression retValAttributionRegexCheck_target(QStringLiteral("%PYARG_0\\s*=[^=]\\s*.+")); - Q_ASSERT(retValAttributionRegexCheck_target.isValid()); - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language); - for (const CodeSnip &snip : qAsConst(snips)) { - if (language == TypeSystem::TargetLangCode) { - if (snip.code().contains(retValAttributionRegexCheck_target)) - return true; - } else { - if (snip.code().contains(retValAttributionRegexCheck_native)) - return true; - } - } - return false; -} - -bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex) -{ - CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny); - const QRegularExpression argRegEx = placeHolderRegex(argumentIndex + 1); - for (const CodeSnip &snip : qAsConst(snips)) { - QString code = snip.code(); - if (code.contains(QLatin1String("%ARGUMENT_NAMES")) || code.contains(argRegEx)) - return true; - } - return false; -} - -bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass) -{ - if (!metaClass || metaClass->baseClassNames().isEmpty()) - return false; - if (metaClass->baseClassNames().size() > 1) - return true; - return hasMultipleInheritanceInAncestry(metaClass->baseClass()); -} - -typedef QMap FunctionGroupMap; -typedef FunctionGroupMap::const_iterator FunctionGroupMapIt; - -bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* metaClass) -{ - if (!metaClass) - return false; - if (metaClass->typeEntry()->isSmartPointer()) - return true; - const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { - AbstractMetaFunctionList overloads; - for (AbstractMetaFunction *func : qAsConst(it.value())) { - if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() - || func->isPrivate() || func->ownerClass() != func->implementingClass() - || func->isConstructor() || func->isOperatorOverload()) - continue; - overloads.append(func); - } - if (overloads.isEmpty()) - continue; - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) - return true; - } - return false; -} - -bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *metaClass) -{ - if (!metaClass) - return false; - if (metaClass->typeEntry()->isSmartPointer()) - return true; - return false; -} - -AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass) -{ - AbstractMetaFunctionList methods; - if (metaClass) { - const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - AbstractMetaFunctionList overloads; - for (AbstractMetaFunction *func : qAsConst(it.value())) { - if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() - || func->isPrivate() || func->ownerClass() != func->implementingClass() - || func->isConstructor() || func->isOperatorOverload()) - continue; - overloads.append(func); - } - if (overloads.isEmpty()) - continue; - if (OverloadData::hasStaticAndInstanceFunctions(overloads)) - methods.append(overloads.first()); - } - } - return methods; -} - -AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass) const -{ - AbstractMetaClassList baseClasses; - if (metaClass) { - const QStringList &baseClassNames = metaClass->baseClassNames(); - for (const QString &parent : baseClassNames) { - AbstractMetaClass *clazz = AbstractMetaClass::findClass(classes(), parent); - if (clazz) - baseClasses << clazz; - } - } - return baseClasses; -} - -const AbstractMetaClass* ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass* metaClass) -{ - if (!metaClass || metaClass->baseClassNames().isEmpty()) - return 0; - if (metaClass->baseClassNames().size() > 1) - return metaClass; - return getMultipleInheritingClass(metaClass->baseClass()); -} - -AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass* metaClass) const -{ - AbstractMetaClassList result; - if (metaClass) { - AbstractMetaClassList baseClasses = getBaseClasses(metaClass); - for (AbstractMetaClass *base : qAsConst(baseClasses)) { - result.append(base); - result.append(getAllAncestors(base)); - } - } - return result; -} - -QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) const -{ - QString result = moduleName.isEmpty() ? packageName() : moduleName; - result.replace(QLatin1Char('.'), QLatin1Char('_')); - return result.toLower() + QLatin1String("_python.h"); -} - -QString ShibokenGenerator::extendedIsConvertibleFunctionName(const TypeEntry* targetType) const -{ - QString p = targetType->targetLangPackage(); - p.replace(QLatin1Char('.'), QLatin1Char('_')); - return QStringLiteral("ExtendedIsConvertible_%1_%2").arg(p, targetType->name()); -} - -QString ShibokenGenerator::extendedToCppFunctionName(const TypeEntry* targetType) const -{ - QString p = targetType->targetLangPackage(); - p.replace(QLatin1Char('.'), QLatin1Char('_')); - return QStringLiteral("ExtendedToCpp_%1_%2").arg(p, targetType->name()); -} - -bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) - -{ - if (metaClass->isNamespace() || isObjectType(metaClass)) - return false; - else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) - return metaClass->hasCloneOperator(); - else - return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet); - - return false; -} - -AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature) -{ - typeSignature = typeSignature.trimmed(); - if (typeSignature.startsWith(QLatin1String("::"))) - typeSignature.remove(0, 2); - - if (m_metaTypeFromStringCache.contains(typeSignature)) - return m_metaTypeFromStringCache.value(typeSignature); - - QString typeString = typeSignature; - bool isConst = typeString.startsWith(QLatin1String("const ")); - if (isConst) - typeString.remove(0, sizeof("const ") / sizeof(char) - 1); - - ReferenceType refType = NoReference; - if (typeString.endsWith(QLatin1String("&&"))) { - refType = RValueReference; - typeString.chop(2); - typeString = typeString.trimmed(); - } else if (typeString.endsWith(QLatin1Char('&'))) { - refType = LValueReference; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - int indirections = 0; - while (typeString.endsWith(QLatin1Char('*'))) { - ++indirections; - typeString.chop(1); - typeString = typeString.trimmed(); - } - - if (typeString.startsWith(QLatin1String("::"))) - typeString.remove(0, 2); - - QString adjustedTypeName = typeString; - QStringList instantiatedTypes; - int lpos = typeString.indexOf(QLatin1Char('<')); - if (lpos > -1) { - int rpos = typeString.lastIndexOf(QLatin1Char('>')); - if ((lpos != -1) && (rpos != -1)) { - QString type = typeString.mid(lpos + 1, rpos - lpos - 1); - int depth = 0; - int start = 0; - for (int i = 0; i < type.count(); ++i) { - if (type.at(i) == QLatin1Char('<')) { - ++depth; - } else if (type.at(i) == QLatin1Char('>')) { - --depth; - } else if (type.at(i) == QLatin1Char(',') && depth == 0) { - instantiatedTypes << type.mid(start, i - start).trimmed(); - start = i + 1; - } - } - instantiatedTypes << type.mid(start).trimmed(); - adjustedTypeName.truncate(lpos); - } - } - - TypeEntry* typeEntry = TypeDatabase::instance()->findType(adjustedTypeName); - - AbstractMetaType* metaType = 0; - if (typeEntry) { - metaType = new AbstractMetaType(); - metaType->setTypeEntry(typeEntry); - metaType->setIndirections(indirections); - metaType->setReferenceType(refType); - metaType->setConstant(isConst); - metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); - for (const QString &instantiation : qAsConst(instantiatedTypes)) { - AbstractMetaType* tmplArgType = buildAbstractMetaTypeFromString(instantiation); - metaType->addInstantiation(tmplArgType); - } - metaType->decideUsagePattern(); - m_metaTypeFromStringCache.insert(typeSignature, metaType); - } - return metaType; -} - -AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry) -{ - QString typeName = typeEntry->qualifiedCppName(); - if (typeName.startsWith(QLatin1String("::"))) - typeName.remove(0, 2); - if (m_metaTypeFromStringCache.contains(typeName)) - return m_metaTypeFromStringCache.value(typeName); - AbstractMetaType* metaType = new AbstractMetaType; - metaType->setTypeEntry(typeEntry); - metaType->setIndirections(0); - metaType->setReferenceType(NoReference); - metaType->setConstant(false); - metaType->decideUsagePattern(); - m_metaTypeFromStringCache.insert(typeName, metaType); - return metaType; -} -AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass) -{ - return ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(metaClass->typeEntry()); -} - -/* -static void dumpFunction(AbstractMetaFunctionList lst) -{ - qDebug() << "DUMP FUNCTIONS: "; - for (AbstractMetaFunction *func : qAsConst(lst)) - qDebug() << "*" << func->ownerClass()->name() - << func->signature() - << "Private: " << func->isPrivate() - << "Empty: " << func->isEmptyFunction() - << "Static:" << func->isStatic() - << "Signal:" << func->isSignal() - << "ClassImplements: " << (func->ownerClass() != func->implementingClass()) - << "is operator:" << func->isOperatorOverload() - << "is global:" << func->isInGlobalScope(); -} -*/ - -static bool isGroupable(const AbstractMetaFunction* func) -{ - if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract())) - return false; - // weird operator overloads - if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? - return false;; - return true; -} - -QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(const AbstractMetaClass* scope) -{ - AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); - - QMap results; - for (AbstractMetaFunction *func : qAsConst(lst)) { - if (isGroupable(func)) - results[func->name()].append(func); - } - return results; -} - -AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet *seen) -{ - AbstractMetaFunctionList results; - AbstractMetaClass* basis; - if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) { - for (; basis; basis = basis->baseClass()) { - const AbstractMetaFunction* inFunc = basis->findFunction(func->name()); - if (inFunc && !seen->contains(inFunc->minimalSignature())) { - seen->insert(inFunc->minimalSignature()); - AbstractMetaFunction* newFunc = inFunc->copy(); - newFunc->setImplementingClass(func->implementingClass()); - results << newFunc; - } - } - } - return results; -} - -AbstractMetaFunctionList ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet *seen) -{ - AbstractMetaFunctionList results; - seen->insert(func->minimalSignature()); - results << const_cast(func) << getInheritedOverloads(func, seen); - return results; -} - -AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName) -{ - AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); - - AbstractMetaFunctionList results; - QSet seenSignatures; - for (AbstractMetaFunction *func : qAsConst(lst)) { - if (func->name() != functionName) - continue; - if (isGroupable(func)) { - // PYSIDE-331: look also into base classes. - results << getFunctionAndInheritedOverloads(func, &seenSignatures); - } - } - return results; -} - -QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction) -{ - AbstractMetaFunctionList overloads = getFunctionOverloads(metaFunction->ownerClass(), metaFunction->name()); - - int minArgs = std::numeric_limits::max(); - int maxArgs = 0; - for (const AbstractMetaFunction* func : qAsConst(overloads)) { - int numArgs = 0; - const AbstractMetaArgumentList &arguments = func->arguments(); - for (const AbstractMetaArgument *arg : arguments) { - if (!func->argumentRemoved(arg->argumentIndex() + 1)) - numArgs++; - } - maxArgs = std::max(maxArgs, numArgs); - minArgs = std::min(minArgs, numArgs); - } - return qMakePair(minArgs, maxArgs); -} - -QMap ShibokenGenerator::options() const -{ - QMap opts(Generator::options()); - opts.insert(QLatin1String(AVOID_PROTECTED_HACK), - QLatin1String("Avoid the use of the '#define protected public' hack.")); - opts.insert(QLatin1String(PARENT_CTOR_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on constructors.")); - opts.insert(QLatin1String(RETURN_VALUE_HEURISTIC), - QLatin1String("Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)")); - opts.insert(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), - QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")); - opts.insert(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), - QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")); - opts.insert(QLatin1String(USE_ISNULL_AS_NB_NONZERO), - QLatin1String("If a class have an isNull()const method, it will be used to compute the value of boolean casts")); - return opts; -} - -static void getCode(QStringList& code, const CodeSnipList& codeSnips) -{ - for (const CodeSnip &snip : qAsConst(codeSnips)) - code.append(snip.code()); -} - -static void getCode(QStringList& code, const TypeEntry* type) -{ - getCode(code, type->codeSnips()); - - CustomConversion* customConversion = type->customConversion(); - if (!customConversion) - return; - - if (!customConversion->nativeToTargetConversion().isEmpty()) - code.append(customConversion->nativeToTargetConversion()); - - const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); - if (toCppConversions.isEmpty()) - return; - - for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions)) - code.append(toNative->conversion()); -} - -bool ShibokenGenerator::doSetup(const QMap& args) -{ - m_useCtorHeuristic = args.contains(QLatin1String(PARENT_CTOR_HEURISTIC)); - m_usePySideExtensions = args.contains(QLatin1String(ENABLE_PYSIDE_EXTENSIONS)); - m_userReturnValueHeuristic = args.contains(QLatin1String(RETURN_VALUE_HEURISTIC)); - m_verboseErrorMessagesDisabled = args.contains(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES)); - m_useIsNullAsNbNonZero = args.contains(QLatin1String(USE_ISNULL_AS_NB_NONZERO)); - m_avoidProtectedHack = args.contains(QLatin1String(AVOID_PROTECTED_HACK)); - - TypeDatabase* td = TypeDatabase::instance(); - QStringList snips; - const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); - for (const PrimitiveTypeEntry *type : primitiveTypeList) - getCode(snips, type); - const ContainerTypeEntryList &containerTypeList = containerTypes(); - for (const ContainerTypeEntry *type : containerTypeList) - getCode(snips, type); - const AbstractMetaClassList &classList = classes(); - for (const AbstractMetaClass *metaClass : classList) - getCode(snips, metaClass->typeEntry()); - getCode(snips, td->findType(packageName())); - const FunctionGroupMap &functionGroups = getFunctionGroups(); - for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { - for (AbstractMetaFunction *func : it.value()) - getCode(snips, func->injectedCodeSnips()); - } - - for (const QString &code : qAsConst(snips)) { - collectContainerTypesFromConverterMacros(code, true); - collectContainerTypesFromConverterMacros(code, false); - } - - return true; -} - -void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro) -{ - QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP["); - int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); - int start = 0; - while ((start = code.indexOf(convMacro, start)) != -1) { - int end = code.indexOf(QLatin1Char(']'), start); - start += offset; - if (code.at(start) != QLatin1Char('%')) { - QString typeString = code.mid(start, end - start); - AbstractMetaType* type = buildAbstractMetaTypeFromString(typeString); - addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); - } - start = end; - } -} - -bool ShibokenGenerator::useCtorHeuristic() const -{ - return m_useCtorHeuristic; -} - -bool ShibokenGenerator::useReturnValueHeuristic() const -{ - return m_userReturnValueHeuristic; -} - -bool ShibokenGenerator::usePySideExtensions() const -{ - return m_usePySideExtensions; -} - -bool ShibokenGenerator::useIsNullAsNbNonZero() const -{ - return m_useIsNullAsNbNonZero; -} - -bool ShibokenGenerator::avoidProtectedHack() const -{ - return m_avoidProtectedHack; -} - -QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const -{ - QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName; - result.replace(QLatin1Char('.'), QLatin1Char('_')); - result.prepend(QLatin1String("Sbk")); - result.append(QLatin1String("Types")); - return result; -} - -QString ShibokenGenerator::convertersVariableName(const QString& moduleName) const -{ - QString result = cppApiVariableName(moduleName); - result.chop(1); - result.append(QLatin1String("Converters")); - return result; -} - -static QString processInstantiationsVariableName(const AbstractMetaType* type) -{ - QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper(); - const AbstractMetaTypeList &instantiations = type->instantiations(); - for (const AbstractMetaType *instantiation : instantiations) { - res += instantiation->isContainer() - ? processInstantiationsVariableName(instantiation) - : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper(); - } - return res; -} -QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName) -{ - if (alternativeTemplateName) { - const AbstractMetaClass* templateBaseClass = metaClass->templateBaseClass(); - if (!templateBaseClass) - return QString(); - QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); - QString instantiations; - const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); - for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) - instantiations += processInstantiationsVariableName(instantiation); - return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations); - } - return getTypeIndexVariableName(metaClass->typeEntry()); -} -QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type) -{ - if (type->isCppPrimitive()) { - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; - if (trueType->basicReferencedTypeEntry()) - type = trueType->basicReferencedTypeEntry(); - } - return QString::fromLatin1("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper()); -} -QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type) -{ - return QString::fromLatin1("SBK%1%2_IDX") - .arg(type->typeEntry()->isContainer() ? QLatin1Char('_') + moduleName().toUpper() : QString(), - processInstantiationsVariableName(type)); -} - -bool ShibokenGenerator::verboseErrorMessagesDisabled() const -{ - return m_verboseErrorMessagesDisabled; -} - -bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData) -{ - if (overloadData.referenceFunction()->isCallOperator()) - return true; - if (overloadData.referenceFunction()->isOperatorOverload()) - return false; - int maxArgs = overloadData.maxArgs(); - int minArgs = overloadData.minArgs(); - return (minArgs != maxArgs) - || (maxArgs > 1) - || overloadData.referenceFunction()->isConstructor() - || overloadData.hasArgumentWithDefaultValue(); -} - -Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType* metaType) -{ - // exclude const on Objects - Options flags; - const TypeEntry* type = metaType->typeEntry(); - bool isCStr = isCString(metaType); - if (metaType->indirections() && !isCStr) { - flags = ExcludeConst; - } else if (metaType->isContainer() - || (type->isPrimitive() && !isCStr) - // const refs become just the value, but pure refs must remain pure. - || (type->isValue() && metaType->isConstant() && metaType->referenceType() == LValueReference)) { - flags = ExcludeConst | ExcludeReference; - } - return flags; -} - -QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg) -{ - if (!arg->defaultValueExpression().isEmpty()) - return arg->defaultValueExpression(); - - //Check modifications - const FunctionModificationList &mods = func->modifications(); - for (const FunctionModification &m : mods) { - for (const ArgumentModification &am : m.argument_mods) { - if (am.index == (arg->argumentIndex() + 1)) - return am.replacedDefaultExpression; - } - } - return QString(); -} - -void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor) -{ - if (defaultCtor.isEmpty() && isCppPrimitive(type)) - return; - QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; - if (ctor.isEmpty()) { - const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->cppSignature()); - qCWarning(lcShiboken()).noquote() << message; - s << ";\n#error " << message << '\n'; - } else { - s << " = " << ctor; - } -} - -void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor) -{ - if (defaultCtor.isEmpty() && isCppPrimitive(type)) - return; - QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; - - if (ctor.isEmpty()) { - const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); - qCWarning(lcShiboken()).noquote() << message; - s << ";\n#error " << message << endl; - } else { - s << " = " << ctor; - } -} - -bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type) -{ - if (!type->isCppPrimitive()) - return false; - const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; - if (trueType->basicReferencedTypeEntry()) - trueType = trueType->basicReferencedTypeEntry(); - QString typeName = trueType->qualifiedCppName(); - return !typeName.contains(QLatin1String("double")) - && !typeName.contains(QLatin1String("float")) - && !typeName.contains(QLatin1String("wchar")); -} -bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type) -{ - return isCppIntegralPrimitive(type->typeEntry()); -} - -QString ShibokenGenerator::msgCouldNotFindMinimalConstructor(const QString &where, const QString &type) -{ - return where + QLatin1String(": Could not find a minimal constructor for type '") + type - + QLatin1String("'. This will result in a compilation error."); -} diff --git a/generator/shiboken2/shibokengenerator.h b/generator/shiboken2/shibokengenerator.h deleted file mode 100644 index 1be56edc8..000000000 --- a/generator/shiboken2/shibokengenerator.h +++ /dev/null @@ -1,556 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SHIBOKENGENERATOR_H -#define SHIBOKENGENERATOR_H - -#define CONV_RULE_OUT_VAR_SUFFIX "_out" -#define CPP_ARG "cppArg" -#define CPP_ARG0 CPP_ARG"0" -#define CPP_ARG_REMOVED "removed_" CPP_ARG -#define CPP_RETURN_VAR "cppResult" -#define CPP_SELF_VAR "cppSelf" -#define PYTHON_ARG "pyArg" -#define PYTHON_ARGS PYTHON_ARG "s" -#define PYTHON_OVERRIDE_VAR "pyOverride" -#define PYTHON_RETURN_VAR "pyResult" -#define PYTHON_SELF_VAR "self" -#define THREAD_STATE_SAVER_VAR "threadStateSaver" -#define BEGIN_ALLOW_THREADS "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS" -#define END_ALLOW_THREADS "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS" -#define PYTHON_TO_CPP_VAR "pythonToCpp" -#define SMART_POINTER_GETTER "kSmartPointerGetter" - -#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\(" -#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\(" -#define CONVERTTOPYTHON_REGEX "%CONVERTTOPYTHON\\[([^\\[]*)\\]\\(" -#define CONVERTTOCPP_REGEX "(\\*?%?[a-zA-Z_][\\w\\.]*(?:\\[[^\\[^<^>]+\\])*)"\ - "(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\(" - -#include - -#include "typesystem.h" - -#include - -class DocParser; -class CodeSnip; -class OverloadData; - -QT_FORWARD_DECLARE_CLASS(QTextStream) - -/** - * Abstract generator that contains common methods used in CppGenerator and HeaderGenerator. - */ -class ShibokenGenerator : public Generator -{ -public: - ShibokenGenerator(); - virtual ~ShibokenGenerator(); - - QString translateTypeForWrapperMethod(const AbstractMetaType* cType, - const AbstractMetaClass* context, Options opt = NoOption) const; - - /** - * Returns a map with all functions grouped, the function name is used as key. - * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} - * \param scope Where to search for functions, null means all global functions. - */ - QMap getFunctionGroups(const AbstractMetaClass* scope = 0); - - /** - * Returns all different inherited overloads of func. - * The function can be called multiple times without duplication. - * \param func the metafunction to be searched in subclasses. - * \param seen the function's minimal signatures already seen. - */ - AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func, QSet *seen); - - /** - * Returns all different inherited overloads of func, and includes func as well. - * The function can be called multiple times without duplication. - * \param func the metafunction to be searched in subclasses. - * \param seen the function's minimal signatures already seen. - */ - AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet *seen); - - /** - * Returns all overloads for a function named \p functionName. - * \param scope scope used to search for overloads. - * \param functionName the function name. - */ - AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName); - /** - * Returns the minimun and maximun number of arguments which this function and all overloads - * can accept. Arguments removed by typesystem are considered as well. - */ - QPair getMinMaxArguments(const AbstractMetaFunction* metaFunction); - /** - * Write a function argument in the C++ in the text stream \p s. - * This function just call \code s << argumentString(); \endcode - * \param s text stream used to write the output. - * \param func the current metafunction. - * \param argument metaargument information to be parsed. - * \param options some extra options. - */ - void writeArgument(QTextStream &s, - const AbstractMetaFunction* func, - const AbstractMetaArgument* argument, - Options options = NoOption) const; - /** - * Create a QString in the C++ format to an function argument. - * \param func the current metafunction. - * \param argument metaargument information to be parsed. - * \param options some extra options. - */ - QString argumentString(const AbstractMetaFunction* func, - const AbstractMetaArgument* argument, - Options options = NoOption) const; - - void writeArgumentNames(QTextStream &s, - const AbstractMetaFunction* func, - Options options = NoOption) const override; - - /** - * Function used to write the fucntion arguments on the class buffer. - * \param s the class output buffer - * \param func the pointer to metafunction information - * \param count the number of function arguments - * \param options some extra options used during the parser - */ - void writeFunctionArguments(QTextStream &s, - const AbstractMetaFunction* func, - Options options = NoOption) const override; - QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; - - /// Utility function for writeCodeSnips. - typedef QPair ArgumentVarReplacementPair; - typedef QVector ArgumentVarReplacementList; - ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func, - bool usePyArgs, TypeSystem::Language language, - const AbstractMetaArgument* lastArg); - - /// Write user's custom code snippets at class or module level. - void writeCodeSnips(QTextStream& s, - const QVector & codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language, - const AbstractMetaClass* context = 0); - /// Write user's custom code snippets at function level. - void writeCodeSnips(QTextStream& s, - const QVector & codeSnips, - TypeSystem::CodeSnipPosition position, - TypeSystem::Language language, - const AbstractMetaFunction* func, - const AbstractMetaArgument* lastArg = 0); - - /// Returns a string with the user's custom code snippets that comply with \p position and \p language. - QString getCodeSnippets(const QVector & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); - - /// Replaces variables for the user's custom code at global or class level. - void processCodeSnip(QString& code, const AbstractMetaClass* context = 0); - - /// Replaces the %CONVERTTOPYTHON type system variable. - inline void replaceConvertToPythonTypeSystemVariable(QString& code) - { - replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code); - } - /// Replaces the %CONVERTTOCPP type system variable. - inline void replaceConvertToCppTypeSystemVariable(QString& code) - { - replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code); - } - /// Replaces the %ISCONVERTIBLE type system variable. - inline void replaceIsConvertibleToCppTypeSystemVariable(QString& code) - { - replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code); - } - /// Replaces the %CHECKTYPE type system variable. - inline void replaceTypeCheckTypeSystemVariable(QString& code) - { - replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code); - } - - /** - * Verifies if any of the function's code injections of the "target" - * type needs the type system variable "%CPPSELF". - * \param func the function to check - * \return true if the function's target code snippets use "%CPPSELF" - */ - bool injectedCodeUsesCppSelf(const AbstractMetaFunction* func); - - /** - * Verifies if any of the function's code injections of the "native" - * type needs the type system variable "%PYSELF". - * \param func the function to check - * \return true if the function's native code snippets use "%PYSELF" - */ - bool injectedCodeUsesPySelf(const AbstractMetaFunction* func); - - /** - * Verifies if any of the function's code injections makes a call - * to the C++ method. This is used by the generator to avoid writing calls - * to C++ when the user custom code already does this. - * \param func the function to check - * \return true if the function's code snippets call the wrapped C++ function - */ - bool injectedCodeCallsCppFunction(const AbstractMetaFunction* func); - - /** - * Verifies if any of the function's code injections of the "native" class makes a - * call to the C++ method. This is used by the generator to avoid writing calls to - * Python overrides of C++ virtual methods when the user custom code already does this. - * \param func the function to check - * \return true if the function's code snippets call the Python override for a C++ virtual method - */ - bool injectedCodeCallsPythonOverride(const AbstractMetaFunction* func); - - /** - * Verifies if any of the function's code injections attributes values to - * the return variable (%0 or %PYARG_0). - * \param func the function to check - * \param language the kind of code snip - * \return true if the function's code attributes values to "%0" or "%PYARG_0" - */ - bool injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language = TypeSystem::TargetLangCode); - - /** - * Verifies if any of the function's code injections uses the type system variable - * for function arguments of a given index. - */ - bool injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex); - - /** - * Function which parse the metafunction information - * \param func the function witch will be parserd - * \param option some extra options - * \param arg_count the number of function arguments - */ - QString functionSignature(const AbstractMetaFunction* func, - QString prepend = QString(), - QString append = QString(), - Options options = NoOption, - int arg_count = -1) const; - - /// Returns true if there are cases of multiple inheritance in any of its ancestors. - bool hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass); - - /// Returns true if the class needs to have a getattro function. - bool classNeedsGetattroFunction(const AbstractMetaClass* metaClass); - - /// Returns true if the class needs to have a setattro function. - bool classNeedsSetattroFunction(const AbstractMetaClass *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. - AbstractMetaFunctionList getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass); - - /// Returns a list of parent classes for a given class. - AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass) const; - - /// Returns a list of all ancestor classes for the given class. - AbstractMetaClassList getAllAncestors(const AbstractMetaClass* metaClass) const; - - const AbstractMetaClass* getMultipleInheritingClass(const AbstractMetaClass* metaClass); - - void writeToPythonConversion(QTextStream& s, const AbstractMetaType* type, - const AbstractMetaClass* context, const QString& argumentName); - void writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context, const QString& inArgName, const QString& outArgName); - void writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, const QString& inArgName, const QString& outArgName); - - /// Returns true if the argument is a pointer that rejects NULL values. - bool shouldRejectNullPointerArgument(const AbstractMetaFunction* 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; - - /// Adds enums eligible for generation from classes/namespaces marked not to be generated. - static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass); - /// Returns the enclosing class for an enum, or NULL if it should be global. - const AbstractMetaClass* getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum); - - QString wrapperName(const AbstractMetaClass* metaClass) const; - QString wrapperName(const AbstractMetaType *metaType) const; - - static QString fullPythonFunctionName(const AbstractMetaFunction* func); - static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum); - static QString protectedFieldGetterName(const AbstractMetaField* field); - static QString protectedFieldSetterName(const AbstractMetaField* field); - - static QString pythonPrimitiveTypeName(const QString& cppTypeName); - static QString pythonPrimitiveTypeName(const PrimitiveTypeEntry* type); - - static QString pythonOperatorFunctionName(QString cppOpFuncName); - static QString pythonOperatorFunctionName(const AbstractMetaFunction* func); - static QString pythonRichCompareOperatorId(QString cppOpFuncName); - static QString pythonRichCompareOperatorId(const AbstractMetaFunction* func); - - static QString cpythonOperatorFunctionName(const AbstractMetaFunction* func); - - static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative); - static QString fixedCppTypeName(const AbstractMetaType* type); - static QString fixedCppTypeName(const TypeEntry* type, QString typeName = QString()); - - static bool isNumber(QString cpythonApiName); - static bool isNumber(const TypeEntry* type); - static bool isNumber(const AbstractMetaType* type); - static bool isPyInt(const TypeEntry* type); - static bool isPyInt(const AbstractMetaType* type); - static bool isPairContainer(const AbstractMetaType* type); - - /** - * Returns true if the type passed has a Python wrapper for it. - * Although namespace has a Python wrapper, it's not considered a type. - */ - static bool isWrapperType(const TypeEntry* type); - static bool isWrapperType(const ComplexTypeEntry* type); - static bool isWrapperType(const AbstractMetaType* metaType); - - /** - * Checks if the type is an Object/QObject or pointer to Value Type. - * In other words, tells if the type is "T*" and T has a Python wrapper. - */ - static bool isPointerToWrapperType(const AbstractMetaType* type); - - /** - * Returns true if \p type is an Object Type used as a value. - */ - static bool isObjectTypeUsedAsValueType(const AbstractMetaType* type); - - static bool isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass); - bool isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const; - bool isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const; - - /// Returns true if the type is a primitive but not a C++ primitive. - static bool isUserPrimitive(const TypeEntry* type); - static bool isUserPrimitive(const AbstractMetaType* type); - - /// Returns true if the type is a C++ primitive, a void*, a const char*, or a std::string. - static bool isCppPrimitive(const TypeEntry* type); - static bool isCppPrimitive(const AbstractMetaType* type); - - /// Returns true if the type is a C++ integral primitive, i.e. bool, char, int, long, and their unsigned counterparts. - static bool isCppIntegralPrimitive(const TypeEntry* type); - static bool isCppIntegralPrimitive(const AbstractMetaType* type); - - /// Checks if an argument type should be dereferenced by the Python method wrapper before calling the C++ method. - static bool shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg); - /// Checks if a meta type should be dereferenced by the Python method wrapper passing it to C++. - static bool shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType); - - static bool visibilityModifiedToPrivate(const AbstractMetaFunction* func); - - QString converterObject(const AbstractMetaType* type); - QString converterObject(const TypeEntry* type); - - QString cpythonBaseName(const AbstractMetaClass* metaClass); - QString cpythonBaseName(const TypeEntry* type); - QString cpythonBaseName(const AbstractMetaType* type); - QString cpythonTypeName(const AbstractMetaClass* metaClass); - QString cpythonTypeName(const TypeEntry* type); - QString cpythonTypeNameExt(const TypeEntry* type); - QString cpythonTypeNameExt(const AbstractMetaType* type); - QString cpythonCheckFunction(const TypeEntry* type, bool genericNumberType = false); - QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false); - /** - * Receives the argument \p type and tries to find the appropriate AbstractMetaType for it - * or a custom type check. - * \param type A string representing the type to be discovered. - * \param metaType A pointer to an AbstractMetaType pointer, to where write a new meta type object - * if one is produced from the \p type string. This object must be deallocated by - * the caller. It will set the target variable to NULL, is \p type is a Python type. - * \return A custom check if \p type is a custom type, or an empty string if \p metaType - * receives an existing type object. - */ - QString guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType); - QString cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false); - QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType = false); - QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg, bool genericNumberType = false); - QString guessCPythonIsConvertible(const QString& type); - - QString cpythonToCppConversionFunction(const AbstractMetaClass* metaClass); - QString cpythonToCppConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0); - QString cpythonToPythonConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0); - QString cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass); - QString cpythonToPythonConversionFunction(const TypeEntry* type); - - QString cpythonFunctionName(const AbstractMetaFunction* func); - QString cpythonMethodDefinitionName(const AbstractMetaFunction* func); - QString cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass); - QString cpythonGetattroFunctionName(const AbstractMetaClass* metaClass); - QString cpythonSetattroFunctionName(const AbstractMetaClass* metaClass); - QString cpythonGetterFunctionName(const AbstractMetaField* metaField); - QString cpythonSetterFunctionName(const AbstractMetaField* metaField); - QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName = QLatin1String(PYTHON_SELF_VAR)); - QString cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName); - QString cpythonWrapperCPtr(const TypeEntry* type, QString argName); - - /// Guesses the scope to where belongs an argument's default value. - QString guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); - - QString cpythonEnumName(const EnumTypeEntry* enumEntry); - QString cpythonEnumName(const AbstractMetaEnum* metaEnum); - - QString cpythonFlagsName(const FlagsTypeEntry* flagsEntry); - QString cpythonFlagsName(const AbstractMetaEnum* metaEnum); - /// Returns the special cast function name, the function used to proper cast class with multiple inheritance. - QString cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass); - - QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; - QString getFormatUnitString(const AbstractMetaFunction* func, bool incRef = false) const; - - /// Returns the file name for the module global header. If no module name is provided the current will be used. - QString getModuleHeaderFileName(const QString& moduleName = QString()) const; - - QString extendedIsConvertibleFunctionName(const TypeEntry* targetType) const; - QString extendedToCppFunctionName(const TypeEntry* targetType) const; - - QMap< QString, QString > options() const override; - - /// Returns true if the user enabled the so called "parent constructor heuristic". - bool useCtorHeuristic() const; - /// Returns true if the user enabled the so called "return value heuristic". - bool useReturnValueHeuristic() const; - /// Returns true if the user enabled PySide extensions. - bool usePySideExtensions() const; - /// Returns true if the generator should use the result of isNull()const to compute boolean casts. - bool useIsNullAsNbNonZero() const; - /// Returns true if the generated code should use the "#define protected public" hack. - bool avoidProtectedHack() const; - QString cppApiVariableName(const QString& moduleName = QString()) const; - QString convertersVariableName(const QString& moduleName = QString()) const; - /** - * Returns the type index variable name for a given class. If \p alternativeTemplateName is true - * and the class is a typedef for a template class instantiation, it will return an alternative name - * made of the template class and the instantiation values, or an empty string if the class isn't - * derived from a template class at all. - */ - QString getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName = false); - QString getTypeIndexVariableName(const TypeEntry* type); - QString getTypeIndexVariableName(const AbstractMetaType* type); - - /// Returns true if the user don't want verbose error messages on the generated bindings. - bool verboseErrorMessagesDisabled() const; - - /** - * Builds an AbstractMetaType object from a QString. - * Returns NULL if no type could be built from the string. - * \param typeSignature The string describing the type to be built. - * \return A new AbstractMetaType object that must be deleted by the caller, or a NULL pointer in case of failure. - */ - AbstractMetaType* buildAbstractMetaTypeFromString(QString typeSignature); - - /// Creates an AbstractMetaType object from a TypeEntry. - AbstractMetaType* buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry); - /// Creates an AbstractMetaType object from an AbstractMetaClass. - AbstractMetaType* buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass); - - void writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor = QString()); - void writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor = QString()); - - /** - * Helper function to return the flags to be used by a meta type when - * it needs to write some converter code. - */ - static Options getConverterOptions(const AbstractMetaType* metaType); - - /** - * Helper function to find for argument default value - */ - static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); -protected: - bool doSetup(const QMap& args); - void collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro); - // verify whether the class is copyable - bool isCopyable(const AbstractMetaClass* metaClass); - - bool m_native_jump_table; - static QHash m_pythonPrimitiveTypeName; - static QHash m_pythonOperators; - static QHash m_formatUnits; - static QHash m_tpFuncs; - static QStringList m_knownPythonTypes; - - void clearTpFuncs(); - - const char* name() const { return "Shiboken"; } - - /// Initializes correspondences between primitive and Python types. - static void initPrimitiveTypesCorrespondences(); - /// Initializes a list of Python known type names. - static void initKnownPythonTypes(); - - void writeFunctionCall(QTextStream& s, - const AbstractMetaFunction* metaFunc, - Options options = NoOption) const; - - void writeUnusedVariableCast(QTextStream& s, const QString& variableName); - - AbstractMetaFunctionList filterFunctions(const AbstractMetaClass* metaClass); - - // All data about extended converters: the type entries of the target type, and a - // list of AbstractMetaClasses accepted as argument for the conversion. - typedef QHash > ExtendedConverterData; - /// 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. - QVector getPrimitiveCustomConversions(); - - /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. - static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); - - Indentor INDENT; - - enum TypeSystemConverterVariable { - TypeSystemCheckFunction = 0, - TypeSystemIsConvertibleFunction, - TypeSystemToCppFunction, - TypeSystemToPythonFunction, - TypeSystemConverterVariables - }; - void replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code); - - static QString msgCouldNotFindMinimalConstructor(const QString &where, const QString &type); - -private: - bool m_useCtorHeuristic; - bool m_userReturnValueHeuristic; - bool m_usePySideExtensions; - bool m_verboseErrorMessagesDisabled; - bool m_useIsNullAsNbNonZero; - bool m_avoidProtectedHack; - - typedef QHash AbstractMetaTypeCache; - AbstractMetaTypeCache m_metaTypeFromStringCache; - - /// Type system converter variable replacement names and regular expressions. - QString m_typeSystemConvName[TypeSystemConverterVariables]; - QRegularExpression m_typeSystemConvRegEx[TypeSystemConverterVariables]; -}; - -#endif // SHIBOKENGENERATOR_H diff --git a/generator/shibokenconfig.h.in b/generator/shibokenconfig.h.in deleted file mode 100644 index 2c86a4a3c..000000000 --- a/generator/shibokenconfig.h.in +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef SHIBOKENCONFIG_H -#define SHIBOKENCONFIG_H - -#define SHIBOKEN_VERSION "@shiboken2_VERSION@" - -#endif diff --git a/generatorrunnerconfig.h.in b/generatorrunnerconfig.h.in deleted file mode 100644 index d291fcc53..000000000 --- a/generatorrunnerconfig.h.in +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef GENERATORRUNNERCONFIG_H -#define GENERATORRUNNERCONFIG_H - -// generatorrunner version -#define GENERATORRUNNER_VERSION "@generator_VERSION@" - -// generatorrunner plugin dir -#define GENERATORRUNNER_PLUGIN_DIR "@generator_plugin_DIR@" - -// module extension -#define MODULE_EXTENSION "@CMAKE_SHARED_LIBRARY_SUFFIX@" - -#endif diff --git a/generatorrunnermacros.h b/generatorrunnermacros.h deleted file mode 100644 index d54ed3b9a..000000000 --- a/generatorrunnermacros.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef GENERATORRUNNERMACROS_H -#define GENERATORRUNNERMACROS_H - -// GENRUNNER_API is used for the public API symbols. -#if defined _WIN32 - #define GENRUNNER_EXPORT __declspec(dllexport) - #if GENRUNNER_EXPORTS - #define GENRUNNER_API GENRUNNER_EXPORT - #endif -#elif __GNUC__ >= 4 - #define GENRUNNER_EXPORT __attribute__ ((visibility("default"))) - #define GENRUNNER_API GENRUNNER_EXPORT -#elif __GNUC__ < 4 - #define GENRUNNER_EXPORT -#endif - -#ifndef GENRUNNER_API - #define GENRUNNER_API -#endif -#endif diff --git a/generators/shiboken/shiboken.cpp b/generators/shiboken/shiboken.cpp deleted file mode 100644 index 829862f19..000000000 --- a/generators/shiboken/shiboken.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "cppgenerator.h" -#include "headergenerator.h" - -EXPORT_GENERATOR_PLUGIN(new CppGenerator << new HeaderGenerator) diff --git a/header.COMM b/header.COMM deleted file mode 100644 index 1c8cb00e7..000000000 --- a/header.COMM +++ /dev/null @@ -1,20 +0,0 @@ -/****************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the module. -** -** $QT_BEGIN_LICENSE:COMM$ -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** $QT_END_LICENSE$ -** -******************************************************************************/ diff --git a/header.LGPL-ONLY b/header.LGPL-ONLY deleted file mode 100644 index 9a676032e..000000000 --- a/header.LGPL-ONLY +++ /dev/null @@ -1,22 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL-ONLY$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you have questions regarding the use of this file, please contact -** us via http://www.qt.io/contact-us/. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ diff --git a/header.LGPL21 b/header.LGPL21 deleted file mode 100644 index 533390b07..000000000 --- a/header.LGPL21 +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/header.LGPL3 b/header.LGPL3 deleted file mode 100644 index d9a65c2e4..000000000 --- a/header.LGPL3 +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/header.LGPL3-COMM b/header.LGPL3-COMM deleted file mode 100644 index b5dc15d38..000000000 --- a/header.LGPL3-COMM +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the FOO module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3-COMM$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - diff --git a/icecc.cmake b/icecc.cmake deleted file mode 100644 index b2bf071aa..000000000 --- a/icecc.cmake +++ /dev/null @@ -1,11 +0,0 @@ -include (CMakeForceCompiler) -option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") -if (ENABLE_ICECC) - find_program(ICECC icecc) - if (ICECC) - message(STATUS "icecc found! Distributed compilation for all!! huhuhu.") - cmake_force_cxx_compiler(${ICECC} icecc) - else(ICECC) - message(FATAL_ERROR "icecc NOT found! re-run cmake without -DENABLE_ICECC") - endif(ICECC) -endif(ENABLE_ICECC) diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt deleted file mode 100644 index e2e5eb427..000000000 --- a/libshiboken/CMakeLists.txt +++ /dev/null @@ -1,69 +0,0 @@ -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) -if(ENABLE_VERSION_SUFFIX) - set(shiboken2_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") -else() - set(shiboken2_SUFFIX "") -endif() - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in" - "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" @ONLY) - -set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) -set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) -set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION}) -set(libshiboken_VERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}.${libshiboken_MICRO_VERSION}") -set(libshiboken_SOVERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}") - -set(libshiboken_SRC -basewrapper.cpp -debugfreehook.cpp -gilstate.cpp -helper.cpp -sbkconverter.cpp -sbkenum.cpp -sbkmodule.cpp -sbkstring.cpp -bindingmanager.cpp -threadstatesaver.cpp -typeresolver.cpp -shibokenbuffer.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_BINARY_DIR} - ${SBK_PYTHON_INCLUDE_DIR}) -add_library(libshiboken SHARED ${libshiboken_SRC}) -target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES}) -set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_EXTENSION_SUFFIX}" - VERSION ${libshiboken_VERSION} - SOVERSION ${libshiboken_SOVERSION} - CXX_STANDARD 11 - DEFINE_SYMBOL LIBSHIBOKEN_EXPORTS) - -install(FILES - autodecref.h - basewrapper.h - bindingmanager.h - conversions.h - gilstate.h - helper.h - sbkconverter.h - sbkenum.h - sbkmodule.h - python25compat.h - sbkdbg.h - sbkstring.h - shiboken.h - shibokenmacros.h - threadstatesaver.h - typeresolver.h - shibokenbuffer.h - sbkpython.h - "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" - DESTINATION include/shiboken2${shiboken2_SUFFIX}) -install(TARGETS libshiboken EXPORT shiboken2 - LIBRARY DESTINATION "${LIB_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - RUNTIME DESTINATION bin) diff --git a/libshiboken/autodecref.h b/libshiboken/autodecref.h deleted file mode 100644 index 1fefcc259..000000000 --- a/libshiboken/autodecref.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef AUTODECREF_H -#define AUTODECREF_H - -#include "sbkpython.h" -#include "basewrapper.h" - -struct SbkObject; -namespace Shiboken -{ - -/** - * AutoDecRef holds a PyObject pointer and decrement its reference counter when destroyed. - */ -struct LIBSHIBOKEN_API AutoDecRef -{ -public: - /** - * 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(pyObj)) {} - - /// Decref the borrowed python reference - ~AutoDecRef() - { - Py_XDECREF(m_pyObj); - } - - inline bool isNull() const { return m_pyObj == 0; } - /// Returns the pointer of the Python object being held. - inline PyObject* object() { return m_pyObj; } - inline operator PyObject*() { return m_pyObj; } - inline operator PyTupleObject*() { return reinterpret_cast(m_pyObj); } - inline operator bool() const { return m_pyObj; } - inline PyObject* operator->() { return m_pyObj; } - - template - T cast() - { - return reinterpret_cast(m_pyObj); - } - - /** - * Decref the current borrowed python reference and take the reference - * borrowed by \p other, so other.isNull() will return true. - */ - void operator=(AutoDecRef& other) - { - Py_XDECREF(m_pyObj); - m_pyObj = other.m_pyObj; - other.m_pyObj = 0; - } - - /** - * Decref the current borrowed python reference and borrow \p other. - */ - void operator=(PyObject* other) - { - Py_XDECREF(m_pyObj); - m_pyObj = other; - } -private: - PyObject* m_pyObj; - AutoDecRef(const AutoDecRef&); - AutoDecRef& operator=(const AutoDecRef&); -}; - -} // namespace Shiboken - -#endif // AUTODECREF_H - diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp deleted file mode 100644 index 5ecda1eaf..000000000 --- a/libshiboken/basewrapper.cpp +++ /dev/null @@ -1,1516 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "basewrapper.h" -#include "basewrapper_p.h" -#include "sbkconverter.h" -#include "sbkenum.h" -#include "autodecref.h" -#include "typeresolver.h" -#include "gilstate.h" -#include -#include -#include -#include -#include -#include -#include "threadstatesaver.h" - -namespace { - void _destroyParentInfo(SbkObject* obj, bool keepReference); -} - -extern "C" -{ - -static void SbkObjectTypeDealloc(PyObject* pyObj); -static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); - -PyTypeObject SbkObjectType_Type = { - PyVarObject_HEAD_INIT(0, 0) - /*tp_name*/ "Shiboken.ObjectType", - /*tp_basicsize*/ sizeof(SbkObjectType), - /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkObjectTypeDealloc, - /*tp_print*/ 0, - /*tp_getattr*/ 0, - /*tp_setattr*/ 0, - /*tp_compare*/ 0, - /*tp_repr*/ 0, - /*tp_as_number*/ 0, - /*tp_as_sequence*/ 0, - /*tp_as_mapping*/ 0, - /*tp_hash*/ 0, - /*tp_call*/ 0, - /*tp_str*/ 0, - /*tp_getattro*/ 0, - /*tp_setattro*/ PyObject_GenericSetAttr, - /*tp_as_buffer*/ 0, - /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - /*tp_doc*/ 0, - /*tp_traverse*/ 0, - /*tp_clear*/ 0, - /*tp_richcompare*/ 0, - /*tp_weaklistoffset*/ 0, - /*tp_iter*/ 0, - /*tp_iternext*/ 0, - /*tp_methods*/ 0, - /*tp_members*/ 0, - /*tp_getset*/ 0, - /*tp_base*/ &PyType_Type, - /*tp_dict*/ 0, - /*tp_descr_get*/ 0, - /*tp_descr_set*/ 0, - /*tp_dictoffset*/ 0, - /*tp_init*/ 0, - /*tp_alloc*/ PyType_GenericAlloc, - /*tp_new*/ SbkObjectTypeTpNew, - /*tp_free*/ PyObject_GC_Del, - /*tp_is_gc*/ 0, - /*tp_bases*/ 0, - /*tp_mro*/ 0, - /*tp_cache*/ 0, - /*tp_subclasses*/ 0, - /*tp_weaklist*/ 0, - /*tp_del*/ 0, - /*tp_version_tag*/ 0 -}; - -static PyObject *SbkObjectGetDict(PyObject* pObj, void *) -{ - SbkObject *obj = reinterpret_cast(pObj); - if (!obj->ob_dict) - obj->ob_dict = PyDict_New(); - if (!obj->ob_dict) - return 0; - Py_INCREF(obj->ob_dict); - return obj->ob_dict; -} - -static PyGetSetDef SbkObjectGetSetList[] = { - {const_cast("__dict__"), SbkObjectGetDict, 0, 0, 0}, - {0, 0, 0, 0, 0} // Sentinel -}; - -static int SbkObject_traverse(PyObject* self, visitproc visit, void* arg) -{ - SbkObject* sbkSelf = reinterpret_cast(self); - - //Visit children - Shiboken::ParentInfo* pInfo = sbkSelf->d->parentInfo; - if (pInfo) { - std::set::const_iterator it = pInfo->children.begin(); - for(; it != pInfo->children.end(); ++it) - Py_VISIT(*it); - } - - //Visit refs - Shiboken::RefCountMap* rInfo = sbkSelf->d->referredObjects; - if (rInfo) { - Shiboken::RefCountMap::const_iterator it = rInfo->begin(); - for (; it != rInfo->end(); ++it) { - std::list::const_iterator ref = it->second.begin(); - for(; ref != it->second.end(); ++ref) - Py_VISIT(*ref); - } - } - - if (sbkSelf->ob_dict) - Py_VISIT(sbkSelf->ob_dict); - return 0; -} - -static int SbkObject_clear(PyObject* self) -{ - SbkObject* sbkSelf = reinterpret_cast(self); - - Shiboken::Object::removeParent(sbkSelf); - - if (sbkSelf->d->parentInfo) - _destroyParentInfo(sbkSelf, true); - - Shiboken::Object::clearReferences(sbkSelf); - - if (sbkSelf->ob_dict) - Py_CLEAR(sbkSelf->ob_dict); - return 0; -} - -SbkObjectType SbkObject_Type = { { { - PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0) - /*tp_name*/ "Shiboken.Object", - /*tp_basicsize*/ sizeof(SbkObject), - /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkDeallocWrapperWithPrivateDtor, - /*tp_print*/ 0, - /*tp_getattr*/ 0, - /*tp_setattr*/ 0, - /*tp_compare*/ 0, - /*tp_repr*/ 0, - /*tp_as_number*/ 0, - /*tp_as_sequence*/ 0, - /*tp_as_mapping*/ 0, - /*tp_hash*/ 0, - /*tp_call*/ 0, - /*tp_str*/ 0, - /*tp_getattro*/ 0, - /*tp_setattro*/ 0, - /*tp_as_buffer*/ 0, - /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, - /*tp_doc*/ 0, - /*tp_traverse*/ SbkObject_traverse, - /*tp_clear*/ SbkObject_clear, - /*tp_richcompare*/ 0, - /*tp_weaklistoffset*/ offsetof(SbkObject, weakreflist), - /*tp_iter*/ 0, - /*tp_iternext*/ 0, - /*tp_methods*/ 0, - /*tp_members*/ 0, - /*tp_getset*/ SbkObjectGetSetList, - /*tp_base*/ 0, - /*tp_dict*/ 0, - /*tp_descr_get*/ 0, - /*tp_descr_set*/ 0, - /*tp_dictoffset*/ offsetof(SbkObject, ob_dict), - /*tp_init*/ 0, - /*tp_alloc*/ 0, - /*tp_new*/ 0, - /*tp_free*/ 0, - /*tp_is_gc*/ 0, - /*tp_bases*/ 0, - /*tp_mro*/ 0, - /*tp_cache*/ 0, - /*tp_subclasses*/ 0, - /*tp_weaklist*/ 0, - /*tp_del*/ 0, - /*tp_version_tag*/ 0 -}, }, - /*priv_data*/ 0 -}; - - -static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete) -{ - SbkObject* sbkObj = reinterpret_cast(pyObj); - PyTypeObject* pyType = Py_TYPE(pyObj); - - // Need to decref the type if this is the dealloc func; if type - // is subclassed, that dealloc func will decref (see subtype_dealloc - // in typeobject.c in the python sources) - bool needTypeDecref = (pyType->tp_dealloc == SbkDeallocWrapper - || pyType->tp_dealloc == SbkDeallocWrapperWithPrivateDtor); - - // Ensure that the GC is no longer tracking this object to avoid a - // possible reentrancy problem. Since there are multiple steps involved - // in deallocating a SbkObject it is possible for the garbage collector to - // be invoked and it trying to delete this object while it is still in - // progress from the first time around, resulting in a double delete and a - // crash. - PyObject_GC_UnTrack(pyObj); - - // Check that Python is still initialized as sometimes this is called by a static destructor - // after Python interpeter is shutdown. - if (sbkObj->weakreflist && Py_IsInitialized()) - PyObject_ClearWeakRefs(pyObj); - - // If I have ownership and is valid delete C++ pointer - if (canDelete && sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { - SbkObjectType* sbkType = reinterpret_cast(pyType); - if (sbkType->d->is_multicpp) { - Shiboken::DeallocVisitor visitor(sbkObj); - Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); - } else { - void* cptr = sbkObj->d->cptr[0]; - Shiboken::Object::deallocData(sbkObj, true); - - Shiboken::ThreadStateSaver threadSaver; - if (Py_IsInitialized()) - threadSaver.save(); - sbkType->d->cpp_dtor(cptr); - } - } else { - Shiboken::Object::deallocData(sbkObj, true); - } - - if (needTypeDecref) - Py_DECREF(pyType); -} - -void SbkDeallocWrapper(PyObject* pyObj) -{ - SbkDeallocWrapperCommon(pyObj, true); -} - -void SbkDeallocWrapperWithPrivateDtor(PyObject* self) -{ - SbkDeallocWrapperCommon(self, false); -} - -void SbkObjectTypeDealloc(PyObject* pyObj) -{ - SbkObjectType* sbkType = reinterpret_cast(pyObj); - - PyObject_GC_UnTrack(pyObj); - Py_TRASHCAN_SAFE_BEGIN(pyObj); - if (sbkType->d) { - if(sbkType->d->user_data && sbkType->d->d_func) { - sbkType->d->d_func(sbkType->d->user_data); - sbkType->d->user_data = 0; - } - free(sbkType->d->original_name); - sbkType->d->original_name = 0; - if (!Shiboken::ObjectType::isUserType(reinterpret_cast(sbkType))) - Shiboken::Conversions::deleteConverter(sbkType->d->converter); - delete sbkType->d; - sbkType->d = 0; - } - Py_TRASHCAN_SAFE_END(pyObj); -} - -PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) -{ -#ifndef IS_PY3K - // Check if all bases are new style before calling type.tp_new - // Was causing gc assert errors in test_bug704.py when - // this check happened after creating the type object. - // Argument parsing take from type.tp_new code. - PyObject* name; - PyObject* pyBases; - PyObject* dict; - static const char* kwlist[] = { "name", "bases", "dict", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:sbktype", (char**)kwlist, - &name, - &PyTuple_Type, &pyBases, - &PyDict_Type, &dict)) - return NULL; - - for(int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) { - PyObject* baseType = PyTuple_GET_ITEM(pyBases, i); - if (PyClass_Check(baseType)) { - PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. PySide only support multiple inheritance from python new style class.", metatype->tp_name); - return 0; - } - } -#endif - - // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); - if (!newType) - return 0; - - Shiboken::ObjectType::initPrivateData(newType); - SbkObjectTypePrivate* d = newType->d; - - std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); - if (bases.size() == 1) { - SbkObjectTypePrivate* parentType = bases.front()->d; - d->mi_offsets = parentType->mi_offsets; - d->mi_init = parentType->mi_init; - d->mi_specialcast = parentType->mi_specialcast; - d->type_discovery = parentType->type_discovery; - d->cpp_dtor = parentType->cpp_dtor; - d->is_multicpp = 0; - d->converter = parentType->converter; - } else { - d->mi_offsets = 0; - d->mi_init = 0; - d->mi_specialcast = 0; - d->type_discovery = 0; - d->cpp_dtor = 0; - d->is_multicpp = 1; - d->converter = 0; - } - if (bases.size() == 1) - d->original_name = strdup(bases.front()->d->original_name); - else - d->original_name = strdup("object"); - d->user_data = 0; - d->d_func = 0; - d->is_user_type = 1; - - std::list::const_iterator it = bases.begin(); - for (; it != bases.end(); ++it) { - if ((*it)->d->subtype_init) - (*it)->d->subtype_init(newType, args, kwds); - } - - return reinterpret_cast(newType); -} - -PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) -{ - SbkObject* self = PyObject_GC_New(SbkObject, subtype); - Py_INCREF(reinterpret_cast(subtype)); - SbkObjectPrivate* d = new SbkObjectPrivate; - - SbkObjectType* sbkType = reinterpret_cast(subtype); - int numBases = ((sbkType->d && sbkType->d->is_multicpp) ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1); - d->cptr = new void*[numBases]; - std::memset(d->cptr, 0, sizeof(void*)*numBases); - d->hasOwnership = 1; - d->containsCppWrapper = 0; - d->validCppObject = 0; - d->parentInfo = 0; - d->referredObjects = 0; - d->cppObjectCreated = 0; - self->ob_dict = 0; - self->weakreflist = 0; - self->d = d; - PyObject_GC_Track(reinterpret_cast(self)); - return reinterpret_cast(self); -} - - -} //extern "C" - - -namespace -{ - -void _destroyParentInfo(SbkObject* obj, bool keepReference) -{ - Shiboken::ParentInfo* pInfo = obj->d->parentInfo; - if (pInfo) { - while(!pInfo->children.empty()) { - SbkObject* first = *pInfo->children.begin(); - // Mark child as invalid - Shiboken::Object::invalidate(first); - Shiboken::Object::removeParent(first, false, keepReference); - } - Shiboken::Object::removeParent(obj, false); - } -} - -} - -namespace Shiboken -{ - -static void decRefPyObjectList(const std::list &pyObj, PyObject* skip = 0); - -static void _walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) -{ - PyObject* bases = currentType->tp_bases; - Py_ssize_t numBases = PyTuple_GET_SIZE(bases); - for (int i = 0; i < numBases; ++i) { - PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); - - if (!PyType_IsSubtype(type, reinterpret_cast(&SbkObject_Type))) { - continue; - } else { - SbkObjectType* sbkType = reinterpret_cast(type); - if (sbkType->d->is_user_type) - _walkThroughClassHierarchy(type, visitor); - else - visitor->visit(sbkType); - } - if (visitor->wasFinished()) - break; - } -} - -void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) -{ - _walkThroughClassHierarchy(currentType, visitor); - visitor->done(); -} - - -bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) -{ - PyObject* sysModules = PyImport_GetModuleDict(); - PyObject* module = PyDict_GetItemString(sysModules, moduleName); - if (!module) { - module = PyImport_ImportModule(moduleName); - if (!module) - return false; - } else { - Py_INCREF(module); - } - - Shiboken::AutoDecRef cppApi(PyObject_GetAttrString(module, "_Cpp_Api")); - Py_DECREF(module); - - if (cppApi.isNull()) - return false; - -#ifdef IS_PY3K - if (PyCapsule_CheckExact(cppApi)) - *cppApiPtr = reinterpret_cast(PyCapsule_GetPointer(cppApi, 0)); -#else - // Python 2.6 doesn't have PyCapsule API, so let's keep usign PyCObject on all Python 2.x - if (PyCObject_Check(cppApi)) - *cppApiPtr = reinterpret_cast(PyCObject_AsVoidPtr(cppApi)); -#endif - return true; -} - -// Wrapper metatype and base type ---------------------------------------------------------- - -void DtorCallerVisitor::visit(SbkObjectType* node) -{ - m_ptrs.push_back(std::make_pair(m_pyObj->d->cptr[m_ptrs.size()], node)); -} - -void DtorCallerVisitor::done() -{ - std::list >::const_iterator it = m_ptrs.begin(); - for (; it != m_ptrs.end(); ++it) { - Shiboken::ThreadStateSaver threadSaver; - threadSaver.save(); - it->second->d->cpp_dtor(it->first); - } -} - -void DeallocVisitor::done() -{ - Shiboken::Object::deallocData(m_pyObj, true); - DtorCallerVisitor::done(); -} - -namespace Conversions { void init(); } - -void init() -{ - static bool shibokenAlreadInitialised = false; - if (shibokenAlreadInitialised) - return; - - Conversions::init(); - - initTypeResolver(); - PyEval_InitThreads(); - - //Init private data - Shiboken::ObjectType::initPrivateData(&SbkObject_Type); - - if (PyType_Ready(&SbkEnumType_Type) < 0) - Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); - - if (PyType_Ready(&SbkObjectType_Type) < 0) - Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); - - if (PyType_Ready(reinterpret_cast(&SbkObject_Type)) < 0) - Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type."); - - shibokenAlreadInitialised = true; -} - -void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads) -{ - std::string msg; - std::string params; - if (args) { - if (PyTuple_Check(args)) { - for (Py_ssize_t i = 0, max = PyTuple_GET_SIZE(args); i < max; ++i) { - if (i) - params += ", "; - PyObject* arg = PyTuple_GET_ITEM(args, i); - params += arg->ob_type->tp_name; - } - } else { - params = args->ob_type->tp_name; - } - } - - if (!cppOverloads) { - msg = "'" + std::string(funcName) + "' called with wrong argument types: " + params; - } else { - msg = "'" + std::string(funcName) + "' called with wrong argument types:\n "; - msg += funcName; - msg += '('; - msg += params; - msg += ")\n"; - msg += "Supported signatures:"; - for (int i = 0; cppOverloads[i]; ++i) { - msg += "\n "; - msg += funcName; - msg += '('; - msg += cppOverloads[i]; - msg += ')'; - } - } - PyErr_SetString(PyExc_TypeError, msg.c_str()); - -} - -class FindBaseTypeVisitor : public HierarchyVisitor -{ - public: - FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {} - virtual void visit(SbkObjectType* node) - { - if (reinterpret_cast(node) == m_typeToFind) { - m_found = true; - finish(); - } - } - bool found() const { return m_found; } - - private: - bool m_found; - PyTypeObject* m_typeToFind; -}; - -std::list splitPyObject(PyObject* pyObj) -{ - std::list result; - if (PySequence_Check(pyObj)) { - AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); - if (!lst.isNull()) { - for (Py_ssize_t i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; ++i) { - PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); - if (Object::checkType(item)) - result.push_back(reinterpret_cast(item)); - } - } - } else { - result.push_back(reinterpret_cast(pyObj)); - } - return result; -} - -static void decRefPyObjectList(const std::list& lst, PyObject *skip) -{ - std::list::const_iterator iter = lst.begin(); - while(iter != lst.end()) { - if (*iter != skip) - Py_DECREF(*iter); - ++iter; - } -} - -namespace ObjectType -{ - -bool checkType(PyTypeObject* type) -{ - return PyType_IsSubtype(type, reinterpret_cast(&SbkObject_Type)); -} - -bool isUserType(PyTypeObject* type) -{ - return checkType(type) && reinterpret_cast(type)->d->is_user_type; -} - -bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) -{ - FindBaseTypeVisitor visitor(ctorType); - walkThroughClassHierarchy(myType, &visitor); - if (!visitor.found()) { - PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name); - return false; - } - return true; -} - - -bool hasExternalCppConversions(SbkObjectType*) { return false; } // DEPRECATED. -bool isExternalConvertible(SbkObjectType *, PyObject *) { return false; } // DEPRECATED. -void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc) {} // DEPRECATED. -void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc) {} // DEPRECATED. -void* callExternalCppConversion(SbkObjectType*, PyObject*) { return 0; } // DEPRECATED. - - -bool hasCast(SbkObjectType* type) -{ - return type->d->mi_specialcast; -} - -void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType) -{ - return sourceType->d->mi_specialcast(Object::cppPointer(obj, targetType), reinterpret_cast(targetType)); -} - -void setCastFunction(SbkObjectType* type, SpecialCastFunction func) -{ - type->d->mi_specialcast = func; -} - -void setOriginalName(SbkObjectType* self, const char* name) -{ - if (self->d->original_name) - free(self->d->original_name); - self->d->original_name = strdup(name); -} - -const char* getOriginalName(SbkObjectType* self) -{ - return self->d->original_name; -} - -void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func) -{ - self->d->type_discovery = func; -} - -void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func) -{ - self->d->type_discovery = (TypeDiscoveryFuncV2)func; -} - -TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self) -{ - // This is an illegal cast because the return value is different, - // but nobody ever used this function, so... =] - return (TypeDiscoveryFunc)self->d->type_discovery; -} - -void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other) -{ - self->d->mi_init = other->d->mi_init; - self->d->mi_offsets = other->d->mi_offsets; - self->d->mi_specialcast = other->d->mi_specialcast; -} - -void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction function) -{ - self->d->mi_init = function; -} - -MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self) -{ - return self->d->mi_init; -} - -void setDestructorFunction(SbkObjectType* self, ObjectDestructor func) -{ - self->d->cpp_dtor = func; -} - -void initPrivateData(SbkObjectType* self) -{ - self->d = new SbkObjectTypePrivate; - memset(self->d, 0, sizeof(SbkObjectTypePrivate)); -} - -bool introduceWrapperType(PyObject* enclosingObject, - const char* typeName, const char* originalName, - SbkObjectType* type, ObjectDestructor cppObjDtor, - SbkObjectType* baseType, PyObject* baseTypes, - bool isInnerClass) -{ - initPrivateData(type); - setOriginalName(type, originalName); - setDestructorFunction(type, cppObjDtor); - - if (baseType) { - type->super.ht_type.tp_base = reinterpret_cast(baseType); - if (baseTypes) { - for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i) - BindingManager::instance().addClassInheritance(reinterpret_cast(PySequence_Fast_GET_ITEM(baseTypes, i)), type); - type->super.ht_type.tp_bases = baseTypes; - } else { - BindingManager::instance().addClassInheritance(baseType, type); - } - } - - if (PyType_Ready(reinterpret_cast(type)) < 0) - return false; - - if (isInnerClass) - return PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast(type)) == 0; - - //PyModule_AddObject steals type's reference. - Py_INCREF(reinterpret_cast(type)); - return PyModule_AddObject(enclosingObject, typeName, reinterpret_cast(type)) == 0; -} - -void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func) -{ - self->d->subtype_init = func; -} - -void* getTypeUserData(SbkObjectType* self) -{ - return self->d->user_data; -} - -void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func) -{ - self->d->user_data = userData; - self->d->d_func = d_func; -} - -} // namespace ObjectType - - -namespace Object -{ - -static void recursive_invalidate(SbkObject* self, std::set& seen); - -bool checkType(PyObject* pyObj) -{ - return ObjectType::checkType(pyObj->ob_type); -} - -bool isUserType(PyObject* pyObj) -{ - return ObjectType::isUserType(pyObj->ob_type); -} - -Py_hash_t hash(PyObject* pyObj) -{ - assert(Shiboken::Object::checkType(pyObj)); - return reinterpret_cast(pyObj); -} - -static void setSequenceOwnership(PyObject* pyObj, bool owner) -{ - if (PySequence_Check(pyObj)) { - std::list objs = splitPyObject(pyObj); - std::list::const_iterator it = objs.begin(); - for(; it != objs.end(); ++it) { - if (owner) - getOwnership(*it); - else - releaseOwnership(*it); - } - } else if (Object::checkType(pyObj)) { - if (owner) - getOwnership(reinterpret_cast(pyObj)); - else - releaseOwnership(reinterpret_cast(pyObj)); - } -} - -void setValidCpp(SbkObject* pyObj, bool value) -{ - pyObj->d->validCppObject = value; -} - -void setHasCppWrapper(SbkObject* pyObj, bool value) -{ - pyObj->d->containsCppWrapper = value; -} - -bool hasCppWrapper(SbkObject* pyObj) -{ - return pyObj->d->containsCppWrapper; -} - -bool wasCreatedByPython(SbkObject* pyObj) -{ - return pyObj->d->cppObjectCreated; -} - -void callCppDestructors(SbkObject* pyObj) -{ - SbkObjectType* sbkType = reinterpret_cast(Py_TYPE(pyObj)); - if (sbkType->d->is_multicpp) { - Shiboken::DtorCallerVisitor visitor(pyObj); - Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor); - } else { - Shiboken::ThreadStateSaver threadSaver; - threadSaver.save(); - sbkType->d->cpp_dtor(pyObj->d->cptr[0]); - } - - /* invalidate needs to be called before deleting pointer array because - it needs to delete entries for them from the BindingManager hash table; - also release wrapper explicitly if object contains C++ wrapper because - invalidate doesn't */ - invalidate(pyObj); - if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) { - BindingManager::instance().releaseWrapper(pyObj); - } - - delete[] pyObj->d->cptr; - pyObj->d->cptr = 0; - pyObj->d->validCppObject = false; -} - -bool hasOwnership(SbkObject* pyObj) -{ - return pyObj->d->hasOwnership; -} - -void getOwnership(SbkObject* self) -{ - // skip if already have the ownership - if (self->d->hasOwnership) - return; - - // skip if this object has parent - if (self->d->parentInfo && self->d->parentInfo->parent) - return; - - // Get back the ownership - self->d->hasOwnership = true; - - if (self->d->containsCppWrapper) - Py_DECREF(reinterpret_cast(self)); // Remove extra ref - else - makeValid(self); // Make the object valid again -} - -void getOwnership(PyObject* pyObj) -{ - if (pyObj) - setSequenceOwnership(pyObj, true); -} - -void releaseOwnership(SbkObject* self) -{ - // skip if the ownership have already moved to c++ - SbkObjectType* selfType = reinterpret_cast(Py_TYPE(self)); - if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(selfType->d->converter)) - return; - - // remove object ownership - self->d->hasOwnership = false; - - // If We have control over object life - if (self->d->containsCppWrapper) - Py_INCREF(reinterpret_cast(self)); // keep the python object alive until the wrapper destructor call - else - invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after -} - -void releaseOwnership(PyObject* self) -{ - setSequenceOwnership(self, false); -} - -/* Needed forward declarations */ -static void recursive_invalidate(PyObject* pyobj, std::set& seen); -static void recursive_invalidate(SbkObject* self, std::set& seen); - -void invalidate(PyObject* pyobj) -{ - std::set seen; - recursive_invalidate(pyobj, seen); -} - -void invalidate(SbkObject* self) -{ - std::set seen; - recursive_invalidate(self, seen); -} - -static void recursive_invalidate(PyObject* pyobj, std::set& seen) -{ - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it = objs.begin(); - for (; it != objs.end(); it++) - recursive_invalidate(*it, seen); -} - -static void recursive_invalidate(SbkObject* self, std::set& seen) -{ - // Skip if this object not is a valid object or if it's already been seen - if (!self || reinterpret_cast(self) == Py_None || seen.find(self) != seen.end()) - return; - seen.insert(self); - - if (!self->d->containsCppWrapper) { - self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class - BindingManager::instance().releaseWrapper(self); - } - - // If it is a parent invalidate all children. - if (self->d->parentInfo) { - // Create a copy because this list can be changed during the process - ChildrenList copy = self->d->parentInfo->children; - ChildrenList::iterator it = copy.begin(); - - for (; it != copy.end(); ++it) { - // invalidate the child - recursive_invalidate(*it, seen); - - // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed - if (!self->d->validCppObject) - removeParent(*it, true, true); - } - } - - // If has ref to other objects invalidate all - if (self->d->referredObjects) { - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter; - for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) { - const std::list lst = iter->second; - std::list::const_iterator it = lst.begin(); - while(it != lst.end()) { - recursive_invalidate(*it, seen); - ++it; - } - } - } -} - -void makeValid(SbkObject* self) -{ - // Skip if this object not is a valid object - if (!self || reinterpret_cast(self) == Py_None || self->d->validCppObject) - return; - - // Mark object as invalid only if this is not a wrapper class - self->d->validCppObject = true; - - // If it is a parent make all children valid - if (self->d->parentInfo) { - ChildrenList::iterator it = self->d->parentInfo->children.begin(); - for (; it != self->d->parentInfo->children.end(); ++it) - makeValid(*it); - } - - // If has ref to other objects make all valid again - if (self->d->referredObjects) { - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter; - for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) { - const std::list lst = iter->second; - std::list::const_iterator it = lst.begin(); - while(it != lst.end()) { - if (Shiboken::Object::checkType(*it)) - makeValid(reinterpret_cast(*it)); - ++it; - } - } - } -} - -bool hasParentInfo(SbkObject* pyObj) -{ - return pyObj->d->parentInfo; -} - -void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) -{ - PyTypeObject* type = Py_TYPE(pyObj); - int idx = 0; - if (reinterpret_cast(type)->d->is_multicpp) - idx = getTypeIndexOnHierarchy(type, desiredType); - if (pyObj->d->cptr) - return pyObj->d->cptr[idx]; - return 0; -} - -std::vector cppPointers(SbkObject* pyObj) -{ - int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj)); - std::vector ptrs(n); - for (int i = 0; i < n; ++i) - ptrs[i] = pyObj->d->cptr[i]; - return ptrs; -} - - -bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) -{ - int idx = 0; - if (reinterpret_cast(Py_TYPE(sbkObj))->d->is_multicpp) - idx = getTypeIndexOnHierarchy(Py_TYPE(sbkObj), desiredType); - - bool alreadyInitialized = sbkObj->d->cptr[idx]; - if (alreadyInitialized) - PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); - else - sbkObj->d->cptr[idx] = cptr; - - sbkObj->d->cppObjectCreated = true; - return !alreadyInitialized; -} - -bool isValid(PyObject* pyObj) -{ - if (!pyObj || pyObj == Py_None - || Py_TYPE(pyObj->ob_type) != &SbkObjectType_Type) { - return true; - } - - SbkObjectPrivate* priv = reinterpret_cast(pyObj)->d; - - if (!priv->cppObjectCreated && isUserType(pyObj)) { - PyErr_Format(PyExc_RuntimeError, "'__init__' method of object's base class (%s) not called.", pyObj->ob_type->tp_name); - return false; - } - - if (!priv->validCppObject) { - PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->tp_name); - return false; - } - - return true; -} - -bool isValid(SbkObject* pyObj, bool throwPyError) -{ - if (!pyObj) - return false; - - SbkObjectPrivate* priv = pyObj->d; - if (!priv->cppObjectCreated && isUserType(reinterpret_cast(pyObj))) { - if (throwPyError) - PyErr_Format(PyExc_RuntimeError, "Base constructor of the object (%s) not called.", Py_TYPE(pyObj)->tp_name); - return false; - } - - if (!priv->validCppObject) { - if (throwPyError) - PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", Py_TYPE(pyObj)->tp_name); - return false; - } - - return true; -} - -bool isValid(PyObject* pyObj, bool throwPyError) -{ - if (!pyObj || pyObj == Py_None || - !PyType_IsSubtype(pyObj->ob_type, reinterpret_cast(&SbkObject_Type))) { - return true; - } - return isValid(reinterpret_cast(pyObj), throwPyError); -} - -SbkObject *findColocatedChild(SbkObject *wrapper, - const SbkObjectType *instanceType) -{ - // Degenerate case, wrapper is the correct wrapper. - if (reinterpret_cast(Py_TYPE(wrapper)) == reinterpret_cast(instanceType)) - return wrapper; - - if (!(wrapper->d && wrapper->d->cptr)) - return 0; - - ParentInfo* pInfo = wrapper->d->parentInfo; - if (!pInfo) - return 0; - - ChildrenList& children = pInfo->children; - - ChildrenList::iterator childrenEnd = children.end(); - for (ChildrenList::iterator iChild = children.begin(); iChild != childrenEnd; ++iChild) { - if (!((*iChild)->d && (*iChild)->d->cptr)) - continue; - if ((*iChild)->d->cptr[0] == wrapper->d->cptr[0]) { - if (reinterpret_cast(Py_TYPE(*iChild)) == reinterpret_cast(instanceType)) - return const_cast((*iChild)); - else - return findColocatedChild(const_cast(*iChild), instanceType); - } - } - return 0; -} - - -PyObject *newObject(SbkObjectType* instanceType, - void* cptr, - bool hasOwnership, - bool isExactType, - const char* typeName) -{ - // Try to find the exact type of cptr. - if (!isExactType) { - PyTypeObject* exactType = 0; - if (typeName) { - exactType = Shiboken::Conversions::getPythonTypeObject(typeName); - if (exactType) - instanceType = reinterpret_cast(exactType); - } - if (!exactType) - instanceType = BindingManager::instance().resolveType(&cptr, instanceType); - } - - bool shouldCreate = true; - bool shouldRegister = true; - SbkObject* self = 0; - - // Some logic to ensure that colocated child field does not overwrite the parent - if (BindingManager::instance().hasWrapper(cptr)) { - SbkObject* existingWrapper = BindingManager::instance().retrieveWrapper(cptr); - - self = findColocatedChild(existingWrapper, instanceType); - if (self) { - // Wrapper already registered for cptr. - // This should not ideally happen, binding code should know when a wrapper - // already exists and retrieve it instead. - shouldRegister = shouldCreate = false; - } else if (hasOwnership && - (!(Shiboken::Object::hasCppWrapper(existingWrapper) || - Shiboken::Object::hasOwnership(existingWrapper)))) { - // Old wrapper is likely junk, since we have ownership and it doesn't. - BindingManager::instance().releaseWrapper(existingWrapper); - } else { - // Old wrapper may be junk caused by some bug in identifying object deletion - // but it may not be junk when a colocated field is accessed for an - // object which was not created by python (returned from c++ factory function). - // Hence we cannot release the wrapper confidently so we do not register. - shouldRegister = false; - } - } - - if (shouldCreate) { - self = reinterpret_cast(SbkObjectTpNew(reinterpret_cast(instanceType), 0, 0)); - self->d->cptr[0] = cptr; - self->d->hasOwnership = hasOwnership; - self->d->validCppObject = 1; - if (shouldRegister) { - BindingManager::instance().registerWrapper(self, cptr); - } - } else { - Py_IncRef(reinterpret_cast(self)); - } - return reinterpret_cast(self); -} - -void destroy(SbkObject* self) -{ - destroy(self, 0); -} - -void destroy(SbkObject* self, void* cppData) -{ - // Skip if this is called with NULL pointer this can happen in derived classes - if (!self) - return; - - // This can be called in c++ side - Shiboken::GilState gil; - - // Remove all references attached to this object - clearReferences(self); - - // Remove the object from parent control - - // Verify if this object has parent - bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent); - - if (self->d->parentInfo) { - // Check for children information and make all invalid if they exists - _destroyParentInfo(self, true); - // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent - } - - //if !hasParent this object could still alive - if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) { - // Remove extra ref used by c++ object this will case the pyobject destruction - // This can cause the object death - Py_DECREF(reinterpret_cast(self)); - } - - //Python Object is not destroyed yet - if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) { - // Remove from BindingManager - Shiboken::BindingManager::instance().releaseWrapper(self); - self->d->hasOwnership = false; - - // the cpp object instance was deleted - delete[] self->d->cptr; - self->d->cptr = 0; - } - - // After this point the object can be death do not use the self pointer bellow -} - -void removeParent(SbkObject* child, bool giveOwnershipBack, bool keepReference) -{ - ParentInfo* pInfo = child->d->parentInfo; - if (!pInfo || !pInfo->parent) { - if (pInfo && pInfo->hasWrapperRef) { - pInfo->hasWrapperRef = false; - } - return; - } - - ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; - // Verify if this child is part of parent list - ChildrenList::iterator iChild = std::find(oldBrothers.begin(), oldBrothers.end(), child); - if (iChild == oldBrothers.end()) - return; - - oldBrothers.erase(iChild); - - pInfo->parent = 0; - - // This will keep the wrapper reference, will wait for wrapper destruction to remove that - if (keepReference && - child->d->containsCppWrapper) { - //If have already a extra ref remove this one - if (pInfo->hasWrapperRef) - Py_DECREF(child); - else - pInfo->hasWrapperRef = true; - return; - } - - // Transfer ownership back to Python - child->d->hasOwnership = giveOwnershipBack; - - // Remove parent ref - Py_DECREF(child); -} - -void setParent(PyObject* parent, PyObject* child) -{ - if (!child || child == Py_None || child == parent) - return; - - /* - * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken - * like tuple and list. - * - * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, - * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString - * follows the sequence protocol. - */ - if (PySequence_Check(child) && !Object::checkType(child)) { - Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); - for (Py_ssize_t i = 0, max = PySequence_Size(seq); i < max; ++i) - setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); - return; - } - - bool parentIsNull = !parent || parent == Py_None; - SbkObject* parent_ = reinterpret_cast(parent); - SbkObject* child_ = reinterpret_cast(child); - - if (!parentIsNull) { - if (!parent_->d->parentInfo) - parent_->d->parentInfo = new ParentInfo; - - // do not re-add a child - if (child_->d->parentInfo && (child_->d->parentInfo->parent == parent_)) - return; - } - - ParentInfo* pInfo = child_->d->parentInfo; - bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; - - //Avoid destroy child during reparent operation - Py_INCREF(child); - - // check if we need to remove this child from the old parent - if (parentIsNull || hasAnotherParent) - removeParent(child_); - - // Add the child to the new parent - pInfo = child_->d->parentInfo; - if (!parentIsNull) { - if (!pInfo) - pInfo = child_->d->parentInfo = new ParentInfo; - - pInfo->parent = parent_; - parent_->d->parentInfo->children.insert(child_); - - // Add Parent ref - Py_INCREF(child_); - - // Remove ownership - child_->d->hasOwnership = false; - } - - // Remove previous safe ref - Py_DECREF(child); -} - -void deallocData(SbkObject* self, bool cleanup) -{ - // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor - if(cleanup) { - removeParent(self); - - if (self->d->parentInfo) - _destroyParentInfo(self, true); - - clearReferences(self); - } - - if (self->d->cptr) { - // Remove from BindingManager - Shiboken::BindingManager::instance().releaseWrapper(self); - delete[] self->d->cptr; - self->d->cptr = 0; - // delete self->d; PYSIDE-205: wrong! - } - delete self->d; // PYSIDE-205: always delete d. - Py_XDECREF(self->ob_dict); - Py_TYPE(self)->tp_free(self); -} - -void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func) -{ - SbkObjectType* ob_type = reinterpret_cast(Py_TYPE(wrapper)); - if (ob_type->d->user_data) - ob_type->d->d_func(ob_type->d->user_data); - - ob_type->d->d_func = d_func; - ob_type->d->user_data = userData; -} - -void* getTypeUserData(SbkObject* wrapper) -{ - return reinterpret_cast(Py_TYPE(wrapper))->d->user_data; -} - -void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) -{ - bool isNone = (!referredObject || (referredObject == Py_None)); - - if (!self->d->referredObjects) - self->d->referredObjects = new Shiboken::RefCountMap; - - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter = refCountMap.find(key); - std::list objects; - if (iter != refCountMap.end()) { - objects = (*iter).second; - std::list::const_iterator found = std::find(objects.begin(), objects.end(), referredObject); - - // skip if objects already exists - if (found != objects.end()) - return; - } - - if (append && !isNone) { - refCountMap[key].push_back(referredObject); - Py_INCREF(referredObject); - } else if (!append) { - if (objects.size() > 0) - decRefPyObjectList(objects, isNone ? 0 : referredObject); - if (isNone) { - if (iter != refCountMap.end()) - refCountMap.erase(iter); - } else { - objects.clear(); - objects.push_back(referredObject); - refCountMap[key] = objects; - Py_INCREF(referredObject); - } - } -} - -void removeReference(SbkObject* self, const char* key, PyObject* referredObject) -{ - if (!referredObject || (referredObject == Py_None)) - return; - - if (!self->d->referredObjects) - return; - - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter = refCountMap.find(key); - if (iter != refCountMap.end()) { - decRefPyObjectList(iter->second); - refCountMap.erase(iter); - } -} - -void clearReferences(SbkObject* self) -{ - if (!self->d->referredObjects) - return; - - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter; - for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) - decRefPyObjectList(iter->second); - self->d->referredObjects->clear(); -} - -std::string info(SbkObject* self) -{ - std::ostringstream s; - std::list bases; - - if (self->d && self->d->cptr) { - if (ObjectType::isUserType(Py_TYPE(self))) - bases = getCppBaseClasses(Py_TYPE(self)); - else - bases.push_back(reinterpret_cast(Py_TYPE(self))); - - s << "C++ address....... "; - std::list::const_iterator it = bases.begin(); - for (int i = 0; it != bases.end(); ++it, ++i) - s << reinterpret_cast(*it)->tp_name << '/' << self->d->cptr[i] << ' '; - s << "\n"; - } - else { - s << "C++ address....... <>\n"; - } - - s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n" - "containsCppWrapper " << self->d->containsCppWrapper << "\n" - "validCppObject.... " << self->d->validCppObject << "\n" - "wasCreatedByPython " << self->d->cppObjectCreated << "\n"; - - - if (self->d->parentInfo && self->d->parentInfo->parent) { - s << "parent............ "; - Shiboken::AutoDecRef parent(PyObject_Str(reinterpret_cast(self->d->parentInfo->parent))); - s << String::toCString(parent) << "\n"; - } - - if (self->d->parentInfo && self->d->parentInfo->children.size()) { - s << "children.......... "; - ChildrenList& children = self->d->parentInfo->children; - for (ChildrenList::const_iterator it = children.begin(); it != children.end(); ++it) { - Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast(*it))); - s << String::toCString(child) << ' '; - } - s << '\n'; - } - - if (self->d->referredObjects && self->d->referredObjects->size()) { - Shiboken::RefCountMap& map = *self->d->referredObjects; - s << "referred objects.. "; - Shiboken::RefCountMap::const_iterator it = map.begin(); - for (; it != map.end(); ++it) { - if (it != map.begin()) - s << " "; - s << '"' << it->first << "\" => "; - std::list::const_iterator j = it->second.begin(); - for (; j != it->second.end(); ++j) { - Shiboken::AutoDecRef obj(PyObject_Str(*j)); - s << String::toCString(obj) << ' '; - } - s << ' '; - } - s << '\n'; - } - return s.str(); -} - -} // namespace Object - -} // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h deleted file mode 100644 index 002337f3c..000000000 --- a/libshiboken/basewrapper.h +++ /dev/null @@ -1,451 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BASEWRAPPER_H -#define BASEWRAPPER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#include -#include - -extern "C" -{ - -struct SbkConverter; -struct SbkObjectPrivate; - -/// Base Python object for all the wrapped C++ classes. -struct LIBSHIBOKEN_API SbkObject -{ - PyObject_HEAD - /// Instance dictionary. - PyObject* ob_dict; - /// List of weak references - PyObject* weakreflist; - SbkObjectPrivate* d; -}; - - -/// Dealloc the python object \p pyObj and the C++ object represented by it. -LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); -LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); - -struct SbkObjectType; - -/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. -typedef int* (*MultipleInheritanceInitFunction)(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*, SbkObjectType*); -typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); -typedef void* (*TypeDiscoveryFuncV2)(void*, SbkObjectType*); - -typedef void* (*ExtendedToCppFunc)(PyObject*); // DEPRECATED. -typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); // DEPRECATED. - -// Used in userdata dealloc function -typedef void (*DeleteUserDataFunc)(void*); - -typedef void (*ObjectDestructor)(void*); - -typedef void (*SubTypeInitHook)(SbkObjectType*, PyObject*, PyObject*); - -extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; -extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; - - -struct SbkObjectTypePrivate; -/// PyTypeObject extended with C++ multiple inheritance information. -struct LIBSHIBOKEN_API SbkObjectType -{ - PyHeapTypeObject super; - SbkObjectTypePrivate* d; -}; - -LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*); - -} // extern "C" - -namespace Shiboken -{ - -/** -* Init shiboken library. -*/ -LIBSHIBOKEN_API void init(); - - -/// Delete the class T allocated on \p cptr. -template -void callCppDestructor(void* cptr) -{ - delete reinterpret_cast(cptr); -} - -/** - * Shiboken::importModule is DEPRECATED. Use Shiboken::Module::import() instead. - */ -SBK_DEPRECATED(LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr)); -LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); - -namespace ObjectType { - -/** -* Returns true if the object is an instance of a type created by the Shiboken generator. -*/ -LIBSHIBOKEN_API bool checkType(PyTypeObject* pyObj); - -/** -* Returns true if this object is an instance of an user defined type derived from an Shiboken type. -*/ -LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj); - -/** -* Returns true if the constructor of \p ctorType can be called for a instance of type \p myType. -* \note This function set a python error when returning false. -*/ -LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); - - -LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType*); // DEPRECATED. -LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType*, PyObject*); // DEPRECATED. -LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc); // DEPRECATED. -LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc); // DEPRECATED. -LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType*, PyObject*); // DEPRECATED. - - -/** - * Tells if the \p type represents an object of a class with multiple inheritance in C++. - * When this occurs, the C++ pointer held by the Python wrapper will need to be cast when - * passed as a parameter that expects a type of its ancestry. - * \returns true if a call to ObjectType::cast() is needed to obtain the correct - * C++ pointer for Python objects of type \p type. - */ -LIBSHIBOKEN_API bool hasCast(SbkObjectType* type); -/** - * Cast the C++ pointer held by a Python object \p obj of type \p sourceType, - * to a C++ pointer of a C++ class indicated by type \p targetType. - * \returns The cast C++ pointer. - */ -LIBSHIBOKEN_API void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType); -/// Set the C++ cast function for \p type. -LIBSHIBOKEN_API void setCastFunction(SbkObjectType* type, SpecialCastFunction func); - -LIBSHIBOKEN_API void setOriginalName(SbkObjectType* self, const char* name); -LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self); - -LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func); -LIBSHIBOKEN_API SBK_DEPRECATED(void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func)); -LIBSHIBOKEN_API SBK_DEPRECATED(TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self)); - -LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other); -LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func); -LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self); - -LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func); - -LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); - -/** - * Initializes a Shiboken wrapper type and adds it to the module, - * or to the enclosing class if the type is an inner class. - * This function also calls initPrivateData and setDestructorFunction. - * \param enclosingObject The module or enclosing class to where the new \p type will be added. - * \param typeName Name by which the type will be known in Python. - * \param originalName Original C++ name of the type. - * \param type The new type to be initialized and added to the module. - * \param cppObjDtor Memory deallocation function for the C++ object held by \p type. - * Should not be used if the underlying C++ class has a private destructor. - * \param baseType Base type from whom the new \p type inherits. - * \param baseTypes Other base types from whom the new \p type inherits. - * \param isInnerClass Tells if the new \p type is an inner class (the default is that it isn't). - * If false then the \p enclosingObject is a module, otherwise it is another - * wrapper type. - * \returns true if the initialization went fine, false otherwise. - */ -LIBSHIBOKEN_API bool introduceWrapperType(PyObject* enclosingObject, - const char* typeName, const char* originalName, - SbkObjectType* type, ObjectDestructor cppObjDtor = 0, - SbkObjectType* baseType = 0, PyObject* baseTypes = 0, - bool isInnerClass = false); - -/** - * Set the subtype init hook for a type. - * - * This hook will be invoked every time the user creates a sub-type inherited from a Shiboken based type. - * The hook gets 3 params, they are: The new type being created, args and kwds. The last two are the very - * same got from tp_new. - */ -LIBSHIBOKEN_API void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func); - -/** - * Get the user data previously set by Shiboken::Object::setTypeUserData - */ -LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* self); -LIBSHIBOKEN_API void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func); - -} - -namespace Object { - -/** - * Returns a string with information about the internal state of the instance object, useful for debug purposes. - */ -LIBSHIBOKEN_API std::string info(SbkObject* self); - -/** -* Returns true if the object is an instance of a type created by the Shiboken generator. -*/ -LIBSHIBOKEN_API bool checkType(PyObject* pyObj); - -/** - * Returns true if this object type is an instance of an user defined type derived from an Shiboken type. - * \see Shiboken::ObjectType::isUserType - */ -LIBSHIBOKEN_API bool isUserType(PyObject* pyObj); - -/** - * Generic function used to make ObjectType hashable, the C++ pointer is used as hash value. - */ -LIBSHIBOKEN_API Py_hash_t hash(PyObject* pyObj); - -/** - * Find a child of given wrapper having same address having the specified type. - */ -LIBSHIBOKEN_API SbkObject *findColocatedChild(SbkObject *wrapper, - const SbkObjectType *instanceType); - -/** - * Bind a C++ object to Python. - * \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++ - * object, in any case you must provide \p instanceType, it'll be used as search starting point - * and as fallback. - * \param typeName If non-null, this will be used as helper to find the correct Python type for this object. - */ -LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, - void* cptr, - bool hasOwnership = true, - bool isExactType = false, - const char* typeName = 0); - -/** - * Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it. - */ -LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); -/** - * Tells shiboken the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. - */ -LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); -/** - * Return true if the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. - */ -LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); - -/** - * Return true if the Python object was created by Python, false otherwise. - * \note This function was added to libshiboken only to be used by shiboken.wasCreatedByPython() - */ -LIBSHIBOKEN_API bool wasCreatedByPython(SbkObject* pyObj); - -/** - * Call the C++ object destructor and invalidates the Python object. - * \note This function was added to libshiboken only to be used by shiboken.delete() - */ -LIBSHIBOKEN_API void callCppDestructors(SbkObject* pyObj); - -/** - * Return true if the Python is responsible for deleting the underlying C++ object. - */ -LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); - -/** - * Sets python as responsible to delete the underlying C++ object. - * \note You this overload only when the PyObject can be a sequence and you want to - * call this function for every item in the sequence. - * \see getOwnership(SbkObject*) - */ -LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); - -/** - * Sets python as responsible to delete the underlying C++ object. - */ -LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); - -/** - * Release the ownership, so Python will not delete the underlying C++ object. - * \note You this overload only when the PyObject can be a sequence and you want to - * call this function for every item in the sequence. - * \see releaseOwnership(SbkObject*) - */ -LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); -/** - * Release the ownership, so Python will not delete the underlying C++ object. - */ -LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); - -/** - * Returns true if the pyObj holds information about their parents. - */ -LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); - -/** - * Get the C++ pointer of type \p desiredType from a Python object. - */ -LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); - -/** - * Return a list with all C++ pointers held from a Python object. - * \note This function was added to libshiboken only to be used by shiboken.getCppPointer() - */ -LIBSHIBOKEN_API std::vector cppPointers(SbkObject* pyObj); - -/** - * Set the C++ pointer of type \p desiredType of a Python object. - */ -LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); - -/** - * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. - */ -LIBSHIBOKEN_API bool isValid(PyObject* pyObj); - -/** - * Returns false if the Python wrapper is not marked as valid. - * \param pyObj the object. - * \param throwPyError sets a Python RuntimeError when the object isn't valid. - */ -LIBSHIBOKEN_API bool isValid(SbkObject* pyObj, bool throwPyError = true); - -/** - * Returns false if the Python wrapper is not marked as valid. - * \param pyObj the object. - * \param throwPyError sets a Python RuntimeError when the object isn't valid. - */ -LIBSHIBOKEN_API bool isValid(PyObject* pyObj, bool throwPyError); - -/** -* Set the parent of \p child to \p parent. -* When an object dies, all their children, grandchildren, etc, are tagged as invalid. -* \param parent the parent object, if null, the child will have no parents. -* \param child the child. -*/ -LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); - -/** -* Remove this child from their parent, if any. -* \param child the child. -*/ -LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); - -/** -* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons. -* \note Do not call this function inside your bindings. -*/ -LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); - -/** - * Mark the object as invalid - */ -LIBSHIBOKEN_API void invalidate(SbkObject* self); - -/** - * Help function can be used to invalidate a sequence of object - **/ -LIBSHIBOKEN_API void invalidate(PyObject* pyobj); - -/** - * Make the object valid again - */ -LIBSHIBOKEN_API void makeValid(SbkObject* self); - -/// \deprecated Use destroy(SbkObject*, void*) -SBK_DEPRECATED(LIBSHIBOKEN_API void destroy(SbkObject* self)); - -/** - * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership - */ -LIBSHIBOKEN_API void destroy(SbkObject* self, void* cppData); - -/** - * Set user data on type of \p wrapper. - * \param wrapper instance object, the user data will be set on his type - * \param userData the user data - * \param d_func a function used to delete the user data - */ -LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func); -/** - * Get the user data previously set by Shiboken::Object::setTypeUserData - */ -LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); - -/** - * Increments the reference count of the referred Python object. - * A previous Python object in the same position identified by the 'key' parameter - * will have its reference counter decremented automatically when replaced. - * All the kept references should be decremented when the Python wrapper indicated by - * 'self' dies. - * No checking is done for any of the passed arguments, since it is meant to be used - * by generated code it is supposed that the generator is correct. - * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument where the referred Object came from. - * \param referredObject the object whose reference is used by the self object. - */ -LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append = false); - -/** - * Removes any reference previously added by keepReference function - * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument from where the referred Object came. - * \param referredObject the object whose reference is used by the self object. - */ -LIBSHIBOKEN_API void removeReference(SbkObject* self, const char* key, PyObject* referredObject); - -} // namespace Object - -} // namespace Shiboken - -#endif // BASEWRAPPER_H diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h deleted file mode 100644 index 129322246..000000000 --- a/libshiboken/basewrapper_p.h +++ /dev/null @@ -1,287 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BASEWRAPPER_P_H -#define BASEWRAPPER_P_H - -#include "sbkpython.h" -#include "basewrapper.h" - -#include -#include -#include -#include - -struct SbkObject; -struct SbkObjectType; -struct SbkConverter; - -namespace Shiboken -{ -/** - * This mapping associates a method and argument of an wrapper object with the wrapper of - * said argument when it needs the binding to help manage its reference count. - */ -typedef std::map > RefCountMap; - -/// Linked list of SbkBaseWrapper pointers -typedef std::set ChildrenList; - -/// Structure used to store information about object parent and children. -struct ParentInfo -{ - /// Default ctor. - ParentInfo() : parent(0), hasWrapperRef(false) {} - /// Pointer to parent object. - SbkObject* parent; - /// List of object children. - ChildrenList children; - /// has internal ref - bool hasWrapperRef; -}; - -} // namespace Shiboken - -extern "C" -{ - -/** - * \internal - * Private data for SbkBaseWrapper - */ -struct SbkObjectPrivate -{ - /// Pointer to the C++ class. - void** cptr; - /// True when Python is responsible for freeing the used memory. - unsigned int hasOwnership : 1; - /// This is true when the C++ class of the wrapped object has a virtual destructor AND was created by Python. - unsigned int containsCppWrapper : 1; - /// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not. - unsigned int validCppObject : 1; - /// Marked as true when the object constructor was called - unsigned int cppObjectCreated : 1; - /// Information about the object parents and children, may be null. - Shiboken::ParentInfo* parentInfo; - /// Manage reference count of objects that are referred to but not owned from. - Shiboken::RefCountMap* referredObjects; - - ~SbkObjectPrivate() - { - delete parentInfo; - parentInfo = 0; - delete referredObjects; - referredObjects = 0; - } -}; - -// TODO-CONVERTERS: to be deprecated/removed -/// The type behaviour was not defined yet -#define BEHAVIOUR_UNDEFINED 0 -/// The type is a value type -#define BEHAVIOUR_VALUETYPE 1 -/// The type is an object type -#define BEHAVIOUR_OBJECTTYPE 2 - -struct SbkObjectTypePrivate -{ - SbkConverter* converter; - int* mi_offsets; - MultipleInheritanceInitFunction mi_init; - - /// Special cast function, null if this class doesn't have multiple inheritance. - SpecialCastFunction mi_specialcast; - TypeDiscoveryFuncV2 type_discovery; - /// Pointer to a function responsible for deletion of the C++ instance calling the proper destructor. - ObjectDestructor cpp_dtor; - /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. - int is_multicpp : 1; - /// True if this type was defined by the user. - int is_user_type : 1; - /// Tells is the type is a value type or an object-type, see BEHAVIOUR_* constants. - // TODO-CONVERTERS: to be deprecated/removed - int type_behaviour : 2; - /// C++ name - char* original_name; - /// Type user data - void* user_data; - DeleteUserDataFunc d_func; - void (*subtype_init)(SbkObjectType*, PyObject*, PyObject*); -}; - - -} // extern "C" - -namespace Shiboken -{ -/** - * Utility function used to transform a PyObject that implements sequence protocol into a std::list. - **/ -std::list splitPyObject(PyObject* pyObj); - -/** -* Visitor class used by walkOnClassHierarchy function. -*/ -class HierarchyVisitor -{ -public: - HierarchyVisitor() : m_wasFinished(false) {} - virtual ~HierarchyVisitor() {} - virtual void visit(SbkObjectType* node) = 0; - virtual void done() {} - void finish() { m_wasFinished = true; }; - bool wasFinished() const { return m_wasFinished; } -private: - bool m_wasFinished; -}; - -class BaseCountVisitor : public HierarchyVisitor -{ -public: - BaseCountVisitor() : m_count(0) {} - - void visit(SbkObjectType*) - { - m_count++; - } - - int count() const { return m_count; } -private: - int m_count; -}; - -class BaseAccumulatorVisitor : public HierarchyVisitor -{ -public: - BaseAccumulatorVisitor() {} - - void visit(SbkObjectType* node) - { - m_bases.push_back(node); - } - - std::list bases() const { return m_bases; } -private: - std::list m_bases; -}; - -class GetIndexVisitor : public HierarchyVisitor -{ -public: - GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {} - virtual void visit(SbkObjectType* node) - { - m_index++; - if (PyType_IsSubtype(reinterpret_cast(node), m_desiredType)) - finish(); - } - int index() const { return m_index; } - -private: - int m_index; - PyTypeObject* m_desiredType; -}; - -/// Call the destructor of each C++ object held by a Python object -class DtorCallerVisitor : public HierarchyVisitor -{ -public: - DtorCallerVisitor(SbkObject* pyObj) : m_pyObj(pyObj) {} - void visit(SbkObjectType* node); - void done(); -protected: - std::list > m_ptrs; - SbkObject* m_pyObj; -}; - -/// Dealloc of each C++ object held by a Python object, this implies a call to the C++ object destructor -class DeallocVisitor : public DtorCallerVisitor -{ -public: - DeallocVisitor(SbkObject* pyObj) : DtorCallerVisitor(pyObj) {} - void done(); -}; - -/// \internal Internal function used to walk on classes inheritance trees. -/** -* Walk on class hierarchy using a DFS algorithm. -* For each pure Shiboken type found, HiearchyVisitor::visit is called and the algorithm consider -* all children of this type as visited. -*/ -void 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::list getCppBaseClasses(PyTypeObject* baseType) -{ - BaseAccumulatorVisitor visitor; - walkThroughClassHierarchy(baseType, &visitor); - return visitor.bases(); -} - -namespace Object -{ -/** -* Decrements the reference counters of every object referred by self. -* \param self the wrapper instance that keeps references to other objects. -*/ -void clearReferences(SbkObject* self); - -/** - * Destroy internal data - **/ -void deallocData(SbkObject* self, bool doCleanup); - -} // namespace Object - -} // namespace Shiboken - -#endif diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp deleted file mode 100644 index 3308ef972..000000000 --- a/libshiboken/bindingmanager.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "basewrapper.h" -#include "basewrapper_p.h" -#include "bindingmanager.h" -#include "sbkdbg.h" -#include "gilstate.h" -#include "sbkstring.h" -#include "debugfreehook.h" - -#include -#include -#include - -namespace Shiboken -{ - -typedef std::unordered_map WrapperMap; - -class Graph -{ -public: - typedef std::list NodeList; - typedef std::unordered_map Edges; - - Edges m_edges; - - Graph() - { - } - - void addEdge(SbkObjectType* from, SbkObjectType* to) - { - m_edges[from].push_back(to); - } - -#ifndef NDEBUG - void dumpDotGraph() - { - std::ofstream file("/tmp/shiboken_graph.dot"); - - file << "digraph D {\n"; - - Edges::const_iterator i = m_edges.begin(); - for (; i != m_edges.end(); ++i) { - SbkObjectType* node1 = i->first; - const NodeList& nodeList = i->second; - NodeList::const_iterator j = nodeList.begin(); - for (; j != nodeList.end(); ++j) - file << '"' << (*j)->super.ht_type.tp_name << "\" -> \"" << node1->super.ht_type.tp_name << "\"\n"; - } - file << "}\n"; - } -#endif - - SbkObjectType* identifyType(void** cptr, SbkObjectType* type, SbkObjectType* baseType) const - { - Edges::const_iterator edgesIt = m_edges.find(type); - if (edgesIt != m_edges.end()) { - const NodeList& adjNodes = m_edges.find(type)->second; - NodeList::const_iterator i = adjNodes.begin(); - for (; i != adjNodes.end(); ++i) { - SbkObjectType* newType = identifyType(cptr, *i, baseType); - if (newType) - return newType; - } - } - void* typeFound = ((type->d && type->d->type_discovery) ? type->d->type_discovery(*cptr, baseType) : 0); - 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 SbkObjectType* instead of - // a possible variation of the C++ instance pointer (*cptr). - if (typeFound != type) - *cptr = typeFound; - return type; - } else { - return 0; - } - } -}; - - -#ifndef NDEBUG -static void showWrapperMap(const WrapperMap& wrapperMap) -{ - if (Py_VerboseFlag > 0) { - fprintf(stderr, "-------------------------------\n"); - fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); - WrapperMap::const_iterator iter; - for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) { - const SbkObject *sbkObj = iter->second; - fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", iter->first, - static_cast(sbkObj), - Py_TYPE(sbkObj)->tp_name, - int(reinterpret_cast(sbkObj)->ob_refcnt)); - } - fprintf(stderr, "-------------------------------\n"); - } -} -#endif - -struct BindingManager::BindingManagerPrivate { - WrapperMap wrapperMapper; - Graph classHierarchy; - bool destroying; - - BindingManagerPrivate() : destroying(false) {} - bool releaseWrapper(void* cptr, SbkObject* wrapper); - void assignWrapper(SbkObject* wrapper, const void* cptr); - -}; - -bool BindingManager::BindingManagerPrivate::releaseWrapper(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. - WrapperMap::iterator iter = wrapperMapper.find(cptr); - if (iter != wrapperMapper.end() && (wrapper == 0 || iter->second == wrapper)) { - wrapperMapper.erase(iter); - return true; - } - return false; -} - -void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, const void* cptr) -{ - assert(cptr); - WrapperMap::iterator iter = wrapperMapper.find(cptr); - if (iter == wrapperMapper.end()) - wrapperMapper.insert(std::make_pair(cptr, wrapper)); -} - -BindingManager::BindingManager() -{ - m_d = new BindingManager::BindingManagerPrivate; - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - debugInstallFreeHook(); -#endif -} - -BindingManager::~BindingManager() -{ -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - debugRemoveFreeHook(); -#endif -#ifndef NDEBUG - showWrapperMap(m_d->wrapperMapper); -#endif - /* Cleanup hanging references. We just invalidate them as when - * the BindingManager is being destroyed the interpreter is alredy - * shutting down. */ - if (Py_IsInitialized()) { // ensure the interpreter is still valid - while (!m_d->wrapperMapper.empty()) { - Object::destroy(m_d->wrapperMapper.begin()->second, const_cast(m_d->wrapperMapper.begin()->first)); - } - assert(m_d->wrapperMapper.size() == 0); - } - delete m_d; -} - -BindingManager& BindingManager::instance() { - static BindingManager singleton; - return singleton; -} - -bool BindingManager::hasWrapper(const void* cptr) -{ - return m_d->wrapperMapper.find(cptr) != m_d->wrapperMapper.end(); -} - -void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) -{ - SbkObjectType* instanceType = reinterpret_cast(Py_TYPE(pyObj)); - SbkObjectTypePrivate* d = instanceType->d; - - if (!d) - return; - - 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((std::size_t) cptr + (*offset))); - offset++; - } - } -} - -void BindingManager::releaseWrapper(SbkObject* sbkObj) -{ - SbkObjectType* sbkType = reinterpret_cast(Py_TYPE(sbkObj)); - SbkObjectTypePrivate* d = sbkType->d; - int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1); - - void** cptrs = reinterpret_cast(sbkObj)->d->cptr; - for (int i = 0; i < numBases; ++i) { - unsigned char *cptr = reinterpret_cast(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((std::size_t) cptr + (*offset)), sbkObj); - offset++; - } - } - } - sbkObj->d->validCppObject = false; -} - -SbkObject* BindingManager::retrieveWrapper(const void* cptr) -{ - WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter == m_d->wrapperMapper.end()) - return 0; - return iter->second; -} - -PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) -{ - 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(wrapper)->ob_refcnt == 0) - return 0; - - if (wrapper->ob_dict) { - PyObject* method = PyDict_GetItemString(wrapper->ob_dict, methodName); - if (method) { - Py_INCREF(reinterpret_cast(method)); - return method; - } - } - - PyObject* pyMethodName = Shiboken::String::fromCString(methodName); - PyObject *method = PyObject_GetAttr(reinterpret_cast(wrapper), pyMethodName); - - if (method && PyMethod_Check(method) - && reinterpret_cast(method)->im_self == reinterpret_cast(wrapper)) { - PyObject* defaultMethod; - PyObject* mro = Py_TYPE(wrapper)->tp_mro; - - // 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 i = 1; i < PyTuple_GET_SIZE(mro) - 1; i++) { - PyTypeObject* parent = reinterpret_cast(PyTuple_GET_ITEM(mro, i)); - if (parent->tp_dict) { - defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName); - if (defaultMethod && reinterpret_cast(method)->im_func != defaultMethod) { - Py_DECREF(pyMethodName); - return method; - } - } - } - } - - Py_XDECREF(method); - Py_DECREF(pyMethodName); - return 0; -} - -void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) -{ - m_d->classHierarchy.addEdge(parent, child); -} - -SbkObjectType* BindingManager::resolveType(void* cptr, SbkObjectType* type) -{ - return resolveType(&cptr, type); -} - -SbkObjectType* BindingManager::resolveType(void** cptr, SbkObjectType* type) -{ - SbkObjectType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); - return identifiedType ? identifiedType : type; -} - -std::set BindingManager::getAllPyObjects() -{ - std::set pyObjects; - const WrapperMap& wrappersMap = m_d->wrapperMapper; - WrapperMap::const_iterator it = wrappersMap.begin(); - for (; it != wrappersMap.end(); ++it) - pyObjects.insert(reinterpret_cast(it->second)); - - return pyObjects; -} - -void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void* data) -{ - WrapperMap copy = m_d->wrapperMapper; - for (WrapperMap::iterator it = copy.begin(); it != copy.end(); ++it) { - if (hasWrapper(it->first)) - visitor(it->second, data); - } -} - -} // namespace Shiboken - diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h deleted file mode 100644 index 80c5add2f..000000000 --- a/libshiboken/bindingmanager.h +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BINDINGMANAGER_H -#define BINDINGMANAGER_H - -#include "sbkpython.h" -#include -#include "shibokenmacros.h" - -struct SbkObject; -struct SbkObjectType; - -namespace Shiboken -{ - -typedef void (*ObjectVisitor)(SbkObject*, void*); - -class LIBSHIBOKEN_API BindingManager -{ -public: - static BindingManager& instance(); - - bool hasWrapper(const void *cptr); - - void registerWrapper(SbkObject* pyObj, void* cptr); - void releaseWrapper(SbkObject* wrapper); - - SbkObject* retrieveWrapper(const void* cptr); - PyObject* getOverride(const void* cptr, const char* methodName); - - void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); - /** - * \deprecated Use \fn resolveType(void**, SbkObjectType*), this version is broken when used with multiple inheritance - * because the \p cptr pointer of the discovered type may be different of the given \p cptr in case - * of multiple inheritance - */ - SBK_DEPRECATED(SbkObjectType* resolveType(void* cptr, SbkObjectType* type)); - /** - * 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. - * \param cptr a pointer to a pointer to the instance of type \p type - * \param type type of *cptr - * \warning This function is slow, use it only as last resort. - */ - SbkObjectType* resolveType(void** cptr, SbkObjectType* type); - - std::set getAllPyObjects(); - - /** - * Calls the function \p visitor for each object registered on binding manager. - * \note As various C++ pointers can point to the same PyObject due to multiple inheritance - * a PyObject can be called more than one time for each PyObject. - * \param visitor function called for each object. - * \param data user data passed as second argument to the visitor function. - */ - void visitAllPyObjects(ObjectVisitor visitor, void* data); - -private: - ~BindingManager(); - // disable copy - BindingManager(); - BindingManager(const BindingManager&); - BindingManager& operator=(const BindingManager&); - - struct BindingManagerPrivate; - BindingManagerPrivate* m_d; -}; - -} // namespace Shiboken - -#endif // BINDINGMANAGER_H - diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h deleted file mode 100644 index f0af2be8e..000000000 --- a/libshiboken/conversions.h +++ /dev/null @@ -1,731 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CONVERSIONS_H -#define CONVERSIONS_H - -#include "sbkpython.h" -#include -#include - -#include "sbkstring.h" -#include "sbkenum.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include "sbkdbg.h" - -// When the user adds a function with an argument unknown for the typesystem, the generator writes type checks as -// TYPENAME_Check, so this macro allows users to add PyObject arguments to their added functions. -#define PyObject_Check(X) true -#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X)) -#include "autodecref.h" - -namespace Shiboken -{ -/** -* This function template is used to get the PyTypeObject of a C++ type T. -* All implementations should be provided by template specializations generated by the generator when -* T isn't a C++ primitive type. -* \see SpecialCastFunction -*/ -template -PyTypeObject* SbkType() -{ - return 0; -} - -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } - -/** - * Convenience template to create wrappers using the proper Python type for a given C++ class instance. - */ -template -inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false) -{ - const char* typeName = 0; - if (!isExactType) - typeName = typeid(*const_cast(cppobj)).name(); - return Object::newObject(reinterpret_cast(SbkType()), - const_cast(cppobj), hasOwnership, isExactType, typeName); -} - -// Base Conversions ---------------------------------------------------------- -// The basic converter must be empty to avoid object types being converted by value. -template struct Converter {}; - -// Pointer conversion specialization for value types. -template -struct Converter -{ - static inline bool checkType(PyObject* pyObj) - { - return Converter::checkType(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); - } - - static PyObject* toPython(const T* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper(cppobj); - return pyobj; - } - - static T* toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - else if (Converter::isConvertible(pyobj)) - return new T(Converter::toCpp(pyobj)); - else if (pyobj == Py_None) - return 0; - - assert(false); - return 0; - } -}; -template struct Converter : Converter {}; - -// Specialization for reference conversions. -template -struct Converter -{ - static inline bool checkType(PyObject* pyObj) { return Converter::checkType(pyObj); } - static inline bool isConvertible(PyObject* pyObj) { return Converter::isConvertible(pyObj); } - static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) { return *Converter::toCpp(pyobj); } -}; - -// Void pointer conversions. -template<> -struct Converter -{ - static inline bool checkType(PyObject *) { return false; } - static inline bool isConvertible(PyObject *) { return true; } - static PyObject* toPython(void* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject *result = reinterpret_cast(cppobj); - Py_INCREF(result); - return result; - } - static void* toCpp(PyObject* pyobj) { return pyobj; } -}; - -// Base converter meant to be inherited by converters for classes that could be -// passed by value. -// Example: "struct Converter : ValueTypeConverter" -template -struct ValueTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - - // The basic version of this method also tries to use the extended 'isConvertible' method. - static inline bool isConvertible(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return true; - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - return ObjectType::isExternalConvertible(shiboType, pyobj); - } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const T& cppobj) - { - PyObject* obj = createWrapper(new T(cppobj), true, true); -// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo::isCppWrapper); - return obj; - } - // Classes with implicit conversions are expected to reimplement 'toCpp' to build T from - // its various implicit constructors. Even classes without implicit conversions could - // get some of those via other modules defining conversion operator for them, thus - // the basic Converter for value types checks for extended conversion and tries to - // use them if it is the case. - static inline T toCpp(PyObject* pyobj) - { - if (!PyObject_TypeCheck(pyobj, SbkType())) { - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { - T* cptr = reinterpret_cast(ObjectType::callExternalCppConversion(shiboType, pyobj)); - const T result = *cptr; - delete cptr; - return result; - } - assert(false); - } - return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - } -}; - -// Base converter meant to be inherited by converters for abstract classes and object types -// (i.e. classes with private copy constructors and = operators). -// Example: "struct Converter : ObjectTypeConverter" -template -struct ObjectTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } - /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer). - static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } - /// Convenience overload that calls "toPython(const T*)" method. - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } - /// Returns a new Python wrapper for the C++ object or an existing one with its reference counter incremented. - static PyObject* toPython(const T* cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); - if (pyobj) - Py_INCREF(pyobj); - else - pyobj = createWrapper(cppobj); - return pyobj; - } - /// Returns the wrapped C++ pointer casted properly, or a NULL pointer if the argument is a Py_None. - static T* toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - SbkObject *sbkObj = reinterpret_cast(pyobj); - SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); - if (ObjectType::hasCast(shiboType)) - return reinterpret_cast(ObjectType::cast(shiboType, sbkObj, SbkType())); - return reinterpret_cast(Object::cppPointer(sbkObj, SbkType())); - } -}; - -template -struct ObjectTypeReferenceConverter : ObjectTypeConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } - static inline T& toCpp(PyObject* pyobj) - { - T* t = Converter::toCpp(pyobj); - assert(t); - return *t; - } -}; - -// PyObject* specialization to avoid converting what doesn't need to be converted. -template<> -struct Converter : ObjectTypeConverter -{ - static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } -}; - -// Primitive Conversions ------------------------------------------------------ -template <> -struct Converter -{ - static inline bool checkType(PyObject* pyobj) { return PyBool_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return PyInt_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(bool cppobj) { return PyBool_FromLong(cppobj); } - static inline bool toCpp(PyObject* pyobj) { return PyInt_AS_LONG(pyobj); } -}; - -/** - * Helper template for checking if a value overflows when casted to type T - */ -template::is_signed > -struct OverFlowChecker; - -template -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG& value) - { - return value < std::numeric_limits::min() || value > std::numeric_limits::max(); - } -}; - -template -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG& value) - { - return value < 0 || static_cast(value) > std::numeric_limits::max(); - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const PY_LONG_LONG &) - { - return false; - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const double &) - { - return false; - } -}; - -template<> -struct OverFlowChecker -{ - static bool check(const double& value) - { - return value < std::numeric_limits::min() || value > std::numeric_limits::max(); - } -}; - -template -struct Converter_PyInt -{ - static inline bool checkType(PyObject* pyobj) { return PyInt_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return SbkNumber_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const PyIntEquiv& cppobj) { return PyInt_FromLong((long) cppobj); } - static PyIntEquiv toCpp(PyObject* pyobj) - { - if (PyFloat_Check(pyobj)) { - double d_result = PyFloat_AS_DOUBLE(pyobj); - // If cast to long directly it could overflow silently - if (OverFlowChecker::check(d_result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast(d_result); - } else { - PY_LONG_LONG result = PyLong_AsLongLong(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return static_cast(result); - } - } -}; - -template -struct Converter_PyULongInt : Converter_PyInt -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const T& cppobj) { return PyLong_FromUnsignedLong(cppobj); } -}; - -/// Specialization to convert char and unsigned char, it accepts Python numbers and strings with just one character. -template -struct CharConverter -{ - static inline bool checkType(PyObject* pyobj) { return SbkChar_Check(pyobj); } - static inline bool isConvertible(PyObject* pyobj) { return SbkChar_Check(pyobj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(const CharType& cppobj) { return PyInt_FromLong(cppobj); } - static CharType toCpp(PyObject* pyobj) - { - if (PyBytes_Check(pyobj)) { - assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check - return PyBytes_AS_STRING(pyobj)[0]; - } else if (PyInt_Check(pyobj)) { - PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return result; - } else if (Shiboken::String::check(pyobj)) { - return Shiboken::String::toCString(pyobj)[0]; - } else { - return 0; - } - } -}; - -template <> struct Converter : Converter_PyULongInt {}; -template <> struct Converter : Converter_PyULongInt {}; -template <> struct Converter : CharConverter -{ - // Should we really return a string? - using CharConverter::toPython; - using CharConverter::isConvertible; - using CharConverter::toCpp; - - - static inline bool isConvertible(PyObject* pyobj) { - return SbkChar_Check(pyobj); - } - - static inline PyObject* toPython(const char& cppObj) { - return Shiboken::String::fromFormat("%c", cppObj); - } - - static char toCpp(PyObject* pyobj) - { - if (PyBytes_Check(pyobj)) { - assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check - return PyBytes_AS_STRING(pyobj)[0]; - } else if (PyInt_Check(pyobj)) { - PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); - if (OverFlowChecker::check(result)) - PyErr_SetObject(PyExc_OverflowError, 0); - return char(result); - } else if (Shiboken::String::check(pyobj)) { - return Shiboken::String::toCString(pyobj)[0]; - } else { - return 0; - } - } -}; -template <> struct Converter : CharConverter {}; -template <> struct Converter : CharConverter {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; -template <> struct Converter : Converter_PyInt {}; - -template <> -struct Converter -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(PY_LONG_LONG cppobj) { return PyLong_FromLongLong(cppobj); } - static inline PY_LONG_LONG toCpp(PyObject* pyobj) { return (PY_LONG_LONG) PyLong_AsLongLong(pyobj); } -}; - -template <> -struct Converter -{ - static inline PyObject* toPython(void* cppobj) - { - return toPython(*reinterpret_cast(cppobj)); - } - static inline PyObject* toPython(unsigned PY_LONG_LONG cppobj) - { - return PyLong_FromUnsignedLongLong(cppobj); - } - static inline unsigned PY_LONG_LONG toCpp(PyObject* pyobj) - { -#if PY_MAJOR_VERSION >= 3 - if (!PyLong_Check(pyobj)) { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - return 0; - } - - return PyLong_AsUnsignedLongLong(pyobj); -#else - if (PyInt_Check(pyobj)) { - long result = (unsigned PY_LONG_LONG) PyInt_AsLong(pyobj); - if (result < 0) { - PyErr_SetObject(PyExc_OverflowError, 0); - return 0; - } else - return (unsigned PY_LONG_LONG) result; - } else if (PyLong_Check(pyobj)) { - return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyobj); - } else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - return 0; - } -#endif // Python 2 - } -}; - -template -struct Converter_PyFloat -{ - static inline bool checkType(PyObject* obj) { return PyFloat_Check(obj); } - static inline bool isConvertible(PyObject* obj) { return SbkNumber_Check(obj); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(PyFloatEquiv cppobj) { return PyFloat_FromDouble((double) cppobj); } - static inline PyFloatEquiv toCpp(PyObject* pyobj) - { - if (PyInt_Check(pyobj) || PyLong_Check(pyobj)) - return (PyFloatEquiv) PyLong_AsLong(pyobj); - return (PyFloatEquiv) PyFloat_AsDouble(pyobj); - } -}; - -template <> struct Converter : Converter_PyFloat {}; -template <> struct Converter : Converter_PyFloat {}; - -// PyEnum Conversions --------------------------------------------------------- -template -struct EnumConverter -{ - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(CppEnum cppenum) - { - return Shiboken::Enum::newItem(Shiboken::SbkType(), (long) cppenum); - } - static inline CppEnum toCpp(PyObject* pyObj) - { - return (CppEnum) Shiboken::Enum::getValue(pyObj);; - } -}; - -// C Sting Types -------------------------------------------------------------- -template -struct Converter_CString -{ - // Note: 0 is also a const char* in C++, so None is accepted in checkType - static inline bool checkType(PyObject* pyObj) { - return Shiboken::String::check(pyObj); - } - static inline bool isConvertible(PyObject* pyObj) { - return Shiboken::String::isConvertible(pyObj); - } - static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } - static inline PyObject* toPython(CString cppobj) - { - if (!cppobj) - Py_RETURN_NONE; - return Shiboken::String::fromCString(cppobj); - } - static inline CString toCpp(PyObject* pyobj) { - if (pyobj == Py_None) - return 0; - return Shiboken::String::toCString(pyobj); - } -}; - -template <> struct Converter : Converter_CString {}; - -template <> struct Converter : Converter_CString -{ - static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } - static inline PyObject* toPython(std::string cppObj) - { - return Shiboken::String::fromCString(cppObj.c_str()); - } - - static inline std::string toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - return std::string(Shiboken::String::toCString(pyobj)); - } -}; - -// C++ containers ------------------------------------------------------------- -// The following container converters are meant to be used for pairs, lists and maps -// that are similar to the STL containers of the same name. - -// For example to create a converter for a std::list the following code is enough: -// template struct Converter > : StdListConverter > {}; - -// And this for a std::map: -// template -// struct Converter > : StdMapConverter > {}; - -template -struct StdListConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - // Sequence conversion are made ONLY for python sequences, not for - // binded types implementing sequence protocol, otherwise this will - // cause a mess like QBitArray being accepted by someone expecting a - // QStringList. - if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj)) - return false; - for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { - AutoDecRef item(PySequence_GetItem(pyObj, i)); - if (!Converter::isConvertible(item)) - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdList& cppobj) - { - PyObject* result = PyList_New((int) cppobj.size()); - typename StdList::const_iterator it = cppobj.begin(); - for (int idx = 0; it != cppobj.end(); ++it, ++idx) { - typename StdList::value_type vh(*it); - PyList_SET_ITEM(result, idx, Converter::toPython(vh)); - } - return result; - } - static StdList toCpp(PyObject* pyobj) - { - if (PyObject_TypeCheck(pyobj, SbkType())) - return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); - - StdList result; - for (int i = 0; i < PySequence_Size(pyobj); i++) { - AutoDecRef pyItem(PySequence_GetItem(pyobj, i)); - result.push_back(Converter::toCpp(pyItem)); - } - return result; - } -}; - -template -struct StdPairConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) - return false; - - AutoDecRef item1(PySequence_GetItem(pyObj, 0)); - AutoDecRef item2(PySequence_GetItem(pyObj, 1)); - - if (!Converter::isConvertible(item1) - && !Converter::isConvertible(item2)) { - return false; - } - return true; - } - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdPair& cppobj) - { - typename StdPair::first_type first(cppobj.first); - typename StdPair::second_type second(cppobj.second); - PyObject* tuple = PyTuple_New(2); - PyTuple_SET_ITEM(tuple, 0, Converter::toPython(first)); - PyTuple_SET_ITEM(tuple, 1, Converter::toPython(second)); - return tuple; - } - static StdPair toCpp(PyObject* pyobj) - { - StdPair result; - AutoDecRef pyFirst(PySequence_GetItem(pyobj, 0)); - AutoDecRef pySecond(PySequence_GetItem(pyobj, 1)); - result.first = Converter::toCpp(pyFirst); - result.second = Converter::toCpp(pySecond); - return result; - } -}; - -template -struct StdMapConverter -{ - static inline bool checkType(PyObject* pyObj) - { - return isConvertible(pyObj); - } - - static inline bool isConvertible(PyObject* pyObj) - { - if (PyObject_TypeCheck(pyObj, SbkType())) - return true; - if ((SbkType() && Object::checkType(pyObj)) || !PyDict_Check(pyObj)) - return false; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyObj, &pos, &key, &value)) { - if (!Converter::isConvertible(key) - || !Converter::isConvertible(value)) { - return false; - } - } - return true; - } - - static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } - static PyObject* toPython(const StdMap& cppobj) - { - PyObject* result = PyDict_New(); - typename StdMap::const_iterator it = cppobj.begin(); - - for (; it != cppobj.end(); ++it) { - PyDict_SetItem(result, - Converter::toPython(it->first), - Converter::toPython(it->second)); - } - - return result; - } - static StdMap toCpp(PyObject* pyobj) - { - StdMap result; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - - while (PyDict_Next(pyobj, &pos, &key, &value)) { - result.insert(typename StdMap::value_type( - Converter::toCpp(key), - Converter::toCpp(value))); - } - return result; - } -}; - - -// class used to translate python objects to another type -template struct PythonConverter {}; - -} // namespace Shiboken - -#endif // CONVERSIONS_H - diff --git a/libshiboken/debugfreehook.cpp b/libshiboken/debugfreehook.cpp deleted file mode 100644 index f5757a70f..000000000 --- a/libshiboken/debugfreehook.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "debugfreehook.h" -#include "bindingmanager.h" -#include "gilstate.h" - -#if defined(_WIN32) && defined(_DEBUG) -#include -#include -#endif - -#ifdef __GLIBC__ -#include -#endif - -#ifdef __APPLE__ -#include -#include -#include -#endif - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK -extern "C" { - -static int testPointerBeingFreed(void *ptr) -{ - // It is an error for a deleted pointer address to still be registered - // in the BindingManager - if (Shiboken::BindingManager::instance().hasWrapper(ptr)) { - Shiboken::GilState state; - - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(ptr); - - fprintf(stderr, "SbkObject still in binding map when deleted: "); - PyObject_Print(reinterpret_cast(wrapper), stderr, 0); - fprintf(stderr, "\n"); - -#ifdef _WIN32 - DebugBreak(); -#else - assert(0); -#endif - return FALSE; - } - - return TRUE; -} - -#if defined(_WIN32) && defined(_DEBUG) -static _CRT_ALLOC_HOOK lastCrtAllocHook; -static int DebugAllocHook(int nAllocType, void *pvData, - size_t nSize, int nBlockUse, long lRequest, - const unsigned char * szFileName, int nLine) -{ - // It is an error for a deleted pointer address to still be registered - // in the BindingManager - if ( nAllocType == _HOOK_FREE) { - if ( !testPointerBeingFreed(pvData) ) { - return 0; - } - } - - if ( lastCrtAllocHook != NULL ) { - return lastCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, - szFileName, nLine); - } - - return 1; -} -#endif // _WIN32 && _DEBUG - -#ifdef __GLIBC__ -static void (*lastFreeHook)(void* ptr, const void* caller); -static void DebugFreeHook(void* ptr, const void* caller) -{ - testPointerBeingFreed(ptr); - - if ( lastFreeHook != NULL ) - lastFreeHook(ptr, caller); -} -#endif // __GLIBC__ - -#ifdef __APPLE__ -static malloc_zone_t lastMallocZone; -static void DebugFreeHook(malloc_zone_t *zone, void *ptr) -{ - testPointerBeingFreed(ptr); - - if ( lastMallocZone.free != NULL ) - lastMallocZone.free(zone, ptr); -} -static void DebugFreeDefiniteSizeHook(malloc_zone_t *zone, void *ptr, size_t size) -{ - testPointerBeingFreed(ptr); - - if ( lastMallocZone.free_definite_size != NULL ) - lastMallocZone.free_definite_size(zone, ptr, size); -} -#endif __APPLE__ - -void debugInstallFreeHook(void) -{ -#if defined(_WIN32) && defined(_DEBUG) - lastCrtAllocHook = _CrtSetAllocHook(DebugAllocHook); -#endif - -#ifdef __GLIBC__ - // __free_hook is not thread safe so it marked as deprecated. Use here - // is hopefully safe and should catch errors in a single threaded program - // and only miss some in a multithreaded program - lastFreeHook = __free_hook; - __free_hook = DebugFreeHook; -#endif - -#ifdef __APPLE__ - malloc_zone_t* zone = malloc_default_zone(); - assert(zone != NULL); - //remove the write protection from the zone struct - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); - } - lastMallocZone = *zone; - zone->free = DebugFreeHook; - zone->free_definite_size = DebugFreeDefiniteSizeHook; - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); - } -#endif -} - -void debugRemoveFreeHook(void) -{ -#if defined(_WIN32) && defined(_DEBUG) - _CrtSetAllocHook(lastCrtAllocHook); -#endif - -#ifdef __GLIBC__ - __free_hook = lastFreeHook; -#endif - -#ifdef __APPLE__ - malloc_zone_t* zone = malloc_default_zone(); - assert(zone != NULL); - //remove the write protection from the zone struct - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); - } - zone->free = lastMallocZone.free; - zone->free_definite_size = lastMallocZone.free_definite_size; - if (zone->version >= 8) { - vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); - } -#endif -} - -} // extern "C" -#endif // SHIBOKEN_INSTALL_DEBUG_FREE_HOOK diff --git a/libshiboken/debugfreehook.h b/libshiboken/debugfreehook.h deleted file mode 100644 index 743d56e4c..000000000 --- a/libshiboken/debugfreehook.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DEBUGFREEHOOK_H -#define DEBUGFREEHOOK_H - -// These functions enable C library runtime hooks to try to catch cases where -// C++ object addresses remain in hash table of valid wrappers when the address -// is passed to free. The hooks are probably not thread safe and thus -// should only be enabled in single threaded environments - -// To enable the hook, uncomment the following define. -//#define SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - -#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK -extern "C" { - -void debugInstallFreeHook(void); -void debugRemoveFreeHook(void); - -} // extern "C" - -#endif // SHIBOKEN_INSTALL_FREE_DEBUG_HOOK - -#endif // DEBUGFREEHOOK_H diff --git a/libshiboken/gilstate.cpp b/libshiboken/gilstate.cpp deleted file mode 100644 index e7406fdd6..000000000 --- a/libshiboken/gilstate.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "gilstate.h" - -namespace Shiboken -{ - -GilState::GilState() - : m_locked(false) -{ - if (Py_IsInitialized()) { - m_gstate = PyGILState_Ensure(); - m_locked = true; - } -} - -GilState::~GilState() -{ - release(); -} - -void GilState::release() -{ - if (m_locked && Py_IsInitialized()) { - PyGILState_Release(m_gstate); - m_locked = false; - } -} - -} // namespace Shiboken - diff --git a/libshiboken/gilstate.h b/libshiboken/gilstate.h deleted file mode 100644 index e0f18a814..000000000 --- a/libshiboken/gilstate.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef GILSTATE_H -#define GILSTATE_H - -#include -#include "sbkpython.h" - -namespace Shiboken -{ - -class LIBSHIBOKEN_API GilState -{ -public: - GilState(); - ~GilState(); - void release(); -private: - PyGILState_STATE m_gstate; - bool m_locked; -}; - -} // namespace Shiboken - -#endif // GILSTATE_H - diff --git a/libshiboken/helper.cpp b/libshiboken/helper.cpp deleted file mode 100644 index 9709d0776..000000000 --- a/libshiboken/helper.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "helper.h" -#include - -namespace Shiboken -{ - -bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) -{ - if (!PySequence_Check(argList)) - return false; - - if (!defaultAppName) - defaultAppName = "PySideApplication"; - - // Check all items - Shiboken::AutoDecRef args(PySequence_Fast(argList, 0)); - int numArgs = PySequence_Fast_GET_SIZE(argList); - for (int i = 0; i < numArgs; ++i) { - PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); - if (!PyBytes_Check(item) && !PyUnicode_Check(item)) - return false; - } - - bool hasEmptyArgList = numArgs == 0; - if (hasEmptyArgList) - numArgs = 1; - - *argc = numArgs; - *argv = new char*[*argc]; - - if (hasEmptyArgList) { - // Try to get the script name - PyObject* globals = PyEval_GetGlobals(); - PyObject* appName = PyDict_GetItemString(globals, "__file__"); - (*argv)[0] = strdup(appName ? Shiboken::String::toCString(appName) : defaultAppName); - } else { - for (int i = 0; i < numArgs; ++i) { - PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); - char* string = 0; - if (Shiboken::String::check(item)) { - string = strdup(Shiboken::String::toCString(item)); - } - (*argv)[i] = string; - } - } - - return true; -} - -int* sequenceToIntArray(PyObject* obj, bool zeroTerminated) -{ - AutoDecRef seq(PySequence_Fast(obj, "Sequence of ints expected")); - if (seq.isNull()) - return 0; - - Py_ssize_t size = PySequence_Fast_GET_SIZE(seq.object()); - int* array = new int[size + (zeroTerminated ? 1 : 0)]; - - for (int i = 0; i < size; i++) { - PyObject* item = PySequence_Fast_GET_ITEM(seq.object(), i); - if (!PyInt_Check(item)) { - PyErr_SetString(PyExc_TypeError, "Sequence of ints expected"); - delete[] array; - return 0; - } else { - array[i] = PyInt_AsLong(item); - } - } - - if (zeroTerminated) - array[size] = 0; - - return array; -} - - -int warning(PyObject* category, int stacklevel, const char* format, ...) -{ - va_list args; - va_start(args, format); -#if _WIN32 - va_list args2 = args; -#else - va_list args2; - va_copy(args2, args); -#endif - - // check the necessary memory - int size = vsnprintf(NULL, 0, format, args) + 1; - char* message = new char[size]; - int result = 0; - if (message) { - // format the message - vsnprintf(message, size, format, args2); - result = PyErr_WarnEx(category, message, stacklevel); - delete [] message; - } - va_end(args2); - va_end(args); - return result; -} - -} // namespace Shiboken diff --git a/libshiboken/helper.h b/libshiboken/helper.h deleted file mode 100644 index f2061b667..000000000 --- a/libshiboken/helper.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HELPER_H -#define HELPER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" -#include "conversions.h" -#include "autodecref.h" - -#define SBK_UNUSED(x) (void)x; - -namespace Shiboken -{ - -template -inline PyObject* makeTuple(const A& a) -{ - return PyTuple_Pack(1, AutoDecRef(Converter::toPython(a)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b) -{ - return PyTuple_Pack(2, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c) -{ - return PyTuple_Pack(3, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d) -{ - return PyTuple_Pack(4, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object(), - AutoDecRef(Converter::toPython(d)).object()); -} - -template -inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e) -{ - return PyTuple_Pack(5, AutoDecRef(Converter::toPython(a)).object(), - AutoDecRef(Converter::toPython(b)).object(), - AutoDecRef(Converter::toPython(c)).object(), - AutoDecRef(Converter::toPython(d)).object(), - AutoDecRef(Converter::toPython(e)).object()); -} - -/** -* It transforms a python sequence into two C variables, argc and argv. -* This function tries to find the application (script) name and put it into argv[0], if -* the application name can't be guessed, defaultAppName will be used. -* -* No memory is allocated is an error occur. -* -* \note argc must be a valid address. -* \note The argv array is allocated using new operator and each item is allocated using malloc. -* \returns True on sucess, false otherwise. -*/ -LIBSHIBOKEN_API bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); - -/** - * Convert a python sequence into a heap-allocated array of ints. - * - * \returns The newly allocated array or NULL in case of error or empty sequence. Check with PyErr_Occurred - * if it was successfull. - */ -LIBSHIBOKEN_API int* sequenceToIntArray(PyObject* obj, bool zeroTerminated = false); - -/** - * Creates and automatically deallocates C++ arrays. - */ -template -class AutoArrayPointer -{ - public: - AutoArrayPointer(int size) { data = new T[size]; } - T& operator[](int pos) { return data[pos]; } - operator T*() const { return data; } - ~AutoArrayPointer() { delete[] data; } - private: - T* data; -}; - -/** - * An utility function used to call PyErr_WarnEx with a formatted message. - */ -LIBSHIBOKEN_API int warning(PyObject* category, int stacklevel, const char* format, ...); - -} // namespace Shiboken - -#endif // HELPER_H diff --git a/libshiboken/python25compat.h b/libshiboken/python25compat.h deleted file mode 100644 index 71c88d86a..000000000 --- a/libshiboken/python25compat.h +++ /dev/null @@ -1,104 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PYTHON25COMPAT_H -#define PYTHON25COMPAT_H -#include -#include - -/* - *The #defines below were taken from Cython-generated code to allow shiboken to be used with python2.5. - * Maybe not all of these defines are useful to us, time will tell which ones are really needed or not. - */ - -#if PY_VERSION_HEX < 0x02060000 -#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) -#define PyVarObject_HEAD_INIT(type, size) \ - PyObject_HEAD_INIT(type) size, -#define PyType_Modified(t) - -typedef struct { - void *buf; - PyObject *obj; - Py_ssize_t len; - Py_ssize_t itemsize; - int readonly; - int ndim; - char *format; - Py_ssize_t *shape; - Py_ssize_t *strides; - Py_ssize_t *suboffsets; - void *internal; -} Py_buffer; - -#define PyBUF_SIMPLE 0 -#define PyBUF_WRITABLE 0x0001 -#define PyBUF_LOCK 0x0002 -#define PyBUF_FORMAT 0x0004 -#define PyBUF_ND 0x0008 -#define PyBUF_STRIDES (0x0010 | PyBUF_ND) -#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) -#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) -#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) -#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) - -#define PyBytes_Check PyString_Check -#define PyBytes_FromString PyString_FromString -#define PyBytes_FromFormat PyString_FromFormat -#define PyBytes_FromStringAndSize PyString_FromStringAndSize -#define PyBytes_GET_SIZE PyString_GET_SIZE -#define PyBytes_AS_STRING PyString_AS_STRING -#define PyBytes_AsString PyString_AsString -#define PyBytes_Concat PyString_Concat -#define PyBytes_Size PyString_Size - -inline PyObject* PyUnicode_FromString(const char* s) -{ - std::size_t len = std::strlen(s); - return PyUnicode_DecodeUTF8(s, len, 0); -} - -#define PyLong_FromSize_t _PyLong_FromSize_t -#define PyLong_AsSsize_t _PyLong_AsSsize_t - -#endif - -#endif diff --git a/libshiboken/sbkconverter.cpp b/libshiboken/sbkconverter.cpp deleted file mode 100644 index b22b33705..000000000 --- a/libshiboken/sbkconverter.cpp +++ /dev/null @@ -1,571 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkconverter.h" -#include "sbkconverter_p.h" -#include "basewrapper_p.h" -#include "autodecref.h" -#include "sbkdbg.h" -#include "helper.h" - -#include - -static SbkConverter** PrimitiveTypeConverters; - -typedef std::unordered_map ConvertersMap; -static ConvertersMap converters; - -namespace Shiboken { -namespace Conversions { - -void init() -{ - static SbkConverter* primitiveTypeConverters[] = { - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter(), - Primitive::createConverter() - }; - PrimitiveTypeConverters = primitiveTypeConverters; - - assert(converters.empty()); - converters["PY_LONG_LONG"] = primitiveTypeConverters[SBK_PY_LONG_LONG_IDX]; - converters["bool"] = primitiveTypeConverters[SBK_BOOL_IDX_1]; - converters["char"] = primitiveTypeConverters[SBK_CHAR_IDX]; - converters["const char *"] = primitiveTypeConverters[SBK_CONSTCHARPTR_IDX]; - converters["double"] = primitiveTypeConverters[SBK_DOUBLE_IDX]; - converters["float"] = primitiveTypeConverters[SBK_FLOAT_IDX]; - converters["int"] = primitiveTypeConverters[SBK_INT_IDX]; - converters["long"] = primitiveTypeConverters[SBK_LONG_IDX]; - converters["short"] = primitiveTypeConverters[SBK_SHORT_IDX]; - converters["signed char"] = primitiveTypeConverters[SBK_SIGNEDCHAR_IDX]; - converters["std::string"] = primitiveTypeConverters[SBK_STD_STRING_IDX]; - converters["unsigned PY_LONG_LONG"] = primitiveTypeConverters[SBK_UNSIGNEDPY_LONG_LONG_IDX]; - converters["unsigned char"] = primitiveTypeConverters[SBK_UNSIGNEDCHAR_IDX]; - converters["unsigned int"] = primitiveTypeConverters[SBK_UNSIGNEDINT_IDX]; - converters["unsigned long"] = primitiveTypeConverters[SBK_UNSIGNEDLONG_IDX]; - converters["unsigned short"] = primitiveTypeConverters[SBK_UNSIGNEDSHORT_IDX]; - converters["void*"] = primitiveTypeConverters[SBK_VOIDPTR_IDX]; -} - -static SbkConverter* createConverterObject(PyTypeObject* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter* converter = new SbkConverter; - converter->pythonType = type; - - converter->pointerToPython = pointerToPythonFunc; - converter->copyToPython = copyToPythonFunc; - - if (toCppPointerCheckFunc && toCppPointerConvFunc) - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); - converter->toCppConversions.clear(); - - return converter; -} - -SbkConverter* createConverter(SbkObjectType* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter *converter = - createConverterObject(reinterpret_cast(type), - toCppPointerConvFunc, toCppPointerCheckFunc, - pointerToPythonFunc, copyToPythonFunc); - type->d->converter = converter; - return converter; -} - -SbkConverter* createConverter(PyTypeObject* type, CppToPythonFunc toPythonFunc) -{ - return createConverterObject(type, 0, 0, 0, toPythonFunc); -} - -void deleteConverter(SbkConverter* converter) -{ - if (converter) { - converter->toCppConversions.clear(); - delete converter; - } -} - -void setCppPointerToPythonFunction(SbkConverter* converter, CppToPythonFunc pointerToPythonFunc) -{ - converter->pointerToPython = pointerToPythonFunc; -} - -void setPythonToCppPointerFunctions(SbkConverter* converter, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc) -{ - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); -} - -void addPythonToCppValueConversion(SbkConverter* converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); -} -void addPythonToCppValueConversion(SbkObjectType* type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); -} - -PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn) -{ - return pointerToPython(type->d->converter, cppIn); -} - -PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn) -{ - assert(converter); - if (!cppIn) - Py_RETURN_NONE; - if (!converter->pointerToPython) { - warning(PyExc_RuntimeWarning, 0, "pointerToPython(): SbkConverter::pointerToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->pointerToPython(cppIn); -} - -PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn) -{ - return referenceToPython(type->d->converter, cppIn); -} - -PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn) -{ - assert(cppIn); - - PyObject *pyOut = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppIn)); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - if (!converter->pointerToPython) { - warning(PyExc_RuntimeWarning, 0, "referenceToPython(): SbkConverter::pointerToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->pointerToPython(cppIn); -} - -static inline PyObject* CopyCppToPython(const SbkConverter *converter, const void *cppIn) -{ - if (!cppIn) - Py_RETURN_NONE; - if (!converter->copyToPython) { - warning(PyExc_RuntimeWarning, 0, "CopyCppToPython(): SbkConverter::copyToPython is null for \"%s\".", - converter->pythonType->tp_name); - Py_RETURN_NONE; - } - return converter->copyToPython(cppIn); -} -PyObject* copyToPython(const SbkObjectType *type, const void *cppIn) -{ - return CopyCppToPython(type->d->converter, cppIn); -} -PyObject* copyToPython(const SbkConverter *converter, const void *cppIn) -{ - return CopyCppToPython(converter, cppIn); -} - -PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn) -{ - assert(pyIn); - return type->d->converter->toCppPointerConversion.first(pyIn); -} - -static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) -{ - assert(pyIn); - const ToCppConversionList& convs = converter->toCppConversions; - for (ToCppConversionList::const_iterator conv = convs.begin(), end = convs.end(); conv != end; ++conv) { - PythonToCppFunc toCppFunc = 0; - if ((toCppFunc = (*conv).first(pyIn))) - return toCppFunc; - } - return 0; -} -PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn) -{ - return IsPythonToCppConvertible(type->d->converter, pyIn); -} -PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) -{ - return IsPythonToCppConvertible(converter, pyIn); -} - -PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn) -{ - if (pyIn != Py_None) { - PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); - if (toCpp) - return toCpp; - } - return isPythonToCppValueConvertible(type, pyIn); -} - -void nonePythonToCppNullPtr(PyObject*, void* cppOut) -{ - assert(cppOut); - *((void**)cppOut) = 0; -} - -void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn) -{ - assert(pyIn); - if (!ObjectType::checkType(desiredType)) - return pyIn; - SbkObjectType *inType = reinterpret_cast(Py_TYPE(pyIn)); - if (ObjectType::hasCast(inType)) - return ObjectType::cast(inType, pyIn, desiredType); - return Object::cppPointer(pyIn, desiredType); -} - -void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut) -{ - assert(type); - assert(pyIn); - assert(cppOut); - *reinterpret_cast(cppOut) = pyIn == Py_None - ? 0 - : cppPointer(reinterpret_cast(type), reinterpret_cast(pyIn)); -} - -void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - assert(converter); - assert(pyIn); - assert(cppOut); - *reinterpret_cast(cppOut) = pyIn == Py_None - ? 0 - : cppPointer(reinterpret_cast(converter->pythonType), reinterpret_cast(pyIn)); -} - -static void _pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - assert(converter); - assert(pyIn); - assert(cppOut); - PythonToCppFunc toCpp = IsPythonToCppConvertible(converter, pyIn); - if (toCpp) - toCpp(pyIn, cppOut); -} - -void pythonToCppCopy(const SbkObjectType *type, PyObject *pyIn, void *cppOut) -{ - assert(type); - _pythonToCppCopy(type->d->converter, pyIn, cppOut); -} - -void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) -{ - _pythonToCppCopy(converter, pyIn, cppOut); -} - -bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCppFunc) -{ - // This is the Object Type or Value Type conversion that only - // retrieves the C++ pointer held in the Python wrapper. - if (toCppFunc == type->d->converter->toCppPointerConversion.second) - return false; - - // Object Types doesn't have any kind of value conversion, - // only C++ pointer retrieval. - if (type->d->converter->toCppConversions.empty()) - return false; - - // The first conversion of the non-pointer conversion list is - // a Value Type's copy to C++ function, which is not an implicit - // conversion. - // Otherwise it must be one of the implicit conversions. - // Note that we don't check if the Python to C++ conversion is in - // the list of the type's conversions, for it is expected that the - // caller knows what he's doing. - ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); - return toCppFunc != (*conv).second; -} - -void registerConverterName(SbkConverter* converter , const char* typeName) -{ - ConvertersMap::iterator iter = converters.find(typeName); - if (iter == converters.end()) - converters.insert(std::make_pair(typeName, converter)); -} - -SbkConverter* getConverter(const char* typeName) -{ - ConvertersMap::const_iterator it = converters.find(typeName); - if (it != converters.end()) - return it->second; - if (Py_VerboseFlag > 0) - SbkDbg() << "Can't find type resolver for type '" << typeName << "'."; - return 0; -} - -SbkConverter* primitiveTypeConverter(int index) -{ - return PrimitiveTypeConverters[index]; -} - -bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn) -{ - assert(type); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type)) - return false; - } - return true; -} -bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn) -{ - assert(converter); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - const Py_ssize_t size = PySequence_Size(pyIn); - for (Py_ssize_t i = 0; i < size; ++i) { - if (!isPythonToCppConvertible(converter, AutoDecRef(PySequence_GetItem(pyIn, i)))) - return false; - } - return true; -} -bool convertibleSequenceTypes(const SbkObjectType *type, PyObject *pyIn) -{ - assert(type); - return convertibleSequenceTypes(type->d->converter, pyIn); -} - -bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn) -{ - assert(firstType); - assert(secondType); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - if (PySequence_Size(pyIn) != 2) - return false; - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 0)), firstType)) - return false; - if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 1)), secondType)) - return false; - return true; -} -bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, - const SbkConverter *secondConverter, bool secondCheckExact, - PyObject *pyIn) -{ - assert(firstConverter); - assert(secondConverter); - assert(pyIn); - if (!PySequence_Check(pyIn)) - return false; - if (PySequence_Size(pyIn) != 2) - return false; - AutoDecRef firstItem(PySequence_GetItem(pyIn, 0)); - if (firstCheckExact) { - if (!PyObject_TypeCheck(firstItem, firstConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(firstConverter, firstItem)) { - return false; - } - AutoDecRef secondItem(PySequence_GetItem(pyIn, 1)); - if (secondCheckExact) { - if (!PyObject_TypeCheck(secondItem, secondConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(secondConverter, secondItem)) { - return false; - } - - return true; -} - -bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn) -{ - assert(keyType); - assert(valueType); - assert(pyIn); - if (!PyDict_Check(pyIn)) - return false; - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(pyIn, &pos, &key, &value)) { - if (!PyObject_TypeCheck(key, keyType)) - return false; - if (!PyObject_TypeCheck(value, valueType)) - return false; - } - return true; -} - -bool convertibleDictTypes(const SbkConverter * keyConverter, bool keyCheckExact, const SbkConverter *valueConverter, - bool valueCheckExact, PyObject *pyIn) -{ - assert(keyConverter); - assert(valueConverter); - assert(pyIn); - if (!PyDict_Check(pyIn)) - return false; - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(pyIn, &pos, &key, &value)) { - if (keyCheckExact) { - if (!PyObject_TypeCheck(key, keyConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(keyConverter, key)) { - return false; - } - if (valueCheckExact) { - if (!PyObject_TypeCheck(value, valueConverter->pythonType)) - return false; - } else if (!isPythonToCppConvertible(valueConverter, value)) { - return false; - } - } - return true; -} - -PyTypeObject* getPythonTypeObject(const SbkConverter *converter) -{ - if (converter) - return converter->pythonType; - return 0; -} - -PyTypeObject* getPythonTypeObject(const char* typeName) -{ - return getPythonTypeObject(getConverter(typeName)); -} - -bool pythonTypeIsValueType(const SbkConverter *converter) -{ - assert(converter); - return converter->pointerToPython && converter->copyToPython; -} - -bool pythonTypeIsObjectType(const SbkConverter *converter) -{ - return converter->pointerToPython && !converter->copyToPython; -} - -bool pythonTypeIsWrapperType(const SbkConverter *converter) -{ - return converter->pointerToPython; -} - -SpecificConverter::SpecificConverter(const char* typeName) - : m_type(InvalidConversion) -{ - m_converter = getConverter(typeName); - if (!m_converter) - return; - const Py_ssize_t len = strlen(typeName); - char lastChar = typeName[len -1]; - if (lastChar == '&') { - m_type = ReferenceConversion; - } else if (lastChar == '*' || pythonTypeIsObjectType(m_converter)) { - m_type = PointerConversion; - } else { - m_type = CopyConversion; - } -} - -PyObject* SpecificConverter::toPython(const void* cppIn) -{ - switch (m_type) { - case CopyConversion: - return copyToPython(m_converter, cppIn); - case PointerConversion: - return pointerToPython(m_converter, *((const void**)cppIn)); - case ReferenceConversion: - return referenceToPython(m_converter, cppIn); - default: - PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'C++ to Python' conversion"); - } - return 0; -} - -void SpecificConverter::toCpp(PyObject* pyIn, void* cppOut) -{ - switch (m_type) { - case CopyConversion: - pythonToCppCopy(m_converter, pyIn, cppOut); - break; - case PointerConversion: - pythonToCppPointer(m_converter, pyIn, cppOut); - break; - case ReferenceConversion: - pythonToCppPointer(m_converter, pyIn, &cppOut); - break; - default: - PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'Python to C++' conversion"); - } -} - -} } // namespace Shiboken::Conversions diff --git a/libshiboken/sbkconverter.h b/libshiboken/sbkconverter.h deleted file mode 100644 index 7489b930d..000000000 --- a/libshiboken/sbkconverter.h +++ /dev/null @@ -1,367 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_H -#define SBK_CONVERTER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#include -#include - -struct SbkObject; -struct SbkObjectType; - -/** - * This is a convenience macro identical to Python's PyObject_TypeCheck, - * except that the arguments have swapped places, for the great convenience - * of generator. - */ -#define SbkObject_TypeCheck(tp, ob) \ - (Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp))) - -extern "C" -{ - -/** - * SbkConverter is used to perform type conversions from C++ - * to Python and vice-versa;.and it is also used for type checking. - * SbkConverter is a private structure that must be accessed - * using the functions provided by the converter API. - */ -struct SbkConverter; - -/** - * Given a void pointer to a C++ object, this function must return - * the proper Python object. It may be either an existing wrapper - * for the C++ object, or a newly create one. Or even the Python - * equivalent of the C++ value passed in the argument. - * - * C++ -> Python - */ -typedef PyObject* (*CppToPythonFunc)(const void*); - -/** - * This function converts a Python object to a C++ value, it may be - * a pointer, value, class, container or primitive type, passed via - * a void pointer, that will be cast properly inside the function. - * This function is usually returned by an IsConvertibleToCppFunc - * function, or obtained knowing the type of the Python object input, - * thus it will not check the Python object type, and will expect - * the void pointer to be pointing to a proper variable. - * - * Python -> C++ - */ -typedef void (*PythonToCppFunc)(PyObject*,void*); - -/** - * Checks if the Python object passed in the argument is convertible to a - * C++ type defined inside the function, it returns the converter function - * that will transform a Python argument into a C++ value. - * It returns NULL if the Python object is not convertible to the C++ type - * that the function represents. - * - * Python -> C++ ? - */ -typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*); - -} // extern "C" - -namespace Shiboken { -namespace Conversions { - - -class LIBSHIBOKEN_API SpecificConverter -{ -public: - enum Type - { - InvalidConversion, - CopyConversion, - PointerConversion, - ReferenceConversion - }; - - explicit SpecificConverter(const char* typeName); - - inline SbkConverter* converter() { return m_converter; } - inline operator SbkConverter*() const { return m_converter; } - - inline bool isValid() { return m_type != InvalidConversion; } - inline operator bool() const { return m_type != InvalidConversion; } - - inline Type conversionType() { return m_type; } - - PyObject* toPython(const void* cppIn); - void toCpp(PyObject* pyIn, void* cppOut); -private: - SbkConverter* m_converter; - Type m_type; -}; - - -/** - * Creates a converter for a wrapper type. - * \param type A Shiboken.ObjectType that will receive the new converter. - * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. - * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. - * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. - * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. - * \returns The new converter referred by the wrapper \p type. - */ -LIBSHIBOKEN_API SbkConverter* createConverter(SbkObjectType* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc = 0); - -/** - * Creates a converter for a non wrapper type (primitive or container type). - * \param type Python type representing to the new converter. - * \param toPythonFunc Function to convert a C++ object to a Python \p type. - * \returns A new type converter. - */ -LIBSHIBOKEN_API SbkConverter* createConverter(PyTypeObject* type, CppToPythonFunc toPythonFunc); - -LIBSHIBOKEN_API void deleteConverter(SbkConverter* converter); - -/// Sets the Python object to C++ pointer conversion function. -LIBSHIBOKEN_API void setCppPointerToPythonFunction(SbkConverter* converter, CppToPythonFunc pointerToPythonFunc); - -/// Sets the C++ pointer to Python object conversion functions. -LIBSHIBOKEN_API void setPythonToCppPointerFunctions(SbkConverter* converter, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc); - -/** - * Adds a new conversion of a Python object to a C++ value. - * This is used in copy and implicit conversions. - */ -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter* converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); - -// C++ -> Python --------------------------------------------------------------------------- - -/** - * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. - * This function is used only for Value and Object Types. - * Example usage: - * TYPE* var; - * PyObject* pyVar = pointerToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn); - -/** - * For the given \p cppIn C++ reference it returns the Python wrapper object, - * always for Object Types, and when they already exist for reference types; - * for when the latter doesn't have an existing wrapper type, the C++ object - * is copied to Python. - * Example usage: - * TYPE& var = SOMETHING; - * PyObject* pyVar = referenceToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn); - -/** - * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. - * This function is used only for Value Types. - * Example usage: - * TYPE var; - * PyObject* pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* copyToPython(const SbkObjectType *type, const void *cppIn); -LIBSHIBOKEN_API PyObject* copyToPython(const SbkConverter *converter, const void *cppIn); - -// Python -> C++ --------------------------------------------------------------------------- - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ pointer. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn); - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ value. - * The resulting converter function will create a copy of the Python object in C++, or implicitly - * convert the object to the expected \p type. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn); - -/** - * Returns a Python to C++ conversion function if the Python object is convertible to a C++ reference. - * The resulting converter function will return the underlying C++ object held by the Python wrapper, - * or a new C++ value if it must be a implicit conversion. - * It returns NULL if the Python object is not convertible to \p type. - */ -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn); - -/// This is the same as isPythonToCppValueConvertible function. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn); - -/** - * Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType. - * It differs from Shiboken::Object::cppPointer because it casts the pointer to a proper - * memory offset depending on the desired type. - */ -LIBSHIBOKEN_API void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn); - -/// Converts a Python object \p pyIn to C++ and stores the result in the C++ pointer passed in \p cppOut. -LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut); -LIBSHIBOKEN_API void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut); - -/// Converts a Python object \p pyIn to C++, and copies the result in the C++ variable passed in \p cppOut. -LIBSHIBOKEN_API void pythonToCppCopy(const SbkObjectType *type, PyObject *pyIn, void *cppOut); -LIBSHIBOKEN_API void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut); - -/** - * Helper function returned by generated convertible checking functions - * that returns a C++ NULL when the input Python object is None. - */ -LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut); - -/** - * Returns true if the \p toCpp function passed is an implicit conversion of Python \p type. - * It is used when C++ expects a reference argument, so it may be the same object received - * from Python, or another created through implicit conversion. - */ -LIBSHIBOKEN_API bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCpp); - -/// Registers a converter with a type name that may be used to retrieve the converter. -LIBSHIBOKEN_API void registerConverterName(SbkConverter* converter, const char* typeName); - -/// Returns the converter for a given type name, or NULL if it wasn't registered before. -LIBSHIBOKEN_API SbkConverter* getConverter(const char* typeName); - -/// Returns the converter for a primitive type. -LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index); - -/// Returns true if a Python sequence is comprised of objects of the given \p type. -LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn); - -/// Returns true if a Python sequence is comprised of objects of a type convertible to the one represented by the given \p converter. -LIBSHIBOKEN_API bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn); - -/// Returns true if a Python sequence is comprised of objects of a type convertible to \p type. -LIBSHIBOKEN_API bool convertibleSequenceTypes(const SbkObjectType *type, PyObject *pyIn); - -/// Returns true if a Python sequence can be converted to a C++ pair. -LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn); - -/// Returns true if a Python sequence can be converted to a C++ pair. -LIBSHIBOKEN_API bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, - const SbkConverter *secondConverter, bool secondCheckExact, - PyObject *pyIn); - -/// Returns true if a Python dictionary can be converted to a C++ hash or map. -LIBSHIBOKEN_API bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn); - -/// Returns true if a Python dictionary can be converted to a C++ hash or map. -LIBSHIBOKEN_API bool convertibleDictTypes(const SbkConverter *keyConverter, bool keyCheckExact, - const SbkConverter *valueConverter, bool valueCheckExact, - PyObject *pyIn); - -/// Returns the Python type object associated with the given \p converter. -LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(const SbkConverter *converter); - -/// Returns the Python type object for the given \p typeName. -LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(const char* typeName); - -/// Returns true if the Python type associated with the converter is a value type. -LIBSHIBOKEN_API bool pythonTypeIsValueType(const SbkConverter *converter); - -/// Returns true if the Python type associated with the converter is an object type. -LIBSHIBOKEN_API bool pythonTypeIsObjectType(const SbkConverter *converter); - -/// Returns true if the Python type associated with the converter is a wrapper type. -LIBSHIBOKEN_API bool pythonTypeIsWrapperType(const SbkConverter *converter); - -#define SBK_PY_LONG_LONG_IDX 0 -// Qt5: name collision in QtCore after QBool is replaced by bool -#define SBK_BOOL_IDX_1 1 -#define SBK_CHAR_IDX 2 -#define SBK_CONSTCHARPTR_IDX 3 -#define SBK_DOUBLE_IDX 4 -#define SBK_FLOAT_IDX 5 -#define SBK_INT_IDX 6 -#define SBK_SIGNEDINT_IDX 6 -#define SBK_LONG_IDX 7 -#define SBK_SHORT_IDX 8 -#define SBK_SIGNEDCHAR_IDX 9 -#define SBK_STD_STRING_IDX 10 -#define SBK_UNSIGNEDPY_LONG_LONG_IDX 11 -#define SBK_UNSIGNEDCHAR_IDX 12 -#define SBK_UNSIGNEDINT_IDX 13 -#define SBK_UNSIGNEDLONG_IDX 14 -#define SBK_UNSIGNEDSHORT_IDX 15 -#define SBK_VOIDPTR_IDX 16 - -template SbkConverter* PrimitiveTypeConverter() { return 0; } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_BOOL_IDX_1); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_CHAR_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_DOUBLE_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_FLOAT_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_INT_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_LONG_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_SHORT_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_STD_STRING_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); } -template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); } - -} } // namespace Shiboken::Conversions - -struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; }; -#define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter) - - -#endif // SBK_CONVERTER_H diff --git a/libshiboken/sbkconverter_p.h b/libshiboken/sbkconverter_p.h deleted file mode 100644 index b38561780..000000000 --- a/libshiboken/sbkconverter_p.h +++ /dev/null @@ -1,574 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_P_H -#define SBK_CONVERTER_P_H - -#include "sbkpython.h" -#include "sbkconverter.h" -#include "sbkstring.h" -#include -#include -#include -#include -#include - -#include "sbkdbg.h" - -extern "C" -{ - -typedef std::pair ToCppConversion; -typedef std::list ToCppConversionList; - -/** - * \internal - * Private structure of SbkConverter. - */ -struct SbkConverter -{ - /** - * Python type associated with this converter. If the type is a Shiboken - * wrapper, then it must be a SbkObjectType; otherwise it will be the - * Python type to which the C++ value will be converted (note that the - * C++ type could be produced from various Python types). - */ - PyTypeObject* pythonType; - /** - * This function converts a C++ object to a Python object of the type - * indicated in pythonType. The identity of the C++ object is kept, - * because it looks for an already existing Python wrapper associated - * with the C++ instance. - * It is used to convert C++ pointers and references to Python objects. - */ - CppToPythonFunc pointerToPython; - /** - * This function converts a C++ object to a Python object of the type - * indicated in pythonType. The identity of the object is not kept, - * because a new instance of the C++ object is created. - * It is used to convert objects passed by value, or reference, if said - * reference can't be traced to an object that already has a Python - * wrapper assigned for it. - */ - CppToPythonFunc copyToPython; - /** - * This is a special case of a Python to C++ conversion. It returns - * the underlying C++ pointer of a Python wrapper passed as parameter - * or NULL if the Python object is a None value. - * It comes separated from the other toCppConversions because if you - * have a Python object representing a Value Type the type checking - * for both ValueType and ValueType* would be the same, thus the first - * check would be true and the second would never be reached. - */ - ToCppConversion toCppPointerConversion; - /** - * This is a list of type checking functions that return the - * proper Python to C++ conversion function, for the given Python - * object. - * For Object Types, that never have implicit conversions, this - * list is always empty. - */ - ToCppConversionList toCppConversions; -}; - -} // extern "C" - -template -struct OverFlowCheckerBase { - static void formatOverFlowMessage(const MaxLimitType& value, - const std::string *valueAsString = 0) - { - std::ostringstream str; - str << "libshiboken: Overflow: Value "; - if (valueAsString != 0 && !valueAsString->empty()) - str << *valueAsString; - else - str << value; - str << " exceeds limits of type " - << " [" << (isSigned ? "signed" : "unsigned") - << "] \"" << typeid(T).name() - << "\" (" << sizeof(T) << "bytes)."; - const std::string message = str.str(); - PyErr_WarnEx(PyExc_RuntimeWarning, message.c_str(), 0); - } - - // Checks if an overflow occurred inside Python code. - // Precondition: use after calls like PyLong_AsLongLong or PyLong_AsUnsignedLongLong. - // Postcondition: if error ocurred, sets the string reference to the string representation of - // the passed value. - static bool checkForInternalPyOverflow(PyObject *pyIn, std::string &valueAsString) - { - if (PyErr_Occurred()) { - PyErr_Print(); - PyObject *stringRepresentation = PyObject_Str(pyIn); - const char *cString = Shiboken::String::toCString(stringRepresentation); - valueAsString.assign(cString); - Py_DECREF(stringRepresentation); - return true; - } - return false; - } -}; - -// Helper template for checking if a value overflows when cast to type T. -// The MaxLimitType size is usually >= than type T size, so that it can still represent values that -// can't be stored in T (unless the types are of course the same). -// TLDR: MaxLimitType is either long long or unsigned long long. -template::is_signed > -struct OverFlowChecker; - -template -struct OverFlowChecker : - public OverFlowCheckerBase { - static bool check(const MaxLimitType& value, PyObject *pyIn) - { - std::string valueAsString; - const bool isOverflow = - OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) - || value < std::numeric_limits::min() - || value > std::numeric_limits::max(); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - } -}; - -template -struct OverFlowChecker - : public OverFlowCheckerBase { - static bool check(const MaxLimitType& value, PyObject *pyIn) - { - std::string valueAsString; - const bool isOverflow = - OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) - || value < 0 - || static_cast(value) > std::numeric_limits::max(); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - } -}; -template<> -struct OverFlowChecker : - public OverFlowCheckerBase { - static bool check(const PY_LONG_LONG &value, PyObject *pyIn) { - std::string valueAsString; - const bool isOverflow = checkForInternalPyOverflow(pyIn, valueAsString); - if (isOverflow) - OverFlowChecker::formatOverFlowMessage(value, &valueAsString); - return isOverflow; - - } -}; -template<> -struct OverFlowChecker { - static bool check(const double &, PyObject *) { return false; } -}; -template<> -struct OverFlowChecker : - public OverFlowCheckerBase { - static bool check(const double& value, PyObject *) - { - const bool result = value < std::numeric_limits::min() - || value > std::numeric_limits::max(); - if (result) - formatOverFlowMessage(value); - return result; - } -}; - -// Basic primitive type converters --------------------------------------------------------- -template PyTypeObject* SbkType() { return 0; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyString_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } -template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } - -template struct Primitive {}; - -template -struct OnePrimitive -{ - static PyObject* toPython(const void*) { return 0; } - static PythonToCppFunc isConvertible(PyObject*) { return 0; } - static void toCpp(PyObject*, void*) {} - static SbkConverter* createConverter() - { - SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType(), Primitive::toPython); - Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::toCpp, Primitive::isConvertible); - return converter; - } -}; -template -struct TwoPrimitive : OnePrimitive -{ - static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; } - static void otherToCpp(PyObject*, void*) {} - static SbkConverter* createConverter() - { - SbkConverter* converter = OnePrimitive::createConverter(); - Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::otherToCpp, Primitive::isOtherConvertible); - return converter; - } -}; - -// Integers -------------------------------------------------------------------------------- - -template -struct IntPrimitive : TwoPrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyInt_FromLong(*reinterpret_cast(cppIn)); - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - double result = PyFloat_AS_DOUBLE(pyIn); - // If cast to long directly it could overflow silently. - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = static_cast(result); - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (PyFloat_Check(pyIn)) - return toCpp; - return 0; - } - static void otherToCpp(PyObject* pyIn, void* cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = static_cast(result); - } - static PythonToCppFunc isOtherConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return 0; - } -}; -template <> struct Primitive : IntPrimitive {}; -template <> struct Primitive : IntPrimitive {}; -template <> struct Primitive : IntPrimitive {}; -template <> struct Primitive : IntPrimitive {}; - -// Unsigned Long Integers ------------------------------------------------------------------ - -template -struct UnsignedLongPrimitive : IntPrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyLong_FromUnsignedLong(*reinterpret_cast(cppIn)); - } -}; -template <> struct Primitive : UnsignedLongPrimitive {}; -template <> struct Primitive : UnsignedLongPrimitive {}; - -// Big integers ---------------------------------------------------------------------------- - -template <> -struct Primitive : OnePrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyLong_FromLongLong(*((PY_LONG_LONG*)cppIn)); - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = result; - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return 0; - } -}; - -template <> -struct Primitive : OnePrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyLong_FromUnsignedLongLong(*((unsigned PY_LONG_LONG*)cppIn)); - } - static void toCpp(PyObject* pyIn, void* cppOut) - { -#if PY_MAJOR_VERSION >= 3 - if (PyLong_Check(pyIn)) { - unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = result; - } - else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - } -#else - if (PyInt_Check(pyIn)) { - long result = PyInt_AsLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = - static_cast(result); - } else if (PyLong_Check(pyIn)) { - unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = result; - } else { - PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); - } -#endif // Python 2 - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return 0; - } -}; - -// Floating point -------------------------------------------------------------------------- - -template -struct FloatPrimitive : TwoPrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyFloat_FromDouble(*reinterpret_cast(cppIn)); - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - *reinterpret_cast(cppOut) = FLOAT(PyLong_AsLong(pyIn)); - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (PyInt_Check(pyIn) || PyLong_Check(pyIn)) - return toCpp; - return 0; - } - static void otherToCpp(PyObject* pyIn, void* cppOut) - { - *reinterpret_cast(cppOut) = FLOAT(PyFloat_AsDouble(pyIn)); - } - static PythonToCppFunc isOtherConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return 0; - } -}; -template <> struct Primitive : FloatPrimitive {}; -template <> struct Primitive : FloatPrimitive {}; - -// Boolean --------------------------------------------------------------------------------- - -template <> -struct Primitive : OnePrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return PyBool_FromLong(*reinterpret_cast(cppIn)); - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return toCpp; - return 0; - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - *reinterpret_cast(cppOut) = PyInt_AS_LONG(pyIn) != 0; - } -}; - -// Characters ------------------------------------------------------------------------------ - -template -struct CharPrimitive : IntPrimitive -{ - static void toCpp(PyObject* pyIn, void* cppOut) - { - *reinterpret_cast(cppOut) = CHAR(Shiboken::String::toCString(pyIn)[0]); - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (Shiboken::String::checkChar(pyIn)) - return toCpp; - return 0; - } - static void otherToCpp(PyObject* pyIn, void* cppOut) - { - PY_LONG_LONG result = PyLong_AsLongLong(pyIn); - if (OverFlowChecker::check(result, pyIn)) - PyErr_SetObject(PyExc_OverflowError, 0); - *reinterpret_cast(cppOut) = CHAR(result); - } - static PythonToCppFunc isOtherConvertible(PyObject* pyIn) - { - if (SbkNumber_Check(pyIn)) - return otherToCpp; - return 0; - } - static SbkConverter* createConverter() - { - SbkConverter* converter = IntPrimitive::createConverter(); - Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive::otherToCpp, CharPrimitive::isOtherConvertible); - return converter; - } - -}; -template <> struct Primitive : CharPrimitive {}; -template <> struct Primitive : CharPrimitive {}; -template <> struct Primitive : CharPrimitive { - using CharPrimitive::toPython; - static PyObject* toPython(const void* cppIn) { - return Shiboken::String::fromCString((const char*)cppIn, 1); - } -}; - - - -// Strings --------------------------------------------------------------------------------- - -template <> -struct Primitive : TwoPrimitive -{ - static PyObject* toPython(const void* cppIn) - { - if (!cppIn) - Py_RETURN_NONE; - return Shiboken::String::fromCString((const char*)cppIn); - } - static void toCpp(PyObject *, void *cppOut) - { - *((const char**)cppOut) = 0; - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (pyIn == Py_None) - return toCpp; - return 0; - } - static void otherToCpp(PyObject* pyIn, void* cppOut) - { - *((const char**)cppOut) = (const char*) Shiboken::String::toCString(pyIn); - } - static PythonToCppFunc isOtherConvertible(PyObject* pyIn) - { - if (Shiboken::String::check(pyIn)) - return otherToCpp; - return 0; - } -}; - -template <> -struct Primitive : TwoPrimitive -{ - static PyObject* toPython(const void* cppIn) - { - return Shiboken::String::fromCString(((std::string*)cppIn)->c_str()); - } - static void toCpp(PyObject *, void *cppOut) - { - *((std::string*)cppOut) = std::string(); - } - static PythonToCppFunc isConvertible(PyObject* pyIn) - { - if (pyIn == Py_None) - return toCpp; - return 0; - } - static void otherToCpp(PyObject* pyIn, void* cppOut) - { - *((std::string*)cppOut) = Shiboken::String::toCString(pyIn); - } - static PythonToCppFunc isOtherConvertible(PyObject* pyIn) - { - if (Shiboken::String::check(pyIn)) - return otherToCpp; - return 0; - } -}; - -// Void pointer ---------------------------------------------------------------------------- - -template <> -struct Primitive : OnePrimitive -{ - static PyObject* toPython(const void* cppIn) - { - SbkDbg() << cppIn; - if (!cppIn) - Py_RETURN_NONE; - PyObject *result = reinterpret_cast(const_cast(cppIn)); - Py_INCREF(result); - return result; - } - static void toCpp(PyObject* pyIn, void* cppOut) - { - SbkDbg() << pyIn; - *reinterpret_cast(cppOut) = pyIn; - } - static PythonToCppFunc isConvertible(PyObject *) - { - return toCpp; - } -}; - -#endif // SBK_CONVERTER_P_H diff --git a/libshiboken/sbkdbg.h b/libshiboken/sbkdbg.h deleted file mode 100644 index 937153adf..000000000 --- a/libshiboken/sbkdbg.h +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKDBG_H -#define SBKDBG_H - -#include "sbkpython.h" -#include "basewrapper.h" -#include - -#ifndef NOCOLOR - #define COLOR_END "\033[0m" - #define COLOR_WHITE "\033[1;37m" - #define COLOR_YELLOW "\033[1;33m" - #define COLOR_GREEN "\033[0;32m" - #define COLOR_RED "\033[0;31m" -#else - #define COLOR_END "" - #define COLOR_WHITE "" - #define COLOR_YELLOW "" - #define COLOR_GREEN "" - #define COLOR_RED "" -#endif - -#ifndef NDEBUG - -class BaseLogger -{ -public: - BaseLogger(std::ostream& output, const char* function, const char* context) - : m_stream(output), m_function(function), m_context(context) {} - ~BaseLogger() - { - m_stream << std::endl; - } - std::ostream& operator()() { return m_stream; }; - template - std::ostream& operator<<(const T& t) - { - m_stream << '['; - if (m_context[0]) - m_stream << COLOR_GREEN << m_context << COLOR_END << "|"; - return m_stream << COLOR_WHITE << m_function << COLOR_END << "] " << t; - } -private: - std::ostream& m_stream; - const char* m_function; - const char* m_context; -}; - -inline std::ostream& operator<<(std::ostream& out, PyObject* obj) -{ - PyObject* repr = Shiboken::Object::isValid(obj, false) ? PyObject_Repr(obj) : 0; - if (repr) { -#ifdef IS_PY3K - PyObject* str = PyUnicode_AsUTF8String(repr); - Py_DECREF(repr); - repr = str; -#endif - out << PyBytes_AS_STRING(repr); - Py_DECREF(repr); - } else { - out << reinterpret_cast(obj); - } - return out; -} - -class _SbkDbg : public BaseLogger -{ -public: - _SbkDbg(const char* function, const char* context = "") : BaseLogger(std::cout, function, context) {} -}; - -#ifdef __GNUG__ -#define SbkDbg(X) _SbkDbg(__PRETTY_FUNCTION__, X"") -#else -#define SbkDbg(X) _SbkDbg(__FUNCTION__, X"") -#endif - -#else - -struct SbkDbg { - template - SbkDbg& operator<<(const T&) { return *this; } -}; - -#endif -#endif // LOGGER_H diff --git a/libshiboken/sbkenum.cpp b/libshiboken/sbkenum.cpp deleted file mode 100644 index 0902077ed..000000000 --- a/libshiboken/sbkenum.cpp +++ /dev/null @@ -1,618 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkenum.h" -#include "sbkstring.h" -#include "sbkconverter.h" -#include "basewrapper.h" -#include "sbkdbg.h" -#include "autodecref.h" -#include "typeresolver.h" -#include "sbkpython.h" - -#include -#include -#include - -#define SBK_ENUM(ENUM) reinterpret_cast(ENUM) - -extern "C" -{ - -struct SbkEnumType -{ - PyHeapTypeObject super; - SbkConverter** converterPtr; - SbkConverter* converter; - const char* cppName; -}; - -struct SbkEnumObject -{ - PyObject_HEAD - long ob_value; - PyObject* ob_name; -}; - -static PyObject* SbkEnumObject_repr(PyObject* self) -{ - const SbkEnumObject *enumObj = reinterpret_cast(self); - if (enumObj->ob_name) - return Shiboken::String::fromFormat("%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name)); - else - return Shiboken::String::fromFormat("%s(%ld)", self->ob_type->tp_name, enumObj->ob_value); -} - -static int SbkEnumObject_print(PyObject* self, FILE* fp, int) -{ - Py_BEGIN_ALLOW_THREADS - const SbkEnumObject *enumObj = reinterpret_cast(self); - if (enumObj->ob_name) - fprintf(fp, "%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name)); - else - fprintf(fp, "%s(%ld)", self->ob_type->tp_name, enumObj->ob_value); - Py_END_ALLOW_THREADS - return 0; -} - -static PyObject* SbkEnumObject_name(PyObject* self, void*) -{ - SbkEnumObject *enum_self = reinterpret_cast(self); - - if (enum_self->ob_name == NULL) - 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 0; - - SbkEnumObject* self = PyObject_New(SbkEnumObject, type); - if (!self) - return 0; - self->ob_value = itemValue; - PyObject* item = Shiboken::Enum::getEnumItemFromValue(type, itemValue); - if (item) { - self->ob_name = SbkEnumObject_name(item, 0); - Py_XDECREF(item); - } else { - self->ob_name = 0; - } - return reinterpret_cast(self); -} - -/* 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 PyInt_FromLong() will result in calling PyLong_FromLong in - * Py3k. - */ -static PyObject* enum_int(PyObject* v) -{ - return PyInt_FromLong(SBK_ENUM(v)->ob_value); -} - -static long getNumberValue(PyObject* v) -{ - PyObject* number = PyNumber_Long(v); - long result = PyLong_AsLong(number); - Py_XDECREF(number); - return result; -} - -static PyObject* enum_and(PyObject* self, PyObject* b) -{ - if (!PyNumber_Check(b)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(b); - return PyInt_FromLong(valA & valB); -} - -static PyObject* enum_or(PyObject* self, PyObject* b) -{ - if (!PyNumber_Check(b)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(b); - return PyInt_FromLong(valA | valB); -} - -static PyObject* enum_xor(PyObject* self, PyObject* b) -{ - if (!PyNumber_Check(b)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(b); - return PyInt_FromLong(valA ^ valB); -} - -static int enum_bool(PyObject* v) -{ - return (SBK_ENUM(v)->ob_value > 0); -} - -static PyObject* enum_add(PyObject* self, PyObject* v) -{ - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(v); - return PyInt_FromLong(valA + valB); -} - -static PyObject* enum_subtract(PyObject* self, PyObject* v) -{ - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(v); - return PyInt_FromLong(valA - valB); -} - -static PyObject* enum_multiply(PyObject* self, PyObject* v) -{ - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(v); - return PyInt_FromLong(valA * valB); -} - -#ifndef IS_PY3K -static PyObject* enum_divide(PyObject* self, PyObject* v) -{ - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(v); - return PyLong_FromLong(valA / valB); -} -#endif - -static PyObject* enum_richcompare(PyObject* self, PyObject* other, int op) -{ - int result = 0; - if (!PyNumber_Check(other)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - - long valA = SBK_ENUM(self)->ob_value; - long valB = getNumberValue(other); - - switch (op) { - case Py_EQ: - result = (valA == valB); - break; - case Py_NE: - result = (valA != valB); - break; - case Py_LE: - result = (valA <= valB); - break; - case Py_GE: - result = (valA >= valB); - break; - case Py_LT: - result = (valA < valB); - break; - case Py_GT: - result = (valA > valB); - break; - default: - PyErr_BadArgument(); - return NULL; - } - if (result) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -static Py_hash_t enum_hash(PyObject* pyObj) -{ - Py_hash_t val = reinterpret_cast(pyObj)->ob_value; - if (val == -1) - val = -2; - return val; -} - -static PyGetSetDef SbkEnumGetSetList[] = { - {const_cast("name"), &SbkEnumObject_name, 0, 0, 0}, - {0, 0, 0, 0, 0} // Sentinel -}; - -static PyNumberMethods enum_as_number = { - /* nb_add */ enum_add, - /* nb_subtract */ enum_subtract, - /* nb_multiply */ enum_multiply, -#ifndef IS_PY3K - /* nb_divide */ enum_divide, -#endif - /* nb_remainder */ 0, - /* nb_divmod */ 0, - /* nb_power */ 0, - /* nb_negative */ 0, - /* nb_positive */ enum_int, - /* nb_absolute */ 0, - /* nb_bool/nb_nonzero */ enum_bool, - /* nb_invert */ 0, - /* nb_lshift */ 0, - /* nb_rshift */ 0, - /* nb_and */ enum_and, - /* nb_xor */ enum_xor, - /* nb_or */ enum_or, -#ifndef IS_PY3K - /* nb_coerce */ 0, -#endif - /* nb_int */ enum_int, -#ifdef IS_PY3K - /* nb_reserved */ 0, - /* nb_float */ 0, -#else - /* nb_long */ enum_int, - /* nb_float */ 0, - /* nb_oct */ 0, - /* nb_hex */ 0, -#endif - - /* nb_inplace_add */ 0, - /* nb_inplace_subtract */ 0, - /* nb_inplace_multiply */ 0, -#ifndef IS_PY3K - /* nb_inplace_div */ 0, -#endif - /* nb_inplace_remainder */ 0, - /* nb_inplace_power */ 0, - /* nb_inplace_lshift */ 0, - /* nb_inplace_rshift */ 0, - /* nb_inplace_and */ 0, - /* nb_inplace_xor */ 0, - /* nb_inplace_or */ 0, - - /* nb_floor_divide */ 0, - /* nb_true_divide */ 0, - /* nb_inplace_floor_divide */ 0, - /* nb_inplace_true_divide */ 0, - - /* nb_index */ enum_int -}; - -static void SbkEnumTypeDealloc(PyObject* pyObj); -static PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); - -PyTypeObject SbkEnumType_Type = { - PyVarObject_HEAD_INIT(0, 0) - /*tp_name*/ "Shiboken.EnumType", - /*tp_basicsize*/ sizeof(SbkEnumType), - /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkEnumTypeDealloc, - /*tp_print*/ 0, - /*tp_getattr*/ 0, - /*tp_setattr*/ 0, - /*tp_compare*/ 0, - /*tp_repr*/ 0, - /*tp_as_number*/ &enum_as_number, - /*tp_as_sequence*/ 0, - /*tp_as_mapping*/ 0, - /*tp_hash*/ 0, - /*tp_call*/ 0, - /*tp_str*/ 0, - /*tp_getattro*/ 0, - /*tp_setattro*/ 0, - /*tp_as_buffer*/ 0, - /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, - /*tp_doc*/ 0, - /*tp_traverse*/ 0, - /*tp_clear*/ 0, - /*tp_richcompare*/ 0, - /*tp_weaklistoffset*/ 0, - /*tp_iter*/ 0, - /*tp_iternext*/ 0, - /*tp_methods*/ 0, - /*tp_members*/ 0, - /*tp_getset*/ 0, - /*tp_base*/ &PyType_Type, - /*tp_dict*/ 0, - /*tp_descr_get*/ 0, - /*tp_descr_set*/ 0, - /*tp_dictoffset*/ 0, - /*tp_init*/ 0, - /*tp_alloc*/ PyType_GenericAlloc, - /*tp_new*/ SbkEnumTypeTpNew, - /*tp_free*/ PyObject_GC_Del, - /*tp_is_gc*/ 0, - /*tp_bases*/ 0, - /*tp_mro*/ 0, - /*tp_cache*/ 0, - /*tp_subclasses*/ 0, - /*tp_weaklist*/ 0, - /*tp_del*/ 0, - /*tp_version_tag*/ 0 -}; - -void SbkEnumTypeDealloc(PyObject* pyObj) -{ - SbkEnumType* sbkType = reinterpret_cast(pyObj); - - PyObject_GC_UnTrack(pyObj); - Py_TRASHCAN_SAFE_BEGIN(pyObj); - if (sbkType->converter) { - Shiboken::Conversions::deleteConverter(sbkType->converter); - } - Py_TRASHCAN_SAFE_END(pyObj); -} - -PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) -{ - SbkEnumType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); - if (!newType) - return 0; - return reinterpret_cast(newType); -} - -} // extern "C" - -namespace Shiboken { - -class DeclaredEnumTypes -{ -public: - DeclaredEnumTypes(); - ~DeclaredEnumTypes(); - static DeclaredEnumTypes& instance(); - void addEnumType(PyTypeObject* type); - -private: - DeclaredEnumTypes(const DeclaredEnumTypes&); - DeclaredEnumTypes& operator=(const DeclaredEnumTypes&); - std::list m_enumTypes; -}; - -namespace Enum { - -bool check(PyObject* pyObj) -{ - return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type; -} - -PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue) -{ - PyObject *key, *value; - Py_ssize_t pos = 0; - PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast("values")); - - while (PyDict_Next(values, &pos, &key, &value)) { - SbkEnumObject *obj = reinterpret_cast(value); - if (obj->ob_value == itemValue) { - Py_INCREF(obj); - return value; - } - } - return 0; -} - -static PyTypeObject* createEnum(const char* fullName, const char* cppName, const char* shortName, PyTypeObject* flagsType) -{ - PyTypeObject* enumType = newTypeWithName(fullName, cppName); - if (flagsType) - enumType->tp_as_number = flagsType->tp_as_number; - if (PyType_Ready(enumType) < 0) - return 0; - Shiboken::TypeResolver::createValueTypeResolver(cppName); - if (shortName) - Shiboken::TypeResolver::createValueTypeResolver(shortName); - return enumType; -} - -PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) -{ - PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType); - Shiboken::TypeResolver::createValueTypeResolver("Qt::WindowType"); - Shiboken::TypeResolver::createValueTypeResolver("WindowType"); - if (enumType && PyModule_AddObject(module, name, reinterpret_cast(enumType)) < 0) - return 0; - if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast(flagsType)) < 0) - return 0; - return enumType; -} - -PyTypeObject* createScopedEnum(SbkObjectType* scope, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) -{ - PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType); - if (enumType && PyDict_SetItemString(scope->super.ht_type.tp_dict, name, reinterpret_cast(enumType)) < 0) - return 0; - if (flagsType && PyDict_SetItemString(scope->super.ht_type.tp_dict, flagsType->tp_name, reinterpret_cast(flagsType)) < 0) - return 0; - return enumType; -} - -static PyObject* createEnumItem(PyTypeObject* enumType, const char* itemName, long itemValue) -{ - PyObject* enumItem = newItem(enumType, itemValue, itemName); - if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) - return 0; - Py_DECREF(enumItem); - return enumItem; -} - -bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue) -{ - PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); - if (enumItem) { - if (PyModule_AddObject(module, itemName, enumItem) < 0) - return false; - Py_DECREF(enumItem); - return true; - } - return false; -} - -bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue) -{ - PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); - if (enumItem) { - if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0) - return false; - Py_DECREF(enumItem); - return true; - } - return false; -} - -PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) -{ - bool newValue = true; - SbkEnumObject* enumObj; - if (!itemName) { - enumObj = reinterpret_cast(getEnumItemFromValue(enumType, itemValue)); - if (enumObj) - return reinterpret_cast(enumObj); - - newValue = false; - } - - enumObj = PyObject_New(SbkEnumObject, enumType); - if (!enumObj) - return 0; - - enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : 0; - enumObj->ob_value = itemValue; - - if (newValue) { - PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast("values")); - if (!values) { - values = PyDict_New(); - PyDict_SetItemString(enumType->tp_dict, const_cast("values"), values); - Py_DECREF(values); // ^ values still alive, because setitemstring incref it - } - PyDict_SetItemString(values, itemName, reinterpret_cast(enumObj)); - } - - return reinterpret_cast(enumObj); -} - -PyTypeObject* newType(const char* name) -{ - return newTypeWithName(name, ""); -} - -PyTypeObject* newTypeWithName(const char* name, const char* cppName) -{ - PyTypeObject* type = reinterpret_cast(new SbkEnumType); - ::memset(type, 0, sizeof(SbkEnumType)); - Py_TYPE(type) = &SbkEnumType_Type; - type->tp_basicsize = sizeof(SbkEnumObject); - type->tp_print = &SbkEnumObject_print; - type->tp_repr = &SbkEnumObject_repr; - type->tp_str = &SbkEnumObject_repr; - type->tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES; - type->tp_name = name; - type->tp_getset = SbkEnumGetSetList; - type->tp_new = SbkEnum_tp_new; - type->tp_as_number = &enum_as_number; - type->tp_richcompare = &enum_richcompare; - type->tp_hash = &enum_hash; - - SbkEnumType* enumType = reinterpret_cast(type); - enumType->cppName = cppName; - enumType->converterPtr = &enumType->converter; - DeclaredEnumTypes::instance().addEnumType(type); - return type; -} - -const char* getCppName(PyTypeObject* enumType) -{ - assert(Py_TYPE(enumType) == &SbkEnumType_Type); - return reinterpret_cast(enumType)->cppName;; -} - -long int getValue(PyObject* enumItem) -{ - assert(Shiboken::Enum::check(enumItem)); - return reinterpret_cast(enumItem)->ob_value; -} - -void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter) -{ - //reinterpret_cast(enumType)->converter = converter; - SBK_CONVERTER(enumType) = converter; -} - -SbkConverter* getTypeConverter(PyTypeObject* enumType) -{ - //return reinterpret_cast(enumType)->converter; - return SBK_CONVERTER(enumType); -} - -} // namespace Enum - -DeclaredEnumTypes& DeclaredEnumTypes::instance() -{ - static DeclaredEnumTypes me; - return me; -} - -DeclaredEnumTypes::DeclaredEnumTypes() -{ -} - -DeclaredEnumTypes::~DeclaredEnumTypes() -{ - std::list::const_iterator it = m_enumTypes.begin(); - for (; it != m_enumTypes.end(); ++it) - delete *it; - m_enumTypes.clear(); -} - -void DeclaredEnumTypes::addEnumType(PyTypeObject* type) -{ - m_enumTypes.push_back(type); -} - -} diff --git a/libshiboken/sbkenum.h b/libshiboken/sbkenum.h deleted file mode 100644 index 4b572dbcc..000000000 --- a/libshiboken/sbkenum.h +++ /dev/null @@ -1,118 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKENUM_H -#define SBKENUM_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -extern "C" -{ - -extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type; -struct SbkObjectType; -struct SbkConverter; - -} // extern "C" - -namespace Shiboken -{ - -inline bool isShibokenEnum(PyObject* pyObj) -{ - return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type; -} - -namespace Enum -{ - 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 = 0); - /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace. - LIBSHIBOKEN_API PyTypeObject* createScopedEnum(SbkObjectType* scope, - const char* name, - const char* fullName, - const char* cppName, - PyTypeObject* flagsType = 0); - - /** - * 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, SbkObjectType* scope, const char* itemName, long itemValue); - - LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); - - /// \deprecated Use 'newTypeWithName' - SBK_DEPRECATED(LIBSHIBOKEN_API PyTypeObject* newType(const char* name)); - LIBSHIBOKEN_API PyTypeObject* newTypeWithName(const char* name, const char* cppName); - LIBSHIBOKEN_API const char* getCppName(PyTypeObject* type); - - LIBSHIBOKEN_API long getValue(PyObject* enumItem); - LIBSHIBOKEN_API PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue); - - /// Sets the enum's type converter. - LIBSHIBOKEN_API void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter); - /// Returns the converter assigned to the enum \p type. - LIBSHIBOKEN_API SbkConverter* getTypeConverter(PyTypeObject* enumType); -} - -} // namespace Shiboken - -#endif // SKB_PYENUM_H diff --git a/libshiboken/sbkmodule.cpp b/libshiboken/sbkmodule.cpp deleted file mode 100644 index 2ea9d56ac..000000000 --- a/libshiboken/sbkmodule.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkmodule.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include - -/// This hash maps module objects to arrays of Python types. -typedef std::unordered_map ModuleTypesMap; - -/// This hash maps module objects to arrays of converters. -typedef std::unordered_map ModuleConvertersMap; - -/// All types produced in imported modules are mapped here. -static ModuleTypesMap moduleTypes; -static ModuleConvertersMap moduleConverters; - -namespace Shiboken -{ -namespace Module -{ - -PyObject* import(const char* moduleName) -{ - PyObject* sysModules = PyImport_GetModuleDict(); - PyObject* module = PyDict_GetItemString(sysModules, moduleName); - if (module) - Py_INCREF(module); - else - module = PyImport_ImportModule(moduleName); - - if (!module) - PyErr_Format(PyExc_ImportError,"could not import module '%s'", moduleName); - - return module; -} - -PyObject* create(const char* moduleName, void* moduleData) -{ - Shiboken::init(); -#ifndef IS_PY3K - return Py_InitModule(moduleName, reinterpret_cast(moduleData)); -#else - return PyModule_Create(reinterpret_cast(moduleData)); -#endif -} - -void registerTypes(PyObject* module, PyTypeObject** types) -{ - ModuleTypesMap::iterator iter = moduleTypes.find(module); - if (iter == moduleTypes.end()) - moduleTypes.insert(std::make_pair(module, types)); -} - -PyTypeObject** getTypes(PyObject* module) -{ - ModuleTypesMap::iterator iter = moduleTypes.find(module); - return (iter == moduleTypes.end()) ? 0 : iter->second; -} - -void registerTypeConverters(PyObject* module, SbkConverter** converters) -{ - ModuleConvertersMap::iterator iter = moduleConverters.find(module); - if (iter == moduleConverters.end()) - moduleConverters.insert(std::make_pair(module, converters)); -} - -SbkConverter** getTypeConverters(PyObject* module) -{ - ModuleConvertersMap::iterator iter = moduleConverters.find(module); - return (iter == moduleConverters.end()) ? 0 : iter->second; -} - -} } // namespace Shiboken::Module diff --git a/libshiboken/sbkmodule.h b/libshiboken/sbkmodule.h deleted file mode 100644 index e1ec7a860..000000000 --- a/libshiboken/sbkmodule.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBK_MODULE_H -#define SBK_MODULE_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#if PY_MAJOR_VERSION >= 3 - #define SBK_MODULE_INIT_ERROR 0 - #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ - extern "C" SBK_EXPORT_MODULE PyObject* PyInit_##ModuleName() { - - #define SBK_MODULE_INIT_FUNCTION_END \ - return module; } -#else - #define SBK_MODULE_INIT_ERROR - #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ - extern "C" SBK_EXPORT_MODULE void init##ModuleName() { - - #define SBK_MODULE_INIT_FUNCTION_END \ - } -#endif - -extern "C" -{ -struct SbkConverter; -} - -namespace Shiboken { -namespace Module { - -/** - * Imports and returns the module named \p moduleName, or a NULL pointer in case of failure. - * If the module is already imported, it increments its reference count before returning it. - * \returns the module specified in \p moduleName or NULL if an error occurs. - */ -LIBSHIBOKEN_API PyObject* import(const char* moduleName); - -/** - * Creates a new Python module named \p moduleName using the information passed in \p moduleData. - * In fact, \p moduleData expects a "PyMethodDef*" object, but that's for Python 2. A void* - * was preferred to make this work with future Python 3 support. - * \returns a newly created module. - */ -LIBSHIBOKEN_API PyObject* create(const char* moduleName, void* moduleData); - -/** - * 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); - -/** - * 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); - -/** - * Registers the list of converters created by \p module for non-wrapper types. - * \param module Module where the converters were created. - * \param converters Array of SbkConverter* objects representing the converters created on \p module. - */ -LIBSHIBOKEN_API void registerTypeConverters(PyObject* module, SbkConverter** converters); - -/** - * Retrieves the array of converters. - * \param module Module where the converters were created. - * \returns A pointer to the SbkConverter* array of converters. - */ -LIBSHIBOKEN_API SbkConverter** getTypeConverters(PyObject* module); - -} } // namespace Shiboken::Module - -#endif // SBK_MODULE_H diff --git a/libshiboken/sbkpython.h b/libshiboken/sbkpython.h deleted file mode 100644 index 208618d50..000000000 --- a/libshiboken/sbkpython.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKPYTHON_H -#define SBKPYTHON_H - -#include "Python.h" -#include "python25compat.h" - -#if PY_MAJOR_VERSION >= 3 - #define IS_PY3K - - #define PyInt_Type PyLong_Type - #define PyInt_Check PyLong_Check - #define PyInt_AS_LONG PyLong_AS_LONG - #define PyInt_AsUnsignedLongLongMask PyLong_AsLongLong - #define PyInt_FromLong PyLong_FromLong - #define PyInt_AsLong PyLong_AsLong - #define SbkNumber_Check PyNumber_Check - #define Py_TPFLAGS_CHECKTYPES 0 - - #define SBK_NB_BOOL(x) (x).nb_bool - #define SBK_PyMethod_New PyMethod_New - #define PyInt_AsSsize_t(x) PyLong_AsSsize_t(x) - #define PyString_Type PyUnicode_Type - -#else - // Note: if there wasn't for the old-style classes, only a PyNumber_Check would suffice. - #define SbkNumber_Check(X) \ - (PyNumber_Check(X) && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__"))) - #define SBK_NB_BOOL(x) (x).nb_nonzero - #define SBK_STR_NAME "str" - #define SBK_PyMethod_New(X, Y) PyMethod_New(X, Y, reinterpret_cast(Py_TYPE(Y))) - - #define Py_hash_t long -#endif - -#endif diff --git a/libshiboken/sbkstring.cpp b/libshiboken/sbkstring.cpp deleted file mode 100644 index 598bccc46..000000000 --- a/libshiboken/sbkstring.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkstring.h" -#include "autodecref.h" - -namespace Shiboken -{ - -namespace String -{ - -bool checkType(PyTypeObject* type) -{ - return type == &PyUnicode_Type -#if PY_MAJOR_VERSION < 3 - || type == &PyString_Type -#endif - ; -} - -bool check(PyObject* obj) -{ - return obj == Py_None || -#if PY_MAJOR_VERSION < 3 - PyString_Check(obj) || -#endif - PyUnicode_Check(obj); -} - -bool checkChar(PyObject* pyobj) -{ - if (check(pyobj) && (len(pyobj) == 1)) - return true; - - return false; -} - -bool isConvertible(PyObject* obj) -{ - return check(obj); -} - -PyObject* fromCString(const char* value) -{ -#ifdef IS_PY3K - return PyUnicode_FromString(value); -#else - return PyBytes_FromString(value); -#endif -} - -PyObject* fromCString(const char* value, int len) -{ -#ifdef IS_PY3K - return PyUnicode_FromStringAndSize(value, len); -#else - return PyBytes_FromStringAndSize(value, len); -#endif -} - -const char* toCString(PyObject* str, Py_ssize_t* len) -{ - if (str == Py_None) - return NULL; -#ifdef IS_PY3K - if (PyUnicode_Check(str)) { - if (len) { - // We need to encode the unicode string into utf8 to know the size of returned char*. - Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str)); - *len = PyBytes_GET_SIZE(uniStr.object()); - } - // Return unicode from str instead of uniStr, because the lifetime of the returned pointer - // depends on the lifetime of str. - return _PyUnicode_AsString(str); - } -#endif - if (PyBytes_Check(str)) { - if (len) - *len = PyBytes_GET_SIZE(str); - return PyBytes_AS_STRING(str); - } - return 0; -} - -bool concat(PyObject** val1, PyObject* val2) -{ - if (PyUnicode_Check(*val1) && PyUnicode_Check(val2)) { - PyObject* result = PyUnicode_Concat(*val1, val2); - Py_DECREF(*val1); - *val1 = result; - return true; - } - - if (PyBytes_Check(*val1) && PyBytes_Check(val2)) { - PyBytes_Concat(val1, val2); - return true; - } - -#if PY_MAJOR_VERSION < 3 - if (PyString_Check(*val1) && PyString_Check(val2)) { - PyString_Concat(val1, val2); - return true; - } -#endif - return false; -} - -PyObject* fromFormat(const char* format, ...) -{ - va_list argp; - va_start(argp, format); - PyObject* result = 0; -#ifdef IS_PY3K - result = PyUnicode_FromFormatV(format, argp); -#else - result = PyString_FromFormatV(format, argp); -#endif - va_end(argp); - return result; -} - -PyObject* fromStringAndSize(const char* str, Py_ssize_t size) -{ -#ifdef IS_PY3K - return PyUnicode_FromStringAndSize(str, size); -#else - return PyString_FromStringAndSize(str, size); -#endif -} - -int compare(PyObject* val1, const char* val2) -{ - if (PyUnicode_Check(val1)) -#ifdef IS_PY3K - return PyUnicode_CompareWithASCIIString(val1, val2); -#else - { - PyObject* uVal2 = PyUnicode_FromString(val2); - bool result = PyUnicode_Compare(val1, uVal2); - Py_XDECREF(uVal2); - return result; - } - if (PyString_Check(val1)) - return strcmp(PyString_AS_STRING(val1), val2); -#endif - return 0; - -} - -Py_ssize_t len(PyObject* str) -{ - if (str == Py_None) - return 0; - - if (PyUnicode_Check(str)) - return PyUnicode_GET_SIZE(str); - - if (PyBytes_Check(str)) - return PyBytes_GET_SIZE(str); - return 0; -} - -} // namespace String - -} // namespace Shiboken diff --git a/libshiboken/sbkstring.h b/libshiboken/sbkstring.h deleted file mode 100644 index 0d498da6d..000000000 --- a/libshiboken/sbkstring.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKSTRING_H -#define SBKSTRING_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -#if PY_MAJOR_VERSION >= 3 - #define SBK_STR_NAME "unicode" -#else - #define SBK_STR_NAME "str" -#endif - -namespace Shiboken -{ -namespace String -{ - LIBSHIBOKEN_API bool check(PyObject* obj); - LIBSHIBOKEN_API bool checkType(PyTypeObject* obj); - LIBSHIBOKEN_API bool checkChar(PyObject* obj); - LIBSHIBOKEN_API bool isConvertible(PyObject* obj); - LIBSHIBOKEN_API PyObject* fromCString(const char* value); - LIBSHIBOKEN_API PyObject* fromCString(const char* value, int len); - LIBSHIBOKEN_API const char* toCString(PyObject* str, Py_ssize_t* len = 0); - LIBSHIBOKEN_API bool concat(PyObject** val1, PyObject* val2); - LIBSHIBOKEN_API PyObject* fromFormat(const char* format, ...); - LIBSHIBOKEN_API PyObject* fromStringAndSize(const char* str, Py_ssize_t size); - LIBSHIBOKEN_API int compare(PyObject* val1, const char* val2); - LIBSHIBOKEN_API Py_ssize_t len(PyObject* str); - -} // namespace String -} // namespace Shiboken - - -#endif - - diff --git a/libshiboken/sbkversion.h.in b/libshiboken/sbkversion.h.in deleted file mode 100644 index 589c5ac26..000000000 --- a/libshiboken/sbkversion.h.in +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKVERSION_H -#define SBKVERSION_H - -#define SHIBOKEN_VERSION "@shiboken_MAJOR_VERSION@.@shiboken_MINOR_VERSION@.@shiboken_MICRO_VERSION@" -#define SHIBOKEN_MAJOR_VERSION @shiboken_MAJOR_VERSION@ -#define SHIBOKEN_MINOR_VERSION @shiboken_MINOR_VERSION@ -#define SHIBOKEN_MICRO_VERSION @shiboken_MICRO_VERSION@ -#define SHIBOKEN_RELEASE_LEVEL "final" -#define SHIBOKEN_SERIAL 0 - -#endif diff --git a/libshiboken/shiboken.h b/libshiboken/shiboken.h deleted file mode 100644 index 2738bf51f..000000000 --- a/libshiboken/shiboken.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SHIBOKEN_H -#define SHIBOKEN_H - -#include "sbkpython.h" -#include "autodecref.h" -#include "basewrapper.h" -#include "bindingmanager.h" -#include "conversions.h" -#include "gilstate.h" -#include "threadstatesaver.h" -#include "helper.h" -#include "sbkconverter.h" -#include "sbkenum.h" -#include "sbkmodule.h" -#include "sbkstring.h" -#include "shibokenmacros.h" -#include "typeresolver.h" -#include "shibokenbuffer.h" - -#endif // SHIBOKEN_H - diff --git a/libshiboken/shibokenbuffer.cpp b/libshiboken/shibokenbuffer.cpp deleted file mode 100644 index 6cc617668..000000000 --- a/libshiboken/shibokenbuffer.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "shibokenbuffer.h" -#include -#include - -bool Shiboken::Buffer::checkType(PyObject* pyObj) -{ - return PyObject_CheckReadBuffer(pyObj); -} - -void* Shiboken::Buffer::getPointer(PyObject* pyObj, Py_ssize_t* size) -{ - -#ifdef IS_PY3K - Py_buffer view; - if (PyObject_GetBuffer(pyObj, &view, PyBUF_ND) == 0) { - if (size) - *size = view.len; - return view.buf; - } else { - return 0; - } -#else - const void* buffer = 0; - Py_ssize_t bufferSize = 0; - - PyObject_AsReadBuffer(pyObj, &buffer, &bufferSize); - - if (size) - *size = bufferSize; - return const_cast(buffer); -#endif -} - -PyObject* Shiboken::Buffer::newObject(void* memory, Py_ssize_t size, Type type) -{ - if (size == 0) - Py_RETURN_NONE; -#ifdef IS_PY3K - Py_buffer view; - memset(&view, 0, sizeof(Py_buffer)); - view.buf = memory; - view.len = size; - view.readonly = type == Shiboken::Buffer::ReadOnly; - view.ndim = 1; - view.itemsize = sizeof(char); - Py_ssize_t shape[] = { size }; - view.shape = shape; - return PyMemoryView_FromBuffer(&view); -#else - return type == ReadOnly ? PyBuffer_FromMemory(memory, size) : PyBuffer_FromReadWriteMemory(memory, size); -#endif -} - -PyObject* Shiboken::Buffer::newObject(const void* memory, Py_ssize_t size) -{ - return newObject(const_cast(memory), size, ReadOnly); -} diff --git a/libshiboken/shibokenbuffer.h b/libshiboken/shibokenbuffer.h deleted file mode 100644 index 18d86c6e1..000000000 --- a/libshiboken/shibokenbuffer.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SHIBOKEN_BUFFER_H -#define SHIBOKEN_BUFFER_H - -#include "sbkpython.h" -#include "shibokenmacros.h" - -namespace Shiboken -{ - -namespace Buffer -{ - enum Type { - ReadOnly, - WriteOnly, - ReadWrite - }; - - /** - * Creates a new Python buffer pointing to a contiguous memory block at - * \p memory of size \p size. - */ - LIBSHIBOKEN_API PyObject* newObject(void* memory, Py_ssize_t size, Type type); - - /** - * Creates a new read only Python buffer pointing to a contiguous memory block at - * \p memory of size \p size. - */ - LIBSHIBOKEN_API PyObject* newObject(const void* memory, Py_ssize_t size); - - /** - * Check if is ok to use \p pyObj as argument in all function under Shiboken::Buffer namespace. - */ - LIBSHIBOKEN_API bool checkType(PyObject* pyObj); - - /** - * Returns a pointer to the memory pointed by the buffer \p pyObj, \p size is filled with the buffer - * size if not null. - * - * If the \p pyObj is a non-contiguous buffer a Python error is set. - */ - LIBSHIBOKEN_API void* getPointer(PyObject* pyObj, Py_ssize_t* size = 0); - -} // namespace Buffer -} // namespace Shiboken - -#endif diff --git a/libshiboken/shibokenmacros.h b/libshiboken/shibokenmacros.h deleted file mode 100644 index acd8f6ada..000000000 --- a/libshiboken/shibokenmacros.h +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SHIBOKENMACROS_H -#define SHIBOKENMACROS_H - -// LIBSHIBOKEN_API macro is used for the public API symbols. -#if defined _WIN32 - #if LIBSHIBOKEN_EXPORTS - #define LIBSHIBOKEN_API __declspec(dllexport) - #else - #ifdef _MSC_VER - #define LIBSHIBOKEN_API __declspec(dllimport) - #endif - #endif - #define SBK_DEPRECATED(func) __declspec(deprecated) func -#elif __GNUC__ >= 4 - #define LIBSHIBOKEN_API __attribute__ ((visibility("default"))) - #define SBK_DEPRECATED(func) func __attribute__ ((deprecated)) -#endif - -#ifndef LIBSHIBOKEN_API - #define LIBSHIBOKEN_API - #define SBK_DEPRECATED(func) func -#endif - -#endif diff --git a/libshiboken/threadstatesaver.cpp b/libshiboken/threadstatesaver.cpp deleted file mode 100644 index 3d3ba81ab..000000000 --- a/libshiboken/threadstatesaver.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "threadstatesaver.h" - -namespace Shiboken -{ - -ThreadStateSaver::ThreadStateSaver() - : m_threadState(0) - {} - -ThreadStateSaver::~ThreadStateSaver() -{ - restore(); -} - -void ThreadStateSaver::save() -{ - if (PyEval_ThreadsInitialized()) - m_threadState = PyEval_SaveThread(); -} - -void ThreadStateSaver::restore() -{ - if (m_threadState) { - PyEval_RestoreThread(m_threadState); - m_threadState = 0; - } -} - -} // namespace Shiboken - diff --git a/libshiboken/threadstatesaver.h b/libshiboken/threadstatesaver.h deleted file mode 100644 index 3fe595d95..000000000 --- a/libshiboken/threadstatesaver.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef THREADSTATESAVER_H -#define THREADSTATESAVER_H - -#include "sbkpython.h" -#include - -namespace Shiboken -{ - -class LIBSHIBOKEN_API ThreadStateSaver -{ -public: - ThreadStateSaver(); - ~ThreadStateSaver(); - void save(); - void restore(); -private: - PyThreadState* m_threadState; - - ThreadStateSaver(const ThreadStateSaver&); - ThreadStateSaver& operator=(const ThreadStateSaver&); -}; - -} // namespace Shiboken - -#endif // THREADSTATESAVER_H - diff --git a/libshiboken/tmp-referencetopython/sbkconverter.cpp b/libshiboken/tmp-referencetopython/sbkconverter.cpp deleted file mode 100644 index c3e25014e..000000000 --- a/libshiboken/tmp-referencetopython/sbkconverter.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkconverter.h" -#include "sbkconverter_p.h" -#include "basewrapper_p.h" - -#include "sbkdbg.h" - -namespace Shiboken { -namespace Conversions { - -static SbkConverter* createConverterObject(PyTypeObject* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter* converter = new SbkConverter; - converter->pythonType = type; - - converter->pointerToPython = pointerToPythonFunc; - converter->copyToPython = copyToPythonFunc; - - converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); - converter->toCppConversions.clear(); - - return converter; -} - -SbkConverter* createConverter(SbkObjectType* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc) -{ - SbkConverter* converter = createConverterObject((PyTypeObject*)type, - toCppPointerConvFunc, toCppPointerCheckFunc, - pointerToPythonFunc, copyToPythonFunc); - type->d->converter = converter; - return converter; -} - -void deleteConverter(SbkConverter* converter) -{ - if (converter) { - converter->toCppConversions.clear(); - delete converter; - } -} - -void addPythonToCppValueConversion(SbkConverter* converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); -} -void addPythonToCppValueConversion(SbkObjectType* type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc) -{ - addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); -} - -PyObject* pointerToPython(SbkObjectType* type, const void* cppIn) -{ - if (!cppIn) - Py_RETURN_NONE; - return type->d->converter->pointerToPython(cppIn); -} - -static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn) -{ - assert(cppIn); - return converter->copyToPython(cppIn); -} -PyObject* copyToPython(SbkObjectType* type, const void* cppIn) -{ - return CopyCppToPython(type->d->converter, cppIn); -} -PyObject* toPython(SbkConverter* converter, const void* cppIn) -{ - return CopyCppToPython(converter, cppIn); -} - -PyObject* referenceToPython(SbkObjectType* type, const void* cppIn) -{ - assert(cppIn); - PyObject* pyOut = (PyObject*)BindingManager::instance().retrieveWrapper(cppIn); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - // If it is Value Type, return a copy of the C++ object. - if (type->d->converter->copyToPython) - return type->d->converter->copyToPython(cppIn); - // If it is an Object Type, return a copy of the C++ object. - return type->d->converter->pointerToPython(cppIn); -} - -PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn) -{ - assert(pyIn); - return type->d->converter->toCppPointerConversion.first(pyIn); -} - -static inline PythonToCppFunc IsPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) -{ - assert(pyIn); - ToCppConversionList& convs = converter->toCppConversions; - for (ToCppConversionList::iterator conv = convs.begin(); conv != convs.end(); ++conv) { - PythonToCppFunc toCppFunc = 0; - if ((toCppFunc = (*conv).first(pyIn))) - return toCppFunc; - } - return 0; -} -PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn) -{ - return IsPythonToCppConvertible(type->d->converter, pyIn); -} -PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) -{ - return IsPythonToCppConvertible(converter, pyIn); -} - -PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn) -{ - if (pyIn != Py_None) { - PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); - if (toCpp) - return toCpp; - } - return isPythonToCppValueConvertible(type, pyIn); -} - -void nonePythonToCppNullPtr(PyObject*, void* cppOut) -{ - assert(cppOut); - *((void**)cppOut) = 0; -} - -void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut) -{ - assert(pyIn); - assert(cppOut); - SbkObjectType* inType = (SbkObjectType*)pyIn->ob_type; - if (ObjectType::hasCast(inType)) - *((void**)cppOut) = ObjectType::cast(inType, (SbkObject*)pyIn, (PyTypeObject*)type); - else - *((void**)cppOut) = Object::cppPointer((SbkObject*)pyIn, (PyTypeObject*)type); -} - -bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc) -{ - // This is the Object Type or Value Type conversion that only - // retrieves the C++ pointer held in the Python wrapper. - if (toCppFunc == type->d->converter->toCppPointerConversion.second) - return false; - - // Object Types doesn't have any kind of value conversion, - // only C++ pointer retrieval. - if (type->d->converter->toCppConversions.empty()) - return false; - - // The first conversion of the non-pointer conversion list is - // a Value Type's copy to C++ function, which is not an implicit - // conversion. - // Otherwise it must be one of the implicit conversions. - // Note that we don't check if the Python to C++ conversion is in - // the list of the type's conversions, for it is expected that the - // caller knows what he's doing. - ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); - return toCppFunc != (*conv).second; -} - -} } // namespace Shiboken::Conversions diff --git a/libshiboken/tmp-referencetopython/sbkconverter.h b/libshiboken/tmp-referencetopython/sbkconverter.h deleted file mode 100644 index d4bbbca1d..000000000 --- a/libshiboken/tmp-referencetopython/sbkconverter.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBK_CONVERTER_H -#define SBK_CONVERTER_H - -#include -#include -#include "shibokenmacros.h" -#include "basewrapper.h" - -extern "C" -{ - -/** - * SbkConverter is used to perform type conversions from C++ - * to Python and vice-versa;.and it is also used for type checking. - * SbkConverter is a private structure that must be accessed - * using the functions provided by the converter API. - */ -struct SbkConverter; - -/** - * Given a void pointer to a C++ object, this function must return - * the proper Python object. It may be either an existing wrapper - * for the C++ object, or a newly create one. Or even the Python - * equivalent of the C++ value passed in the argument. - * - * C++ -> Python - */ -typedef PyObject* (*CppToPythonFunc)(const void*); - -/** - * This function converts a Python object to a C++ value, it may be - * a pointer, value, class, container or primitive type, passed via - * a void pointer, that will be cast properly inside the function. - * This function is usually returned by an IsConvertibleToCppFunc - * function, or obtained knowing the type of the Python object input, - * thus it will not check the Python object type, and will expect - * the void pointer to be pointing to a proper variable. - * - * Python -> C++ - */ -typedef void (*PythonToCppFunc)(PyObject*,void*); - -/** - * Checks if the Python object passed in the argument is convertible to a - * C++ type defined inside the function, it returns the converter function - * that will transform a Python argument into a C++ value. - * It returns NULL if the Python object is not convertible to the C++ type - * that the function represents. - * - * Python -> C++ ? - */ -typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*); - -} // extern "C" - - -namespace Shiboken { -namespace Conversions { - -/** - * Creates a converter for a wrapper type. - * \param type A Shiboken.ObjectType that will receive the new converter. - * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. - * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. - * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. - * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. - * \returns The new converter referred by the wrapper \p type. - */ -LIBSHIBOKEN_API SbkConverter* createConverter(SbkObjectType* type, - PythonToCppFunc toCppPointerConvFunc, - IsConvertibleToCppFunc toCppPointerCheckFunc, - CppToPythonFunc pointerToPythonFunc, - CppToPythonFunc copyToPythonFunc = 0); - -LIBSHIBOKEN_API void deleteConverter(SbkConverter* converter); - -/** - * Adds a new conversion of a Python object to a C++ value. - * This is used in copy and implicit conversions. - */ -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter* converter, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); -LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type, - PythonToCppFunc pythonToCppFunc, - IsConvertibleToCppFunc isConvertibleToCppFunc); - -// C++ -> Python --------------------------------------------------------------------------- - -/** - * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. - * This function is used only for Value and Object Types. - * Example usage: - * TYPE* var; - * PyObject* pyVar = pointerToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* pointerToPython(SbkObjectType* type, const void* cppIn); - -/** - * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. - * This function is used only for Value Types. - * Example usage: - * TYPE var; - * PyObject* pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* copyToPython(SbkObjectType* type, const void* cppIn); - -// TODO:WRITEDOCSTRING - used only for Value Types - cppIn must point to a value -/** - * Retrieves the Python wrapper object for the given C++ reference pointed by \p cppIn. - * This function is used only for Value and Object Types. - * It differs from pointerToPython() for not checking for a NULL pointer. - * Example usage: - * TYPE& var = SOMETHING; - * PyObject* pyVar = copyToPython(SBKTYPE, &var); - */ -LIBSHIBOKEN_API PyObject* referenceToPython(SbkObjectType* type, const void* cppIn); - -// TODO:WRITEDOCSTRING - used only for Primitives and Containers (and Value Types) - cppIn must point to a primitive, container or value type -/// This is the same as copyToPython function. -LIBSHIBOKEN_API PyObject* toPython(SbkConverter* converter, const void* cppIn); - -// Python -> C++ convertibility checks ----------------------------------------------------- - -// TODO:WRITEDOCSTRING -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn); - -// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn); - -// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn); - -/// This is the same as isPythonToCppValueConvertible function. -LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn); - -// Python -> C++ --------------------------------------------------------------------------- - -// TODO:WRITEDOCSTRING - function used by the generated [TYPE]_PythonToCpp_[TYPE]_PTR -LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut); - -// TODO:WRITEDOCSTRING - function used by the generated isConvertible when the PyObject is None, -// making a C++ NULL pointer the result of the toCpp function call. -// DRAFT: When the Python object is a Py_None, it's C++ conversion is always a NULL pointer. -LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut); - -// TODO:WRITEDOCSTRING - tells if \p toCpp is an implicit conversion. -LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCpp); - -} } // namespace Shiboken::Conversions - -#endif // SBK_CONVERTER_H diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp deleted file mode 100644 index b23eb6371..000000000 --- a/libshiboken/typeresolver.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typeresolver.h" -#include "sbkdbg.h" -#include -#include -#include -#include "basewrapper_p.h" - -using namespace Shiboken; - -typedef std::unordered_map TypeResolverMap; -static TypeResolverMap typeResolverMap; - -struct TypeResolver::TypeResolverPrivate -{ - CppToPythonFunc cppToPython; - PythonToCppFunc pythonToCpp; - PyTypeObject* pyType; -}; - -static void deinitTypeResolver() -{ - for (TypeResolverMap::const_iterator it = typeResolverMap.begin(); it != typeResolverMap.end(); ++it) - delete it->second; - typeResolverMap.clear(); -} - -void Shiboken::initTypeResolver() -{ - assert(typeResolverMap.empty()); - std::atexit(deinitTypeResolver); -} - -TypeResolver::TypeResolver() : m_d(new TypeResolverPrivate) -{ -} - -TypeResolver* TypeResolver::createTypeResolver(const char* typeName, - CppToPythonFunc cppToPy, - PythonToCppFunc pyToCpp, - PyTypeObject* pyType) -{ - TypeResolver*& tr = typeResolverMap[typeName]; - if (!tr) { - tr = new TypeResolver; - tr->m_d->cppToPython = cppToPy; - tr->m_d->pythonToCpp = pyToCpp; - tr->m_d->pyType = pyType; - - /* - * Note: - * - * Value types are also registered as object types, but the generator *always* first register the value - * type version in the TypeResolver and it *must* always do it! otherwise this code wont work. - */ - if (pyType && PyType_IsSubtype(pyType, reinterpret_cast(&SbkObject_Type))) { - SbkObjectType* sbkType = reinterpret_cast(pyType); - // TODO-CONVERTERS: to be deprecated - if (!sbkType->d->type_behaviour) { - const size_t len = strlen(typeName); - sbkType->d->type_behaviour = typeName[len -1] == '*' ? BEHAVIOUR_OBJECTTYPE : BEHAVIOUR_VALUETYPE; - } - } - } - return tr; -} - -TypeResolver::~TypeResolver() -{ - delete m_d; -} - -TypeResolver* TypeResolver::get(const char* typeName) -{ - TypeResolverMap::const_iterator it = typeResolverMap.find(typeName); - if (it != typeResolverMap.end()) { - return it->second; - } else { - if (Py_VerboseFlag > 0) - SbkDbg() << "Can't find type resolver for " << typeName; - return 0; - } -} - -void TypeResolver::toCpp(PyObject* pyObj, void** place) -{ - m_d->pythonToCpp(pyObj, place); -} - -PyObject* TypeResolver::toPython(void* cppObj) -{ - return m_d->cppToPython(cppObj); -} - -PyTypeObject* TypeResolver::pythonType() -{ - return m_d->pyType; -} - -TypeResolver::Type TypeResolver::getType(const char* name) -{ - const size_t len = strlen(name); - bool isObjTypeName = name[len - 1] == '*'; - if (TypeResolver::get(name)) { - // great, we found the type in our first attempt! - return isObjTypeName ? ObjectType : ValueType; - } else { - // Type not found... let's copy the string. - std::string typeName(name); - if (isObjTypeName) - typeName.erase(len - 1, 1); - else - typeName += '*'; - isObjTypeName = !isObjTypeName; - - if (TypeResolver::get(typeName.c_str())) - return isObjTypeName ? ObjectType : ValueType; - else - return UnknownType; - } -} - diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h deleted file mode 100644 index bc56522fe..000000000 --- a/libshiboken/typeresolver.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of PySide2. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPERESOLVER_H -#define TYPERESOLVER_H - -#include "shibokenmacros.h" -#include "conversions.h" - -namespace Shiboken -{ - -/* To C++ convertion functions. */ -template -inline void pythonToValueType(PyObject* pyobj, void** data) -{ - *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); -} - -template -inline void pythonToObjectType(PyObject* pyobj, void** data) -{ - *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); -} - -template -inline PyObject* objectTypeToPython(void* cptr) -{ - return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); -} - -template -inline PyObject* referenceTypeToPython(void* cptr) -{ - // cptr comes the same way it come when we have a value type, but - // we deliver a Python object of a reference - return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); -} - -/** -* \internal This function is not part of the public API. -* Initialize the TypeResource internal cache. -*/ -void initTypeResolver(); - -class LIBSHIBOKEN_API TypeResolver -{ -public: - enum Type - { - ObjectType, - ValueType, - UnknownType - }; - - typedef PyObject* (*CppToPythonFunc)(void*); - typedef void (*PythonToCppFunc)(PyObject*, void**); - - ~TypeResolver(); - - template - static TypeResolver* createValueTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType()); - } - - template - static TypeResolver* createObjectTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &objectTypeToPython, &pythonToObjectType, SbkType()); - } - - /** - * This kind of type resolver is used only when we have a signal with a reference in their arguments - * like on QSqlTableModel::primeInsert. - */ - template - static TypeResolver* createReferenceTypeResolver(const char* typeName) - { - return createTypeResolver(typeName, &referenceTypeToPython, &pythonToValueType, SbkType()); - } - - static Type getType(const char* name); - static TypeResolver* get(const char* typeName); - - PyObject* toPython(void* cppObj); - void toCpp(PyObject* pyObj, void** place); - PyTypeObject* pythonType(); - -private: - struct TypeResolverPrivate; - TypeResolverPrivate* m_d; - - TypeResolver(); - // disable object copy - TypeResolver(const TypeResolver&); - TypeResolver& operator=(const TypeResolver&); - - static TypeResolver* createTypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType); -}; -} - -#endif diff --git a/shibokenmodule/CMakeLists.txt b/shibokenmodule/CMakeLists.txt deleted file mode 100644 index 7e90b51ab..000000000 --- a/shibokenmodule/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -project(shibokenmodule) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shibokenmodule.txt.in" - "${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt" @ONLY) - - -set(sample_SRC -${CMAKE_CURRENT_BINARY_DIR}/shiboken2/shiboken2_module_wrapper.cpp -) - -add_custom_command(OUTPUT ${sample_SRC} -# Note: shiboken2 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/shiboken2/pull/11 -COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt ${GENERATOR_EXTRA_FLAGS} -WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -COMMENT "Running generator for 'shiboken2'..." -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${libshiboken_SOURCE_DIR} - ${libshiboken_BINARY_DIR}) -add_library(shibokenmodule MODULE ${sample_SRC}) -set_property(TARGET shibokenmodule PROPERTY PREFIX "") -set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "shiboken2") -if(WIN32) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "shiboken2_d") - endif() - set_property(TARGET shibokenmodule PROPERTY SUFFIX ".pyd") -endif() -target_link_libraries(shibokenmodule - ${SBK_PYTHON_LIBRARIES} - libshiboken) - -add_dependencies(shibokenmodule shiboken2) - -install(TARGETS shibokenmodule DESTINATION ${PYTHON_SITE_PACKAGES}) \ No newline at end of file diff --git a/shibokenmodule/nothing.h b/shibokenmodule/nothing.h deleted file mode 100644 index e69de29bb..000000000 diff --git a/shibokenmodule/shibokenmodule.txt.in b/shibokenmodule/shibokenmodule.txt.in deleted file mode 100644 index c5adc6091..000000000 --- a/shibokenmodule/shibokenmodule.txt.in +++ /dev/null @@ -1,16 +0,0 @@ -[generator-project] - -generator-set = shiboken - -header-file = @CMAKE_CURRENT_SOURCE_DIR@/nothing.h -typesystem-file = @CMAKE_CURRENT_SOURCE_DIR@/typesystem_shiboken.xml - -output-directory = @CMAKE_CURRENT_BINARY_DIR@ - -# include-path = @libsample_SOURCE_DIR@ - -typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ - -avoid-protected-hack -#enable-parent-ctor-heuristic -#use-isnull-as-nb_nonzero diff --git a/shibokenmodule/typesystem_shiboken.xml b/shibokenmodule/typesystem_shiboken.xml deleted file mode 100644 index 18ab52e80..000000000 --- a/shibokenmodule/typesystem_shiboken.xml +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - bool isValid = Shiboken::Object::isValid(%1, false); - %PYARG_0 = %CONVERTTOPYTHON[bool](isValid); - - - - - - Shiboken::Object::invalidate(%1); - - - - - - if (Shiboken::ObjectType::checkType((PyTypeObject*)%2)) - %PYARG_0 = Shiboken::Object::newObject((SbkObjectType*)%2, (void*)%1, false, true); - else - PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); - - - - - - if (Shiboken::Object::checkType(%1)) { - std::vector<void*> ptrs = Shiboken::Object::cppPointers((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."); - } - - - - - - if (Shiboken::Object::checkType(%1)) { - Shiboken::Object::callCppDestructors((SbkObject*)%1); - } else { - PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); - } - - - - - - if (Shiboken::Object::checkType(%1)) { - bool hasOwnership = Shiboken::Object::hasOwnership((SbkObject*)%1); - %PYARG_0 = %CONVERTTOPYTHON[bool](hasOwnership); - } else { - PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); - } - - - - - - if (Shiboken::Object::checkType(%1)) { - bool wasCreatedByPython = Shiboken::Object::wasCreatedByPython((SbkObject*)%1); - %PYARG_0 = %CONVERTTOPYTHON[bool](wasCreatedByPython); - } else { - PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); - } - - - - - - if (!Shiboken::Object::checkType(%1)) { - %PYARG_0 = Shiboken::String::fromCString("Ordinary Python type."); - } else { - std::string str = Shiboken::Object::info((SbkObject*)%1); - %PYARG_0 = Shiboken::String::fromCString(str.c_str()); - } - - - - - - std::set<PyObject*> setAll = Shiboken::BindingManager::instance().getAllPyObjects(); - PyObject* listAll = PyList_New(0); - if (listAll == NULL) - return NULL; - - const std::set<PyObject*>::iterator end = setAll.end(); - for (std::set<PyObject*>::iterator iter = setAll.begin(); iter != end; ++iter) { - if (*iter != NULL) { - if (PyList_Append(listAll, *iter) != 0) { - Py_DECREF(listAll); - return NULL; - } - } - } - return listAll; - - - - - - - - // Add __version__ and __version_info__ attributes to the module - PyObject* version = PyTuple_New(5); - PyTuple_SET_ITEM(version, 0, PyInt_FromLong(SHIBOKEN_MAJOR_VERSION)); - PyTuple_SET_ITEM(version, 1, PyInt_FromLong(SHIBOKEN_MINOR_VERSION)); - PyTuple_SET_ITEM(version, 2, PyInt_FromLong(SHIBOKEN_MICRO_VERSION)); - PyTuple_SET_ITEM(version, 3, Shiboken::String::fromCString(SHIBOKEN_RELEASE_LEVEL)); - PyTuple_SET_ITEM(version, 4, PyInt_FromLong(SHIBOKEN_SERIAL)); - PyModule_AddObject(module, "__version_info__", version); - PyModule_AddStringConstant(module, "__version__", SHIBOKEN_VERSION); - - diff --git a/sources/shiboken2/.gitattributes b/sources/shiboken2/.gitattributes new file mode 100644 index 000000000..adbe833c1 --- /dev/null +++ b/sources/shiboken2/.gitattributes @@ -0,0 +1,2 @@ +.gitignore export-ignore +.gitattributes export-ignore diff --git a/sources/shiboken2/.gitignore b/sources/shiboken2/.gitignore new file mode 100644 index 000000000..adb1e4594 --- /dev/null +++ b/sources/shiboken2/.gitignore @@ -0,0 +1,8 @@ +build +.kdev4 +*.log +*.pyc +*.o +*.so +.*.swp +*.kdev4 diff --git a/sources/shiboken2/AUTHORS b/sources/shiboken2/AUTHORS new file mode 100644 index 000000000..4bb16b2dd --- /dev/null +++ b/sources/shiboken2/AUTHORS @@ -0,0 +1,12 @@ +John Cummings +John Ehresman +Roman Lacko +Matthew Woehlke +Anderson Lizardo +Bruno Araujo +Hugo Parente Lima +Lauro Moura +Luciano Wolf +Marcelo Lira +Renato Araujo Oliveira Filho + diff --git a/sources/shiboken2/ApiExtractor/AUTHORS b/sources/shiboken2/ApiExtractor/AUTHORS new file mode 100644 index 000000000..6e802fb53 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/AUTHORS @@ -0,0 +1,8 @@ +Anderson Lizardo +Bruno Araujo +Hugo Parente Lima +Lauro Moura +Luciano Wolf +Marcelo Lira +Renato Araujo Oliveira Filho + diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt new file mode 100644 index 000000000..6cb3e0185 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -0,0 +1,90 @@ +project(apiextractor) + +find_package(LibXml2 2.6.32) +find_package(LibXslt 1.1.19) + +option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE) + +if (NOT DISABLE_DOCSTRINGS) + if (NOT LIBXSLT_FOUND OR NOT LIBXML2_FOUND) + set(DISABLE_DOCSTRINGS TRUE CACHE BOOL "Disable doc strings" PARENT_SCOPE) + set(DISABLE_DOCSTRINGS TRUE) + message(WARNING "libxslt and/or libxml not found, disabling support for doc strings!") + endif() +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif() + +if(BUILD_TESTS) + set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests) +endif () + +set(QT_USE_QTCORE 1) +set(QT_USE_QTXML 1) +add_definitions(-DQT_PLUGIN) +add_definitions(-DQT_SHARED) +add_definitions(-DRXX_ALLOCATOR_INIT_0) + +set(apiextractor_SRC +apiextractor.cpp +abstractmetabuilder.cpp +abstractmetalang.cpp +fileout.cpp +graph.cpp +reporthandler.cpp +typeparser.cpp +typesystem.cpp +include.cpp +typedatabase.cpp +# Clang +clangparser/compilersupport.cpp +clangparser/clangparser.cpp +clangparser/clangbuilder.cpp +clangparser/clangdebugutils.cpp +clangparser/clangutils.cpp +# Old parser +parser/codemodel.cpp +) + +set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES}) +set(APIEXTRACTOR_EXTRA_LIBRARIES ${CLANG_EXTRA_LIBRARIES}) + +if (NOT DISABLE_DOCSTRINGS) + set(apiextractor_SRC + ${apiextractor_SRC} + docparser.cpp + doxygenparser.cpp + qtdocparser.cpp + ) + set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR}) + set(APIEXTRACTOR_EXTRA_LIBRARIES ${APIEXTRACTOR_EXTRA_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES}) +endif() + +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) + +set(CMAKE_AUTOMOC ON) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/parser + ${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp + ${APIEXTRACTOR_EXTRA_INCLUDES} + ${Qt5Core_INCLUDE_DIRS} + ${Qt5Xml_INCLUDE_DIRS} + ) + +add_library(apiextractor STATIC ${apiextractor_SRC} ${apiextractor_RCCS_SRC}) +target_link_libraries(apiextractor + ${Qt5Xml_LIBRARIES} + ${Qt5XmlPatterns_LIBRARIES} + ${APIEXTRACTOR_EXTRA_LIBRARIES} + ) + +set_property(TARGET apiextractor PROPERTY CXX_STANDARD 11) + +if (BUILD_TESTS) + enable_testing() + add_subdirectory(tests) +endif() diff --git a/sources/shiboken2/ApiExtractor/COPYING b/sources/shiboken2/ApiExtractor/COPYING new file mode 100644 index 000000000..4ccd71466 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/COPYING @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +------------------------------------------------------------------------- diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp new file mode 100644 index 000000000..3b2ecf8e1 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -0,0 +1,3459 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "abstractmetabuilder_p.h" +#include "reporthandler.h" +#include "typedatabase.h" + +#include +#include + +#include "parser/codemodel.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include "graph.h" +#include + +static inline QString colonColon() { return QStringLiteral("::"); } + +static QString stripTemplateArgs(const QString &name) +{ + int pos = name.indexOf(QLatin1Char('<')); + return pos < 0 ? name : name.left(pos); +} + +static QStringList parseTemplateType(const QString& name) { + int n = name.indexOf(QLatin1Char('<')); + if (n <= 0) { + // If name starts with '<' or contains an unmatched (i.e. any) '>', we + // reject it + if (n == 0 || name.count(QLatin1Char('>'))) + return QStringList(); + // Doesn't look like a template instantiation; just return the name + return QStringList() << name; + } + + // Split the type name into the template name and template arguments; the + // part before the opening '<' is the template name + // + // Example: + // "foo, D>" -> ( "foo", "A", "bar", "D" ) + QStringList result; + result << name.left(n).trimmed(); + + // Extract template arguments + int i, depth = 1; + const int l = name.length(); + for (i = n + 1; i < l; ++i) { + // Consume balanced '<'/'>' within a single argument so that we won't + // split on ',' as part of a single argument which is itself a + // multi-argument template type + if (name[i] == QLatin1Char('<')) { + ++depth; + } else if (name[i] == QLatin1Char('>')) { + if (--depth == 0) + break; + } else if (name[i] == QLatin1Char(',') && depth == 1) { + // Encountered ',' in template argument list that is not within + // another template name; add current argument to result and start + // working on the next argument + result << name.mid(n + 1, i - n - 1).trimmed(); + n = i; + } + } + if (i >= l) // arg list not closed + return QStringList(); + if (i + 1 < l) // arg list closed before end of name + return QStringList(); + + // Add final argument and return result + result << name.mid(n + 1, i - n - 1).trimmed(); + return result; +} + +AbstractMetaBuilderPrivate::AbstractMetaBuilderPrivate() : m_currentClass(0), + m_logDirectory(QLatin1String(".") + QDir::separator()) +{ +} + +AbstractMetaBuilderPrivate::~AbstractMetaBuilderPrivate() +{ + qDeleteAll(m_globalEnums); + qDeleteAll(m_globalFunctions); + qDeleteAll(m_templates); + qDeleteAll(m_smartPointers); + qDeleteAll(m_metaClasses); +} + +AbstractMetaBuilder::AbstractMetaBuilder() : d(new AbstractMetaBuilderPrivate) +{ + d->q = this; +} + +AbstractMetaBuilder::~AbstractMetaBuilder() +{ + delete d; +} + +AbstractMetaClassList AbstractMetaBuilder::classes() const +{ + return d->m_metaClasses; +} + +AbstractMetaClassList AbstractMetaBuilder::templates() const +{ + return d->m_templates; +} + +AbstractMetaClassList AbstractMetaBuilder::smartPointers() const +{ + return d->m_smartPointers; +} + +AbstractMetaFunctionList AbstractMetaBuilder::globalFunctions() const +{ + return d->m_globalFunctions; +} + +AbstractMetaEnumList AbstractMetaBuilder::globalEnums() const +{ + return d->m_globalEnums; +} + +QSet AbstractMetaBuilder::qtMetaTypeDeclaredTypeNames() const +{ + return d->m_qmetatypeDeclaredTypenames; +} + +void AbstractMetaBuilderPrivate::checkFunctionModifications() +{ + TypeDatabase *types = TypeDatabase::instance(); + const SingleTypeEntryHash entryHash = types->entries(); + + for (SingleTypeEntryHash::const_iterator it = entryHash.cbegin(), end = entryHash.cend(); it != end; ++it) { + const TypeEntry *entry = it.value(); + if (!entry) + continue; + if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing) + continue; + + const ComplexTypeEntry* centry = static_cast(entry); + FunctionModificationList modifications = centry->functionModifications(); + + for (const FunctionModification &modification : qAsConst(modifications)) { + QString signature = modification.signature; + + QString name = signature.trimmed(); + name.truncate(name.indexOf(QLatin1Char('('))); + + AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry->qualifiedCppName()); + if (!clazz) + continue; + + const AbstractMetaFunctionList functions = clazz->functions(); + bool found = false; + QStringList possibleSignatures; + for (AbstractMetaFunction *function : functions) { + if (function->minimalSignature() == signature && function->implementingClass() == clazz) { + found = true; + break; + } + + if (function->originalName() == name) { + possibleSignatures.append(function->minimalSignature() + QLatin1String(" in ") + + function->implementingClass()->name()); + } + } + + if (!found) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("signature '%1' for function modification in '%2' not found. Possible candidates: %3") + .arg(signature, clazz->qualifiedCppName(), possibleSignatures.join(QLatin1String(", "))); + } + } + } +} + +AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem argument) +{ + AbstractMetaClass* returned = 0; + bool ok = false; + AbstractMetaType* type = translateType(argument->type(), &ok); + if (ok && type && type->typeEntry() && type->typeEntry()->isComplex()) { + const TypeEntry *entry = type->typeEntry(); + returned = AbstractMetaClass::findClass(m_metaClasses, entry->name()); + } + delete type; + return returned; +} + +AbstractMetaClass *AbstractMetaBuilder::createMetaClass() +{ + return new AbstractMetaClass(); +} + +AbstractMetaEnum *AbstractMetaBuilder::createMetaEnum() +{ + return new AbstractMetaEnum(); +} + +AbstractMetaEnumValue *AbstractMetaBuilder::createMetaEnumValue() +{ + return new AbstractMetaEnumValue(); +} + +AbstractMetaField *AbstractMetaBuilder::createMetaField() +{ + return new AbstractMetaField(); +} + +AbstractMetaFunction *AbstractMetaBuilder::createMetaFunction() +{ + return new AbstractMetaFunction(); +} + +AbstractMetaArgument *AbstractMetaBuilder::createMetaArgument() +{ + return new AbstractMetaArgument(); +} + +AbstractMetaType *AbstractMetaBuilder::createMetaType() +{ + return new AbstractMetaType(); +} + +/** + * Checks the argument of a hash function and flags the type if it is a complex type + */ +void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function_item) +{ + ArgumentList arguments = function_item->arguments(); + if (arguments.size() == 1) { + if (AbstractMetaClass *cls = argumentToClass(arguments.at(0))) + cls->setHasHashFunction(true); + } +} + +/** + * Check if a class has a debug stream operator that can be used as toString + */ + +void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem function_item) +{ + ArgumentList arguments = function_item->arguments(); + if (arguments.size() == 2) { + if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) { + ArgumentModelItem arg = arguments.at(1); + if (AbstractMetaClass *cls = argumentToClass(arg)) { + if (arg->type().indirections() < 2) + cls->setToStringCapability(true); + } + } + } +} + +void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item) +{ + if (item->accessPolicy() != CodeModel::Public) + return; + + ArgumentList arguments = item->arguments(); + AbstractMetaClass* baseoperandClass; + bool firstArgumentIsSelf = true; + bool unaryOperator = false; + + baseoperandClass = argumentToClass(arguments.at(0)); + + if (arguments.size() == 1) { + unaryOperator = true; + } else if (!baseoperandClass + || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) { + baseoperandClass = argumentToClass(arguments.at(1)); + firstArgumentIsSelf = false; + } else { + bool ok; + AbstractMetaType* type = translateType(item->type(), &ok); + const TypeEntry* retType = ok ? type->typeEntry() : 0; + AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1)); + if (otherArgClass && retType + && (retType->isValue() || retType->isObject()) + && retType != baseoperandClass->typeEntry() + && retType == otherArgClass->typeEntry()) { + baseoperandClass = AbstractMetaClass::findClass(m_metaClasses, retType); + firstArgumentIsSelf = false; + } + delete type; + } + + if (baseoperandClass) { + AbstractMetaClass* oldCurrentClass = m_currentClass; + m_currentClass = baseoperandClass; + AbstractMetaFunction *metaFunction = traverseFunction(item); + if (metaFunction && !metaFunction->isInvalid()) { + // Strip away first argument, since that is the containing object + AbstractMetaArgumentList arguments = metaFunction->arguments(); + if (firstArgumentIsSelf || unaryOperator) { + AbstractMetaArgument* first = arguments.takeFirst(); + if (!unaryOperator && first->type()->indirections()) + metaFunction->setPointerOperator(true); + delete first; + metaFunction->setArguments(arguments); + } else { + // If the operator method is not unary and the first operator is + // not of the same type of its owning class we suppose that it + // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)). + // All operator overloads that operate over a class are already + // being added as member functions of that class by the API Extractor. + AbstractMetaArgument* last = arguments.takeLast(); + if (last->type()->indirections()) + metaFunction->setPointerOperator(true); + delete last; + + metaFunction->setArguments(arguments); + metaFunction->setReverseOperator(true); + } + metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); + metaFunction->setVisibility(AbstractMetaFunction::Public); + metaFunction->setOriginalAttributes(metaFunction->attributes()); + setupFunctionDefaults(metaFunction, baseoperandClass); + baseoperandClass->addFunction(metaFunction); + Q_ASSERT(!metaFunction->wasPrivate()); + } else if (metaFunction) { + delete metaFunction; + } + + m_currentClass = oldCurrentClass; + } +} + +void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item) +{ + ArgumentList arguments = item->arguments(); + if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) { + AbstractMetaClass* streamClass = argumentToClass(arguments.at(0)); + AbstractMetaClass* streamedClass = argumentToClass(arguments.at(1)); + + if (streamClass && streamedClass && (streamClass->isStream())) { + AbstractMetaClass *oldCurrentClass = m_currentClass; + m_currentClass = streamedClass; + AbstractMetaFunction *streamFunction = traverseFunction(item); + + if (streamFunction && !streamFunction->isInvalid()) { + QString name = item->name(); + streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction); + // Strip first argument, since that is the containing object + AbstractMetaArgumentList arguments = streamFunction->arguments(); + if (!streamClass->typeEntry()->generateCode()) + delete arguments.takeLast(); + else + delete arguments.takeFirst(); + + streamFunction->setArguments(arguments); + + *streamFunction += AbstractMetaAttributes::Final; + *streamFunction += AbstractMetaAttributes::Public; + streamFunction->setOriginalAttributes(streamFunction->attributes()); + +// streamFunction->setType(0); + + AbstractMetaClass *funcClass; + + if (!streamClass->typeEntry()->generateCode()) { + AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments()); + streamFunction->setArguments(reverseArgs); + streamFunction->setReverseOperator(true); + funcClass = streamedClass; + } else { + funcClass = streamClass; + } + + setupFunctionDefaults(streamFunction, funcClass); + funcClass->addFunction(streamFunction); + if (funcClass == streamClass) + funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include()); + else + funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); + + m_currentClass = oldCurrentClass; + } else if (streamFunction) { + delete streamFunction; + } + + } + } +} + +void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom, + const TypeDatabase *types, + const NamespaceModelItem &scope) +{ + const ClassList &scopeClasses = scope->classes(); + for (const ClassModelItem &item : scopeClasses) { + QString qualifiedName = item->qualifiedName().join(colonColon()); + TypeEntry* entry = types->findType(qualifiedName); + if (entry) { + if (isQObject(dom, qualifiedName) && entry->isComplex()) + ((ComplexTypeEntry*) entry)->setQObject(true); + } + } + + const NamespaceList &namespaces = scope->namespaces(); + for (const NamespaceModelItem &n : namespaces) { + if (scope != n) + fixQObjectForScope(dom, types, n); + } +} + +void AbstractMetaBuilderPrivate::sortLists() +{ + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) + cls->sortFunctions(); +} + +FileModelItem AbstractMetaBuilderPrivate::buildDom(const QByteArrayList &arguments, + unsigned clangFlags) +{ + clang::Builder builder; + FileModelItem result = clang::parse(arguments, clangFlags, builder) + ? builder.dom() : FileModelItem(); + const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics(); + if (const int diagnosticsCount = diagnostics.size()) { + QDebug d = qWarning(); + d.nospace(); + d.noquote(); + d << "Clang: " << diagnosticsCount << " diagnostic messages:\n"; + for (int i = 0; i < diagnosticsCount; ++i) + d << " " << diagnostics.at(i) << '\n'; + } + return result; +} + +void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) +{ + const TypeDatabase *types = TypeDatabase::instance(); + + pushScope(dom); + + // fix up QObject's in the type system.. + fixQObjectForScope(dom, types, dom); + + // Start the generation... + const ClassList &typeValues = dom->classes(); + ReportHandler::setProgressReference(typeValues); + for (const ClassModelItem &item : typeValues) { + ReportHandler::progress(QLatin1String("Generating class model...")); + AbstractMetaClass *cls = traverseClass(dom, item); + if (!cls) + continue; + + addAbstractMetaClass(cls); + } + + // We need to know all global enums + const EnumList &enums = dom->enums(); + ReportHandler::setProgressReference(enums); + for (const EnumModelItem &item : enums) { + ReportHandler::progress(QLatin1String("Generating enum model...")); + AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet()); + if (metaEnum) { + if (metaEnum->typeEntry()->generateCode()) + m_globalEnums << metaEnum; + } + } + + const QSet &namespaceTypeValues = dom->uniqueNamespaces(); + ReportHandler::setProgressReference(namespaceTypeValues); + for (NamespaceModelItem item : namespaceTypeValues) { + ReportHandler::progress(QLatin1String("Generating namespace model...")); + AbstractMetaClass *metaClass = traverseNamespace(dom, item); + if (metaClass) + m_metaClasses << metaClass; + } + + // Go through all typedefs to see if we have defined any + // specific typedefs to be used as classes. + const TypeDefList typeDefs = dom->typeDefs(); + ReportHandler::setProgressReference(typeDefs); + for (const TypeDefModelItem &typeDef : typeDefs) { + ReportHandler::progress(QLatin1String("Resolving typedefs...")); + AbstractMetaClass* cls = traverseTypeDef(dom, typeDef); + addAbstractMetaClass(cls); + } + + figureOutEnumValues(); + + for (const ClassModelItem &item : typeValues) + traverseClassMembers(item); + + for (const NamespaceModelItem &item : namespaceTypeValues) + traverseNamespaceMembers(item); + + // Global functions + const FunctionList &functions = dom->functions(); + for (const FunctionModelItem &func : functions) { + if (func->accessPolicy() != CodeModel::Public || func->name().startsWith(QLatin1String("operator"))) + continue; + + FunctionTypeEntry* funcEntry = types->findFunctionType(func->name()); + if (!funcEntry || !funcEntry->generateCode()) + continue; + + AbstractMetaFunction* metaFunc = traverseFunction(func); + if (!metaFunc) + continue; + + if (!funcEntry->hasSignature(metaFunc->minimalSignature())) { + delete metaFunc; + continue; + } + + applyFunctionModifications(metaFunc); + + setInclude(funcEntry, func->fileName()); + if (metaFunc->typeEntry()) + delete metaFunc->typeEntry(); + + metaFunc->setTypeEntry(funcEntry); + m_globalFunctions << metaFunc; + } + + ReportHandler::setProgressReference(m_metaClasses); + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { + ReportHandler::progress(QLatin1String("Fixing class inheritance...")); + if (!cls->isInterface() && !cls->isNamespace()) + setupInheritance(cls); + } + + ReportHandler::setProgressReference(m_metaClasses); + for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) { + ReportHandler::progress(QLatin1String("Detecting inconsistencies in class model...")); + cls->fixFunctions(); + + if (!cls->typeEntry()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("class '%1' does not have an entry in the type system") + .arg(cls->name()); + } else { + bool couldAddDefaultCtors = !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace(); + if (couldAddDefaultCtors) { + if (!cls->hasConstructors()) + cls->addDefaultConstructor(); + if (cls->typeEntry()->isValue() && !cls->isAbstract() && !cls->hasCopyConstructor()) + cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls)); + } + } + + if (cls->isAbstract() && !cls->isInterface()) + cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper")); + } + const TypeEntryHash allEntries = types->allEntries(); + ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem...")); + for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { + for (TypeEntry *entry : it.value()) { + if (entry->isPrimitive()) + continue; + + if ((entry->isValue() || entry->isObject()) + && !entry->isString() + && !entry->isChar() + && !entry->isContainer() + && !entry->isCustom() + && !entry->isVariant() + && !AbstractMetaClass::findClass(m_metaClasses, entry->qualifiedCppName())) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") + .arg(entry->qualifiedCppName()); + } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) { + const FunctionTypeEntry* fte = static_cast(entry); + const QStringList &signatures = fte->signatures(); + for (const QString &signature : signatures) { + bool ok = false; + for (AbstractMetaFunction* func : qAsConst(m_globalFunctions)) { + if (signature == func->minimalSignature()) { + ok = true; + break; + } + } + if (!ok) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.") + .arg(signature); + } + } + } else if (entry->isEnum()) { + const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier(); + AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name); + + bool enumFound = false; + if (cls) { + enumFound = cls->findEnum(entry->targetLangName()); + } else { // Global enum + for (AbstractMetaEnum *metaEnum : qAsConst(m_enums)) { + if (metaEnum->typeEntry() == entry) { + enumFound = true; + break; + } + } + } + if (!enumFound) { + entry->setCodeGeneration(TypeEntry::GenerateNothing); + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("enum '%1' is specified in typesystem, but not declared") + .arg(entry->qualifiedCppName()); + } + + } + } + } + + { + const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash")); + for (const FunctionModelItem &item : hashFunctions) + registerHashFunction(item); + } + + { + const FunctionList &streamOps = dom->findFunctions(QLatin1String("operator<<")); + for (const FunctionModelItem &item : streamOps) + registerToStringCapability(item); + } + + { + FunctionList binaryOperators = dom->findFunctions(QStringLiteral("operator==")); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator!="))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator<="))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator>="))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator<"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator+"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator/"))); + // Filter binary operators, skipping for example + // class Iterator { ... Value *operator*() ... }; + const FunctionList potentiallyBinaryOperators = + dom->findFunctions(QStringLiteral("operator*")) + + dom->findFunctions(QStringLiteral("operator&")); + for (const FunctionModelItem &item : potentiallyBinaryOperators) { + if (!item->arguments().isEmpty()) + binaryOperators.append(item); + } + binaryOperators.append(dom->findFunctions(QStringLiteral("operator-"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator&"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator|"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator^"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator~"))); + binaryOperators.append(dom->findFunctions(QStringLiteral("operator>"))); + + for (const FunctionModelItem &item : qAsConst(binaryOperators)) + traverseOperatorFunction(item); + } + + { + const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<")) + + dom->findFunctions(QLatin1String("operator>>")); + for (const FunctionModelItem &item : streamOperators) + traverseStreamOperator(item); + } + + figureOutDefaultEnumArguments(); + checkFunctionModifications(); + + // sort all classes topologically + m_metaClasses = classesTopologicalSorted(); + + for (AbstractMetaClass* cls : qAsConst(m_metaClasses)) { +// setupEquals(cls); +// setupComparable(cls); + setupClonable(cls); + setupExternalConversion(cls); + + // sort all inner classes topologically + if (!cls->typeEntry()->codeGeneration() || cls->innerClasses().size() < 2) + continue; + + cls->setInnerClasses(classesTopologicalSorted(cls)); + } + + dumpLog(); + + sortLists(); + + m_currentClass = 0; + + // Functions added to the module on the type system. + const AddedFunctionList &globalUserFunctions = types->globalUserFunctions(); + for (const AddedFunction &addedFunc : globalUserFunctions) { + AbstractMetaFunction* metaFunc = traverseFunction(addedFunc); + metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction); + m_globalFunctions << metaFunc; + } + + std::puts(""); +} + +bool AbstractMetaBuilder::build(const QByteArrayList &arguments, unsigned clangFlags) +{ + const FileModelItem dom = d->buildDom(arguments, clangFlags); + if (dom.isNull()) + return false; + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCDebug(lcShiboken) << dom.data(); + d->traverseDom(dom); + return true; +} + +void AbstractMetaBuilder::setLogDirectory(const QString& logDir) +{ + d->m_logDirectory = logDir; + if (!d->m_logDirectory.endsWith(QDir::separator())) + d->m_logDirectory.append(QDir::separator()); +} + +void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls) +{ + if (!cls) + return; + + cls->setOriginalAttributes(cls->attributes()); + if (cls->typeEntry()->isContainer()) { + m_templates << cls; + } else if (cls->typeEntry()->isSmartPointer()) { + m_smartPointers << cls; + } else { + m_metaClasses << cls; + if (cls->typeEntry()->designatedInterface()) { + AbstractMetaClass* interface = cls->extractInterface(); + m_metaClasses << interface; + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name()); + } + } +} + +AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom, + const NamespaceModelItem &namespaceItem) +{ + QString namespaceName = + (!m_namespacePrefix.isEmpty() ? m_namespacePrefix + colonColon() : QString()) + + namespaceItem->name(); + NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName); + + if (TypeDatabase::instance()->isClassRejected(namespaceName)) { + m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled); + return 0; + } + + if (!type) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName); + return 0; + } + + AbstractMetaClass* metaClass = q->createMetaClass(); + metaClass->setTypeEntry(type); + + *metaClass += AbstractMetaAttributes::Public; + + m_currentClass = metaClass; + + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + qCDebug(lcShiboken) + << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name()); + } + + traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations()); + + pushScope(namespaceItem); + m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); + + const ClassList &classes = namespaceItem->classes(); + for (const ClassModelItem &cls : classes) { + AbstractMetaClass* mjc = traverseClass(dom, cls); + if (mjc) { + metaClass->addInnerClass(mjc); + mjc->setEnclosingClass(metaClass); + addAbstractMetaClass(mjc); + } + } + + // Go through all typedefs to see if we have defined any + // specific typedefs to be used as classes. + const TypeDefList typeDefs = namespaceItem->typeDefs(); + for (const TypeDefModelItem &typeDef : typeDefs) { + AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); + if (cls) { + metaClass->addInnerClass(cls); + cls->setEnclosingClass(metaClass); + addAbstractMetaClass(cls); + } + } + + // Traverse namespaces recursively + const QSet &innerNamespaces = namespaceItem->uniqueNamespaces(); + for (const NamespaceModelItem &ni : innerNamespaces) { + AbstractMetaClass* mjc = traverseNamespace(dom, ni); + if (mjc) { + metaClass->addInnerClass(mjc); + mjc->setEnclosingClass(metaClass); + addAbstractMetaClass(mjc); + } + } + + m_currentClass = 0; + + popScope(); + m_namespacePrefix = currentScope()->qualifiedName().join(colonColon()); + + if (!type->include().isValid()) + setInclude(type, namespaceItem->fileName()); + + return metaClass; +} + +struct Operator +{ + enum Type { Complement, Plus, ShiftRight, ShiftLeft, None }; + + Operator() : type(None) {} + + int calculate(int x) + { + switch (type) { + case Complement: return ~value; + case Plus: return x + value; + case ShiftRight: return x >> value; + case ShiftLeft: return x << value; + case None: return x; + } + return x; + } + + Type type; + int value; +}; + + + +Operator findOperator(QString* s) +{ + const char *names[] = { + "~", + "+", + ">>", + "<<" + }; + + for (int i = 0; i < Operator::None; ++i) { + QString name = QLatin1String(names[i]); + QString str = *s; + int splitPoint = str.indexOf(name); + if (splitPoint > -1) { + bool ok; + QString right = str.mid(splitPoint + name.length()); + Operator op; + + op.value = right.toInt(&ok); + if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u')) + op.value = right.left(right.length() - 1).toUInt(&ok, 0); + + if (ok) { + op.type = Operator::Type(i); + if (splitPoint > 0) + *s = str.left(splitPoint).trimmed(); + else + *s = QString(); + return op; + } + } + } + return Operator(); +} + +int AbstractMetaBuilderPrivate::figureOutEnumValue(const QString &stringValue, + int oldValuevalue, + AbstractMetaEnum *metaEnum, + AbstractMetaFunction *metaFunction) +{ + if (stringValue.isEmpty()) + return oldValuevalue; + + QStringList stringValues = stringValue.split(QLatin1Char('|')); + + int returnValue = 0; + + bool matched = false; + + for (int i = 0; i < stringValues.size(); ++i) { + QString s = stringValues.at(i).trimmed(); + + bool ok; + int v; + + Operator op = findOperator(&s); + + if (s.length() > 0 && s.at(0) == QLatin1Char('0')) + v = s.toUInt(&ok, 0); + else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u')) + v = s.left(s.length() - 1).toUInt(&ok, 0); + else + v = s.toInt(&ok); + + if (ok || s.isEmpty()) { + matched = true; + } else if (m_enumValues.contains(s)) { + v = m_enumValues[s]->value(); + matched = true; + } else { + if (metaEnum) { + v = findOutValueFromString(s, matched); + if (!matched) { + QString enclosingClass = QString(metaEnum->enclosingClass() ? metaEnum->enclosingClass()->name() + colonColon() : QString()); + qCWarning(lcShiboken).noquote().nospace() + << "unhandled enum value: " << s << " in " + << enclosingClass << metaEnum->name() << " from header '" + << metaEnum->typeEntry()->include().name() << '\''; + } + } else { + qCWarning(lcShiboken) << "unhandled enum value: Unknown enum"; + } + } + + if (matched) + returnValue |= op.calculate(v); + } + + if (!matched) { + QString warn = QStringLiteral("unmatched enum %1").arg(stringValue); + + if (metaFunction) { + warn += QStringLiteral(" when parsing default value of '%1' in class '%2'") + .arg(metaFunction->name(), metaFunction->implementingClass()->name()); + } + warn += QLatin1String(" from header '") + metaEnum->typeEntry()->include().name() + + QLatin1Char('\''); + + qCWarning(lcShiboken).noquote().nospace() << warn; + returnValue = oldValuevalue; + } + + return returnValue; +} + +void AbstractMetaBuilderPrivate::figureOutEnumValuesForClass(AbstractMetaClass *metaClass, + QSet *classes) +{ + AbstractMetaClass* base = metaClass->baseClass(); + + if (base && !classes->contains(base)) + figureOutEnumValuesForClass(base, classes); + + if (classes->contains(metaClass)) + return; + + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum* e : enums) { + if (!e) { + qCWarning(lcShiboken).noquote().nospace() << "bad enum in class " << metaClass->name(); + continue; + } + AbstractMetaEnumValueList lst = e->values(); + int value = 0; + for (int i = 0; i < lst.size(); ++i) { + value = figureOutEnumValue(lst.at(i)->stringValue(), value, e); + lst.at(i)->setValue(value); + value++; + } + } + + *classes += metaClass; +} + + +void AbstractMetaBuilderPrivate::figureOutEnumValues() +{ + // Keep a set of classes that we already traversed. We use this to + // enforce that we traverse base classes prior to subclasses. + QSet classes; + for (AbstractMetaClass *c : qAsConst(m_metaClasses)) + figureOutEnumValuesForClass(c, &classes); + + for (AbstractMetaEnum* metaEnum : qAsConst(m_globalEnums)) { + AbstractMetaEnumValueList enumValues = metaEnum->values(); + int value = 0; + for (int i = 0; i < enumValues.size(); ++i) { + value = figureOutEnumValue(enumValues.at(i)->stringValue(), value, metaEnum); + enumValues.at(i)->setValue(value); + value++; + } + } +} + +void AbstractMetaBuilderPrivate::figureOutDefaultEnumArguments() +{ + for (AbstractMetaClass* metaClass : qAsConst(m_metaClasses)) { + const AbstractMetaFunctionList &functions = metaClass->functions(); + for (AbstractMetaFunction* metaFunction : functions) { + const AbstractMetaArgumentList &arguments = metaFunction->arguments(); + for (AbstractMetaArgument *arg : arguments) { + QString expr = arg->defaultValueExpression(); + if (expr.isEmpty()) + continue; + + if (!metaFunction->replacedDefaultExpression(metaFunction->implementingClass(), + arg->argumentIndex() + 1).isEmpty()) { + continue; + } + + arg->setDefaultValueExpression(expr); + } + } + } +} + + +AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem, + AbstractMetaClass *enclosing, + const QSet &enumsDeclarations) +{ + QString qualifiedName = enumItem->qualifiedName().join(colonColon()); + + TypeEntry* typeEntry = 0; + if (enumItem->accessPolicy() == CodeModel::Private) { + QStringList names = enumItem->qualifiedName(); + QString enumName = names.last(); + QString nspace; + if (names.size() > 1) + nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); + typeEntry = new EnumTypeEntry(nspace, enumName, 0); + TypeDatabase::instance()->addType(typeEntry); + } else if (!enumItem->isAnonymous()) { + typeEntry = TypeDatabase::instance()->findType(qualifiedName); + } else { + QStringList tmpQualifiedName = enumItem->qualifiedName(); + const EnumeratorList &enums = enumItem->enumerators(); + for (const EnumeratorModelItem& enumValue : enums) { + tmpQualifiedName.removeLast(); + tmpQualifiedName << enumValue->name(); + qualifiedName = tmpQualifiedName.join(colonColon()); + typeEntry = TypeDatabase::instance()->findType(qualifiedName); + if (typeEntry) + break; + } + } + + QString enumName = enumItem->name(); + + QString className; + if (m_currentClass) + className = m_currentClass->typeEntry()->qualifiedCppName(); + + QString rejectReason; + if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) { + if (typeEntry) + typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); + m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled); + return 0; + } + + if (!typeEntry || !typeEntry->isEnum()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("enum '%1' does not have a type entry or is not an enum") + .arg(qualifiedName); + m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem); + return 0; + } + + AbstractMetaEnum *metaEnum = q->createMetaEnum(); + if (enumsDeclarations.contains(qualifiedName) + || enumsDeclarations.contains(enumName)) { + metaEnum->setHasQEnumsDeclaration(true); + } + + metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry); + switch (enumItem->accessPolicy()) { + case CodeModel::Public: + *metaEnum += AbstractMetaAttributes::Public; + break; + case CodeModel::Protected: + *metaEnum += AbstractMetaAttributes::Protected; + break; + case CodeModel::Private: + *metaEnum += AbstractMetaAttributes::Private; + typeEntry->setCodeGeneration(TypeEntry::GenerateNothing); + break; + default: + break; + } + + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName(); + + const EnumeratorList &enums = enumItem->enumerators(); + for (const EnumeratorModelItem &value : enums) { + + AbstractMetaEnumValue *metaEnumValue = q->createMetaEnumValue(); + metaEnumValue->setName(value->name()); + // Deciding the enum value... + + metaEnumValue->setStringValue(value->value()); + metaEnum->addEnumValue(metaEnumValue); + + if (ReportHandler::isDebug(ReportHandler::FullDebug)) { + qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = " + << metaEnumValue->value() << " = " << metaEnumValue->value(); + } + + // Add into global register... + if (enclosing) + m_enumValues[enclosing->name() + colonColon() + metaEnumValue->name()] = metaEnumValue; + else + m_enumValues[metaEnumValue->name()] = metaEnumValue; + } + + m_enums << metaEnum; + + if (!metaEnum->typeEntry()->include().isValid()) + setInclude(metaEnum->typeEntry(), enumItem->fileName()); + + metaEnum->setOriginalAttributes(metaEnum->attributes()); + + // Register all enum values on Type database + const EnumeratorList &enumerators = enumItem->enumerators(); + for (EnumeratorModelItem e : enumItem->enumerators()) { + QString name; + if (enclosing) { + name += enclosing->name(); + name += colonColon(); + } + name += e->name(); + EnumValueTypeEntry* enumValue = new EnumValueTypeEntry(name, e->value(), static_cast(typeEntry), typeEntry->version()); + TypeDatabase::instance()->addType(enumValue); + } + + return metaEnum; +} + +AbstractMetaClass* AbstractMetaBuilderPrivate::traverseTypeDef(const FileModelItem &dom, + const TypeDefModelItem &typeDef) +{ + TypeDatabase* types = TypeDatabase::instance(); + QString className = stripTemplateArgs(typeDef->name()); + + QString fullClassName = className; + // we have an inner class + if (m_currentClass) { + fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + + colonColon() + fullClassName; + } + + // If this is the alias for a primitive type + // we store the aliased type on the alias + // TypeEntry + PrimitiveTypeEntry* ptype = types->findPrimitiveType(className); + if (ptype) { + QString typeDefName = typeDef->type().qualifiedName()[0]; + ptype->setReferencedTypeEntry(types->findPrimitiveType(typeDefName)); + return 0; + } + + + // If we haven't specified anything for the typedef, then we don't care + ComplexTypeEntry* type = types->findComplexType(fullClassName); + if (!type) + return 0; + + if (type->isObject()) + static_cast(type)->setQObject(isQObject(dom, stripTemplateArgs(typeDef->type().qualifiedName().join(colonColon())))); + + AbstractMetaClass *metaClass = q->createMetaClass(); + metaClass->setTypeDef(true); + metaClass->setTypeEntry(type); + metaClass->setBaseClassNames(QStringList() << typeDef->type().qualifiedName().join(colonColon())); + *metaClass += AbstractMetaAttributes::Public; + + // Set the default include file name + if (!type->include().isValid()) + setInclude(type, typeDef->fileName()); + + fillAddedFunctions(metaClass); + + return metaClass; +} + +AbstractMetaClass *AbstractMetaBuilderPrivate::traverseClass(const FileModelItem &dom, + const ClassModelItem &classItem) +{ + QString className = stripTemplateArgs(classItem->name()); + QString fullClassName = className; + + // we have inner an class + if (m_currentClass) { + fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + + colonColon() + fullClassName; + } + + ComplexTypeEntry* type = TypeDatabase::instance()->findComplexType(fullClassName); + AbstractMetaBuilder::RejectReason reason = AbstractMetaBuilder::NoReason; + + if (fullClassName == QLatin1String("QMetaTypeId")) { + // QtScript: record which types have been declared + int lpos = classItem->name().indexOf(QLatin1Char('<')); + int rpos = classItem->name().lastIndexOf(QLatin1Char('>')); + if ((lpos != -1) && (rpos != -1)) { + QString declaredTypename = classItem->name().mid(lpos + 1, rpos - lpos - 1); + m_qmetatypeDeclaredTypenames.insert(declaredTypename); + } + } + + if (TypeDatabase::instance()->isClassRejected(fullClassName)) { + reason = AbstractMetaBuilder::GenerationDisabled; + } else if (!type) { + TypeEntry *te = TypeDatabase::instance()->findType(fullClassName); + if (te && !te->isComplex()) + reason = AbstractMetaBuilder::RedefinedToNotClass; + else + reason = AbstractMetaBuilder::NotInTypeSystem; + } else if (type->codeGeneration() == TypeEntry::GenerateNothing) { + reason = AbstractMetaBuilder::GenerationDisabled; + } + if (reason != AbstractMetaBuilder::NoReason) { + m_rejectedClasses.insert(fullClassName, reason); + return 0; + } + + if (type->isObject()) + ((ObjectTypeEntry*)type)->setQObject(isQObject(dom, fullClassName)); + + AbstractMetaClass *metaClass = q->createMetaClass(); + metaClass->setTypeEntry(type); + metaClass->setBaseClassNames(classItem->baseClasses()); + *metaClass += AbstractMetaAttributes::Public; + if (type->stream()) + metaClass->setStream(true); + + AbstractMetaClass* oldCurrentClass = m_currentClass; + m_currentClass = metaClass; + + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + const QString message = type->isContainer() + ? QStringLiteral("container: '%1'").arg(fullClassName) + : QStringLiteral("class: '%1'").arg(metaClass->fullName()); + qCDebug(lcShiboken) << message; + } + + TemplateParameterList template_parameters = classItem->templateParameters(); + QVector template_args; + template_args.clear(); + for (int i = 0; i < template_parameters.size(); ++i) { + const TemplateParameterModelItem ¶m = template_parameters.at(i); + TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name(), type->version()); + param_type->setOrdinal(i); + template_args.append(param_type); + } + metaClass->setTemplateArguments(template_args); + + parseQ_Property(metaClass, classItem->propertyDeclarations()); + + traverseEnums(classItem, metaClass, classItem->enumsDeclarations()); + + // Inner classes + { + const ClassList &innerClasses = classItem->classes(); + for (const ClassModelItem &ci : innerClasses) { + AbstractMetaClass *cl = traverseClass(dom, ci); + if (cl) { + cl->setEnclosingClass(metaClass); + metaClass->addInnerClass(cl); + m_metaClasses << cl; + } + } + + } + + // Go through all typedefs to see if we have defined any + // specific typedefs to be used as classes. + const TypeDefList typeDefs = classItem->typeDefs(); + for (const TypeDefModelItem &typeDef : typeDefs) { + AbstractMetaClass *cls = traverseTypeDef(dom, typeDef); + if (cls) { + cls->setEnclosingClass(metaClass); + addAbstractMetaClass(cls); + } + } + + + m_currentClass = oldCurrentClass; + + // Set the default include file name + if (!type->include().isValid()) + setInclude(type, classItem->fileName()); + + return metaClass; +} + +void AbstractMetaBuilderPrivate::traverseScopeMembers(ScopeModelItem item, + AbstractMetaClass *metaClass) +{ + // Classes/Namespace members + traverseFields(item, metaClass); + traverseFunctions(item, metaClass); + + // Inner classes + const ClassList &innerClasses = item->classes(); + for (const ClassModelItem& ci : innerClasses) + traverseClassMembers(ci); +} + +AbstractMetaClass* AbstractMetaBuilderPrivate::currentTraversedClass(ScopeModelItem item) +{ + QString className = stripTemplateArgs(item->name()); + QString fullClassName = className; + + // This is an inner class + if (m_currentClass) + fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName; + + AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, fullClassName); + if (!metaClass) + metaClass = AbstractMetaClass::findClass(m_templates, fullClassName); + + if (!metaClass) + metaClass = AbstractMetaClass::findClass(m_smartPointers, fullClassName); + return metaClass; +} + +void AbstractMetaBuilderPrivate::traverseClassMembers(ClassModelItem item) +{ + AbstractMetaClass* metaClass = currentTraversedClass(item); + if (!metaClass) + return; + + AbstractMetaClass* oldCurrentClass = m_currentClass; + m_currentClass = metaClass; + + // Class members + traverseScopeMembers(item, metaClass); + + m_currentClass = oldCurrentClass; +} + +void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem item) +{ + AbstractMetaClass* metaClass = currentTraversedClass(item); + if (!metaClass) + return; + + AbstractMetaClass* oldCurrentClass = m_currentClass; + m_currentClass = metaClass; + + // Namespace members + traverseScopeMembers(item, metaClass); + + // Inner namespaces + const QSet &innerNamespaces = item->uniqueNamespaces(); + for (const NamespaceModelItem &ni : innerNamespaces) + traverseNamespaceMembers(ni); + + m_currentClass = oldCurrentClass; +} + +static inline QString fieldSignatureWithType(VariableModelItem field) +{ + return field->name() + QStringLiteral(" -> ") + field->type().toString(); +} + +static inline QString qualifiedFieldSignatureWithType(const QString &className, + VariableModelItem field) +{ + return className + colonColon() + fieldSignatureWithType(field); +} + +AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem field, + const AbstractMetaClass *cls) +{ + QString fieldName = field->name(); + QString className = m_currentClass->typeEntry()->qualifiedCppName(); + + // Ignore friend decl. + if (field->isFriend()) + return 0; + + if (field->accessPolicy() == CodeModel::Private) + return 0; + + QString rejectReason; + if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) { + m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason, + AbstractMetaBuilder::GenerationDisabled); + return 0; + } + + + AbstractMetaField *metaField = q->createMetaField(); + metaField->setName(fieldName); + metaField->setEnclosingClass(cls); + + bool ok; + TypeInfo fieldType = field->type(); + AbstractMetaType *metaType = translateType(fieldType, &ok); + + if (!metaType || !ok) { + const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon()); + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'") + .arg(m_currentClass->name(), fieldName, type); + delete metaField; + return 0; + } + + metaField->setType(metaType); + + AbstractMetaAttributes::Attributes attr = 0; + if (field->isStatic()) + attr |= AbstractMetaAttributes::Static; + + CodeModel::AccessPolicy policy = field->accessPolicy(); + if (policy == CodeModel::Public) + attr |= AbstractMetaAttributes::Public; + else if (policy == CodeModel::Protected) + attr |= AbstractMetaAttributes::Protected; + else + attr |= AbstractMetaAttributes::Private; + metaField->setAttributes(attr); + + return metaField; +} + +void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item, + AbstractMetaClass *metaClass) +{ + const VariableList &variables = scope_item->variables(); + for (const VariableModelItem &field : variables) { + AbstractMetaField* metaField = traverseField(field, metaClass); + + if (metaField && !metaField->isModifiedRemoved()) { + metaField->setOriginalAttributes(metaField->attributes()); + metaClass->addField(metaField); + } + } +} + +void AbstractMetaBuilderPrivate::setupFunctionDefaults(AbstractMetaFunction *metaFunction, + AbstractMetaClass *metaClass) +{ + // Set the default value of the declaring class. This may be changed + // in fixFunctions later on + metaFunction->setDeclaringClass(metaClass); + + // Some of the queries below depend on the implementing class being set + // to function properly. Such as function modifications + metaFunction->setImplementingClass(metaClass); + + if (metaFunction->name() == QLatin1String("operator_equal")) + metaClass->setHasEqualsOperator(true); + + if (!metaFunction->isFinalInTargetLang() + && metaFunction->isRemovedFrom(metaClass, TypeSystem::TargetLangCode)) { + *metaFunction += AbstractMetaAttributes::FinalInCpp; + } +} + +void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction) +{ + if (!metaFunction->isConversionOperator()) + return; + + TypeDatabase* types = TypeDatabase::instance(); + static const QRegularExpression operatorRegExp(QStringLiteral("^operator ")); + Q_ASSERT(operatorRegExp.isValid()); + QString castTo = metaFunction->name().remove(operatorRegExp).trimmed(); + + if (castTo.endsWith(QLatin1Char('&'))) + castTo.chop(1); + if (castTo.startsWith(QLatin1String("const "))) + castTo.remove(0, 6); + + TypeEntry* retType = types->findType(castTo); + if (!retType) + return; + + AbstractMetaType* metaType = q->createMetaType(); + metaType->setTypeEntry(retType); + metaFunction->replaceType(metaType); +} + +static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other) +{ + if (!type && !other) + return true; + if (!type || !other) + return false; + return type->typeEntry() == other->typeEntry() + && type->isConstant() == other->isConstant() + && type->referenceType() == other->referenceType() + && type->indirections() == other->indirections(); +} + +static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other) +{ + if (!func && !other) + return true; + if (!func || !other) + return false; + if (func->arguments().count() != other->arguments().count() + || func->isConstant() != other->isConstant() + || func->isStatic() != other->isStatic() + || !_compareAbstractMetaTypes(func->type(), other->type())) { + return false; + } + for (int i = 0; i < func->arguments().count(); ++i) { + if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type())) + return false; + } + return true; +} + +// Fix the arguments of template classes that take the class itself, for example: +// "QList(const QList &)" to "QList(const QList &)". +static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass) +{ + const QVector &templateTypes = metaClass->templateArguments(); + if (templateTypes.isEmpty()) + return false; + + const QStringList classType = metaClass->typeEntry()->qualifiedCppName().split(colonColon()); + QStringList fixedClassType = classType; + fixedClassType.last().append(QLatin1Char('<')); + for (int i = 0, count = templateTypes.size(); i < count; ++i) { + if (i) + fixedClassType.last().append(QLatin1String(", ")); + fixedClassType.last().append(templateTypes.at(i)->qualifiedCppName()); + } + fixedClassType.last().append(QLatin1String(" >")); + + bool templateTypeFixed = false; + TypeInfo functionType = function->type(); + if (functionType.qualifiedName() == classType) { + templateTypeFixed = true; + functionType.setQualifiedName(fixedClassType); + function->setType(functionType); + } + + ArgumentList arguments = function->arguments(); + for (int i = 0; i < arguments.size(); ++i) { + ArgumentModelItem arg = arguments.at(i); + TypeInfo type = arg->type(); + if (type.qualifiedName() == classType) { + type.setQualifiedName(fixedClassType); + arg->setType(type); + templateTypeFixed = true; + } + } + return templateTypeFixed; +} + +AbstractMetaFunctionList AbstractMetaBuilderPrivate::classFunctionList(const ScopeModelItem &scopeItem) +{ + AbstractMetaFunctionList result; + const FunctionList &scopeFunctionList = scopeItem->functions(); + result.reserve(scopeFunctionList.size()); + for (const FunctionModelItem &function : scopeFunctionList) { + if (AbstractMetaFunction *metaFunction = traverseFunction(function)) + result.append(metaFunction); + } + return result; +} + +// For template classes, entries with more specific types may exist from out-of- +// line definitions. If there is a declaration which matches it after fixing +// the parameters, remove it as duplicate. For example: +// template class Vector { public: +// Vector(const Vector &rhs); +// }; +// template class +// Vector::Vector(const Vector&) {} // More specific, remove declaration. + +class DuplicatingFunctionPredicate : public std::unary_function { +public: + explicit DuplicatingFunctionPredicate(const AbstractMetaFunction *f) : m_function(f) {} + + bool operator()(const AbstractMetaFunction *rhs) const + { + return rhs != m_function && rhs->name() == m_function->name() + && _compareAbstractMetaFunctions(m_function, rhs); + } + +private: + const AbstractMetaFunction *m_function; +}; + +AbstractMetaFunctionList AbstractMetaBuilderPrivate::templateClassFunctionList(const ScopeModelItem &scopeItem, + AbstractMetaClass *metaClass) +{ + AbstractMetaFunctionList result; + AbstractMetaFunctionList unchangedFunctions; + + const FunctionList &scopeFunctionList = scopeItem->functions(); + result.reserve(scopeFunctionList.size()); + unchangedFunctions.reserve(scopeFunctionList.size()); + for (FunctionModelItem function : scopeFunctionList) { + // This fixes method's arguments and return types that are templates + // but the template variable wasn't declared in the C++ header. + const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass); + if (AbstractMetaFunction *metaFunction = traverseFunction(function)) { + result.append(metaFunction); + if (!templateTypeFixed) + unchangedFunctions.append(metaFunction); + } + } + + const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.begin(); + const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.end(); + for (int i = result.size() - 1; i >= 0; --i) { + AbstractMetaFunction *function = result.at(i); + if (!unchangedFunctions.contains(function) + && unchangedEnd != std::find_if(unchangedBegin, unchangedEnd, DuplicatingFunctionPredicate(function))) { + delete result.takeAt(i); + } + } + return result; +} + +void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, + AbstractMetaClass *metaClass) +{ + + const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty() + ? classFunctionList(scopeItem) + : templateClassFunctionList(scopeItem, metaClass); + + for (AbstractMetaFunction *metaFunction : functions){ + metaFunction->setOriginalAttributes(metaFunction->attributes()); + if (metaClass->isNamespace()) + *metaFunction += AbstractMetaAttributes::Static; + + QPropertySpec *read = 0; + if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) { + // Property reader must be in the form " name()" + if (metaFunction->type() && (read->type() == metaFunction->type()->typeEntry()) && (metaFunction->arguments().size() == 0)) { + *metaFunction += AbstractMetaAttributes::PropertyReader; + metaFunction->setPropertySpec(read); + } + } else if (QPropertySpec* write = metaClass->propertySpecForWrite(metaFunction->name())) { + // Property setter must be in the form "void name()" + // make sure the function was created with all aguments, some argument can be missing during the pareser because of errors on typesystem + if ((!metaFunction->type()) && (metaFunction->arguments().size() == 1) && (write->type() == metaFunction->arguments().at(0)->type()->typeEntry())) { + *metaFunction += AbstractMetaAttributes::PropertyWriter; + metaFunction->setPropertySpec(write); + } + } else if (QPropertySpec* reset = metaClass->propertySpecForReset(metaFunction->name())) { + // Property resetter must be in the form "void name()" + if ((!metaFunction->type()) && (metaFunction->arguments().size() == 0)) { + *metaFunction += AbstractMetaAttributes::PropertyResetter; + metaFunction->setPropertySpec(reset); + } + } + + const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); + const bool isInvalidConstructor = metaFunction->isConstructor() + && ((metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction) + || metaFunction->isInvalid()); + if ((isInvalidDestructor || isInvalidConstructor) + && !metaClass->hasNonPrivateConstructor()) { + *metaClass += AbstractMetaAttributes::Final; + } else if (metaFunction->isConstructor() && !metaFunction->isPrivate()) { + *metaClass -= AbstractMetaAttributes::Final; + metaClass->setHasNonPrivateConstructor(true); + } + + // Classes with virtual destructors should always have a shell class + // (since we aren't registering the destructors, we need this extra check) + if (metaFunction->isDestructor() && !metaFunction->isFinal()) + metaClass->setForceShellClass(true); + + if (!metaFunction->isDestructor() + && !metaFunction->isInvalid() + && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { + + setupFunctionDefaults(metaFunction, metaClass); + + if (metaFunction->isSignal() && metaClass->hasSignal(metaFunction)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("signal '%1' in class '%2' is overloaded.") + .arg(metaFunction->name(), metaClass->name()); + } + + if (metaFunction->isSignal() && !metaClass->isQObject()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("signal '%1' in non-QObject class '%2'") + .arg(metaFunction->name(), metaClass->name()); + } + + if (metaFunction->isConversionOperator()) + fixReturnTypeOfConversionOperator(metaFunction); + + metaClass->addFunction(metaFunction); + applyFunctionModifications(metaFunction); + } else if (metaFunction->isDestructor()) { + metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); + metaClass->setHasProtectedDestructor(metaFunction->isProtected()); + metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); + } + if (!metaFunction->ownerClass()) { + delete metaFunction; + metaFunction = 0; + } + } + + fillAddedFunctions(metaClass); +} + +void AbstractMetaBuilderPrivate::fillAddedFunctions(AbstractMetaClass *metaClass) +{ + // Add the functions added by the typesystem + const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions(); + for (const AddedFunction &addedFunc : addedFunctions) + traverseFunction(addedFunc, metaClass); +} + +void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func) +{ + const FunctionModificationList &mods = func->modifications(func->implementingClass()); + AbstractMetaFunction& funcRef = *func; + for (const FunctionModification &mod : mods) { + if (mod.isRenameModifier()) { + func->setOriginalName(func->name()); + func->setName(mod.renamedTo()); + } else if (mod.isAccessModifier()) { + funcRef -= AbstractMetaAttributes::Public; + funcRef -= AbstractMetaAttributes::Protected; + funcRef -= AbstractMetaAttributes::Private; + funcRef -= AbstractMetaAttributes::Friendly; + + if (mod.isPublic()) + funcRef += AbstractMetaAttributes::Public; + else if (mod.isProtected()) + funcRef += AbstractMetaAttributes::Protected; + else if (mod.isPrivate()) + funcRef += AbstractMetaAttributes::Private; + else if (mod.isFriendly()) + funcRef += AbstractMetaAttributes::Friendly; + } + + if (mod.isFinal()) + funcRef += AbstractMetaAttributes::FinalInTargetLang; + else if (mod.isNonFinal()) + funcRef -= AbstractMetaAttributes::FinalInTargetLang; + } +} + +bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass) +{ + Q_ASSERT(!metaClass->isInterface()); + + if (m_setupInheritanceDone.contains(metaClass)) + return true; + + m_setupInheritanceDone.insert(metaClass); + + QStringList baseClasses = metaClass->baseClassNames(); + + // we only support our own containers and ONLY if there is only one baseclass + if (baseClasses.size() == 1 && baseClasses.first().contains(QLatin1Char('<'))) { + TypeParser::Info info; + ComplexTypeEntry* baseContainerType; + AbstractMetaClass* templ = findTemplateClass(baseClasses.first(), metaClass, &info, &baseContainerType); + if (templ) { + setupInheritance(templ); + inheritTemplate(metaClass, templ, info); + metaClass->typeEntry()->setBaseContainerType(templ->typeEntry()); + return true; + } + + if (baseContainerType) { + // Container types are not necessarily wrapped as 'real' classes, + // but there may still be classes derived from them. In such case, + // we still need to set the base container type in order to + // generate correct code for type conversion checking. + // + // Additionally, we consider this case as successfully setting up + // inheritance. + metaClass->typeEntry()->setBaseContainerType(baseContainerType); + return true; + } + + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("template baseclass '%1' of '%2' is not known") + .arg(baseClasses.first(), metaClass->name()); + return false; + } + + TypeDatabase* types = TypeDatabase::instance(); + + int primary = -1; + int primaries = 0; + for (int i = 0; i < baseClasses.size(); ++i) { + + if (types->isClassRejected(baseClasses.at(i))) + continue; + + TypeEntry* baseClassEntry = types->findType(baseClasses.at(i)); + if (!baseClassEntry) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("class '%1' inherits from unknown base class '%2'") + .arg(metaClass->name(), baseClasses.at(i)); + } else if (!baseClassEntry->designatedInterface()) { // true for primary base class + primaries++; + primary = i; + } + } + + if (primary >= 0) { + AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary)); + if (!baseClass) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("unknown baseclass for '%1': '%2'") + .arg(metaClass->name(), baseClasses.at(primary)); + return false; + } + metaClass->setBaseClass(baseClass); + } + + for (int i = 0; i < baseClasses.size(); ++i) { + if (types->isClassRejected(baseClasses.at(i))) + continue; + + if (i != primary) { + AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i)); + if (!baseClass) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i)); + return false; + } + + setupInheritance(baseClass); + + QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name(); + AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName); + if (!iface) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName); + return false; + } + metaClass->addInterface(iface); + + const AbstractMetaClassList &interfaces = iface->interfaces(); + for (AbstractMetaClass* iface : interfaces) + metaClass->addInterface(iface); + } + } + + return true; +} + +void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem, + AbstractMetaClass *metaClass, + const QStringList &enumsDeclarations) +{ + const EnumList &enums = scopeItem->enums(); + for (const EnumModelItem &enumItem : enums) { + AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet::fromList(enumsDeclarations)); + if (metaEnum) { + metaClass->addEnum(metaEnum); + metaEnum->setEnclosingClass(metaClass); + } + } +} + +AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc) +{ + return traverseFunction(addedFunc, 0); +} + +AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFunction& addedFunc, + AbstractMetaClass *metaClass) +{ + AbstractMetaFunction *metaFunction = q->createMetaFunction(); + metaFunction->setConstant(addedFunc.isConstant()); + metaFunction->setName(addedFunc.name()); + metaFunction->setOriginalName(addedFunc.name()); + AbstractMetaClass::Attributes visibility = + addedFunc.access() == AddedFunction::Public + ? AbstractMetaAttributes::Public : AbstractMetaAttributes::Protected; + metaFunction->setVisibility(visibility); + metaFunction->setUserAdded(true); + AbstractMetaAttributes::Attribute isStatic = addedFunc.isStatic() ? AbstractMetaFunction::Static : AbstractMetaFunction::None; + metaFunction->setAttributes(metaFunction->attributes() | AbstractMetaAttributes::Final | isStatic); + metaFunction->setType(translateType(addedFunc.version(), addedFunc.returnType())); + + + QVector args = addedFunc.arguments(); + AbstractMetaArgumentList metaArguments; + + for (int i = 0; i < args.count(); ++i) { + AddedFunction::TypeInfo& typeInfo = args[i]; + AbstractMetaArgument *metaArg = q->createMetaArgument(); + AbstractMetaType* type = translateType(addedFunc.version(), typeInfo); + decideUsagePattern(type); + metaArg->setType(type); + metaArg->setArgumentIndex(i); + metaArg->setDefaultValueExpression(typeInfo.defaultValue); + metaArg->setOriginalDefaultValueExpression(typeInfo.defaultValue); + metaArguments.append(metaArg); + } + + metaFunction->setArguments(metaArguments); + if (metaFunction->isOperatorOverload() && !metaFunction->isCallOperator()) { + if (metaArguments.size() > 2) { + qCWarning(lcShiboken) << "An operator overload need to have 0, 1 or 2 arguments if it's reverse."; + } else if (metaArguments.size() == 2) { + // Check if it's a reverse operator + if (metaArguments[1]->type()->typeEntry() == metaClass->typeEntry()) { + metaFunction->setReverseOperator(true); + // we need to call these two function to cache the old signature (with two args) + // we do this buggy behaviour to comply with the original apiextractor buggy behaviour. + metaFunction->signature(); + metaFunction->minimalSignature(); + metaArguments.removeLast(); + metaFunction->setArguments(metaArguments); + } else { + qCWarning(lcShiboken) << "Operator overload can have two arguments only if it's a reverse operator!"; + } + } + } + + + // Find the correct default values + for (int i = 0; i < metaArguments.size(); ++i) { + AbstractMetaArgument* metaArg = metaArguments.at(i); + + //use relace-default-expression for set default value + QString replacedExpression; + if (m_currentClass) + replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); + + if (!replacedExpression.isEmpty()) { + QString expr = replacedExpression; + if (!metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { + metaArg->setDefaultValueExpression(expr); + metaArg->setOriginalDefaultValueExpression(expr); + + if (metaArg->type()->isEnum() || metaArg->type()->isFlags()) + m_enumDefaultArguments << QPair(metaArg, metaFunction); + } + } + } + + metaFunction->setOriginalAttributes(metaFunction->attributes()); + fixArgumentNames(metaFunction); + + if (metaClass) { + const AbstractMetaArgumentList fargs = metaFunction->arguments(); + if (metaClass->isNamespace()) + *metaFunction += AbstractMetaFunction::Static; + if (metaFunction->name() == metaClass->name()) { + metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); + if (fargs.size() == 1) { + const TypeEntry *te = fargs.first()->type()->typeEntry(); + if (te->isCustom()) + metaFunction->setExplicit(true); + if (te->name() == metaFunction->name()) + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + } + } else { + metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); + } + + metaFunction->setDeclaringClass(metaClass); + metaFunction->setImplementingClass(metaClass); + metaClass->addFunction(metaFunction); + metaClass->setHasNonPrivateConstructor(true); + } + + return metaFunction; +} + +void AbstractMetaBuilderPrivate::fixArgumentNames(AbstractMetaFunction *func) +{ + if (func->arguments().isEmpty()) + return; + const FunctionModificationList &mods = func->modifications(m_currentClass); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (!argMod.renamed_to.isEmpty()) { + AbstractMetaArgument* arg = func->arguments().at(argMod.index - 1); + arg->setOriginalName(arg->name()); + arg->setName(argMod.renamed_to, false); + } + } + } + + AbstractMetaArgumentList arguments = func->arguments(); + for (int i = 0, size = arguments.size(); i < size; ++i) { + if (arguments.at(i)->name().isEmpty()) + arguments[i]->setName(QLatin1String("arg__") + QString::number(i + 1), false); + } +} + +static QString functionSignature(FunctionModelItem functionItem) +{ + QStringList args; + const ArgumentList &arguments = functionItem->arguments(); + for (const ArgumentModelItem &arg : arguments) + args << arg->type().toString(); + return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')'); +} + +static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem &functionItem, + const QString &className = QString()) +{ + QString result = functionItem->type().toString() + QLatin1Char(' '); + if (!className.isEmpty()) + result += className + colonColon(); + result += functionSignature(functionItem); + return result; +} + +static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n) +{ + QString result; + QTextStream str(&result); + str << "unmatched type '" << arg->type().toString() << "' in parameter #" + << (n + 1); + if (!arg->name().isEmpty()) + str << " \"" << arg->name() << '"'; + return result; +} + +static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n) +{ + QString result; + QTextStream str(&result); + str << "'void' encountered at parameter #" << (n + 1); + if (!arg->name().isEmpty()) + str << " \"" << arg->name() << '"'; + return result; +} + +AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem) +{ + if (!functionItem->templateParameters().isEmpty()) + return nullptr; + QString functionName = functionItem->name(); + QString className; + if (m_currentClass) { + // Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT + // and overridden metaObject(), QGADGET helpers + if (functionName == QLatin1String("qt_check_for_QGADGET_macro") + || functionName.startsWith(QLatin1String("qt_meta"))) { + return nullptr; + } + className = m_currentClass->typeEntry()->qualifiedCppName(); + if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject")) + return nullptr; + } + + // 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); + return 0; + } + else if (TypeDatabase::instance()->isFunctionRejected(className, + functionSignature(functionItem), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + return 0; + } + + Q_ASSERT(functionItem->functionType() == CodeModel::Normal + || functionItem->functionType() == CodeModel::Signal + || functionItem->functionType() == CodeModel::Slot); + + if (functionItem->isFriend()) + return 0; + + AbstractMetaFunction *metaFunction = q->createMetaFunction(); + metaFunction->setConstant(functionItem->isConstant()); + + if (ReportHandler::isDebug(ReportHandler::MediumDebug)) + qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()"; + + metaFunction->setName(functionName); + metaFunction->setOriginalName(functionItem->name()); + + if (functionItem->isAbstract()) + *metaFunction += AbstractMetaAttributes::Abstract; + + if (!metaFunction->isAbstract()) + *metaFunction += AbstractMetaAttributes::Native; + + if (!functionItem->isVirtual()) + *metaFunction += AbstractMetaAttributes::Final; + + if (functionItem->isInvokable()) + *metaFunction += AbstractMetaAttributes::Invokable; + + if (functionItem->isStatic()) { + *metaFunction += AbstractMetaAttributes::Static; + *metaFunction += AbstractMetaAttributes::Final; + } + + // Access rights + if (functionItem->accessPolicy() == CodeModel::Public) + *metaFunction += AbstractMetaAttributes::Public; + else if (functionItem->accessPolicy() == CodeModel::Private) + *metaFunction += AbstractMetaAttributes::Private; + else + *metaFunction += AbstractMetaAttributes::Protected; + + + QString strippedClassName = className; + int cc_pos = strippedClassName.lastIndexOf(colonColon()); + if (cc_pos > 0) + strippedClassName = strippedClassName.mid(cc_pos + 2); + + TypeInfo functionType = functionItem->type(); + + if (TypeDatabase::instance()->isReturnTypeRejected(className, functionType.toString(), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + delete metaFunction; + return nullptr; + } + + if (functionName.startsWith(QLatin1Char('~'))) { + metaFunction->setFunctionType(AbstractMetaFunction::DestructorFunction); + metaFunction->setInvalid(true); + } else if (stripTemplateArgs(functionName) == strippedClassName) { + metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); + // Check for Copy/Move down below + metaFunction->setExplicit(functionItem->isExplicit()); + metaFunction->setName(m_currentClass->name()); + } else { + bool ok; + AbstractMetaType* type = translateType(functionType, &ok); + + if (!ok) { + Q_ASSERT(type == 0); + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("skipping function '%1', unmatched return type '%2'") + .arg(originalQualifiedSignatureWithReturn, + functionItem->type().toString()); + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType); + metaFunction->setInvalid(true); + return metaFunction; + } + + metaFunction->setType(type); + + if (functionItem->functionType() == CodeModel::Signal) + metaFunction->setFunctionType(AbstractMetaFunction::SignalFunction); + else if (functionItem->functionType() == CodeModel::Slot) + metaFunction->setFunctionType(AbstractMetaFunction::SlotFunction); + } + + ArgumentList arguments = functionItem->arguments(); + + if (arguments.size() == 1) { + ArgumentModelItem arg = arguments.at(0); + TypeInfo type = arg->type(); + if (type.qualifiedName().first() == QLatin1String("void") && type.indirections() == 0) + arguments.pop_front(); + } + + AbstractMetaArgumentList metaArguments; + + for (int i = 0; i < arguments.size(); ++i) { + ArgumentModelItem arg = arguments.at(i); + + if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) { + m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled); + delete metaFunction; + return nullptr; + } + + bool ok; + AbstractMetaType* metaType = translateType(arg->type(), &ok); + if (!ok) { + Q_ASSERT(metaType == 0); + const QString reason = msgUnmatchedParameterType(arg, i); + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("skipping function '%1', %2") + .arg(originalQualifiedSignatureWithReturn, reason); + const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn + + QLatin1String(": ") + reason; + m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); + metaFunction->setInvalid(true); + return metaFunction; + } + + if (metaType == Q_NULLPTR) { + const QString reason = msgVoidParameterType(arg, i); + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("skipping function '%1': %2") + .arg(originalQualifiedSignatureWithReturn, reason); + const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn + + QLatin1String(": ") + reason; + m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType); + metaFunction->setInvalid(true); + return metaFunction; + } + + AbstractMetaArgument *metaArgument = q->createMetaArgument(); + + metaArgument->setType(metaType); + metaArgument->setName(arg->name()); + metaArgument->setArgumentIndex(i); + metaArguments << metaArgument; + } + + metaFunction->setArguments(metaArguments); + + // Find the correct default values + for (int i = 0; i < arguments.size(); ++i) { + ArgumentModelItem arg = arguments.at(i); + AbstractMetaArgument* metaArg = metaArguments.at(i); + + //use relace-default-expression for set default value + QString replacedExpression; + if (m_currentClass) { + replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1); + } else { + FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature()); + if (!mods.isEmpty()) { + QVector argMods = mods.first().argument_mods; + if (!argMods.isEmpty()) + replacedExpression = argMods.first().replacedDefaultExpression; + } + } + + bool hasDefaultValue = false; + if (arg->defaultValue() || !replacedExpression.isEmpty()) { + QString expr = arg->defaultValueExpression(); + expr = fixDefaultValue(arg, metaArg->type(), metaFunction, m_currentClass, i); + metaArg->setOriginalDefaultValueExpression(expr); + + if (metaFunction->removedDefaultExpression(m_currentClass, i + 1)) { + expr.clear(); + } else if (!replacedExpression.isEmpty()) { + expr = replacedExpression; + } + metaArg->setDefaultValueExpression(expr); + + if (metaArg->type()->isEnum() || metaArg->type()->isFlags()) + m_enumDefaultArguments << QPair(metaArg, metaFunction); + + hasDefaultValue = !expr.isEmpty(); + } + + //Check for missing argument name + if (hasDefaultValue + && !metaArg->hasName() + && !metaFunction->isOperatorOverload() + && !metaFunction->isSignal() + && metaFunction->argumentName(i+1, false, m_currentClass).isEmpty()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Argument %1 on function '%2::%3' has default expression but does not have name.") + .arg(i+1).arg(className, metaFunction->minimalSignature()); + } + + } + + fixArgumentNames(metaFunction); + + // Determine class special functions + if (m_currentClass && metaFunction->arguments().size() == 1) { + const AbstractMetaType *argType = metaFunction->arguments().first()->type(); + if (argType->typeEntry() == m_currentClass->typeEntry() && argType->indirections() == 0) { + if (metaFunction->isConstructor()) { + switch (argType->referenceType()) { + case NoReference: + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + break; + case LValueReference: + if (argType->isConstant()) + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + break; + case RValueReference: + metaFunction->setFunctionType(AbstractMetaFunction::MoveConstructorFunction); + break; + } + } else if (metaFunction->name() == QLatin1String("operator=")) { + switch (argType->referenceType()) { + case NoReference: + metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); + break; + case LValueReference: + if (argType->isConstant()) + metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); + break; + case RValueReference: + metaFunction->setFunctionType(AbstractMetaFunction::MoveAssignmentOperatorFunction); + break; + } + } + } + } + return metaFunction; +} + +AbstractMetaType *AbstractMetaBuilderPrivate::translateType(double vr, + const AddedFunction::TypeInfo &typeInfo) +{ + Q_ASSERT(!typeInfo.name.isEmpty()); + TypeDatabase* typeDb = TypeDatabase::instance(); + TypeEntry* type; + + QString typeName = typeInfo.name; + + if (typeName == QLatin1String("void")) + return 0; + + type = typeDb->findType(typeName); + + // test if the type is a template, like a container + bool isTemplate = false; + QStringList templateArgs; + if (!type && typeInfo.name.contains(QLatin1Char('<'))) { + const QStringList& parsedType = parseTemplateType(typeInfo.name); + if (parsedType.isEmpty()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Template type parsing failed for '%1'").arg(typeInfo.name); + } else { + templateArgs = parsedType.mid(1); + isTemplate = (type = typeDb->findContainerType(parsedType[0])); + } + } + + if (!type) { + QStringList candidates; + SingleTypeEntryHash entries = typeDb->entries(); + for (SingleTypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { + // Let's try to find the type in different scopes. + if (it.key().endsWith(colonColon() + typeName)) + candidates.append(it.key()); + } + + QString msg = QStringLiteral("Type '%1' wasn't found in the type database.\n").arg(typeName); + + if (candidates.isEmpty()) + qFatal(qPrintable(QString(msg + QLatin1String("Declare it in the type system using the proper <*-type> tag."))), NULL); + + msg += QLatin1String("Remember to inform the full qualified name for the type you want to use.\nCandidates are:\n"); + candidates.sort(); + for (const QString& candidate : qAsConst(candidates)) { + msg += QLatin1String(" ") + candidate + QLatin1Char('\n'); + } + qFatal(qPrintable(msg), NULL); + } + + AbstractMetaType *metaType = q->createMetaType(); + metaType->setTypeEntry(type); + metaType->setIndirections(typeInfo.indirections); + if (typeInfo.isReference) + metaType->setReferenceType(LValueReference); + metaType->setConstant(typeInfo.isConstant); + if (isTemplate) { + for (const QString& templateArg : qAsConst(templateArgs)) { + AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg)); + metaType->addInstantiation(metaArgType); + } + metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); + } + + return metaType; +} + +static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName) +{ + const TypeEntry* type = 0; + QStringList context = metaClass->qualifiedCppName().split(colonColon()); + while(!type && (context.size() > 0) ) { + type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName); + context.removeLast(); + } + return type; +} + +AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, + bool *ok, bool resolveType, + bool resolveScope) +{ + Q_ASSERT(ok); + *ok = true; + + // 1. Test the type info without resolving typedefs in case this is present in the + // type system + TypeInfo typei; + if (resolveType) { + bool ok; + AbstractMetaType* t = translateType(_typei, &ok, false, resolveScope); + if (t && ok) + return t; + Q_ASSERT(t == 0); + } + + if (!resolveType) { + typei = _typei; + } else { + // Go through all parts of the current scope (including global namespace) + // to resolve typedefs. The parser does not properly resolve typedefs in + // 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 = m_scopes.size() - 1; + while (i >= 0) { + typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)); + if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon())) + break; + } + + } + + if (typei.isFunctionPointer()) { + *ok = false; + return 0; + } + + QString errorMessage; + TypeParser::Info typeInfo = TypeParser::parse(typei.toString(), &errorMessage); + if (typeInfo.is_busted) { + qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString() + << "\": " << errorMessage; + *ok = false; + return 0; + } + + // 2. Handle pointers specified as arrays with unspecified size + bool arrayOfUnspecifiedSize = false; + if (typeInfo.arrays.size() > 0) { + arrayOfUnspecifiedSize = true; + for (int i = 0; i < typeInfo.arrays.size(); ++i) + arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty(); + + if (!arrayOfUnspecifiedSize) { + TypeInfo newInfo; + //newInfo.setArguments(typei.arguments()); + newInfo.setIndirections(typei.indirections()); + newInfo.setConstant(typei.isConstant()); + newInfo.setFunctionPointer(typei.isFunctionPointer()); + newInfo.setQualifiedName(typei.qualifiedName()); + newInfo.setReferenceType(typei.referenceType()); + newInfo.setVolatile(typei.isVolatile()); + + AbstractMetaType* elementType = translateType(newInfo, ok); + if (!(*ok)) + return 0; + + for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) { + QString s = typeInfo.arrays.at(i); + bool _ok; + int elems = findOutValueFromString(s, _ok); + + AbstractMetaType *arrayType = q->createMetaType(); + arrayType->setArrayElementCount(elems); + arrayType->setArrayElementType(elementType); + arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); + decideUsagePattern(arrayType); + + elementType = arrayType; + } + + return elementType; + } else { + typeInfo.indirections += typeInfo.arrays.size(); + } + } + + QStringList qualifierList = typeInfo.qualified_name; + if (qualifierList.isEmpty()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("horribly broken type '%1'").arg(_typei.toString()); + *ok = false; + return 0; + } + + QString qualifiedName = qualifierList.join(colonColon()); + QString name = qualifierList.takeLast(); + + // 3. Special case 'void' type + if (name == QLatin1String("void") && !typeInfo.indirections) + return 0; + + // 4. Special case QFlags (include instantiation in name) + if (qualifiedName == QLatin1String("QFlags")) + qualifiedName = typeInfo.toString(); + + const TypeEntry *type = 0; + // 5. Try to find the type + + // 5.1 - Try first using the current scope + if (m_currentClass) { + type = findTypeEntryUsingContext(m_currentClass, qualifiedName); + + // 5.1.1 - Try using the class parents' scopes + if (!type && !m_currentClass->baseClassNames().isEmpty()) { + const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass); + for (const AbstractMetaClass *cls : baseClasses) { + type = findTypeEntryUsingContext(cls, qualifiedName); + if (type) + break; + } + } + } + + // 5.2 - Try without scope + if (!type) + type = TypeDatabase::instance()->findType(qualifiedName); + + // 6. No? Try looking it up as a flags type + if (!type) + type = TypeDatabase::instance()->findFlagsType(qualifiedName); + + // 7. No? Try looking it up as a container type + if (!type) + type = TypeDatabase::instance()->findContainerType(name); + + // 8. No? Check if the current class is a template and this type is one + // of the parameters. + if (!type && m_currentClass) { + const QVector &template_args = m_currentClass->templateArguments(); + for (TypeEntry *te : template_args) { + if (te->name() == qualifiedName) + type = te; + } + } + + // 9. Try finding the type by prefixing it with the current + // context and all baseclasses of the current context + if (!type && !TypeDatabase::instance()->isClassRejected(qualifiedName) && m_currentClass && resolveScope) { + QStringList contexts; + contexts.append(m_currentClass->qualifiedCppName()); + contexts.append(currentScope()->qualifiedName().join(colonColon())); + + + TypeInfo info = typei; + bool subclassesDone = false; + while (!contexts.isEmpty() && !type) { + type = TypeDatabase::instance()->findType(contexts.at(0) + colonColon() + qualifiedName); + contexts.pop_front(); + + // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so + // enum types from there may be addressed without any scope resolution in properties. + if (!contexts.size() && !subclassesDone) { + contexts << QLatin1String("Qt"); + subclassesDone = true; + } + } + + } + + if (!type) { + *ok = false; + return 0; + } + + // Used to for diagnostics later... + m_usedTypes << type; + + // These are only implicit and should not appear in code... + Q_ASSERT(!type->isInterface()); + + AbstractMetaType *metaType = q->createMetaType(); + metaType->setTypeEntry(type); + metaType->setIndirections(typeInfo.indirections); + metaType->setReferenceType(typeInfo.referenceType); + metaType->setConstant(typeInfo.is_constant); + metaType->setOriginalTypeDescription(_typei.toString()); + + for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) { + TypeInfo info; + info.setConstant(ta.is_constant); + info.setReferenceType(ta.referenceType); + info.setIndirections(ta.indirections); + + info.setFunctionPointer(false); + info.setQualifiedName(ta.instantiationName().split(colonColon())); + + AbstractMetaType* targType = translateType(info, ok); + if (!(*ok)) { + delete metaType; + return 0; + } + + metaType->addInstantiation(targType, true); + } + + // The usage pattern *must* be decided *after* the possible template + // instantiations have been determined, or else the absence of + // such instantiations will break the caching scheme of + // AbstractMetaType::cppSignature(). + decideUsagePattern(metaType); + + return metaType; +} + + +int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok) +{ + int value = stringValue.toInt(&ok); + if (ok) + return value; + + if (stringValue == QLatin1String("true") || stringValue == QLatin1String("false")) { + ok = true; + return (stringValue == QLatin1String("true")); + } + + // 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_]*$")); + Q_ASSERT(variableNameRegExp.isValid()); + if (!variableNameRegExp.match(stringValue).hasMatch()) { + ok = true; + return 0; + } + + AbstractMetaEnumValue *enumValue = AbstractMetaClass::findEnumValue(m_metaClasses, stringValue); + if (enumValue) { + ok = true; + return enumValue->value(); + } + + for (AbstractMetaEnum *metaEnum : qAsConst(m_globalEnums)) { + const AbstractMetaEnumValueList &values = metaEnum->values(); + for (const AbstractMetaEnumValue *ev : values) { + if (ev->name() == stringValue) { + ok = true; + return ev->value(); + } + } + } + + ok = false; + return 0; +} + +void AbstractMetaBuilderPrivate::decideUsagePattern(AbstractMetaType *metaType) +{ + metaType->decideUsagePattern(); +} + +QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item, + AbstractMetaType *type, + AbstractMetaFunction *fnc, + AbstractMetaClass *implementingClass, + int /* argumentIndex */) +{ + QString functionName = fnc->name(); + QString className = implementingClass ? implementingClass->qualifiedCppName() : QString(); + + QString expr = item->defaultValueExpression(); + if (type) { + if (type->isPrimitive()) { + if (type->name() == QLatin1String("boolean")) { + if (expr != QLatin1String("false") && expr != QLatin1String("true")) { + bool ok = false; + int number = expr.toInt(&ok); + if (ok && number) + expr = QLatin1String("true"); + else + expr = QLatin1String("false"); + } + } else { + // This can be an enum or flag so I need to delay the + // translation untill all namespaces are completly + // processed. This is done in figureOutEnumValues() + } + } else if (type->isFlags() || type->isEnum()) { + bool isNumber; + expr.toInt(&isNumber); + if (!isNumber && expr.indexOf(colonColon()) < 0) { + // Add the enum/flag scope to default value, making it usable + // from other contexts beside its owner class hierarchy + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch match = typeRegEx.match(type->minimalSignature()); + if (match.hasMatch()) + expr.prepend(match.captured(1)); + } + } else if (type->isContainer() && expr.contains(QLatin1Char('<'))) { + static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); + static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + if (typeMatch.hasMatch() && defaultMatch.hasMatch()) + expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2); + } else { + // Here the default value is supposed to be a constructor, + // a class field, or a constructor receiving a class field + static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)")); + Q_ASSERT(defaultRegEx.isValid()); + const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr); + QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString(); + if (defaultValueCtorName.endsWith(QLatin1Char('('))) + defaultValueCtorName.chop(1); + + // Fix the scope for constructor using the already + // resolved argument type as a reference. + // The following regular expression extracts any + // use of namespaces/scopes from the type string. + static const QRegularExpression typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$")); + Q_ASSERT(typeRegEx.isValid()); + const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature()); + + QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString(); + QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString(); + if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName) + expr.prepend(typeNamespace); + + // Fix scope if the parameter is a field of the current class + if (implementingClass) { + const AbstractMetaFieldList &fields = implementingClass->fields(); + for (const AbstractMetaField *field : fields) { + if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field->name()) { + expr = defaultMatch.captured(1) + implementingClass->name() + + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3); + break; + } + } + } + } + } else { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("undefined type for default value '%3' of argument in function '%1', class '%2'") + .arg(functionName, className, item->defaultValueExpression()); + + expr = QString(); + } + + return expr; +} + +bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QString &qualifiedName) +{ + if (qualifiedName == QLatin1String("QObject")) + return true; + + ClassModelItem classItem = dom->findClass(qualifiedName); + + if (!classItem) { + QStringList names = qualifiedName.split(colonColon()); + NamespaceModelItem ns = dom; + for (int i = 0; i < names.size() - 1 && ns; ++i) + ns = ns->findNamespace(names.at(i)); + if (ns && names.size() >= 2) + classItem = ns->findClass(names.at(names.size() - 1)); + } + + bool isqobject = classItem && classItem->extendsClass(QLatin1String("QObject")); + + if (classItem && !isqobject) { + QStringList baseClasses = classItem->baseClasses(); + for (int i = 0; i < baseClasses.count(); ++i) { + + isqobject = isQObject(dom, baseClasses.at(i)); + if (isqobject) + break; + } + } + + return isqobject; +} + + +bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringList& qualified_name) +{ + CodeModelItem item = dom->model()->findItem(qualified_name, dom); + return item && item->kind() == _EnumModelItem::__node_kind; +} + +AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name, + const AbstractMetaClass *context, + TypeParser::Info *info, + ComplexTypeEntry **baseContainerType) const +{ + TypeParser::Info localInfo; + if (!info) + info = &localInfo; + + TypeDatabase* types = TypeDatabase::instance(); + + QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon()); + 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(); + QString completeName = prefix + name; + const TypeParser::Info parsed = TypeParser::parse(completeName, &errorMessage); + if (parsed.is_busted) { + qWarning().noquote().nospace() << "Unable to parse type \"" << completeName + << "\" while looking for template \"" << name << "\": " << errorMessage; + continue; + } + *info = parsed; + QString qualifiedName = info->qualified_name.join(colonColon()); + + AbstractMetaClass* templ = 0; + for (AbstractMetaClass *c : qAsConst(m_templates)) { + if (c->typeEntry()->name() == qualifiedName) { + templ = c; + break; + } + } + + if (!templ) + templ = AbstractMetaClass::findClass(m_metaClasses, qualifiedName); + + if (templ) + return templ; + + if (baseContainerType) + *baseContainerType = types->findContainerType(qualifiedName); + } + + return 0; +} + +AbstractMetaClassList AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const +{ + AbstractMetaClassList baseClasses; + const QStringList &baseClassNames = metaClass->baseClassNames(); + for (const QString& parent : baseClassNames) { + AbstractMetaClass* cls = 0; + if (parent.contains(QLatin1Char('<'))) + cls = findTemplateClass(parent, metaClass); + else + cls = AbstractMetaClass::findClass(m_metaClasses, parent); + + if (cls) + baseClasses << cls; + } + return baseClasses; +} + +bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const +{ + if (metaClass->hasPrivateCopyConstructor()) + return true; + const AbstractMetaClassList &baseClasses = getBaseClasses(metaClass); + for (const AbstractMetaClass *cls : baseClasses) { + if (ancestorHasPrivateCopyConstructor(cls)) + return true; + } + return false; +} + +AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector &templateTypes, + const AbstractMetaType *metaType, + bool *ok) +{ + if (ok) + *ok = true; + if (!metaType || (!metaType->typeEntry()->isTemplateArgument() && !metaType->hasInstantiations())) + return metaType ? metaType->copy() : 0; + + AbstractMetaType *returned = metaType->copy(); + returned->setOriginalTemplateType(metaType->copy()); + + if (returned->typeEntry()->isTemplateArgument()) { + const TemplateArgumentEntry* tae = static_cast(returned->typeEntry()); + + // If the template is intantiated with void we special case this as rejecting the functions that use this + // parameter from the instantiation. + if (templateTypes.size() <= tae->ordinal() || templateTypes.at(tae->ordinal())->typeEntry()->name() == QLatin1String("void")) { + if (ok) + *ok = false; + return 0; + } + + AbstractMetaType* t = returned->copy(); + t->setTypeEntry(templateTypes.at(tae->ordinal())->typeEntry()); + t->setIndirections(templateTypes.at(tae->ordinal())->indirections() + t->indirections() ? 1 : 0); + decideUsagePattern(t); + + delete returned; + returned = inheritTemplateType(templateTypes, t, ok); + if (ok && !(*ok)) + return 0; + } + + if (returned->hasInstantiations()) { + AbstractMetaTypeList instantiations = returned->instantiations(); + for (int i = 0; i < instantiations.count(); ++i) { + AbstractMetaType *type = instantiations[i]; + instantiations[i] = inheritTemplateType(templateTypes, type, ok); + if (ok && !(*ok)) + return 0; + } + returned->setInstantiations(instantiations, true); + } + + return returned; +} + +bool AbstractMetaBuilderPrivate::inheritTemplate(AbstractMetaClass *subclass, + const AbstractMetaClass *templateClass, + const TypeParser::Info &info) +{ + QVector targs = info.template_instantiations; + QVector templateTypes; + + if (subclass->isTypeDef()) { + subclass->setHasCloneOperator(templateClass->hasCloneOperator()); + subclass->setHasEqualsOperator(templateClass->hasEqualsOperator()); + subclass->setHasHashFunction(templateClass->hasHashFunction()); + subclass->setHasNonPrivateConstructor(templateClass->hasNonPrivateConstructor()); + subclass->setHasPrivateDestructor(templateClass->hasPrivateDestructor()); + subclass->setHasProtectedDestructor(templateClass->hasProtectedDestructor()); + subclass->setHasVirtualDestructor(templateClass->hasVirtualDestructor()); + } + + for (const TypeParser::Info &i : qAsConst(targs)) { + QString typeName = i.qualified_name.join(colonColon()); + QStringList possibleNames; + possibleNames << subclass->qualifiedCppName() + colonColon() + typeName; + possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName; + if (subclass->enclosingClass()) + possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName; + possibleNames << typeName; + + TypeDatabase* typeDb = TypeDatabase::instance(); + TypeEntry* t = 0; + QString templateParamName; + for (const QString &possibleName : qAsConst(possibleNames)) { + t = typeDb->findType(possibleName); + if (t) { + QString templateParamName = possibleName; + break; + } + } + + if (t) { + AbstractMetaType *temporaryType = q->createMetaType(); + temporaryType->setTypeEntry(t); + temporaryType->setConstant(i.is_constant); + temporaryType->setReferenceType(i.referenceType); + temporaryType->setIndirections(i.indirections); + temporaryType->decideUsagePattern(); + templateTypes << temporaryType; + } else { + qCWarning(lcShiboken).noquote().nospace() + << "Ignoring template parameter " << templateParamName << " from " + << info.instantiationName() << ", because I don't know what it is."; + } + } + + AbstractMetaFunctionList funcs = subclass->functions(); + const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions(); + for (const AbstractMetaFunction *function : templateClassFunctions) { + if (function->isModifiedRemoved(TypeSystem::All)) + continue; + + AbstractMetaFunction *f = function->copy(); + f->setArguments(AbstractMetaArgumentList()); + + bool ok = true; + AbstractMetaType *ftype = function->type(); + f->replaceType(inheritTemplateType(templateTypes, ftype, &ok)); + if (!ok) { + delete f; + continue; + } + + const AbstractMetaArgumentList &arguments = function->arguments(); + for (AbstractMetaArgument *argument : arguments) { + AbstractMetaType* atype = argument->type(); + + AbstractMetaArgument *arg = argument->copy(); + arg->replaceType(inheritTemplateType(templateTypes, atype, &ok)); + if (!ok) + break; + f->addArgument(arg); + } + + if (!ok) { + delete f; + continue; + } + + // There is no base class in the target language to inherit from here, so + // the template instantiation is the class that implements the function. + f->setImplementingClass(subclass); + + // We also set it as the declaring class, since the superclass is + // supposed to disappear. This allows us to make certain function modifications + // on the inherited functions. + f->setDeclaringClass(subclass); + + + if (f->isConstructor() && subclass->isTypeDef()) { + f->setName(subclass->name()); + f->setOriginalName(subclass->name()); + } else if (f->isConstructor()) { + delete f; + continue; + } + + // if the instantiation has a function named the same as an existing + // function we have shadowing so we need to skip it. + bool found = false; + for (int i = 0; i < funcs.size(); ++i) { + if (funcs.at(i)->name() == f->name()) { + found = true; + continue; + } + } + if (found) { + delete f; + continue; + } + + ComplexTypeEntry* te = subclass->typeEntry(); + FunctionModificationList mods = function->modifications(templateClass); + for (int i = 0; i < mods.size(); ++i) { + FunctionModification mod = mods.at(i); + mod.signature = f->minimalSignature(); + + // If we ever need it... Below is the code to do + // substitution of the template instantation type inside + // injected code.. +#if 0 + if (mod.modifiers & Modification::CodeInjection) { + for (int j = 0; j < template_types.size(); ++j) { + CodeSnip &snip = mod.snips.last(); + QString code = snip.code(); + code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j), + template_types.at(j)->typeEntry()->qualifiedCppName()); + snip.codeList.clear(); + snip.addCode(code); + } + } +#endif + te->addFunctionModification(mod); + } + + subclass->addFunction(f); + } + + subclass->setTemplateBaseClass(templateClass); + subclass->setTemplateBaseClassInstantiations(templateTypes); + subclass->setInterfaces(templateClass->interfaces()); + subclass->setBaseClass(templateClass->baseClass()); + + return true; +} + +void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass, + const QStringList &declarations) +{ + for (int i = 0; i < declarations.size(); ++i) { + QString p = declarations.at(i); + + QStringList l = p.split(QLatin1String(" ")); + + + QStringList qualifiedScopeName = currentScope()->qualifiedName(); + bool ok = false; + AbstractMetaType* type = 0; + QString scope; + for (int j = qualifiedScopeName.size(); j >= 0; --j) { + scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join(colonColon()) + colonColon() : QString(); + TypeInfo info; + info.setQualifiedName((scope + l.at(0)).split(colonColon())); + + type = translateType(info, &ok); + if (type && ok) + break; + } + + if (!type || !ok) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Unable to decide type of property: '%1' in class '%2'") + .arg(l.at(0), metaClass->name()); + continue; + } + + QString typeName = scope + l.at(0); + + QPropertySpec* spec = new QPropertySpec(type->typeEntry()); + spec->setName(l.at(1)); + spec->setIndex(i); + + for (int pos = 2; pos + 1 < l.size(); pos += 2) { + if (l.at(pos) == QLatin1String("READ")) + spec->setRead(l.at(pos + 1)); + else if (l.at(pos) == QLatin1String("WRITE")) + spec->setWrite(l.at(pos + 1)); + else if (l.at(pos) == QLatin1String("DESIGNABLE")) + spec->setDesignable(l.at(pos + 1)); + else if (l.at(pos) == QLatin1String("RESET")) + spec->setReset(l.at(pos + 1)); + } + + metaClass->addPropertySpec(spec); + delete type; + } +} + +static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls) +{ + AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible); + functions << cls->queryFunctions(AbstractMetaClass::Visible); + + for (AbstractMetaFunction *f : qAsConst(functions)) { + const AbstractMetaFunction::FunctionType t = f->functionType(); + if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction) + return f; + } + return 0; +} + +void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls) +{ + bool result = true; + + // find copy ctor for the current class + AbstractMetaFunction* copyCtor = findCopyCtor(cls); + if (copyCtor) { // if exists a copy ctor in this class + result = copyCtor->isPublic(); + } else { // else... lets find one in the parent class + QQueue baseClasses; + if (cls->baseClass()) + baseClasses.enqueue(cls->baseClass()); + baseClasses << cls->interfaces().toList(); + + while (!baseClasses.isEmpty()) { + AbstractMetaClass* currentClass = baseClasses.dequeue(); + baseClasses << currentClass->interfaces().toList(); + if (currentClass->baseClass()) + baseClasses.enqueue(currentClass->baseClass()); + + copyCtor = findCopyCtor(currentClass); + if (copyCtor) { + result = copyCtor->isPublic(); + break; + } + } + } + cls->setHasCloneOperator(result); +} + +void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls) +{ + const AbstractMetaFunctionList &convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp); + for (AbstractMetaFunction *func : convOps) { + if (func->isModifiedRemoved()) + continue; + AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type()->typeEntry()); + if (!metaClass) + continue; + metaClass->addExternalConversionOperator(func); + } + const AbstractMetaClassList &innerClasses = cls->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) + setupExternalConversion(innerClass); +} + +static void writeRejectLogFile(const QString &name, + const QMap &rejects) +{ + QFile f(name); + if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("failed to write log file: '%1'") + .arg(QDir::toNativeSeparators(f.fileName())); + return; + } + + QTextStream s(&f); + + + for (int reason = 0; reason < AbstractMetaBuilder::NoReason; ++reason) { + s << QString(72, QLatin1Char('*')) << endl; + 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; + + default: + s << "unknown reason"; + break; + } + + s << endl; + + for (QMap::const_iterator it = rejects.constBegin(); + it != rejects.constEnd(); ++it) { + if (it.value() != reason) + continue; + s << " - " << it.key() << endl; + } + + s << QString(72, QLatin1Char('*')) << endl << endl; + } + +} + +void AbstractMetaBuilderPrivate::dumpLog() const +{ + writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_classes.log"), m_rejectedClasses); + writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_enums.log"), m_rejectedEnums); + writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_functions.log"), m_rejectedFunctions); + writeRejectLogFile(m_logDirectory + QLatin1String("mjb_rejected_fields.log"), m_rejectedFields); +} + +AbstractMetaClassList AbstractMetaBuilderPrivate::classesTopologicalSorted(const AbstractMetaClass *cppClass, + const Dependencies &additionalDependencies) const +{ + QLinkedList unmappedResult; + QHash map; + QHash reverseMap; + + const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses; + + int i = 0; + for (AbstractMetaClass *clazz : classList) { + if (map.contains(clazz->qualifiedCppName())) + continue; + map[clazz->qualifiedCppName()] = i; + reverseMap[i] = clazz; + i++; + } + + Graph graph(map.count()); + + for (const Dependency &dep : additionalDependencies) { + const int parentIndex = map.value(dep.parent, -1); + const int childIndex = map.value(dep.child, -1); + if (parentIndex >= 0 && childIndex >= 0) { + graph.addEdge(parentIndex, childIndex); + } else { + qCWarning(lcShiboken).noquote().nospace() + << "AbstractMetaBuilder::classesTopologicalSorted(): Invalid additional dependency: " + << dep.child << " -> " << dep.parent << '.'; + } + } + + // TODO choose a better name to these regexs + static const QRegularExpression regex1(QStringLiteral("\\(.*\\)")); + Q_ASSERT(regex1.isValid()); + static const QRegularExpression regex2(QStringLiteral("::.*")); + Q_ASSERT(regex2.isValid()); + for (AbstractMetaClass *clazz : classList) { + if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName())) + graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]); + + const AbstractMetaClassList &bases = getBaseClasses(clazz); + for (AbstractMetaClass *baseClass : bases) { + // Fix polymorphic expression + if (clazz->baseClass() == baseClass) + clazz->setBaseClass(baseClass); + + if (map.contains(baseClass->qualifiedCppName())) + graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]); + } + + const AbstractMetaFunctionList &functions = clazz->functions(); + for (AbstractMetaFunction *func : functions) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + // check methods with default args + QString defaultExpression = arg->originalDefaultValueExpression(); + if (!defaultExpression.isEmpty()) { + if (defaultExpression == QLatin1String("0") && arg->type()->isValue()) + defaultExpression = arg->type()->name(); + + defaultExpression.remove(regex1); + defaultExpression.remove(regex2); + } + if (!defaultExpression.isEmpty()) { + QString exprClassName = clazz->qualifiedCppName() + colonColon() + defaultExpression; + if (!map.contains(exprClassName)) { + bool found = false; + for (AbstractMetaClass *baseClass : bases) { + exprClassName = baseClass->qualifiedCppName() + colonColon() + defaultExpression; + if (map.contains(exprClassName)) { + found = true; + break; + } + } + if (!found) { + if (map.contains(defaultExpression)) + exprClassName = defaultExpression; + else + exprClassName.clear(); + } + } + if (!exprClassName.isEmpty() && exprClassName != clazz->qualifiedCppName()) + graph.addEdge(map[exprClassName], map[clazz->qualifiedCppName()]); + } + } + } + } + + AbstractMetaClassList result; + unmappedResult = graph.topologicalSort(); + if (unmappedResult.isEmpty() && graph.nodeCount()) { + QTemporaryFile tempFile; + tempFile.setAutoRemove(false); + tempFile.open(); + QHash hash; + QHash::iterator it = map.begin(); + for (; it != map.end(); ++it) + hash[it.value()] = it.key(); + graph.dumpDot(hash, tempFile.fileName()); + qCWarning(lcShiboken).noquote().nospace() + << "Cyclic dependency found! Graph can be found at " + << QDir::toNativeSeparators(tempFile.fileName()); + } else { + for (int i : qAsConst(unmappedResult)) { + Q_ASSERT(reverseMap.contains(i)); + if (!reverseMap[i]->isInterface()) + result << reverseMap[i]; + } + } + + return result; +} + +AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClass *cppClass, + const Dependencies &additionalDependencies) const +{ + return d->classesTopologicalSorted(cppClass, additionalDependencies); +} + +AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractMetaArgumentList &list) +{ + AbstractMetaArgumentList ret; + + int index = list.size(); + for (AbstractMetaArgument *arg : list) { + arg->setArgumentIndex(index); + ret.prepend(arg); + index--; + } + + return ret; +} + +void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader) +{ + d->m_globalHeader = QFileInfo(globalHeader); +} + +void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const +{ + QFileInfo info(fileName); + if (m_globalHeader.fileName() != info.fileName()) + te->setInclude(Include(Include::IncludePath, info.fileName())); +} + +#ifndef QT_NO_DEBUG_STREAM +template +static void debugFormatSequence(QDebug &d, const char *key, const Container& c, + const char *separator = ", ") +{ + typedef typename Container::const_iterator ConstIt; + if (c.isEmpty()) + return; + const ConstIt begin = c.begin(); + const ConstIt end = c.end(); + d << "\n " << key << '[' << c.size() << "]=("; + for (ConstIt it = begin; it != end; ++it) { + if (it != begin) + d << separator; + d << *it; + } + d << ')'; +} + +void AbstractMetaBuilder::formatDebug(QDebug &debug) const +{ + debug << "m_globalHeader=" << d->m_globalHeader.absoluteFilePath(); + debugFormatSequence(debug, "qtMetaTypeDeclaredTypeNames", d->m_qmetatypeDeclaredTypenames); + debugFormatSequence(debug, "globalEnums", d->m_globalEnums, "\n"); + debugFormatSequence(debug, "globalFunctions", d->m_globalFunctions, "\n"); + if (const int scopeCount = d->m_scopes.size()) { + debug << "\n scopes[" << scopeCount << "]=("; + for (int i = 0; i < scopeCount; ++i) { + if (i) + debug << ", "; + _CodeModelItem::formatKind(debug, d->m_scopes.at(i)->kind()); + debug << " \"" << d->m_scopes.at(i)->name() << '"'; + } + debug << ')'; + } + debugFormatSequence(debug, "classes", d->m_metaClasses, "\n"); + debugFormatSequence(debug, "templates", d->m_templates, "\n"); +} + +QDebug operator<<(QDebug d, const AbstractMetaBuilder &ab) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaBuilder("; + ab.formatDebug(d); + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h new file mode 100644 index 000000000..f7427d488 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACTMETABUILDER_H +#define ABSTRACTMETABUILDER_H + +#include "abstractmetalang_typedefs.h" +#include "dependency.h" + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +class AbstractMetaBuilderPrivate; +class AbstractMetaClass; +class AbstractMetaEnumValue; + +class AbstractMetaBuilder +{ +public: + enum RejectReason { + NotInTypeSystem, + GenerationDisabled, + RedefinedToNotClass, + UnmatchedArgumentType, + UnmatchedReturnType, + ApiIncompatible, + NoReason + }; + + AbstractMetaBuilder(); + virtual ~AbstractMetaBuilder(); + + AbstractMetaClassList classes() const; + AbstractMetaClassList templates() const; + AbstractMetaClassList smartPointers() const; + AbstractMetaFunctionList globalFunctions() const; + AbstractMetaEnumList globalEnums() const; + // QtScript + QSet qtMetaTypeDeclaredTypeNames() const; + + /** + * Sorts a list of classes topologically, if an AbstractMetaClass object + * is passed the list of classes will be its inner classes, otherwise + * the list will be the module global classes. + * \return a list of classes sorted topologically + */ + AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, + const Dependencies &additionalDependencies = Dependencies()) const; + + bool build(const QByteArrayList &arguments, unsigned clangFlags = 0); + void setLogDirectory(const QString& logDir); + + /** + * AbstractMetaBuilder should know what's the global header being used, + * so any class declared under this header wont have the include file + * filled. + */ + void setGlobalHeader(const QString& globalHeader); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const; +#endif + +protected: + virtual AbstractMetaClass *createMetaClass(); + virtual AbstractMetaEnum *createMetaEnum(); + virtual AbstractMetaEnumValue *createMetaEnumValue(); + virtual AbstractMetaField *createMetaField(); + virtual AbstractMetaFunction *createMetaFunction(); + virtual AbstractMetaArgument *createMetaArgument(); + virtual AbstractMetaType *createMetaType(); + +private: + friend class AbstractMetaBuilderPrivate; + AbstractMetaBuilderPrivate *d; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaBuilder &ab); +#endif + +#endif // ABSTRACTMETBUILDER_H diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h new file mode 100644 index 000000000..96a6fdbfd --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACTMETABUILDER_P_H +#define ABSTRACTMETABUILDER_P_H + +#include "abstractmetabuilder.h" +#include "parser/codemodel_fwd.h" +#include "abstractmetalang.h" +#include "typesystem.h" +#include "typeparser.h" + +#include +#include + +class TypeDatabase; + +class AbstractMetaBuilderPrivate +{ +public: + AbstractMetaBuilderPrivate(); + ~AbstractMetaBuilderPrivate(); + + static FileModelItem buildDom(const QByteArrayList &arguments, unsigned clangFlags); + void traverseDom(const FileModelItem &dom); + + void dumpLog() const; + AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR, + const Dependencies &additionalDependencies = Dependencies()) const; + ScopeModelItem popScope() { return m_scopes.takeLast(); } + + void pushScope(ScopeModelItem item) { m_scopes << item; } + + ScopeModelItem currentScope() const { return m_scopes.last(); } + + AbstractMetaClass *argumentToClass(ArgumentModelItem); + + void figureOutEnumValuesForClass(AbstractMetaClass *metaClass, QSet *classes); + int figureOutEnumValue(const QString &name, int value, AbstractMetaEnum *meta_enum, AbstractMetaFunction *metaFunction = 0); + void figureOutEnumValues(); + void figureOutDefaultEnumArguments(); + + void addAbstractMetaClass(AbstractMetaClass *cls); + AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, + const TypeDefModelItem &typeDef); + AbstractMetaClass *traverseClass(const FileModelItem &dom, + const ClassModelItem &item); + AbstractMetaClass *currentTraversedClass(ScopeModelItem item); + void traverseScopeMembers(ScopeModelItem item, AbstractMetaClass *metaClass); + void traverseClassMembers(ClassModelItem scopeItem); + void traverseNamespaceMembers(NamespaceModelItem scopeItem); + bool setupInheritance(AbstractMetaClass *metaClass); + AbstractMetaClass *traverseNamespace(const FileModelItem &dom, + const NamespaceModelItem &item); + AbstractMetaEnum *traverseEnum(EnumModelItem item, AbstractMetaClass *enclosing, + const QSet &enumsDeclarations); + void traverseEnums(ScopeModelItem item, AbstractMetaClass *parent, + const QStringList &enumsDeclarations); + AbstractMetaFunctionList classFunctionList(const ScopeModelItem &scopeItem); + AbstractMetaFunctionList templateClassFunctionList(const ScopeModelItem &scopeItem, + AbstractMetaClass *metaClass); + void traverseFunctions(ScopeModelItem item, AbstractMetaClass *parent); + void applyFunctionModifications(AbstractMetaFunction* func); + void traverseFields(ScopeModelItem item, AbstractMetaClass *parent); + void traverseStreamOperator(FunctionModelItem functionItem); + void traverseOperatorFunction(FunctionModelItem item); + AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc); + AbstractMetaFunction* traverseFunction(const AddedFunction &addedFunc, + AbstractMetaClass *metaClass); + AbstractMetaFunction *traverseFunction(FunctionModelItem function); + AbstractMetaField *traverseField(VariableModelItem field, + const AbstractMetaClass *cls); + void checkFunctionModifications(); + void registerHashFunction(FunctionModelItem functionItem); + void registerToStringCapability(FunctionModelItem functionItem); + + /** + * A conversion operator function should not have its owner class as + * its return type, but unfortunately it does. This function fixes the + * return type of operator functions of this kind making the return type + * be the same as it is supposed to generate when used in C++. + * If the returned type is a wrapped C++ class, this method also adds the + * conversion operator to the collection of external conversions of the + * said class. + * \param metaFunction conversion operator function to be fixed. + */ + void fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction); + + void parseQ_Property(AbstractMetaClass *metaClass, const QStringList &declarations); + void setupEquals(AbstractMetaClass *metaClass); + void setupComparable(AbstractMetaClass *metaClass); + void setupClonable(AbstractMetaClass *cls); + void setupExternalConversion(AbstractMetaClass *cls); + void setupFunctionDefaults(AbstractMetaFunction *metaFunction, + AbstractMetaClass *metaClass); + + QString fixDefaultValue(ArgumentModelItem item, AbstractMetaType *type, + AbstractMetaFunction *fnc, AbstractMetaClass *, + int argumentIndex); + AbstractMetaType* translateType(double vr, const AddedFunction::TypeInfo &typeInfo); + AbstractMetaType *translateType(const TypeInfo &type, bool *ok, + bool resolveType = true, + bool resolveScope = true); + + int findOutValueFromString(const QString &stringValue, bool &ok); + + void decideUsagePattern(AbstractMetaType *type); + + AbstractMetaClass *findTemplateClass(const QString& name, const AbstractMetaClass *context, + TypeParser::Info *info = Q_NULLPTR, + ComplexTypeEntry **baseContainerType = Q_NULLPTR) const; + AbstractMetaClassList getBaseClasses(const AbstractMetaClass *metaClass) const; + bool ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const; + + bool inheritTemplate(AbstractMetaClass *subclass, + const AbstractMetaClass *templateClass, + const TypeParser::Info &info); + AbstractMetaType *inheritTemplateType(const QVector &templateTypes, + const AbstractMetaType *metaType, + bool *ok = Q_NULLPTR); + + bool isQObject(const FileModelItem &dom, const QString &qualifiedName); + bool isEnum(const FileModelItem &dom, const QStringList &qualifiedName); + + void fixQObjectForScope(const FileModelItem &dom, const TypeDatabase *types, + const NamespaceModelItem &item); + + void sortLists(); + AbstractMetaArgumentList reverseList(const AbstractMetaArgumentList &list); + void setInclude(TypeEntry *te, const QString &fileName) const; + void fixArgumentNames(AbstractMetaFunction *func); + void fillAddedFunctions(AbstractMetaClass *metaClass); + + AbstractMetaBuilder *q; + AbstractMetaClassList m_metaClasses; + AbstractMetaClassList m_templates; + AbstractMetaClassList m_smartPointers; + AbstractMetaFunctionList m_globalFunctions; + AbstractMetaEnumList m_globalEnums; + + QSet m_usedTypes; + + typedef QMap RejectMap; + + RejectMap m_rejectedClasses; + RejectMap m_rejectedEnums; + RejectMap m_rejectedFunctions; + RejectMap m_rejectedFields; + + QList m_enums; + + QList > m_enumDefaultArguments; + + QHash m_enumValues; + + AbstractMetaClass *m_currentClass; + QList m_scopes; + QString m_namespacePrefix; + + QSet m_setupInheritanceDone; + + // QtScript + QSet m_qmetatypeDeclaredTypenames; + + QString m_logDirectory; + QFileInfo m_globalHeader; +}; + +#endif // ABSTRACTMETBUILDER_P_H diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp new file mode 100644 index 000000000..4fa009fd2 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -0,0 +1,2784 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "abstractmetalang.h" +#include "reporthandler.h" +#include "typedatabase.h" +#include "typesystem.h" + +#ifndef QT_NO_DEBUG_STREAM +# include +# include +#endif + +#include +#include + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaAttributes("; + if (aa) + d << aa->attributes(); + else + d << '0'; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +/******************************************************************************* + * AbstractMetaVariable + */ + +AbstractMetaVariable::AbstractMetaVariable(const AbstractMetaVariable &other) +{ + m_originalName = other.m_originalName; + m_name = other.m_name; + m_type = other.m_type->copy(); + m_hasName = other.m_hasName; + m_doc = other.m_doc; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaVariable *av) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaVariable("; + if (av) { + d << av->type()->name() << ' ' << av->name(); + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +/******************************************************************************* + * AbstractMetaType + */ + +AbstractMetaType::AbstractMetaType() + :m_typeEntry(0), + m_arrayElementCount(0), + m_arrayElementType(0), + m_originalTemplateType(0), + m_pattern(InvalidPattern), + m_constant(false), + m_cppInstantiation(true), + m_indirections(0), + m_reserved(0), + m_referenceType(NoReference) +{ +} + +AbstractMetaType::~AbstractMetaType() +{ + qDeleteAll(m_children); + m_instantiations.clear(); +} + +QString AbstractMetaType::package() const +{ + return m_typeEntry->targetLangPackage(); +} + +QString AbstractMetaType::name() const +{ + if (m_name.isNull()) + // avoid constLast to stay Qt 5.5 compatible + m_name = m_typeEntry->targetLangName().split(QLatin1String("::")).last(); + return m_name; +} + +QString AbstractMetaType::fullName() const +{ + return m_typeEntry->qualifiedTargetLangName(); +} + +AbstractMetaType *AbstractMetaType::copy() const +{ + AbstractMetaType *cpy = new AbstractMetaType; + + cpy->setTypeUsagePattern(typeUsagePattern()); + cpy->setConstant(isConstant()); + cpy->setReferenceType(referenceType()); + cpy->setIndirections(indirections()); + cpy->setInstantiations(instantiations()); + cpy->setArrayElementCount(arrayElementCount()); + cpy->setOriginalTypeDescription(originalTypeDescription()); + cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0); + + cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0); + + cpy->setTypeEntry(typeEntry()); + + return cpy; +} + +QString AbstractMetaType::cppSignature() const +{ + if (m_cachedCppSignature.isEmpty()) { + if (isConstant()) + m_cachedCppSignature += QLatin1String("const "); + + m_cachedCppSignature += typeEntry()->qualifiedCppName(); + + if (hasInstantiationInCpp()) { + AbstractMetaTypeList types = instantiations(); + m_cachedCppSignature += QLatin1Char('<'); + for (int i = 0; i < types.count(); ++i) { + if (i > 0) + m_cachedCppSignature += QLatin1String(", "); + m_cachedCppSignature += types[i]->cppSignature(); + } + m_cachedCppSignature += QLatin1String(" >"); + } + + if (indirections() || m_referenceType != NoReference) { + m_cachedCppSignature += QLatin1Char(' '); + if (indirections()) + m_cachedCppSignature += QString(indirections(), QLatin1Char('*')); + switch (referenceType()) { + case NoReference: + break; + case LValueReference: + m_cachedCppSignature += QLatin1Char('&'); + break; + case RValueReference: + m_cachedCppSignature += QLatin1String("&&"); + break; + } + } + } + return m_cachedCppSignature; +} + +AbstractMetaType::TypeUsagePattern AbstractMetaType::determineUsagePattern() const +{ + if (m_typeEntry->isTemplateArgument() || m_referenceType == RValueReference) + return InvalidPattern; + + if (m_typeEntry->isPrimitive() && (!actualIndirections() + || (isConstant() && m_referenceType == LValueReference && !indirections()))) { + return PrimitivePattern; + } + + if (m_typeEntry->isVoid()) + return NativePointerPattern; + + if (m_typeEntry->isVarargs()) + return VarargsPattern; + + if (m_typeEntry->isString() && indirections() == 0 + && (isConstant() == (m_referenceType == LValueReference) + || isConstant())) { + return StringPattern; + } + + if (m_typeEntry->isChar() + && indirections() == 0 + && isConstant() == (m_referenceType == LValueReference)) { + return CharPattern; + } + + if (m_typeEntry->isJObjectWrapper() + && indirections() == 0 + && isConstant() == (m_referenceType == LValueReference)) { + return JObjectWrapperPattern; + } + + if (m_typeEntry->isVariant() + && indirections() == 0 + && isConstant() == (m_referenceType == LValueReference)) { + return VariantPattern; + } + + if (m_typeEntry->isEnum() && actualIndirections() == 0) + return EnumPattern; + + if (m_typeEntry->isObject()) { + if (indirections() == 0 && m_referenceType == NoReference) + return ValuePattern; + return static_cast(m_typeEntry)->isQObject() + ? QObjectPattern : ObjectPattern; + } + + if (m_typeEntry->isContainer() && indirections() == 0) + return ContainerPattern; + + if (m_typeEntry->isSmartPointer() && indirections() == 0) + return SmartPointerPattern; + + if (m_typeEntry->isFlags() && indirections() == 0 + && (isConstant() == (m_referenceType == LValueReference))) + return FlagsPattern; + + if (m_typeEntry->isArray()) + return ArrayPattern; + + if (m_typeEntry->isThread()) { + Q_ASSERT(indirections() == 1); + return ThreadPattern; + } + + if (m_typeEntry->isValue()) + return indirections() == 1 ? ValuePointerPattern : ValuePattern; + + if (ReportHandler::isDebug(ReportHandler::FullDebug)) { + qCDebug(lcShiboken) + << QStringLiteral("native pointer pattern for '%1'").arg(cppSignature()); + } + return NativePointerPattern; +} + +void AbstractMetaType::decideUsagePattern() +{ + TypeUsagePattern pattern = determineUsagePattern(); + if (m_typeEntry->isObject() && indirections() == 1 + && m_referenceType == LValueReference && isConstant()) { + // const-references to pointers can be passed as pointers + setReferenceType(NoReference); + setConstant(false); + pattern = static_cast(m_typeEntry)->isQObject() + ? QObjectPattern : ObjectPattern; + } + setTypeUsagePattern(pattern); +} + +bool AbstractMetaType::hasTemplateChildren() const +{ + QStack children; + children << m_children; + + // Recursively iterate over the children / descendants of the type, to check if any of them + // corresponds to a template argument type. + while (!children.isEmpty()) { + AbstractMetaType *child = children.pop(); + if (child->typeEntry()->isTemplateArgument()) + return true; + children << child->m_children; + } + + return false; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaType *at) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaType("; + if (at) + d << at->name(); + else + d << '0'; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +/******************************************************************************* + * AbstractMetaArgument + */ +AbstractMetaArgument *AbstractMetaArgument::copy() const +{ + return new AbstractMetaArgument(*this); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaArgument *aa) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaArgument("; + if (aa) + d << aa->toString(); + else + d << '0'; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +/******************************************************************************* + * AbstractMetaFunction + */ +AbstractMetaFunction::~AbstractMetaFunction() +{ + qDeleteAll(m_arguments); + delete m_type; +} + +/******************************************************************************* + * Indicates that this function has a modification that removes it + */ +bool AbstractMetaFunction::isModifiedRemoved(int types) const +{ + const FunctionModificationList &mods = modifications(implementingClass()); + for (const FunctionModification &mod : mods) { + if (!mod.isRemoveModifier()) + continue; + + if ((mod.removal & types) == types) + return true; + } + + return false; +} + +bool AbstractMetaFunction::needsCallThrough() const +{ + if (ownerClass()->isInterface()) + return false; + if (referenceCounts(implementingClass()).size() > 0) + return true; + if (argumentsHaveNativeId() || !isStatic()) + return true; + + for (const AbstractMetaArgument *arg : m_arguments) { + if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags()) + return true; + } + + if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags())) + return true; + + for (int i = -1; i <= arguments().size(); ++i) { + TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i); + if (owner != TypeSystem::InvalidOwnership) + return true; + } + + return false; +} + +bool AbstractMetaFunction::needsSuppressUncheckedWarning() const +{ + for (int i = -1; i <= arguments().size(); ++i) { + const QVector &referenceCounts = this->referenceCounts(implementingClass(), i); + for (const ReferenceCount &referenceCount : referenceCounts) { + if (referenceCount.action != ReferenceCount::Set) + return true; + } + } + return false; +} + +QString AbstractMetaFunction::marshalledName() const +{ + QString returned = QLatin1String("__qt_") + name(); + for (const AbstractMetaArgument *arg : m_arguments) { + returned += QLatin1Char('_'); + if (arg->type()->isNativePointer()) { + returned += QLatin1String("nativepointer"); + } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) { + returned += QLatin1String("int"); + } else { + QString a = arg->type()->name(); + a.replace(QLatin1String("[]"), QLatin1String("_3")); + a.replace(QLatin1Char('.'), QLatin1Char('_')); + returned += a; + } + } + return returned; +} + +bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const +{ + return compareTo(&other) & NameLessThan; +} + + +/*! + Returns a mask of CompareResult describing how this function is + compares to another function +*/ +AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const +{ + CompareResult result = 0; + + // Enclosing class... + if (ownerClass() == other->ownerClass()) + result |= EqualImplementor; + + // Attributes + if (attributes() == other->attributes()) + result |= EqualAttributes; + + // Compare types + AbstractMetaType *t = type(); + AbstractMetaType *ot = other->type(); + if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) + result |= EqualReturnType; + + // Compare names + int cmp = originalName().compare(other->originalName()); + + if (cmp < 0) + result |= NameLessThan; + else if (!cmp) + result |= EqualName; + + // compare name after modification... + cmp = modifiedName().compare(other->modifiedName()); + if (!cmp) + result |= EqualModifiedName; + + // Compare arguments... + AbstractMetaArgumentList minArguments; + AbstractMetaArgumentList maxArguments; + if (arguments().size() < other->arguments().size()) { + minArguments = arguments(); + maxArguments = other->arguments(); + } else { + minArguments = other->arguments(); + maxArguments = arguments(); + } + + int minCount = minArguments.size(); + int maxCount = maxArguments.size(); + bool same = true; + for (int i = 0; i < maxCount; ++i) { + if (i < minCount) { + const AbstractMetaArgument *min_arg = minArguments.at(i); + const AbstractMetaArgument *max_arg = maxArguments.at(i); + if (min_arg->type()->name() != max_arg->type()->name() + && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) { + same = false; + break; + } + } else { + if (maxArguments.at(i)->defaultValueExpression().isEmpty()) { + same = false; + break; + } + } + } + + if (same) + result |= minCount == maxCount ? EqualArguments : EqualDefaultValueOverload; + + return result; +} + +AbstractMetaFunction *AbstractMetaFunction::copy() const +{ + AbstractMetaFunction *cpy = new AbstractMetaFunction; + cpy->setName(name()); + cpy->setOriginalName(originalName()); + cpy->setOwnerClass(ownerClass()); + cpy->setImplementingClass(implementingClass()); + cpy->setFunctionType(functionType()); + cpy->setAttributes(attributes()); + cpy->setDeclaringClass(declaringClass()); + if (type()) + cpy->setType(type()->copy()); + cpy->setConstant(isConstant()); + cpy->setOriginalAttributes(originalAttributes()); + + for (AbstractMetaArgument *arg : m_arguments) + cpy->addArgument(arg->copy()); + + Q_ASSERT((!type() && !cpy->type()) + || (type()->instantiations() == cpy->type()->instantiations())); + + return cpy; +} + +bool AbstractMetaFunction::usesRValueReferences() const +{ + if (m_functionType == MoveConstructorFunction || m_functionType == MoveAssignmentOperatorFunction) + return true; + if (m_type && m_type->referenceType() == RValueReference) + return true; + for (const AbstractMetaArgument *a : m_arguments) { + if (a->type()->referenceType() == RValueReference) + return true; + } + return false; +} + +QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const +{ + AbstractMetaArgumentList arguments = this->arguments(); + if (arguments.size() == resolvedArguments.size()) { + QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')'); + return QStringList(TypeDatabase::normalizedSignature(signature)); + } else { + QStringList returned; + + AbstractMetaArgument *argument = arguments.at(resolvedArguments.size()); + QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::")); + for (int i = 0; i < minimalTypeSignature.size(); ++i) { + returned += introspectionCompatibleSignatures(QStringList(resolvedArguments) + << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::"))); + } + + return returned; + } +} + +QString AbstractMetaFunction::signature() const +{ + if (m_cachedSignature.isEmpty()) { + m_cachedSignature = m_originalName; + + m_cachedSignature += QLatin1Char('('); + + for (int i = 0; i < m_arguments.count(); ++i) { + AbstractMetaArgument *a = m_arguments.at(i); + AbstractMetaType *t = a->type(); + if (t) { + if (i > 0) + m_cachedSignature += QLatin1String(", "); + m_cachedSignature += t->cppSignature(); + // We need to have the argument names in the qdoc files + m_cachedSignature += QLatin1Char(' '); + m_cachedSignature += a->name(); + } else { + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("No abstract meta type found for argument '%1' while" + "constructing signature for function '%2'.") + .arg(a->name(), name()); + } + } + m_cachedSignature += QLatin1Char(')'); + + if (isConstant()) + m_cachedSignature += QLatin1String(" const"); + } + return m_cachedSignature; +} + +int AbstractMetaFunction::actualMinimumArgumentCount() const +{ + AbstractMetaArgumentList arguments = this->arguments(); + + int count = 0; + for (int i = 0; i < arguments.size(); ++i && ++count) { + if (argumentRemoved(i + 1)) + --count; + else if (!arguments.at(i)->defaultValueExpression().isEmpty()) + break; + } + + return count; +} + +// Returns reference counts for argument at idx, or all arguments if idx == -2 +QVector AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const +{ + QVector returned; + + const FunctionModificationList &mods = this->modifications(cls); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argumentMod : mod.argument_mods) { + if (argumentMod.index != idx && idx != -2) + continue; + returned += argumentMod.referenceCounts; + } + } + + return returned; +} + + +ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const +{ + const FunctionModificationList &mods = this->modifications(cls); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argumentMod : mod.argument_mods) { + if (argumentMod.index != idx) + continue; + return argumentMod.owner; + } + } + return ArgumentOwner(); +} + + +QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const +{ + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key + && !argumentModification.replacedDefaultExpression.isEmpty()) { + return argumentModification.replacedDefaultExpression; + } + } + } + + return QString(); +} + +bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const +{ + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key + && argumentModification.removedDefaultExpression) { + return true; + } + } + } + + return false; +} + +bool AbstractMetaFunction::resetObjectAfterUse(int argumentIdx) const +{ + const AbstractMetaClass *cls = declaringClass(); + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == argumentIdx && argumentModification.resetAfterUse) + return true; + } + } + + return false; +} + +QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argumentIdx) const +{ + Q_ASSERT(nullPointersDisabled(mainClass, argumentIdx)); + + const AbstractMetaClass *cls = mainClass; + if (!cls) + cls = implementingClass(); + + do { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == argumentIdx + && argumentModification.noNullPointers) { + return argumentModification.nullPointerDefaultValue; + } + } + } + cls = cls->baseClass(); + } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class + + return QString(); + +} + +bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argumentIdx) const +{ + const AbstractMetaClass *cls = mainClass; + if (!cls) + cls = implementingClass(); + + do { + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == argumentIdx + && argumentModification.noNullPointers) { + return true; + } + } + } + + cls = cls->baseClass(); + } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class + + return false; +} + +QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index != key) + continue; + + for (const CodeSnip &snip : argumentModification.conversion_rules) { + if (snip.language == language && !snip.code().isEmpty()) + return snip.code(); + } + } + } + + return QString(); +} + +QString AbstractMetaFunction::argumentReplaced(int key) const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key && !argumentModification.replace_value.isEmpty()) + return argumentModification.replace_value; + } + } + + return QString(); +} + +// FIXME If we remove a arg. in the method at the base class, it will not reflect here. +bool AbstractMetaFunction::argumentRemoved(int key) const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key) { + if (argumentModification.removed) + return true; + } + } + } + + return false; +} + +bool AbstractMetaFunction::isVirtualSlot() const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + if (modification.isVirtualSlot()) + return true; + } + + return false; +} + +bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const +{ + typedef QHash::const_iterator OwnershipMapIt; + + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index != key) + continue; + + for (OwnershipMapIt it = argumentModification.ownerships.cbegin(), end = argumentModification.ownerships.cend(); it != end; ++it) { + if (it.value() == TypeSystem::CppOwnership) + return true; + } + + } + } + + return false; +} + +bool AbstractMetaFunction::isDeprecated() const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + if (modification.isDeprecated()) + return true; + } + return false; +} + +bool AbstractMetaFunction::isThread() const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + if (modification.isThread()) + return true; + } + return false; +} + +bool AbstractMetaFunction::allowThread() const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + if (modification.allowThread()) + return true; + } + return false; +} + + +TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const +{ + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key) + return argumentModification.ownerships.value(language, TypeSystem::InvalidOwnership); + } + } + + return TypeSystem::InvalidOwnership; +} + +bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const +{ + return isRemovedFrom(cls, TypeSystem::All); +} + +bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const +{ + const FunctionModificationList &modifications = this->modifications(cls); + for (const FunctionModification &modification : modifications) { + if ((modification.removal & language) == language) + return true; + } + + return false; + +} + +QString AbstractMetaFunction::typeReplaced(int key) const +{ + const FunctionModificationList &modifications = this->modifications(declaringClass()); + for (const FunctionModification &modification : modifications) { + for (const ArgumentModification &argumentModification : modification.argument_mods) { + if (argumentModification.index == key + && !argumentModification.modified_type.isEmpty()) { + return argumentModification.modified_type; + } + } + } + + return QString(); +} + +QString AbstractMetaFunction::minimalSignature() const +{ + if (!m_cachedMinimalSignature.isEmpty()) + return m_cachedMinimalSignature; + + QString minimalSignature = originalName() + QLatin1Char('('); + AbstractMetaArgumentList arguments = this->arguments(); + + for (int i = 0; i < arguments.count(); ++i) { + AbstractMetaType *t = arguments.at(i)->type(); + if (t) { + if (i > 0) + minimalSignature += QLatin1Char(','); + minimalSignature += t->minimalSignature(); + } else { + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("No abstract meta type found for argument '%1' while constructing" + " minimal signature for function '%2'.") + .arg(arguments.at(i)->name(), name()); + } + } + minimalSignature += QLatin1Char(')'); + if (isConstant()) + minimalSignature += QLatin1String("const"); + + minimalSignature = TypeDatabase::normalizedSignature(minimalSignature); + m_cachedMinimalSignature = minimalSignature; + + return minimalSignature; +} + +FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const +{ + if (!implementor) + implementor = ownerClass(); + + if (!implementor) + return TypeDatabase::instance()->functionModifications(minimalSignature()); + + FunctionModificationList mods; + while (implementor) { + mods += implementor->typeEntry()->functionModifications(minimalSignature()); + if ((implementor == implementor->baseClass()) || + (implementor == implementingClass() && (mods.size() > 0))) + break; + const AbstractMetaClassList &interfaces = implementor->interfaces(); + for (const AbstractMetaClass *interface : interfaces) + mods += this->modifications(interface); + implementor = implementor->baseClass(); + } + return mods; +} + +bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const +{ + return !modifications(implementor).isEmpty(); +} + +QString AbstractMetaFunction::argumentName(int index, + bool /* create */, + const AbstractMetaClass * /* implementor */) const +{ + return m_arguments[--index]->name(); +} + +bool AbstractMetaFunction::isCallOperator() const +{ + return m_name == QLatin1String("operator()"); +} + +bool AbstractMetaFunction::hasInjectedCode() const +{ + const FunctionModificationList &mods = modifications(ownerClass()); + for (const FunctionModification &mod : mods) { + if (mod.isCodeInjection()) + return true; + } + return false; +} + +CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const +{ + CodeSnipList result; + const FunctionModificationList &mods = modifications(ownerClass()); + for (const FunctionModification &mod : mods) { + if (mod.isCodeInjection()) { + for (const CodeSnip &snip : mod.snips) { + if ((snip.language & language) && (snip.position == position || position == TypeSystem::CodeSnipPositionAny)) + result << snip; + } + } + } + return result; +} + +bool AbstractMetaFunction::hasSignatureModifications() const +{ + const FunctionModificationList &mods = modifications(); + for (const FunctionModification &mod : mods) { + if (mod.isRenameModifier()) + return true; + for (const ArgumentModification &argmod : mod.argument_mods) { + // since zero represents the return type and we're + // interested only in checking the function arguments, + // it will be ignored. + if (argmod.index > 0) + return true; + } + } + return false; +} + +bool AbstractMetaFunction::isConversionOperator(QString funcName) +{ + static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$")); + Q_ASSERT(opRegEx.isValid()); + return opRegEx.match(funcName).hasMatch(); +} + +bool AbstractMetaFunction::isOperatorOverload(QString funcName) +{ + if (isConversionOperator(funcName)) + return true; + + static const QRegularExpression opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?" + "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~" + "|\\[\\]|\\s+delete\\[?\\]?" + "|\\(\\)" + "|\\s+new\\[?\\]?)$")); + Q_ASSERT(opRegEx.isValid()); + return opRegEx.match(funcName).hasMatch(); +} + +bool AbstractMetaFunction::isCastOperator() const +{ + return originalName().startsWith(QLatin1String("operator ")); +} + +bool AbstractMetaFunction::isArithmeticOperator() const +{ + if (!isOperatorOverload()) + return false; + + QString name = originalName(); + + // It's a dereference operator! + if (name == QLatin1String("operator*") && m_arguments.isEmpty()) + return false; + + return name == QLatin1String("operator+") || name == QLatin1String("operator+=") + || name == QLatin1String("operator-") || name == QLatin1String("operator-=") + || name == QLatin1String("operator*") || name == QLatin1String("operator*=") + || name == QLatin1String("operator/") || name == QLatin1String("operator/=") + || name == QLatin1String("operator%") || name == QLatin1String("operator%=") + || name == QLatin1String("operator++") || name == QLatin1String("operator--"); +} + +bool AbstractMetaFunction::isBitwiseOperator() const +{ + if (!isOperatorOverload()) + return false; + + QString name = originalName(); + return name == QLatin1String("operator<<") || name == QLatin1String("operator<<=") + || name == QLatin1String("operator>>") || name == QLatin1String("operator>>=") + || name == QLatin1String("operator&") || name == QLatin1String("operator&=") + || name == QLatin1String("operator|") || name == QLatin1String("operator|=") + || name == QLatin1String("operator^") || name == QLatin1String("operator^=") + || name == QLatin1String("operator~"); +} + +bool AbstractMetaFunction::isComparisonOperator() const +{ + if (!isOperatorOverload()) + return false; + + QString name = originalName(); + return name == QLatin1String("operator<") || name == QLatin1String("operator<=") + || name == QLatin1String("operator>") || name == QLatin1String("operator>=") + || name == QLatin1String("operator==") || name == QLatin1String("operator!="); +} + +bool AbstractMetaFunction::isLogicalOperator() const +{ + if (!isOperatorOverload()) + return false; + + QString name = originalName(); + return name == QLatin1String("operator!") + || name == QLatin1String("operator&&") + || name == QLatin1String("operator||"); +} + +bool AbstractMetaFunction::isSubscriptOperator() const +{ + if (!isOperatorOverload()) + return false; + + return originalName() == QLatin1String("operator[]"); +} + +bool AbstractMetaFunction::isAssignmentOperator() const +{ + return m_functionType == AssignmentOperatorFunction + || m_functionType == MoveAssignmentOperatorFunction; +} + +bool AbstractMetaFunction::isOtherOperator() const +{ + if (!isOperatorOverload()) + return false; + + return !isArithmeticOperator() + && !isBitwiseOperator() + && !isComparisonOperator() + && !isLogicalOperator() + && !isConversionOperator() + && !isSubscriptOperator() + && !isAssignmentOperator(); +} + +int AbstractMetaFunction::arityOfOperator() const +{ + if (!isOperatorOverload() || isCallOperator()) + return -1; + + int arity = m_arguments.size(); + + // Operator overloads that are class members + // implicitly includes the instance and have + // one parameter less than their arity, + // so we increment it. + if (ownerClass() && arity < 2) + arity++; + + return arity; +} + +bool AbstractMetaFunction::isInplaceOperator() const +{ + if (!isOperatorOverload()) + return false; + + QString name = originalName(); + return name == QLatin1String("operator+=") || name == QLatin1String("operator&=") + || name == QLatin1String("operator-=") || name == QLatin1String("operator|=") + || name == QLatin1String("operator*=") || name == QLatin1String("operator^=") + || name == QLatin1String("operator/=") || name == QLatin1String("operator<<=") + || name == QLatin1String("operator%=") || name == QLatin1String("operator>>="); +} + +bool AbstractMetaFunction::isVirtual() const +{ + return !isFinal() && !isSignal() && !isStatic() && !isFinalInCpp() && !isConstructor(); +} + +QString AbstractMetaFunction::modifiedName() const +{ + if (m_cachedModifiedName.isEmpty()) { + const FunctionModificationList &mods = modifications(implementingClass()); + for (const FunctionModification &mod : mods) { + if (mod.isRenameModifier()) { + m_cachedModifiedName = mod.renamedToName; + break; + } + } + if (m_cachedModifiedName.isEmpty()) + m_cachedModifiedName = name(); + } + return m_cachedModifiedName; +} + +QString AbstractMetaFunction::targetLangSignature(bool minimal) const +{ + QString s; + + // Attributes... + if (!minimal) { + // Return type + if (type()) + s += type()->name() + QLatin1Char(' '); + else + s += QLatin1String("void "); + } + + s += modifiedName(); + s += QLatin1Char('('); + + int j = 0; + for (int i = 0; i < m_arguments.size(); ++i) { + if (argumentRemoved(i + 1)) + continue; + if (j) { + s += QLatin1Char(','); + if (!minimal) + s += QLatin1Char(' '); + } + s += m_arguments.at(i)->type()->name(); + + if (!minimal) { + s += QLatin1Char(' '); + s += m_arguments.at(i)->name(); + } + ++j; + } + + s += QLatin1Char(')'); + + return s; +} + + +bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b) +{ + return a->signature() < b->signature(); +} + +#ifndef QT_NO_DEBUG_STREAM +static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af) +{ + d << '"' << af->minimalSignature() << '"'; +} + +void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const +{ + d << m_functionType << ' ' << m_type << ' ' << m_name << '('; + for (int i = 0, count = m_arguments.size(); i < count; ++i) { + if (i) + d << ", "; + d << m_arguments.at(i); + } + d << "), signature=\"" << minimalSignature() << '"'; + if (m_constant) + d << " [const]"; + if (m_invalid) + d << " [invalid]"; + if (m_reverse) + d << " [reverse]"; + if (m_userAdded) + d << " [userAdded]"; + if (m_explicit) + d << " [explicit]"; + if (m_pointerOperator) + d << " [operator->]"; + if (m_isCallOperator) + d << " [operator()]"; + if (m_class) + d << " class: " << m_class->name(); + if (m_implementingClass) + d << " implementing class: " << m_implementingClass->name(); + if (m_declaringClass) + d << " declaring class: " << m_declaringClass->name(); +} + +QDebug operator<<(QDebug d, const AbstractMetaFunction *af) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaFunction("; + if (af) { +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + if (d.verbosity() > 2) { + af->formatDebugVerbose(d); + } else { +#endif + d << "signature="; + formatMetaFunctionBrief(d, af); +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + } +#endif + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +/******************************************************************************* + * AbstractMetaClass + */ +AbstractMetaClass::~AbstractMetaClass() +{ + qDeleteAll(m_functions); + qDeleteAll(m_fields); + qDeleteAll(m_enums); + if (hasTemplateBaseClassInstantiations()) + qDeleteAll(templateBaseClassInstantiations()); +} + +/******************************************************************************* + * Returns true if this class is a subclass of the given class + */ +bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const +{ + Q_ASSERT(cls); + + const AbstractMetaClass *clazz = this; + while (clazz) { + if (clazz == cls) + return true; + + clazz = clazz->baseClass(); + } + + return false; +} + +/******************************************************************************* + * Constructs an interface based on the functions and enums in this + * class and returns it... + */ +AbstractMetaClass *AbstractMetaClass::extractInterface() +{ + Q_ASSERT(typeEntry()->designatedInterface()); + + if (!m_extractedInterface) { + AbstractMetaClass *iface = new AbstractMetaClass; + iface->setAttributes(attributes()); + iface->setBaseClass(0); + + iface->setTypeEntry(typeEntry()->designatedInterface()); + + for (AbstractMetaFunction *function : qAsConst(m_functions)) { + if (!function->isConstructor()) + iface->addFunction(function->copy()); + } + +// iface->setEnums(enums()); +// setEnums(AbstractMetaEnumList()); + + for (const AbstractMetaField *field : qAsConst(m_fields)) { + if (field->isPublic()) { + AbstractMetaField *new_field = field->copy(); + new_field->setEnclosingClass(iface); + iface->addField(new_field); + } + } + + m_extractedInterface = iface; + addInterface(iface); + } + + return m_extractedInterface; +} + +/******************************************************************************* + * Returns a list of all the functions with a given name + */ +AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const +{ + AbstractMetaFunctionList returned; + for (AbstractMetaFunction *function : m_functions) { + if (function->name() == name) + returned.append(function); + } + + return returned; +} + +/******************************************************************************* + * Returns a list of all the functions retrieved during parsing which should + * be added to the API. + */ +AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const +{ + FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang; + + // Interfaces don't implement functions + if (isInterface()) + default_flags |= ClassImplements; + + // Only public functions in final classes + // default_flags |= isFinal() ? WasPublic : 0; + FunctionQueryOptions public_flags; + if (isFinal()) + public_flags |= WasPublic; + + // Constructors + AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags); + + // Final functions + returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); + + // Virtual functions + returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags); + + // Static functions + returned += queryFunctions(StaticFunctions | default_flags | public_flags); + + // Empty, private functions, since they aren't caught by the other ones + returned += queryFunctions(Empty | Invisible); + + return returned; +} + +AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const +{ + const AbstractMetaFunctionList &list = functionsInShellClass(); + + AbstractMetaFunctionList returned; + for (AbstractMetaFunction *f : list) { + if (!f->isFinalInCpp() || f->isVirtualSlot()) + returned += f; + } + + return returned; +} + +AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const +{ + if (!hasCloneOperator() && !hasExternalConversionOperators()) + return AbstractMetaFunctionList(); + + AbstractMetaFunctionList returned; + const AbstractMetaFunctionList list = queryFunctions(Constructors) + externalConversionOperators(); + + // Exclude anything that uses rvalue references, be it a move + // constructor "QPolygon(QPolygon &&)" or something else like + // "QPolygon(QVector &&)". + for (AbstractMetaFunction *f : list) { + if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) + && !f->isExplicit() + && f->functionType() != AbstractMetaFunction::CopyConstructorFunction + && !f->usesRValueReferences() + && !f->isModifiedRemoved() + && (f->originalAttributes() & Public)) { + returned += f; + } + } + return returned; +} + +AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptions query) const +{ + const AbstractMetaFunctionList &list = queryFunctions(OperatorOverloads | Visible); + AbstractMetaFunctionList returned; + for (AbstractMetaFunction *f : list) { + if (((query & ArithmeticOp) && f->isArithmeticOperator()) + || ((query & BitwiseOp) && f->isBitwiseOperator()) + || ((query & ComparisonOp) && f->isComparisonOperator()) + || ((query & LogicalOp) && f->isLogicalOperator()) + || ((query & SubscriptionOp) && f->isSubscriptOperator()) + || ((query & AssignmentOp) && f->isAssignmentOperator()) + || ((query & ConversionOp) && f->isConversionOperator()) + || ((query & OtherOp) && f->isOtherOperator())) + returned += f; + } + + return returned; +} + +bool AbstractMetaClass::hasOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isOperatorOverload() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasArithmeticOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasBitwiseOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasComparisonOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasLogicalOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasSubscriptOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isSubscriptOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasAssignmentOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isAssignmentOperator() && !f->isPrivate()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasConversionOperatorOverload() const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->ownerClass() == f->implementingClass() && f->isConversionOperator() && !f->isPrivate()) + return true; + } + return false; +} + +/******************************************************************************* + * Returns a list of all functions that should be declared and implemented in + * the shell class which is generated as a wrapper on top of the actual C++ class + */ +AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const +{ + // Only functions and only protected and public functions + FunctionQueryOptions default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell; + + // All virtual functions + AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags); + + // All functions explicitly set to be implemented by the shell class + // (mainly superclass functions that are hidden by other declarations) + returned += queryFunctions(ForcedShellFunctions | default_flags); + + // All functions explicitly set to be virtual slots + returned += queryFunctions(VirtualSlots | default_flags); + + return returned; +} + +/******************************************************************************* + * Returns a list of all functions that require a public override function to + * be generated in the shell class. This includes all functions that were originally + * protected in the superclass. + */ +AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const +{ + return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang) + + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang); +} + +AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const +{ + return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) + + queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell); +} + +void AbstractMetaClass::sortFunctions() +{ + qSort(m_functions.begin(), m_functions.end(), function_sorter); +} + +void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions) +{ + m_functions = functions; + + // Functions must be sorted by name before next loop + sortFunctions(); + + QString currentName; + bool hasVirtuals = false; + AbstractMetaFunctionList finalFunctions; + for (AbstractMetaFunction *f : qAsConst(m_functions)) { + f->setOwnerClass(this); + + m_hasVirtualSlots = m_hasVirtualSlots || f->isVirtualSlot(); + m_hasVirtuals = m_hasVirtuals || f->isVirtualSlot() || hasVirtualDestructor(); + m_isPolymorphic = m_isPolymorphic || m_hasVirtuals; + m_hasNonpublic = m_hasNonpublic || !f->isPublic(); + + // If we have non-virtual overloads of a virtual function, we have to implement + // all the overloads in the shell class to override the hiding rule + if (currentName == f->name()) { + hasVirtuals = hasVirtuals || !f->isFinal(); + if (f->isFinal()) + finalFunctions += f; + } else { + if (hasVirtuals && finalFunctions.size() > 0) { + for (AbstractMetaFunction *final_function : qAsConst(finalFunctions)) { + *final_function += AbstractMetaAttributes::ForceShellImplementation; + + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("hiding of function '%1' in class '%2'") + .arg(final_function->name(), name()); + } + } + + hasVirtuals = !f->isFinal(); + finalFunctions.clear(); + if (f->isFinal()) + finalFunctions += f; + currentName = f->name(); + } + } +} + +bool AbstractMetaClass::hasFieldAccessors() const +{ + for (const AbstractMetaField *field : m_fields) { + if (field->getter() || field->setter()) + return true; + } + + return false; +} + +bool AbstractMetaClass::hasDefaultToStringFunction() const +{ + const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString")); + for (const AbstractMetaFunction *f : funcs) { + if (!f->actualMinimumArgumentCount()) + return true; + } + return false; +} + +void AbstractMetaClass::addFunction(AbstractMetaFunction *function) +{ + Q_ASSERT(!function->signature().startsWith(QLatin1Char('('))); + function->setOwnerClass(this); + + if (!function->isDestructor()) + m_functions << function; + else + Q_ASSERT(false); //memory leak + + m_hasVirtualSlots |= function->isVirtualSlot(); + m_hasVirtuals |= !function->isFinal() || function->isVirtualSlot() || hasVirtualDestructor(); + m_isPolymorphic |= m_hasVirtuals; + m_hasNonpublic |= !function->isPublic(); +} + +bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const +{ + if (!other->isSignal()) + return false; + + for (const AbstractMetaFunction *f : m_functions) { + if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName) + return other->modifiedName() == f->modifiedName(); + } + + return false; +} + + +QString AbstractMetaClass::name() const +{ + return QString(m_typeEntry->targetLangName()).split(QLatin1String("::")).last(); +} + +void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass) +{ + m_baseClass = baseClass; + if (baseClass) + m_isPolymorphic |= baseClass->isPolymorphic(); +} + +QString AbstractMetaClass::package() const +{ + return m_typeEntry->targetLangPackage(); +} + +bool AbstractMetaClass::isInterface() const +{ + return m_typeEntry->isInterface(); +} + +bool AbstractMetaClass::isNamespace() const +{ + return m_typeEntry->isNamespace(); +} + +bool AbstractMetaClass::isQObject() const +{ + return m_typeEntry->isQObject(); +} + +QString AbstractMetaClass::qualifiedCppName() const +{ + return m_typeEntry->qualifiedCppName(); +} + +bool AbstractMetaClass::hasFunction(const QString &str) const +{ + return findFunction(str); +} + +const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& functionName) const +{ + for (const AbstractMetaFunction *f : m_functions) { + if (f->name() == functionName) + return f; + } + return 0; +} + +bool AbstractMetaClass::hasProtectedFunctions() const +{ + for (AbstractMetaFunction *func : m_functions) { + if (func->isProtected()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasProtectedFields() const +{ + for (const AbstractMetaField *field : m_fields) { + if (field->isProtected()) + return true; + } + return false; +} + +bool AbstractMetaClass::hasProtectedMembers() const +{ + return hasProtectedFields() || hasProtectedFunctions(); +} + +bool AbstractMetaClass::generateShellClass() const +{ + return m_forceShellClass || + (!isFinal() + && (hasVirtualFunctions() + || hasProtectedFunctions() + || hasFieldAccessors())); +} + +QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const +{ + for (int i = 0; i < m_propertySpecs.size(); ++i) + if (name == m_propertySpecs.at(i)->read()) + return m_propertySpecs.at(i); + return 0; +} + +QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const +{ + for (int i = 0; i < m_propertySpecs.size(); ++i) + if (name == m_propertySpecs.at(i)->write()) + return m_propertySpecs.at(i); + return 0; +} + +QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const +{ + for (int i = 0; i < m_propertySpecs.size(); ++i) { + if (name == m_propertySpecs.at(i)->reset()) + return m_propertySpecs.at(i); + } + return 0; +} + +typedef QHash AbstractMetaClassBaseTemplateInstantiationsMap; +Q_GLOBAL_STATIC(AbstractMetaClassBaseTemplateInstantiationsMap, metaClassBaseTemplateInstantiations); + +bool AbstractMetaClass::hasTemplateBaseClassInstantiations() const +{ + if (!templateBaseClass()) + return false; + return metaClassBaseTemplateInstantiations()->contains(this); +} + +AbstractMetaTypeList AbstractMetaClass::templateBaseClassInstantiations() const +{ + if (!templateBaseClass()) + return AbstractMetaTypeList(); + return metaClassBaseTemplateInstantiations()->value(this); +} + +void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations) +{ + if (!templateBaseClass()) + return; + metaClassBaseTemplateInstantiations()->insert(this, instantiations); +} + +static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) +{ + for (const AbstractMetaFunction *f : l) { + if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar) + return true; + } + return false; +} + +AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0) +{ +} + +AbstractMetaField::~AbstractMetaField() +{ + delete m_setter; + delete m_getter; +} + +AbstractMetaField *AbstractMetaField::copy() const +{ + AbstractMetaField *returned = new AbstractMetaField; + returned->setEnclosingClass(0); + returned->setAttributes(attributes()); + returned->setName(name()); + returned->setType(type()->copy()); + returned->setOriginalAttributes(originalAttributes()); + + return returned; +} + +/******************************************************************************* + * Indicates that this field has a modification that removes it + */ +bool AbstractMetaField::isModifiedRemoved(int types) const +{ + const FieldModificationList &mods = modifications(); + for (const FieldModification &mod : mods) { + if (!mod.isRemoveModifier()) + continue; + + if ((mod.removal & types) == types) + return true; + } + + return false; +} + +static QString upCaseFirst(const QString &str) +{ + Q_ASSERT(!str.isEmpty()); + QString s = str; + s[0] = s.at(0).toUpper(); + return s; +} + +static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, + AbstractMetaAttributes::Attributes type) +{ + AbstractMetaFunction *f = new AbstractMetaFunction; + + f->setName(name); + f->setOriginalName(name); + f->setOwnerClass(g->enclosingClass()); + f->setImplementingClass(g->enclosingClass()); + f->setDeclaringClass(g->enclosingClass()); + + AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native + | AbstractMetaAttributes::Final + | type; + if (g->isStatic()) + attr |= AbstractMetaAttributes::Static; + if (g->isPublic()) + attr |= AbstractMetaAttributes::Public; + else if (g->isProtected()) + attr |= AbstractMetaAttributes::Protected; + else + attr |= AbstractMetaAttributes::Private; + f->setAttributes(attr); + f->setOriginalAttributes(attr); + + const FieldModificationList &mods = g->modifications(); + for (const FieldModification &mod : mods) { + if (mod.isRenameModifier()) + f->setName(mod.renamedTo()); + if (mod.isAccessModifier()) { + if (mod.isPrivate()) + f->setVisibility(AbstractMetaAttributes::Private); + else if (mod.isProtected()) + f->setVisibility(AbstractMetaAttributes::Protected); + else if (mod.isPublic()) + f->setVisibility(AbstractMetaAttributes::Public); + else if (mod.isFriendly()) + f->setVisibility(AbstractMetaAttributes::Friendly); + } + } + return f; +} + +FieldModificationList AbstractMetaField::modifications() const +{ + const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications(); + FieldModificationList returned; + + for (const FieldModification &mod : mods) { + if (mod.name == name()) + returned += mod; + } + + return returned; +} + +const AbstractMetaFunction *AbstractMetaField::setter() const +{ + if (!m_setter) { + m_setter = createXetter(this, + QLatin1String("set") + upCaseFirst(name()), + AbstractMetaAttributes::SetterFunction); + AbstractMetaArgumentList arguments; + AbstractMetaArgument *argument = new AbstractMetaArgument; + argument->setType(type()->copy()); + argument->setName(name()); + arguments.append(argument); + m_setter->setArguments(arguments); + } + return m_setter; +} + +const AbstractMetaFunction *AbstractMetaField::getter() const +{ + if (!m_getter) { + m_getter = createXetter(this, + name(), + AbstractMetaAttributes::GetterFunction); + m_getter->setType(type()); + } + + return m_getter; +} + +#ifndef QT_NO_DEBUG_STREAM +static void formatMetaAttributes(QDebug &d, AbstractMetaAttributes::Attributes value) +{ + static const int meIndex = AbstractMetaAttributes::staticMetaObject.indexOfEnumerator("Attribute"); + Q_ASSERT(meIndex >= 0); + const QMetaEnum me = AbstractMetaAttributes::staticMetaObject.enumerator(meIndex); + d << me.valueToKeys(value); +} + +static void formatMetaField(QDebug &d, const AbstractMetaField *af) +{ + formatMetaAttributes(d, af->attributes()); + d << ' ' << af->type()->name() << " \"" << af->name() << '"'; +} + +QDebug operator<<(QDebug d, const AbstractMetaField *af) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaField("; + if (af) + formatMetaField(d, af); + else + d << '0'; + d << ')'; + return d; +} + +static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue *v) +{ + const QString &name = v->stringValue(); + if (!name.isEmpty()) + d << name << '='; + d << v->value(); +} + +QDebug operator<<(QDebug d, const AbstractMetaEnumValue *v) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaEnumValue("; + if (v) + formatMetaEnumValue(d, v); + else + d << '0'; + d << ')'; + return d; +} + +QDebug operator<<(QDebug d, const AbstractMetaEnum *ae) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaEnum("; + if (ae) { + d << ae->fullName() << '['; + const AbstractMetaEnumValueList &values = ae->values(); + for (int i = 0, count = values.size(); i < count; ++i) { + if (i) + d << ' '; + formatMetaEnumValue(d, values.at(i)); + } + d << ']'; + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +bool AbstractMetaClass::hasConstructors() const +{ + return queryFunctions(Constructors).size(); +} + +bool AbstractMetaClass::hasCopyConstructor() const +{ + const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); + for (const AbstractMetaFunction* ctor : ctors) { + if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction) + return true; + } + return false; +} + +bool AbstractMetaClass::hasPrivateCopyConstructor() const +{ + const AbstractMetaFunctionList &ctors = queryFunctions(Constructors); + for (const AbstractMetaFunction *ctor : ctors) { + if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate()) + return true; + } + return false; +} + +void AbstractMetaClass::addDefaultConstructor() +{ + AbstractMetaFunction *f = new AbstractMetaFunction; + f->setOriginalName(name()); + f->setName(name()); + f->setOwnerClass(this); + f->setFunctionType(AbstractMetaFunction::ConstructorFunction); + f->setArguments(AbstractMetaArgumentList()); + f->setDeclaringClass(this); + + AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; + attr |= AbstractMetaAttributes::Public; + attr |= AbstractMetaAttributes::Final; + f->setAttributes(attr); + f->setImplementingClass(this); + f->setOriginalAttributes(f->attributes()); + + addFunction(f); + this->setHasNonPrivateConstructor(true); +} + +void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) +{ + AbstractMetaFunction* f = new AbstractMetaFunction; + f->setOriginalName(name()); + f->setName(name()); + f->setOwnerClass(this); + f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + f->setDeclaringClass(this); + + AbstractMetaType* argType = new AbstractMetaType; + argType->setTypeEntry(typeEntry()); + argType->setReferenceType(LValueReference); + argType->setConstant(true); + argType->setTypeUsagePattern(AbstractMetaType::ValuePattern); + + AbstractMetaArgument* arg = new AbstractMetaArgument; + arg->setType(argType); + arg->setName(name()); + f->addArgument(arg); + + AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native; + attr |= AbstractMetaAttributes::Final; + if (isPrivate) + attr |= AbstractMetaAttributes::Private; + else + attr |= AbstractMetaAttributes::Public; + f->setAttributes(attr); + f->setImplementingClass(this); + f->setOriginalAttributes(f->attributes()); + + addFunction(f); +} + +bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const +{ + return functions_contains(m_functions, f); +} + +/* Goes through the list of functions and returns a list of all + functions matching all of the criteria in \a query. + */ + +AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const +{ + AbstractMetaFunctionList functions; + + for (AbstractMetaFunction *f : m_functions) { + + if ((query & VirtualSlots) && !f->isVirtualSlot()) + continue; + + if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) + continue; + + if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) + continue; + + if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) + continue; + + if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) + continue; + + if ((query & Visible) && f->isPrivate()) + continue; + + if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) + continue; + + if ((query & Invisible) && !f->isPrivate()) + continue; + + if ((query & Empty) && !f->isEmptyFunction()) + continue; + + if ((query & WasPublic) && !f->wasPublic()) + continue; + + if ((query & WasVisible) && f->wasPrivate()) + continue; + + if ((query & WasProtected) && !f->wasProtected()) + continue; + + if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) + continue; + + if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) + continue; + + if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) + continue; + + if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) + continue; + + if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) + continue; + + if ((query & Signals) && (!f->isSignal())) + continue; + + if ((query & ForcedShellFunctions) && + (!f->isForcedShellImplementation() || !f->isFinal())) { + continue; + } + + if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass())) + continue; + + if (!(query & Constructors) && f->isConstructor()) + continue; + + // Destructors are never included in the functions of a class currently + /* + if ((query & Destructors) && (!f->isDestructor() + || f->ownerClass() != f->implementingClass()) + || f->isDestructor() && (query & Destructors) == 0) { + continue; + }*/ + + if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) + continue; + + if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) + continue; + + if ((query & NonStaticFunctions) && (f->isStatic())) + continue; + + if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) + continue; + + if ((query & NormalFunctions) && (f->isSignal())) + continue; + + if ((query & AbstractFunctions) && !f->isAbstract()) + continue; + + if ((query & OperatorOverloads) && !f->isOperatorOverload()) + continue; + + functions << f; + } + + return functions; +} + +bool AbstractMetaClass::hasSignals() const +{ + return cppSignalFunctions().size() > 0; +} + + +/** + * Adds the specified interface to this class by adding all the + * functions in the interface to this class. + */ +void AbstractMetaClass::addInterface(AbstractMetaClass *interface) +{ + Q_ASSERT(!m_interfaces.contains(interface)); + m_interfaces << interface; + + m_isPolymorphic |= interface->isPolymorphic(); + + if (m_extractedInterface && m_extractedInterface != interface) + m_extractedInterface->addInterface(interface); + + +#if 0 + const AbstractMetaFunctionList &funcs = interface->functions(); + for (AbstractMetaFunction *function : funcs) + if (!hasFunction(function) && !function->isConstructor()) { + AbstractMetaFunction *cpy = function->copy(); + cpy->setImplementingClass(this); + + // Setup that this function is an interface class. + cpy->setInterfaceClass(interface); + *cpy += AbstractMetaAttributes::InterfaceFunction; + + // Copy the modifications in interface into the implementing classes. + const FunctionModificationList &mods = function->modifications(interface); + for (const FunctionModification &mod : mods) + m_typeEntry->addFunctionModification(mod); + + // It should be mostly safe to assume that when we implement an interface + // we don't "pass on" pure virtual functions to our sublcasses... +// *cpy -= AbstractMetaAttributes::Abstract; + + addFunction(cpy); + } +#endif + +} + + +void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces) +{ + m_interfaces = interfaces; + for (const AbstractMetaClass *interface : interfaces) { + if (interface) + m_isPolymorphic |= interface->isPolymorphic(); + } +} + + +AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName) +{ + for (AbstractMetaEnum *e : qAsConst(m_enums)) { + if (e->name() == enumName) + return e; + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnum(enumName); + + return 0; +} + + + + +/*! Recursivly searches for the enum value named \a enumValueName in + this class and its superclasses and interfaces. Values belonging to + \a meta_enum are excluded from the search. +*/ +AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum) +{ + for (AbstractMetaEnum *e : qAsConst(m_enums)) { + if (e != meta_enum) + continue; + const AbstractMetaEnumValueList &values = e->values(); + for (AbstractMetaEnumValue *v : values) { + if (v->name() == enumValueName) + return v; + } + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnumValue(enumValueName, meta_enum); + + if (baseClass()) + return baseClass()->findEnumValue(enumValueName, meta_enum); + + return 0; +} + + +/*! + * Searches through all of this class' enums for a value matching the + * name \a enumValueName. The name is excluding the class/namespace + * prefix. The function recursivly searches interfaces and baseclasses + * of this class. + */ +AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName) +{ + for (AbstractMetaEnum *e : qAsConst(m_enums)) { + const AbstractMetaEnumValueList &values = e->values(); + for (AbstractMetaEnumValue *v : values) { + if (v->name() == enumValueName) + return e; + } + } + + if (typeEntry()->designatedInterface()) + return extractInterface()->findEnumForValue(enumValueName); + + if (baseClass()) + return baseClass()->findEnumForValue(enumValueName); + + return 0; +} + + +static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) +{ + if (!type) + return; + + Q_ASSERT(metaClass); + const TypeEntry *entry = (type ? type->typeEntry() : 0); + if (entry && entry->isComplex()) { + const ComplexTypeEntry *centry = static_cast(entry); + ComplexTypeEntry *class_entry = metaClass->typeEntry(); + if (class_entry && centry->include().isValid()) + class_entry->addExtraInclude(centry->include()); + } + + if (type->hasInstantiations()) { + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) + addExtraIncludeForType(metaClass, instantiation); + } +} + +static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, const AbstractMetaFunction *meta_function) +{ + Q_ASSERT(metaClass); + Q_ASSERT(meta_function); + addExtraIncludeForType(metaClass, meta_function->type()); + + const AbstractMetaArgumentList &arguments = meta_function->arguments(); + for (AbstractMetaArgument *argument : arguments) + addExtraIncludeForType(metaClass, argument->type()); +} + +void AbstractMetaClass::fixFunctions() +{ + if (m_functionsFixed) + return; + else + m_functionsFixed = true; + + AbstractMetaClass *superClass = baseClass(); + AbstractMetaFunctionList funcs = functions(); + + if (superClass) + superClass->fixFunctions(); + int iface_idx = 0; + while (superClass || iface_idx < interfaces().size()) { + // 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. + AbstractMetaFunctionList superFuncs; + if (superClass) { + // 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 -= AbstractMetaAttributes::FinalInTargetLang; + } + superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements); + AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); + superFuncs += virtuals; + } else { + superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions); + AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions); + superFuncs += virtuals; + } + + QSet funcsToAdd; + for (int sfi = 0; sfi < superFuncs.size(); ++sfi) { + AbstractMetaFunction *sf = superFuncs.at(sfi); + + if (sf->isRemovedFromAllLanguages(sf->implementingClass())) + continue; + + // skip functions added in base classes + if (sf->isUserAdded() && sf->declaringClass() != this) + continue; + + // 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 = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction()); + for (int fi = 0; fi < funcs.size(); ++fi) { + AbstractMetaFunction *f = funcs.at(fi); + if (f->isRemovedFromAllLanguages(f->implementingClass())) + continue; + + + const AbstractMetaFunction::CompareResult cmp = f->compareTo(sf); + + if (cmp & AbstractMetaFunction::EqualModifiedName) { + add = false; + if (cmp & AbstractMetaFunction::EqualArguments) { + // Same function, propegate virtual... + if (!(cmp & AbstractMetaFunction::EqualAttributes)) { + if (!f->isEmptyFunction()) { + if (!sf->isFinalInCpp() && f->isFinalInCpp()) { + *f -= AbstractMetaAttributes::FinalInCpp; + } + if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { + *f -= AbstractMetaAttributes::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 + } + } + + if (f->visibility() != sf->visibility()) { + QString warn = QStringLiteral("visibility of function '%1' modified in class '%2'") + .arg(f->name(), name()); + qCWarning(lcShiboken).noquote().nospace() << warn; +#if 0 + // If new visibility is private, we can't + // do anything. If it isn't, then we + // prefer the parent class's visibility + // setting for the function. + if (!f->isPrivate() && !sf->isPrivate()) + f->setVisibility(sf->visibility()); +#endif + // 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()) { + f->setFunctionType(AbstractMetaFunction::EmptyFunction); + *f += AbstractMetaAttributes::FinalInTargetLang; + *f += AbstractMetaAttributes::FinalInCpp; + } + } + + // 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; + } else if (mod.isPrivate()) { + isBaseImplPrivate = true; + break; + } + } + + if (!hasNonFinalModifier && !isBaseImplPrivate) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Shadowing: %1::%2 and %3::%4") + .arg(sf->implementingClass()->name(), sf->signature(), + f->implementingClass()->name(), f->signature()); + } + } + } + + } + + if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) { + AbstractMetaArgumentList arguments; + if (f->arguments().size() < sf->arguments().size()) + arguments = sf->arguments(); + else + arguments = f->arguments(); + //TODO: fix this + //for (int i=0; isetDefaultValueExpression("<#>" + QString()); + } + + + // Otherwise we have function shadowing and we can + // skip the thing... + } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) { + // In the case of function shadowing where the function name has been altered to + // avoid conflict, we don't copy in the original. + add = false; + } + } + + if (add) + funcsToAdd << sf; + } + + for (AbstractMetaFunction *f : qAsConst(funcsToAdd)) + funcs << f->copy(); + + if (superClass) + superClass = superClass->baseClass(); + else + iface_idx++; + } + + bool hasPrivateConstructors = false; + bool hasPublicConstructors = false; + for (AbstractMetaFunction *func : qAsConst(funcs)) { + const FunctionModificationList &mods = func->modifications(this); + for (const FunctionModification &mod : mods) { + if (mod.isRenameModifier()) { + func->setName(mod.renamedTo()); + } + } + + // Make sure class is abstract if one of the functions is + if (func->isAbstract()) { + (*this) += AbstractMetaAttributes::Abstract; + (*this) -= AbstractMetaAttributes::Final; + } + + if (func->isConstructor()) { + if (func->isPrivate()) + hasPrivateConstructors = true; + else + hasPublicConstructors = true; + } + + + + // Make sure that we include files for all classes that are in use + + if (!func->isRemovedFrom(this, TypeSystem::ShellCode)) + addExtraIncludesForFunction(this, func); + } + + if (hasPrivateConstructors && !hasPublicConstructors) { + (*this) += AbstractMetaAttributes::Abstract; + (*this) -= AbstractMetaAttributes::Final; + } + + for (AbstractMetaFunction *f1 : qAsConst(funcs)) { + for (AbstractMetaFunction *f2 : qAsConst(funcs)) { + if (f1 != f2) { + const AbstractMetaFunction::CompareResult cmp = f1->compareTo(f2); + if ((cmp & AbstractMetaFunction::EqualName) + && !f1->isFinalInCpp() + && f2->isFinalInCpp()) { + *f2 += AbstractMetaAttributes::FinalOverload; + } + } + } + } + + setFunctions(funcs); +} + + +QString AbstractMetaType::minimalSignature() const +{ + QString minimalSignature; + if (isConstant()) + minimalSignature += QLatin1String("const "); + minimalSignature += typeEntry()->qualifiedCppName(); + if (hasInstantiations()) { + AbstractMetaTypeList instantiations = this->instantiations(); + minimalSignature += QLatin1String("< "); + for (int i = 0; i < instantiations.size(); ++i) { + if (i > 0) + minimalSignature += QLatin1Char(','); + minimalSignature += instantiations[i]->minimalSignature(); + } + minimalSignature += QLatin1String(" >"); + } + + for (int j = 0; j < indirections(); ++j) + minimalSignature += QLatin1Char('*'); + switch (referenceType()) { + case NoReference: + break; + case LValueReference: + minimalSignature += QLatin1Char('&'); + break; + case RValueReference: + minimalSignature += QLatin1String("&&"); + break; + } + + return minimalSignature; +} + +bool AbstractMetaType::hasNativeId() const +{ + return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased(); +} + +bool AbstractMetaType::isTargetLangEnum() const +{ + return isEnum() && !static_cast(typeEntry())->forceInteger(); +} + +bool AbstractMetaType::isTargetLangFlags() const +{ + return isFlags() && !static_cast(typeEntry())->forceInteger(); +} + + +/******************************************************************************* + * Other stuff... + */ + + +AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &classes, + const EnumTypeEntry *entry) +{ + Q_ASSERT(entry->isEnum()); + + QString qualifiedName = entry->qualifiedCppName(); + int pos = qualifiedName.lastIndexOf(QLatin1String("::")); + + QString enumName; + QString className; + + if (pos > 0) { + enumName = qualifiedName.mid(pos + 2); + className = qualifiedName.mid(0, pos); + } else { + enumName = qualifiedName; + className = TypeDatabase::globalNamespaceClassName(entry); + } + + AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes, className); + if (!metaClass) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("AbstractMeta::findEnum(), unknown class '%1' in '%2'") + .arg(className, entry->qualifiedCppName()); + return 0; + } + + return metaClass->findEnum(enumName); +} + +AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, + const QString &name) +{ + QStringList lst = name.split(QLatin1String("::")); + + if (lst.size() > 1) { + QString prefixName = lst.at(0); + QString enumName = lst.at(1); + + AbstractMetaClass* cl = findClass(classes, prefixName); + if (cl) + return cl->findEnumValue(enumName, 0); + } + + for (AbstractMetaClass *metaClass : classes) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *metaEnum : enums) { + AbstractMetaEnumValue* enumValue = metaClass->findEnumValue(name, metaEnum); + if (enumValue) + return enumValue; + } + } + + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("no matching enum '%1'").arg(name); + return 0; +} + +/*! + * Searches the list after a class that mathces \a name; either as + * C++, Target language base name or complete Target language package.class name. + */ + +AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + const QString &name) +{ + if (name.isEmpty()) + return 0; + + for (AbstractMetaClass *c : classes) { + if (c->qualifiedCppName() == name) + return c; + } + + for (AbstractMetaClass *c : classes) { + if (c->fullName() == name) + return c; + } + + for (AbstractMetaClass *c : classes) { + if (c->name() == name) + return c; + } + + return 0; +} + +AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes, + const TypeEntry* typeEntry) +{ + for (AbstractMetaClass* c : classes) { + if (c->typeEntry() == typeEntry) + return c; + } + return 0; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaClass *ac) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "AbstractMetaClass("; + if (ac) { + d << '"' << ac->fullName() << '"'; + if (ac->m_baseClass) + d << ", inherits \"" << ac->m_baseClass->name() << '"'; + const AbstractMetaEnumList &enums = ac->enums(); + if (!enums.isEmpty()) + d << ", enums[" << enums.size() << "]=" << enums; + const AbstractMetaFunctionList &functions = ac->functions(); + if (!functions.isEmpty()) { + const int count = functions.size(); + d << ", functions=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + if (d.verbosity() > 2) + d << functions.at(i); + else +#endif + formatMetaFunctionBrief(d, functions.at(i)); + } + d << ')'; + } + const AbstractMetaFieldList &fields = ac->fields(); + if (!fields.isEmpty()) { + const int count = fields.size(); + d << ", fields=[" << count << "]("; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + formatMetaField(d, fields.at(i)); + } + d << ')'; + } + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +QString AbstractMetaEnum::name() const +{ + return m_typeEntry->targetLangName(); +} + +QString AbstractMetaEnum::qualifier() const +{ + return m_typeEntry->targetLangQualifier(); +} + +QString AbstractMetaEnum::package() const +{ + return m_typeEntry->targetLangPackage(); +} + +bool AbstractMetaEnum::isAnonymous() const +{ + return m_typeEntry->isAnonymous(); +} diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h new file mode 100644 index 000000000..4d6d5fb1f --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -0,0 +1,1976 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACTMETALANG_H +#define ABSTRACTMETALANG_H + +#include "abstractmetalang_typedefs.h" +#include "typesystem_enums.h" +#include "typesystem_typedefs.h" + +#include "parser/codemodel_enums.h" + +#include +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) + +class AbstractMeta; +class AbstractMetaClass; +class AbstractMetaField; +class AbstractMetaFunction; +class AbstractMetaType; +class AbstractMetaVariable; +class AbstractMetaArgument; +class AbstractMetaEnumValue; +class AbstractMetaEnum; +class QPropertySpec; + +class CodeSnip; +class ComplexTypeEntry; +class EnumTypeEntry; +class FlagsTypeEntry; +class FunctionTypeEntry; +class TypeEntry; + +struct ArgumentOwner; +struct FieldModification; +struct FunctionModification; +struct ReferenceCount; + +class Documentation +{ +public: + enum Format { + Native, + Target + }; + + Documentation() + : m_format(Documentation::Native) {} + + Documentation(const QString& value, Format fmt = Documentation::Native) + : m_data(value), m_format(fmt) {} + + QString value() const + { + return m_data; + } + + void setValue(const QString& value, Format fmt = Documentation::Native) + { + m_data = value; m_format = fmt; + } + + Documentation::Format format() const + { + return m_format; + } + +private: + QString m_data; + Format m_format; + +}; + +class AbstractMetaAttributes +{ + Q_GADGET +public: + AbstractMetaAttributes() : m_attributes(0), m_originalAttributes(0) {}; + + enum Attribute { + None = 0x00000000, + + Private = 0x00000001, + Protected = 0x00000002, + Public = 0x00000004, + Friendly = 0x00000008, + Visibility = 0x0000000f, + + Native = 0x00000010, + Abstract = 0x00000020, + Static = 0x00000040, + + FinalInTargetLang = 0x00000080, + FinalInCpp = 0x00000100, + ForceShellImplementation = 0x00000200, + + GetterFunction = 0x00000400, + SetterFunction = 0x00000800, + + FinalOverload = 0x00001000, + InterfaceFunction = 0x00002000, + + PropertyReader = 0x00004000, + PropertyWriter = 0x00008000, + PropertyResetter = 0x00010000, + + Fake = 0x00020000, + + Invokable = 0x00040000, + + Final = FinalInTargetLang | FinalInCpp + }; + Q_DECLARE_FLAGS(Attributes, Attribute) + Q_FLAG(Attribute) + + Attributes attributes() const + { + return m_attributes; + } + + void setAttributes(Attributes attributes) + { + m_attributes = attributes; + } + + Attributes originalAttributes() const + { + return m_originalAttributes; + } + + void setOriginalAttributes(Attributes attributes) + { + m_originalAttributes = attributes; + } + + Attributes visibility() const + { + return m_attributes & Visibility; + } + + void setVisibility(Attributes visi) + { + m_attributes = (m_attributes & ~Visibility) | visi; + } + + void operator+=(Attribute attribute) + { + m_attributes |= attribute; + } + + void operator-=(Attribute attribute) + { + m_attributes &= ~attribute; + } + + bool isNative() const + { + return m_attributes & Native; + } + + bool isFinal() const + { + return (m_attributes & Final) == Final; + } + + bool isFinalInTargetLang() const + { + return m_attributes & FinalInTargetLang; + } + + bool isFinalInCpp() const + { + return m_attributes & FinalInCpp; + } + + bool isAbstract() const + { + return m_attributes & Abstract; + } + + bool isStatic() const + { + return m_attributes & Static; + } + + bool isForcedShellImplementation() const + { + return m_attributes & ForceShellImplementation; + } + + bool isInterfaceFunction() const + { + return m_attributes & InterfaceFunction; + } + + bool isFinalOverload() const + { + return m_attributes & FinalOverload; + } + + bool isInvokable() const + { + return m_attributes & Invokable; + } + + bool isPropertyReader() const + { + return m_attributes & PropertyReader; + } + + bool isPropertyWriter() const + { + return m_attributes & PropertyWriter; + } + + bool isPropertyResetter() const + { + return m_attributes & PropertyResetter; + } + + bool isPrivate() const + { + return m_attributes & Private; + } + + bool isProtected() const + { + return m_attributes & Protected; + } + + bool isPublic() const + { + return m_attributes & Public; + } + + bool isFriendly() const + { + return m_attributes & Friendly; + } + + bool wasPrivate() const + { + return m_originalAttributes & Private; + } + + bool wasProtected() const + { + return m_originalAttributes & Protected; + } + + bool wasPublic() const + { + return m_originalAttributes & Public; + } + + bool wasFriendly() const + { + return m_originalAttributes & Friendly; + } + + void setDocumentation(const Documentation& doc) + { + m_doc = doc; + } + + Documentation documentation() const + { + return m_doc; + } + +private: + Attributes m_attributes; + Attributes m_originalAttributes; + Documentation m_doc; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaAttributes::Attributes) + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaAttributes *aa); +#endif + +class AbstractMetaType +{ + Q_GADGET +public: + + enum TypeUsagePattern { + InvalidPattern, + PrimitivePattern, + FlagsPattern, + EnumPattern, + ValuePattern, + StringPattern, + CharPattern, + ObjectPattern, + QObjectPattern, + ValuePointerPattern, + NativePointerPattern, + ContainerPattern, + SmartPointerPattern, + VariantPattern, + VarargsPattern, + JObjectWrapperPattern, + ArrayPattern, + ThreadPattern + }; + Q_ENUM(TypeUsagePattern) + + AbstractMetaType(); + ~AbstractMetaType(); + + QString package() const; + QString name() const; + QString fullName() const; + + void setTypeUsagePattern(TypeUsagePattern pattern) + { + m_pattern = pattern; + } + TypeUsagePattern typeUsagePattern() const + { + return m_pattern; + } + + // true when use pattern is container + bool hasInstantiations() const + { + return !m_instantiations.isEmpty(); + } + + void addInstantiation(AbstractMetaType* inst, bool owner = false) + { + if (owner) + m_children << inst; + m_instantiations << inst; + } + + void setInstantiations(const AbstractMetaTypeList &insts, bool owner = false) + { + m_instantiations = insts; + if (owner) { + m_children.clear(); + m_children = insts; + } + } + + AbstractMetaTypeList instantiations() const + { + return m_instantiations; + } + + void setInstantiationInCpp(bool incpp) + { + m_cppInstantiation = incpp; + } + bool hasInstantiationInCpp() const + { + return hasInstantiations() && m_cppInstantiation; + } + + QString minimalSignature() const; + + // true when the type is a QtJambiObject subclass + bool hasNativeId() const; + + // returns true if the typs is used as a non complex primitive, no & or *'s + bool isPrimitive() const + { + return m_pattern == PrimitivePattern; + } + + // returns true if the type is used as an enum + bool isEnum() const + { + return m_pattern == EnumPattern; + } + + // returns true if the type is used as a QObject * + bool isQObject() const + { + return m_pattern == QObjectPattern; + } + + // returns true if the type is used as an object, e.g. Xxx * + bool isObject() const + { + return m_pattern == ObjectPattern; + } + + // returns true if the type is used as an array, e.g. Xxx[42] + bool isArray() const + { + return m_pattern == ArrayPattern; + } + + // returns true if the type is used as a value type (X or const X &) + bool isValue() const + { + return m_pattern == ValuePattern; + } + + bool isValuePointer() const + { + return m_pattern == ValuePointerPattern; + } + + // returns true for more complex types... + bool isNativePointer() const + { + return m_pattern == NativePointerPattern; + } + + // returns true if the type was originally a QString or const QString & or equivalent for QLatin1String + bool isTargetLangString() const + { + return m_pattern == StringPattern; + } + + // returns true if the type was originally a QChar or const QChar & + bool isTargetLangChar() const + { + return m_pattern == CharPattern; + } + + // return true if the type was originally a QVariant or const QVariant & + bool isVariant() const + { + return m_pattern == VariantPattern; + } + + // return true if the type was originally a varargs + bool isVarargs() const + { + return m_pattern == VarargsPattern; + } + + // return true if the type was originally a JObjectWrapper or const JObjectWrapper & + bool isJObjectWrapper() const + { + return m_pattern == JObjectWrapperPattern; + } + + // returns true if the type was used as a container + bool isContainer() const + { + return m_pattern == ContainerPattern; + } + + // returns true if the type was used as a smart pointer + bool isSmartPointer() const { return m_pattern == SmartPointerPattern; } + + // returns true if the type was used as a flag + bool isFlags() const + { + return m_pattern == FlagsPattern; + } + + // returns true if the type was used as a thread + bool isThread() const + { + return m_pattern == ThreadPattern; + } + + bool isConstant() const + { + return m_constant; + } + void setConstant(bool constant) + { + m_constant = constant; + } + + ReferenceType referenceType() const { return m_referenceType; } + void setReferenceType(ReferenceType ref) { m_referenceType = ref; } + + /** + * Says if the type is to be implemented using target language + * equivalent of C++ enums, i.e. not plain ints. + * /return true if the type is to be implemented using target + * language enums + */ + bool isTargetLangEnum() const; + bool isIntegerEnum() const + { + return isEnum() && !isTargetLangEnum(); + } + + /** + * Says if the type is to be implemented using target language + * equivalent of Qt's QFlags, i.e. not plain ints. + * /return true if the type is to be implemented using target + * language QFlags + */ + bool isTargetLangFlags() const; + bool isIntegerFlags() const + { + return isFlags() && !isTargetLangFlags(); + } + + int actualIndirections() const + { + return m_indirections + (m_referenceType == LValueReference ? 1 : 0); + } + int indirections() const + { + return m_indirections; + } + void setIndirections(int indirections) + { + m_indirections = indirections; + } + + void setArrayElementCount(int n) + { + m_arrayElementCount = n; + } + int arrayElementCount() const + { + return m_arrayElementCount; + } + + const AbstractMetaType *arrayElementType() const + { + return m_arrayElementType; + } + void setArrayElementType(const AbstractMetaType *t) + { + m_arrayElementType = t; + } + + QString cppSignature() const; + + AbstractMetaType *copy() const; + + const TypeEntry *typeEntry() const + { + return m_typeEntry; + } + void setTypeEntry(const TypeEntry *type) + { + m_typeEntry = type; + } + + void setOriginalTypeDescription(const QString &otd) + { + m_originalTypeDescription = otd; + } + QString originalTypeDescription() const + { + return m_originalTypeDescription; + } + + void setOriginalTemplateType(const AbstractMetaType *type) + { + m_originalTemplateType = type; + } + const AbstractMetaType *originalTemplateType() const + { + return m_originalTemplateType; + } + + AbstractMetaType *getSmartPointerInnerType() const + { + Q_ASSERT(isSmartPointer()); + AbstractMetaTypeList instantiations = this->instantiations(); + Q_ASSERT(!instantiations.isEmpty()); + AbstractMetaType *innerType = instantiations.at(0); + return innerType; + } + + QString getSmartPointerInnerTypeName() const + { + Q_ASSERT(isSmartPointer()); + AbstractMetaType *innerType = getSmartPointerInnerType(); + Q_ASSERT(innerType); + return innerType->name(); + } + + /// Decides and sets the proper usage patter for the current meta type. + void decideUsagePattern(); + + bool hasTemplateChildren() const; + +private: + TypeUsagePattern determineUsagePattern() const; + + const TypeEntry *m_typeEntry; + AbstractMetaTypeList m_instantiations; + QString m_package; + mutable QString m_name; + mutable QString m_cachedCppSignature; + QString m_originalTypeDescription; + + int m_arrayElementCount; + const AbstractMetaType *m_arrayElementType; + const AbstractMetaType *m_originalTemplateType; + + TypeUsagePattern m_pattern; + uint m_constant : 1; + uint m_cppInstantiation : 1; + int m_indirections : 4; + uint m_reserved : 26; // unused + ReferenceType m_referenceType; + AbstractMetaTypeList m_children; + + Q_DISABLE_COPY(AbstractMetaType); +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaType *at); +#endif + +class AbstractMetaVariable +{ +public: + AbstractMetaVariable() : m_type(0), m_hasName(false) {} + AbstractMetaVariable(const AbstractMetaVariable &other); + + virtual ~AbstractMetaVariable() + { + delete m_type; + } + + AbstractMetaType *type() const + { + return m_type; + } + void setType(AbstractMetaType *type) + { + Q_ASSERT(m_type == 0); + m_type = type; + } + void replaceType(AbstractMetaType *type) + { + if (m_type) + delete m_type; + m_type = type; + } + + QString name() const + { + return m_name; + } + void setName(const QString &name, bool realName = true) + { + m_name = name; + m_hasName = realName; + } + bool hasName() const + { + return m_hasName; + } + QString originalName() const + { + return m_originalName; + } + void setOriginalName(const QString& name) + { + m_originalName = name; + } + void setDocumentation(const Documentation& doc) + { + m_doc = doc; + } + Documentation documentation() const + { + return m_doc; + } + +private: + QString m_originalName; + QString m_name; + AbstractMetaType *m_type; + bool m_hasName; + + Documentation m_doc; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaVariable *av); +#endif + +class AbstractMetaArgument : public AbstractMetaVariable +{ +public: + AbstractMetaArgument() : m_argumentIndex(0) {}; + + QString defaultValueExpression() const + { + return m_expression; + } + void setDefaultValueExpression(const QString &expr) + { + m_expression = expr; + } + + QString originalDefaultValueExpression() const + { + return m_originalExpression; + } + void setOriginalDefaultValueExpression(const QString &expr) + { + m_originalExpression = expr; + } + + QString toString() const + { + return type()->name() + QLatin1Char(' ') + AbstractMetaVariable::name() + + (m_expression.isEmpty() ? QString() : QLatin1String(" = ") + m_expression); + } + + int argumentIndex() const + { + return m_argumentIndex; + } + void setArgumentIndex(int argIndex) + { + m_argumentIndex = argIndex; + } + + AbstractMetaArgument *copy() const; +private: + QString m_expression; + QString m_originalExpression; + int m_argumentIndex; + + friend class AbstractMetaClass; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaArgument *aa); +#endif + +class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes +{ +public: + AbstractMetaField(); + ~AbstractMetaField(); + + const AbstractMetaClass *enclosingClass() const + { + return m_class; + } + void setEnclosingClass(const AbstractMetaClass *cls) + { + m_class = cls; + } + + const AbstractMetaFunction *getter() const; + const AbstractMetaFunction *setter() const; + + FieldModificationList modifications() const; + + bool isModifiedRemoved(int types = TypeSystem::All) const; + + using AbstractMetaVariable::setDocumentation; + using AbstractMetaVariable::documentation; + + AbstractMetaField *copy() const; + +private: + mutable AbstractMetaFunction *m_getter; + mutable AbstractMetaFunction *m_setter; + const AbstractMetaClass *m_class; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaField *af); +#endif + +class AbstractMetaFunction : public AbstractMetaAttributes +{ + Q_GADGET +public: + enum FunctionType { + ConstructorFunction, + CopyConstructorFunction, + MoveConstructorFunction, + AssignmentOperatorFunction, + MoveAssignmentOperatorFunction, + DestructorFunction, + NormalFunction, + SignalFunction, + EmptyFunction, + SlotFunction, + GlobalScopeFunction + }; + Q_ENUM(FunctionType) + + enum CompareResultFlag { + EqualName = 0x00000001, + EqualArguments = 0x00000002, + EqualAttributes = 0x00000004, + EqualImplementor = 0x00000008, + EqualReturnType = 0x00000010, + EqualDefaultValueOverload = 0x00000020, + EqualModifiedName = 0x00000040, + + NameLessThan = 0x00001000, + + PrettySimilar = EqualName | EqualArguments, + Equal = 0x0000001f, + NotEqual = 0x00001000 + }; + Q_DECLARE_FLAGS(CompareResult, CompareResultFlag) + Q_FLAG(CompareResultFlag) + + AbstractMetaFunction() + : m_typeEntry(0), + m_functionType(NormalFunction), + m_type(0), + m_class(0), + m_implementingClass(0), + m_declaringClass(0), + m_propertySpec(0), + m_constant(false), + m_invalid(false), + m_reverse(false), + m_userAdded(false), + m_explicit(false), + m_pointerOperator(false), + m_isCallOperator(false) + { + } + + ~AbstractMetaFunction(); + + QString name() const + { + return m_name; + } + + void setName(const QString &name) + { + m_name = name; + } + + QString originalName() const + { + return m_originalName.isEmpty() ? name() : m_originalName; + } + + void setOriginalName(const QString &name) + { + m_originalName = name; + } + + void setReverseOperator(bool reverse) + { + m_reverse = reverse; + } + + bool isReverseOperator() const + { + return m_reverse; + } + + /** + * Returns true if this is a operator and the "self" operand is a pointer. + * e.g. class Foo {}; operator+(SomeEnum, Foo*); + */ + bool isPointerOperator() const + { + return m_pointerOperator; + } + + void setPointerOperator(bool value) + { + m_pointerOperator = value; + } + + void setExplicit(bool isExplicit) + { + m_explicit = isExplicit; + } + /** + * Says if the function (a constructor) was declared as explicit in C++. + * \return true if the function was declared as explicit in C++ + */ + bool isExplicit() const + { + return m_explicit; + } + + static bool isConversionOperator(QString funcName); + bool isConversionOperator() const + { + return isConversionOperator(originalName()); + } + + static bool isOperatorOverload(QString funcName); + bool isOperatorOverload() const + { + return isOperatorOverload(originalName()); + } + bool isCastOperator() const; + + bool isArithmeticOperator() const; + bool isBitwiseOperator() const; + bool isComparisonOperator() const; + bool isLogicalOperator() const; + bool isSubscriptOperator() const; + bool isAssignmentOperator() const; // Assignment or move assignment + bool isOtherOperator() const; + + /** + * Informs the arity of the operator or -1 if the function is not + * an operator overload. + * /return the arity of the operator or -1 + */ + int arityOfOperator() const; + bool isUnaryOperator() const { return arityOfOperator() == 1; } + bool isBinaryOperator() const { return arityOfOperator() == 2; } + bool isInplaceOperator() const; + + // TODO: ths function *should* know if it is virtual + // instead of asking to your implementing class. + bool isVirtual() const; + bool isThread() const; + bool allowThread() const; + QString modifiedName() const; + + QString minimalSignature() const; + QStringList possibleIntrospectionCompatibleSignatures() const; + + QString marshalledName() const; + + // true if one or more of the arguments are of QtJambiObject subclasses + bool argumentsHaveNativeId() const + { + for (const AbstractMetaArgument *arg : m_arguments) { + if (arg->type()->hasNativeId()) + return true; + } + + return false; + } + + bool isModifiedRemoved(int types = TypeSystem::All) const; + + AbstractMetaType *type() const + { + return m_type; + } + void setType(AbstractMetaType *type) + { + Q_ASSERT(m_type == 0); + m_type = type; + } + + void replaceType(AbstractMetaType *type) + { + if (m_type) + delete m_type; + m_type = type; + } + + // The class that has this function as a member. + const AbstractMetaClass *ownerClass() const + { + return m_class; + } + void setOwnerClass(const AbstractMetaClass *cls) + { + m_class = cls; + } + + // The first class in a hierarchy that declares the function + const AbstractMetaClass *declaringClass() const + { + return m_declaringClass; + } + void setDeclaringClass(const AbstractMetaClass *cls) + { + m_declaringClass = cls; + } + + // The class that actually implements this function + const AbstractMetaClass *implementingClass() const + { + return m_implementingClass; + } + void setImplementingClass(const AbstractMetaClass *cls) + { + m_implementingClass = cls; + } + + bool needsCallThrough() const; + + AbstractMetaArgumentList arguments() const + { + return m_arguments; + } + void setArguments(const AbstractMetaArgumentList &arguments) + { + m_arguments = arguments; + } + void addArgument(AbstractMetaArgument *argument) + { + m_arguments << argument; + } + int actualMinimumArgumentCount() const; + + void setInvalid(bool on) + { + m_invalid = on; + } + bool isInvalid() const + { + return m_invalid; + } + bool isDeprecated() const; + bool isDestructor() const + { + return functionType() == DestructorFunction; + } + bool isConstructor() const + { + return m_functionType == ConstructorFunction || m_functionType == CopyConstructorFunction + || m_functionType == MoveConstructorFunction; + } + bool isNormal() const + { + return functionType() == NormalFunction || isSlot() || isInGlobalScope(); + } + bool isInGlobalScope() const + { + return functionType() == GlobalScopeFunction; + } + bool isSignal() const + { + return functionType() == SignalFunction; + } + bool isSlot() const + { + return functionType() == SlotFunction; + } + bool isEmptyFunction() const + { + return functionType() == EmptyFunction; + } + FunctionType functionType() const + { + return m_functionType; + } + void setFunctionType(FunctionType type) + { + m_functionType = type; + } + + bool usesRValueReferences() const; + QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const; + QString signature() const; + QString targetLangSignature(bool minimal = false) const; + bool shouldReturnThisObject() const + { + return QLatin1String("this") == argumentReplaced(0); + } + bool shouldIgnoreReturnValue() const + { + return QLatin1String("void") == argumentReplaced(0); + } + + bool isConstant() const + { + return m_constant; + } + void setConstant(bool constant) + { + m_constant = constant; + } + + /// Returns true if the AbstractMetaFunction was added by the user via the type system description. + bool isUserAdded() const + { + return m_userAdded; + } + void setUserAdded(bool userAdded) + { + m_userAdded = userAdded; + } + + QString toString() const + { + return m_name; + } + + CompareResult compareTo(const AbstractMetaFunction *other) const; + + bool operator <(const AbstractMetaFunction &a) const; + + AbstractMetaFunction *copy() const; + + QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const; + bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const; + QString conversionRule(TypeSystem::Language language, int idx) const; + QVector referenceCounts(const AbstractMetaClass *cls, int idx = -2) const; + ArgumentOwner argumentOwner(const AbstractMetaClass *cls, int idx) const; + + bool nullPointersDisabled(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; + QString nullPointerDefaultValue(const AbstractMetaClass *cls = 0, int argument_idx = 0) const; + + bool resetObjectAfterUse(int argument_idx) const; + + // Returns whether garbage collection is disabled for the argument in any context + bool disabledGarbageCollection(const AbstractMetaClass *cls, int key) const; + + // Returns the ownership rules for the given argument in the given context + TypeSystem::Ownership ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int idx) const; + + bool isVirtualSlot() const; + + QString typeReplaced(int argument_index) const; + bool isRemovedFromAllLanguages(const AbstractMetaClass *) const; + bool isRemovedFrom(const AbstractMetaClass *, TypeSystem::Language language) const; + bool argumentRemoved(int) const; + + QString argumentReplaced(int key) const; + bool needsSuppressUncheckedWarning() const; + + bool hasModifications(const AbstractMetaClass *implementor) const; + /** + * Verifies if any modification to the function is an inject code. + * \return true if there is inject code modifications to the function. + */ + bool hasInjectedCode() const; + /** + * Returns a list of code snips for this function. + * The code snips can be filtered by position and language. + * \return list of code snips + */ + CodeSnipList injectedCodeSnips(TypeSystem::CodeSnipPosition position = TypeSystem::CodeSnipPositionAny, + TypeSystem::Language language = TypeSystem::All) const; + + /** + * Verifies if any modification to the function alters/removes its + * arguments types or default values. + * \return true if there is some modification to function signature + */ + bool hasSignatureModifications() const; + FunctionModificationList modifications(const AbstractMetaClass* implementor = 0) const; + + /** + * 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 = 0) const; + + void setPropertySpec(QPropertySpec *spec) + { + m_propertySpec = spec; + } + + QPropertySpec *propertySpec() const + { + return m_propertySpec; + } + + FunctionTypeEntry* typeEntry() const + { + return m_typeEntry; + } + + void setTypeEntry(FunctionTypeEntry* typeEntry) + { + m_typeEntry = typeEntry; + } + + bool isCallOperator() const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebugVerbose(QDebug &d) const; +#endif + +private: + QString m_name; + QString m_originalName; + mutable QString m_cachedMinimalSignature; + mutable QString m_cachedSignature; + mutable QString m_cachedModifiedName; + + FunctionTypeEntry* m_typeEntry; + FunctionType m_functionType; + AbstractMetaType *m_type; + const AbstractMetaClass *m_class; + const AbstractMetaClass *m_implementingClass; + const AbstractMetaClass *m_declaringClass; + QPropertySpec *m_propertySpec; + AbstractMetaArgumentList m_arguments; + uint m_constant : 1; + uint m_invalid : 1; + uint m_reverse : 1; + uint m_userAdded : 1; + uint m_explicit : 1; + uint m_pointerOperator : 1; + uint m_isCallOperator : 1; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::CompareResult) + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaFunction *af); +#endif + +class AbstractMetaEnumValue +{ +public: + AbstractMetaEnumValue() + : m_valueSet(false), m_value(0) + { + } + + int value() const + { + return m_value; + } + + void setValue(int value) + { + m_valueSet = true; + m_value = value; + } + + QString stringValue() const + { + return m_stringValue; + } + + void setStringValue(const QString &v) + { + m_stringValue = v; + } + + QString name() const + { + return m_name; + } + + void setName(const QString &name) + { + m_name = name; + } + + bool isValueSet() const + { + return m_valueSet; + } + + void setDocumentation(const Documentation& doc) + { + m_doc = doc; + } + + Documentation documentation() const + { + return m_doc; + } + +private: + QString m_name; + QString m_stringValue; + + bool m_valueSet; + int m_value; + + Documentation m_doc; +}; + +class AbstractMetaEnum : public AbstractMetaAttributes +{ +public: + AbstractMetaEnum() : m_typeEntry(0), m_class(0), m_hasQenumsDeclaration(false) {} + ~AbstractMetaEnum() + { + qDeleteAll(m_enumValues); + } + + AbstractMetaEnumValueList values() const + { + return m_enumValues; + } + + void addEnumValue(AbstractMetaEnumValue *enumValue) + { + m_enumValues << enumValue; + } + + QString name() const; + + QString qualifier() const; + + QString package() const; + + QString fullName() const + { + return package() + QLatin1Char('.') + qualifier() + QLatin1Char('.') + name(); + } + + // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class? + void setHasQEnumsDeclaration(bool on) + { + m_hasQenumsDeclaration = on; + } + + bool hasQEnumsDeclaration() const + { + return m_hasQenumsDeclaration; + } + + EnumTypeEntry *typeEntry() const + { + return m_typeEntry; + } + + void setTypeEntry(EnumTypeEntry *entry) + { + m_typeEntry = entry; + } + + AbstractMetaClass *enclosingClass() const + { + return m_class; + } + + void setEnclosingClass(AbstractMetaClass *c) + { + m_class = c; + } + + bool isAnonymous() const; + +private: + AbstractMetaEnumValueList m_enumValues; + EnumTypeEntry *m_typeEntry; + AbstractMetaClass *m_class; + + uint m_hasQenumsDeclaration : 1; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AbstractMetaEnum *ae); +#endif + +class AbstractMetaClass : public AbstractMetaAttributes +{ + Q_GADGET +public: + enum FunctionQueryOption { + Constructors = 0x0000001, // Only constructors + //Destructors = 0x0000002, // Only destructors. Not included in class. + VirtualFunctions = 0x0000004, // Only virtual functions (virtual in both TargetLang and C++) + FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang + FinalInCppFunctions = 0x0000010, // Only functions that are non-virtual in C++ + ClassImplements = 0x0000020, // Only functions implemented by the current class + Inconsistent = 0x0000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++) + StaticFunctions = 0x0000080, // Only static functions + Signals = 0x0000100, // Only signals + NormalFunctions = 0x0000200, // Only functions that aren't signals + Visible = 0x0000400, // Only public and protected functions + ForcedShellFunctions = 0x0000800, // Only functions that are overridden to be implemented in the shell class + WasPublic = 0x0001000, // Only functions that were originally public + WasProtected = 0x0002000, // Only functions that were originally protected + 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++ + NonEmptyFunctions = 0x0040000, // Only functions with target language API implementations + VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang + AbstractFunctions = 0x0100000, // Only abstract functions + WasVisible = 0x0200000, // Only functions that were public or protected in the original code + NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang + NotRemovedFromShell = 0x0800000, // Only functions that have not been removed from the shell class + VirtualSlots = 0x1000000, // Only functions that are set as virtual slots in the type system + OperatorOverloads = 0x2000000 // Only functions that are operator overloads + }; + Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption) + Q_FLAG(FunctionQueryOption) + + enum OperatorQueryOption { + ArithmeticOp = 0x01, // Arithmetic: +, -, *, /, %, +=, -=, *=, /=, %=, ++, --, unary+, unary- + BitwiseOp = 0x02, // Bitwise: <<, <<=, >>, >>=, ~, &, &=, |, |=, ^, ^= + ComparisonOp = 0x04, // Comparison: <, <=, >, >=, !=, == + LogicalOp = 0x08, // Logical: !, &&, || + ConversionOp = 0x10, // Conversion: operator [const] TYPE() + SubscriptionOp = 0x20, // Subscription: [] + AssignmentOp = 0x40, // Assignment: = + OtherOp = 0x80, // The remaining operators: call(), etc + AllOperators = ArithmeticOp | BitwiseOp | ComparisonOp + | LogicalOp | ConversionOp | SubscriptionOp + | AssignmentOp | OtherOp + }; + Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption) + Q_FLAG(OperatorQueryOption) + + AbstractMetaClass() + : m_hasVirtuals(false), + m_isPolymorphic(false), + m_hasNonpublic(false), + m_hasVirtualSlots(false), + m_hasNonPrivateConstructor(false), + m_functionsFixed(false), + m_hasPrivateDestructor(false), + m_hasProtectedDestructor(false), + m_hasVirtualDestructor(false), + m_forceShellClass(false), + m_hasHashFunction(false), + m_hasEqualsOperator(false), + m_hasCloneOperator(false), + m_isTypeDef(false), + m_hasToStringCapability(false), + m_enclosingClass(0), + m_baseClass(0), + m_templateBaseClass(0), + m_extractedInterface(0), + m_typeEntry(0), + m_stream(false) + { + } + + virtual ~AbstractMetaClass(); + + AbstractMetaClass *extractInterface(); + void fixFunctions(); + + AbstractMetaFunctionList functions() const + { + return m_functions; + } + + void setFunctions(const AbstractMetaFunctionList &functions); + void addFunction(AbstractMetaFunction *function); + bool hasFunction(const AbstractMetaFunction *f) const; + bool hasFunction(const QString &str) const; + const AbstractMetaFunction* findFunction(const QString& functionName) const; + bool hasSignal(const AbstractMetaFunction *f) const; + + bool hasConstructors() const; + bool hasCopyConstructor() const; + bool hasPrivateCopyConstructor() const; + + void addDefaultConstructor(); + void addDefaultCopyConstructor(bool isPrivate = false); + + bool hasNonPrivateConstructor() const + { + return m_hasNonPrivateConstructor; + } + + void setHasNonPrivateConstructor(bool value) + { + m_hasNonPrivateConstructor = value; + } + + bool hasPrivateDestructor() const + { + return m_hasPrivateDestructor; + } + + void setHasPrivateDestructor(bool value) + { + m_hasPrivateDestructor = value; + } + + bool hasProtectedDestructor() const + { + return m_hasProtectedDestructor; + } + + void setHasProtectedDestructor(bool value) + { + m_hasProtectedDestructor = value; + } + + bool hasVirtualDestructor() const + { + return m_hasVirtualDestructor; + } + + void setHasVirtualDestructor(bool value) + { + m_hasVirtualDestructor = value; + } + + AbstractMetaFunctionList queryFunctionsByName(const QString &name) const; + AbstractMetaFunctionList queryFunctions(FunctionQueryOptions query) const; + AbstractMetaFunctionList functionsInTargetLang() const; + AbstractMetaFunctionList functionsInShellClass() const; + inline AbstractMetaFunctionList cppSignalFunctions() const; + AbstractMetaFunctionList publicOverrideFunctions() const; + AbstractMetaFunctionList virtualOverrideFunctions() const; + AbstractMetaFunctionList virtualFunctions() const; + AbstractMetaFunctionList implicitConversions() const; + + /** + * Retrieves all class' operator overloads that meet + * query criteria defined with the OperatorQueryOption + * enum. + * /param query composition of OperatorQueryOption enum values + * /return list of operator overload methods that meet the + * query criteria + */ + AbstractMetaFunctionList operatorOverloads(OperatorQueryOptions query = AllOperators) const; + + bool hasOperatorOverload() const; + bool hasArithmeticOperatorOverload() const; + bool hasBitwiseOperatorOverload() const; + bool hasComparisonOperatorOverload() const; + bool hasLogicalOperatorOverload() const; + bool hasSubscriptOperatorOverload() const; + bool hasAssignmentOperatorOverload() const; + bool hasConversionOperatorOverload() const; + + AbstractMetaFieldList fields() const + { + return m_fields; + } + + void setFields(const AbstractMetaFieldList &fields) + { + m_fields = fields; + } + + void addField(AbstractMetaField *field) + { + m_fields << field; + } + + AbstractMetaEnumList enums() const + { + return m_enums; + } + void setEnums(const AbstractMetaEnumList &enums) + { + m_enums = enums; + } + + void addEnum(AbstractMetaEnum *e) + { + m_enums << e; + } + + AbstractMetaEnum *findEnum(const QString &enumName); + AbstractMetaEnum *findEnumForValue(const QString &enumName); + AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum); + + AbstractMetaClassList interfaces() const + { + return m_interfaces; + } + void addInterface(AbstractMetaClass *interface); + void setInterfaces(const AbstractMetaClassList &interface); + + QString fullName() const + { + return package() + QLatin1Char('.') + name(); + } + + /** + * Retrieves the class name without any namespace/scope information. + * /return the class name without scope information + */ + QString name() const; + + QString baseClassName() const + { + return m_baseClass ? m_baseClass->name() : QString(); + } + + AbstractMetaClass *baseClass() const + { + return m_baseClass; + } + + void setBaseClass(AbstractMetaClass *base_class); + + const AbstractMetaClass *enclosingClass() const + { + return m_enclosingClass; + } + + void setEnclosingClass(AbstractMetaClass *cl) + { + m_enclosingClass = cl; + } + + const AbstractMetaClassList& innerClasses() const + { + return m_innerClasses; + } + + void addInnerClass(AbstractMetaClass* cl) + { + m_innerClasses << cl; + } + + void setInnerClasses(AbstractMetaClassList innerClasses) + { + m_innerClasses = innerClasses; + } + + QString package() const; + + bool isInterface() const; + + bool isNamespace() const; + + bool isQObject() const; + + bool isQtNamespace() const + { + return isNamespace() && name() == QLatin1String("Qt"); + } + + QString qualifiedCppName() const; + + bool hasSignals() const; + bool inheritsFrom(const AbstractMetaClass *other) const; + + void setForceShellClass(bool on) + { + m_forceShellClass = on; + } + + bool generateShellClass() const; + + bool hasVirtualSlots() const + { + return m_hasVirtualSlots; + } + + /** + * Says if a class has any virtual functions of its own. + * \return true if the class implements any virtual methods + */ + bool hasVirtualFunctions() const + { + return !isFinal() && m_hasVirtuals; + } + /** + * Says if the class that declares or inherits a virtual function. + * \return true if the class implements or inherits any virtual methods + */ + bool isPolymorphic() const + { + return m_isPolymorphic; + } + + /** + * Tells if this class has one or more functions that are protected. + * \return true if the class has protected functions. + */ + bool hasProtectedFunctions() const; + + /** + * Tells if this class has one or more fields (member variables) that are protected. + * \return true if the class has protected fields. + */ + bool hasProtectedFields() const; + + /** + * Tells if this class has one or more members (functions or fields) that are protected. + * \return true if the class has protected members. + */ + bool hasProtectedMembers() const; + + + QVector templateArguments() const + { + return m_templateArgs; + } + + void setTemplateArguments(const QVector &args) + { + m_templateArgs = args; + } + + bool hasFieldAccessors() const; + + // only valid during metabuilder's run + QStringList baseClassNames() const + { + return m_baseClassNames; + } + + void setBaseClassNames(const QStringList &names) + { + m_baseClassNames = names; + } + + const ComplexTypeEntry *typeEntry() const + { + return m_typeEntry; + } + + ComplexTypeEntry *typeEntry() + { + return m_typeEntry; + } + + void setTypeEntry(ComplexTypeEntry *type) + { + m_typeEntry = type; + } + + void setHasHashFunction(bool on) + { + m_hasHashFunction = on; + } + + bool hasHashFunction() const + { + return m_hasHashFunction; + } + virtual bool hasDefaultToStringFunction() const; + + void setHasEqualsOperator(bool on) + { + m_hasEqualsOperator = on; + } + + bool hasEqualsOperator() const + { + return m_hasEqualsOperator; + } + + void setHasCloneOperator(bool on) + { + m_hasCloneOperator = on; + } + + bool hasCloneOperator() const + { + return m_hasCloneOperator; + } + + void addPropertySpec(QPropertySpec *spec) + { + m_propertySpecs << spec; + } + + QVector propertySpecs() const + { + return m_propertySpecs; + } + + QPropertySpec *propertySpecForRead(const QString &name) const; + QPropertySpec *propertySpecForWrite(const QString &name) const; + QPropertySpec *propertySpecForReset(const QString &name) const; + + /// Returns a list of conversion operators for this class. The conversion operators are defined in other classes of the same module. + AbstractMetaFunctionList externalConversionOperators() const + { + return m_externalConversionOperators; + } + /// Adds a converter operator for this class. + void addExternalConversionOperator(AbstractMetaFunction* conversionOp) + { + if (!m_externalConversionOperators.contains(conversionOp)) + m_externalConversionOperators.append(conversionOp); + } + /// Returns true if this class has any converter operators defined elsewhere. + bool hasExternalConversionOperators() const + { + return !m_externalConversionOperators.isEmpty(); + } + + void sortFunctions(); + + const AbstractMetaClass *templateBaseClass() const + { + return m_templateBaseClass; + } + + void setTemplateBaseClass(const AbstractMetaClass *cls) + { + m_templateBaseClass = cls; + } + + bool hasTemplateBaseClassInstantiations() const; + AbstractMetaTypeList templateBaseClassInstantiations() const; + void setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations); + + void setTypeDef(bool typeDef) { m_isTypeDef = typeDef; } + bool isTypeDef() const { return m_isTypeDef; } + + void setStream(bool stream) + { + m_stream = stream; + } + + bool isStream() const + { + return m_stream; + } + + void setToStringCapability(bool value) + { + m_hasToStringCapability = value; + } + + bool hasToStringCapability() const + { + return m_hasToStringCapability; + } + + static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, + const QString &name); + static AbstractMetaClass *findClass(const AbstractMetaClassList &classes, + const TypeEntry* typeEntry); + static AbstractMetaEnumValue *findEnumValue(const AbstractMetaClassList &classes, + const QString &string); + static AbstractMetaEnum *findEnum(const AbstractMetaClassList &classes, + const EnumTypeEntry *entry); + +private: +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug d, const AbstractMetaClass *ac); +#endif + uint m_hasVirtuals : 1; + uint m_isPolymorphic : 1; + uint m_hasNonpublic : 1; + uint m_hasVirtualSlots : 1; + uint m_hasNonPrivateConstructor : 1; + uint m_functionsFixed : 1; + uint m_hasPrivateDestructor : 1; + uint m_hasProtectedDestructor : 1; + uint m_hasVirtualDestructor : 1; + uint m_forceShellClass : 1; + uint m_hasHashFunction : 1; + uint m_hasEqualsOperator : 1; + uint m_hasCloneOperator : 1; + uint m_isTypeDef : 1; + uint m_hasToStringCapability : 1; + + const AbstractMetaClass *m_enclosingClass; + AbstractMetaClass *m_baseClass; + const AbstractMetaClass *m_templateBaseClass; + AbstractMetaFunctionList m_functions; + AbstractMetaFieldList m_fields; + AbstractMetaEnumList m_enums; + AbstractMetaClassList m_interfaces; + AbstractMetaClass *m_extractedInterface; + QVector m_propertySpecs; + AbstractMetaClassList m_innerClasses; + + AbstractMetaFunctionList m_externalConversionOperators; + + QStringList m_baseClassNames; + QVector m_templateArgs; + ComplexTypeEntry *m_typeEntry; +// FunctionModelItem m_qDebugStreamFunction; + + bool m_stream; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::FunctionQueryOptions) +Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::OperatorQueryOptions) + +class QPropertySpec +{ +public: + QPropertySpec(const TypeEntry *type) + : m_type(type), + m_index(-1) + {} + + const TypeEntry *type() const + { + return m_type; + } + + QString name() const + { + return m_name; + } + + void setName(const QString &name) + { + m_name = name; + } + + QString read() const + { + return m_read; + } + + void setRead(const QString &read) + { + m_read = read; + } + + QString write() const + { + return m_write; + } + + void setWrite(const QString &write) + { + m_write = write; + } + + QString designable() const + { + return m_designable; + } + + void setDesignable(const QString &designable) + { + m_designable = designable; + } + + QString reset() const + { + return m_reset; + } + + void setReset(const QString &reset) + { + m_reset = reset; + } + + int index() const + { + return m_index; + } + + void setIndex(int index) + { + m_index = index; + } + +private: + QString m_name; + QString m_read; + QString m_write; + QString m_designable; + QString m_reset; + const TypeEntry *m_type; + int m_index; +}; + +inline AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const +{ + return queryFunctions(Signals + | Visible + | NotRemovedFromTargetLang); +} + +#endif // ABSTRACTMETALANG_H diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h new file mode 100644 index 000000000..da8369895 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACTMETALANG_TYPEDEFS_H +#define ABSTRACTMETALANG_TYPEDEFS_H + +#include + +class AbstractMetaClass; +class AbstractMetaField; +class AbstractMetaArgument; +class AbstractMetaEnum; +class AbstractMetaEnumValue; +class AbstractMetaFunction; +class AbstractMetaType; + +typedef QVector AbstractMetaArgumentList; +typedef QVector AbstractMetaClassList; +typedef QVector AbstractMetaEnumList; +typedef QVector AbstractMetaEnumValueList; +typedef QVector AbstractMetaFieldList; +typedef QVector AbstractMetaFunctionList; +typedef QVector AbstractMetaTypeList; + +#endif // ABSTRACTMETALANG_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/apiextractor.cpp b/sources/shiboken2/ApiExtractor/apiextractor.cpp new file mode 100644 index 000000000..abb7c08b9 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp @@ -0,0 +1,317 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "apiextractor.h" +#include "abstractmetalang.h" + +#include +#include +#include +#include +#include +#include + +#include "reporthandler.h" +#include "typesystem.h" +#include "fileout.h" +#include "abstractmetabuilder.h" +#include "typedatabase.h" +#include "typesystem.h" + +static bool appendFile(const QString& sourceFileName, QFile& targetFile) +{ + QFile sourceFile(sourceFileName); + if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) { + std::cerr << "Cannot open " << qPrintable(QDir::toNativeSeparators(sourceFileName)) + << ": " << qPrintable(sourceFile.errorString()) << '\n'; + return false; + } + targetFile.write(sourceFile.readAll()); + return true; +} + +ApiExtractor::ApiExtractor() : m_builder(0) +{ + // Environment TYPESYSTEMPATH + QString envTypesystemPaths = QFile::decodeName(getenv("TYPESYSTEMPATH")); + if (!envTypesystemPaths.isEmpty()) + TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths); +} + +ApiExtractor::~ApiExtractor() +{ + delete m_builder; +} + +void ApiExtractor::addTypesystemSearchPath (const QString& path) +{ + TypeDatabase::instance()->addTypesystemPath(path); +} + +void ApiExtractor::addTypesystemSearchPath(const QStringList& paths) +{ + for (const QString &path : paths) + addTypesystemSearchPath(path); +} + +void ApiExtractor::addIncludePath(const HeaderPath& path) +{ + m_includePaths << path; +} + +void ApiExtractor::addIncludePath(const HeaderPaths& paths) +{ + m_includePaths << paths; +} + +void ApiExtractor::setLogDirectory(const QString& logDir) +{ + m_logDirectory = logDir; +} + +void ApiExtractor::setCppFileName(const QString& cppFileName) +{ + m_cppFileName = cppFileName; +} + +void ApiExtractor::setTypeSystem(const QString& typeSystemFileName) +{ + m_typeSystemFileName = typeSystemFileName; +} + +void ApiExtractor::setDebugLevel(ReportHandler::DebugLevel debugLevel) +{ + ReportHandler::setDebugLevel(debugLevel); +} + +void ApiExtractor::setSuppressWarnings ( bool value ) +{ + TypeDatabase::instance()->setSuppressWarnings(value); +} + +void ApiExtractor::setSilent ( bool value ) +{ + ReportHandler::setSilent(value); +} + +bool ApiExtractor::setApiVersion(const QString& package, const QString &version) +{ + return TypeDatabase::instance()->setApiVersion(package, version); +} + +void ApiExtractor::setDropTypeEntries(QString dropEntries) +{ + dropEntries.remove(QLatin1Char(' ')); + QStringList entries = dropEntries.split(QLatin1Char(';')); + TypeDatabase::instance()->setDropTypeEntries(entries); +} + +AbstractMetaEnumList ApiExtractor::globalEnums() const +{ + Q_ASSERT(m_builder); + return m_builder->globalEnums(); +} + +AbstractMetaFunctionList ApiExtractor::globalFunctions() const +{ + Q_ASSERT(m_builder); + return m_builder->globalFunctions(); +} + +AbstractMetaClassList ApiExtractor::classes() const +{ + Q_ASSERT(m_builder); + return m_builder->classes(); +} + +AbstractMetaClassList ApiExtractor::smartPointers() const +{ + Q_ASSERT(m_builder); + return m_builder->smartPointers(); +} + +AbstractMetaClassList ApiExtractor::classesTopologicalSorted(const Dependencies &additionalDependencies) const +{ + Q_ASSERT(m_builder); + return m_builder->classesTopologicalSorted(Q_NULLPTR, additionalDependencies); +} + +PrimitiveTypeEntryList ApiExtractor::primitiveTypes() const +{ + return TypeDatabase::instance()->primitiveTypes(); +} + +ContainerTypeEntryList ApiExtractor::containerTypes() const +{ + return TypeDatabase::instance()->containerTypes(); +} + +QSet ApiExtractor::qtMetaTypeDeclaredTypeNames() const +{ + Q_ASSERT(m_builder); + return m_builder->qtMetaTypeDeclaredTypeNames(); +} + +static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry) +{ + const AbstractMetaEnum* result = 0; + for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { + if (metaEnum->typeEntry() == typeEntry) { + result = metaEnum; + break; + } + } + if (result) + break; + result = findEnumOnClasses(metaClass->innerClasses(), typeEntry); + } + return result; +} + +const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const +{ + if (!typeEntry) + return 0; + const AbstractMetaEnumList &globalEnums = m_builder->globalEnums(); + for (AbstractMetaEnum* metaEnum : globalEnums) { + if (metaEnum->typeEntry() == typeEntry) + return metaEnum; + } + return findEnumOnClasses(m_builder->classes(), typeEntry); +} + +const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const +{ + if (!typeEntry) + return 0; + if (typeEntry->isFlags()) + return findAbstractMetaEnum(reinterpret_cast(typeEntry)); + if (typeEntry->isEnum()) + return findAbstractMetaEnum(reinterpret_cast(typeEntry)); + return 0; +} + +const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const +{ + if (!typeEntry) + return 0; + return findAbstractMetaEnum(typeEntry->originator()); +} + +const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const AbstractMetaType* metaType) const +{ + if (!metaType) + return 0; + return findAbstractMetaEnum(metaType->typeEntry()); +} + +int ApiExtractor::classCount() const +{ + Q_ASSERT(m_builder); + return m_builder->classes().count(); +} + +bool ApiExtractor::run() +{ + if (m_builder) + return false; + + if (m_typeSystemFileName.isEmpty()) { + std::cerr << "You must specify a Type System file." << std::endl; + return false; + } else if (!TypeDatabase::instance()->parseFile(m_typeSystemFileName)) { + std::cerr << "Cannot parse file: " << qPrintable(m_typeSystemFileName); + return false; + } + + const QString pattern = QDir::tempPath() + QLatin1Char('/') + + QFileInfo(m_cppFileName).baseName() + QStringLiteral("_XXXXXX.hpp"); + QTemporaryFile ppFile(pattern); + bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES"); + // make sure that a tempfile can be written + if (!ppFile.open()) { + std::cerr << "could not create tempfile " << qPrintable(pattern) + << ": " << qPrintable(ppFile.errorString()) << '\n'; + return false; + } + + if (!appendFile(m_cppFileName, ppFile)) + return false; + const QString preprocessedCppFileName = ppFile.fileName(); + ppFile.close(); + m_builder = new AbstractMetaBuilder; + m_builder->setLogDirectory(m_logDirectory); + m_builder->setGlobalHeader(m_cppFileName); + QByteArrayList arguments; + arguments.reserve(m_includePaths.size() + 1); + for (const HeaderPath &headerPath : qAsConst(m_includePaths)) + arguments.append(HeaderPath::includeOption(headerPath)); + arguments.append(QFile::encodeName(preprocessedCppFileName)); + qCDebug(lcShiboken) << __FUNCTION__ << arguments; + const bool result = m_builder->build(arguments); + if (!result) + autoRemove = false; + if (!autoRemove) { + ppFile.setAutoRemove(false); + std::cerr << "Keeping temporary file: " << qPrintable(QDir::toNativeSeparators(preprocessedCppFileName)) << '\n'; + } + return result; +} + +#ifndef QT_NO_DEBUG_STREAM +template +static void debugFormatSequence(QDebug &d, const char *key, const Container& c) +{ + typedef typename Container::const_iterator ConstIt; + if (c.isEmpty()) + return; + const ConstIt begin = c.begin(); + const ConstIt end = c.end(); + d << "\n " << key << '[' << c.size() << "]=("; + for (ConstIt it = begin; it != end; ++it) { + if (it != begin) + d << ", "; + d << *it; + } + d << ')'; +} + +QDebug operator<<(QDebug d, const ApiExtractor &ae) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "ApiExtractor(typeSystem=\"" << ae.typeSystem() << "\", cppFileName=\"" + << ae.cppFileName() << ", "; + ae.m_builder->formatDebug(d); + d << ')'; + return d; +} +#endif // QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/apiextractor.h b/sources/shiboken2/ApiExtractor/apiextractor.h new file mode 100644 index 000000000..ac90f5b2f --- /dev/null +++ b/sources/shiboken2/ApiExtractor/apiextractor.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef APIEXTRACTOR_H +#define APIEXTRACTOR_H + +#include "reporthandler.h" +#include "dependency.h" +#include "abstractmetalang_typedefs.h" +#include "apiextractormacros.h" +#include "header_paths.h" +#include "typedatabase_typedefs.h" +#include "typesystem_typedefs.h" +#include + +class AbstractMetaBuilder; +class AbstractMetaClass; +class AbstractMetaEnum; +class AbstractMetaFunction; +class AbstractMetaType; +class ContainerTypeEntry; +class EnumTypeEntry; +class FlagsTypeEntry; +class PrimitiveTypeEntry; +class TypeEntry; + +QT_BEGIN_NAMESPACE +class QDebug; +class QIODevice; +QT_END_NAMESPACE + +class ApiExtractor +{ +public: + ApiExtractor(); + ~ApiExtractor(); + + void setTypeSystem(const QString& typeSystemFileName); + QString typeSystem() const { return m_typeSystemFileName; } + void setCppFileName(const QString& cppFileName); + QString cppFileName() const { return m_cppFileName; } + void setDebugLevel(ReportHandler::DebugLevel debugLevel); + void setSuppressWarnings(bool value); + void setSilent(bool value); + void addTypesystemSearchPath(const QString& path); + void addTypesystemSearchPath(const QStringList& paths); + void addIncludePath(const HeaderPath& path); + void addIncludePath(const HeaderPaths& paths); + HeaderPaths includePaths() const { return m_includePaths; } + void setLogDirectory(const QString& logDir); + bool setApiVersion(const QString& package, const QString& version); + void setDropTypeEntries(QString dropEntries); + + AbstractMetaEnumList globalEnums() const; + AbstractMetaFunctionList globalFunctions() const; + AbstractMetaClassList classes() const; + AbstractMetaClassList smartPointers() const; + AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const; + PrimitiveTypeEntryList primitiveTypes() const; + ContainerTypeEntryList containerTypes() const; + QSet qtMetaTypeDeclaredTypeNames() const; + + const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const; + const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const; + const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const; + const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const; + + int classCount() const; + + bool run(); +private: + QString m_typeSystemFileName; + QString m_cppFileName; + HeaderPaths m_includePaths; + AbstractMetaBuilder* m_builder; + QString m_logDirectory; + + // disable copy + ApiExtractor(const ApiExtractor&); + ApiExtractor& operator=(const ApiExtractor&); +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug d, const ApiExtractor &ae); +#endif +}; + +#endif // APIEXTRACTOR_H diff --git a/sources/shiboken2/ApiExtractor/apiextractormacros.h b/sources/shiboken2/ApiExtractor/apiextractormacros.h new file mode 100644 index 000000000..41a710773 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/apiextractormacros.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef APIEXTRACTORMACROS_H +#define APIEXTRACTORMACROS_H + + +// APIEXTRACTOR_API is used for the public API symbols. +#if defined _WIN32 + #define APIEXTRACTOR_DEPRECATED(func) __declspec(deprecated) func +#elif __GNUC__ >= 4 + #define APIEXTRACTOR_DEPRECATED(func) func __attribute__ ((deprecated)) +#else + #define APIEXTRACTOR_DEPRECATED(func) func +#endif +#endif diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp new file mode 100644 index 000000000..dc0c59dd5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -0,0 +1,770 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangbuilder.h" +#include "compilersupport.h" +#include "clangutils.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#if QT_VERSION < 0x050800 +# define Q_FALLTHROUGH() (void)0 +#endif + +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 + || c.kind == CXCursor_ClassTemplate + || c.kind == CXCursor_ClassTemplatePartialSpecialization; +} + +static inline bool withinClassDeclaration(const CXCursor &cursor) +{ + return isClassCursor(clang_getCursorLexicalParent(cursor)); +} + +static QString fixTypeName(QString t) +{ + // Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**" + int pos = t.size() - 1; + for (; pos >= 0 && (t.at(pos) == QLatin1Char('&') || t.at(pos) == QLatin1Char('*')); --pos) {} + if (pos > 0 && t.at(pos) == QLatin1Char(' ')) + t.remove(pos, 1); + return t; +} + +// Insert template parameter to class name: "Foo<>" -> "Foo" -> "Foo" +// This needs to be done immediately when template parameters are encountered since +// the class name "Foo" is the scope for nested items. +static bool insertTemplateParameterIntoClassName(const QString &parmName, QString *name) +{ + if (Q_UNLIKELY(!name->endsWith(QLatin1Char('>')))) + return false; + const bool needsComma = name->at(name->size() - 2) != QLatin1Char('<'); + const int insertionPos = name->size() - 1; + name->insert(insertionPos, parmName); + if (needsComma) + name->insert(insertionPos, QLatin1Char(',')); + return true; +} + +static inline bool insertTemplateParameterIntoClassName(const QString &parmName, + const ClassModelItem &item) +{ + QString name = item->name(); + const bool result = insertTemplateParameterIntoClassName(parmName, &name); + item->setName(name); + return result; +} + +static inline CodeModel::AccessPolicy accessPolicy(CX_CXXAccessSpecifier access) +{ + CodeModel::AccessPolicy result = CodeModel::Public; + switch (access) { + case CX_CXXProtected: + result = CodeModel::Protected; + break; + case CX_CXXPrivate: + result = CodeModel::Private; + break; + default: + break; + } + return result; +} + +static void setFileName(const CXCursor &cursor, _CodeModelItem *item) +{ + const SourceRange range = getCursorRange(cursor); + if (!range.first.file.isEmpty()) { // Has been observed to be 0 for invalid locations + item->setFileName(QDir::cleanPath(range.first.file)); + item->setStartPosition(int(range.first.line), int(range.first.column)); + item->setEndPosition(int(range.second.line), int(range.second.column)); + } +} + +class BuilderPrivate { +public: + typedef QHash CursorClassHash; + typedef QHash CursorTypedefHash; + + explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel) + { + m_scopeStack.push(NamespaceModelItem(new _FileModelItem(m_model))); + } + + // Determine scope from top item. Note that the scope list does not necessarily + // match the scope stack in case of forward-declared inner classes whose definition + // appears in the translation unit while the scope is the outer class. + void updateScope() + { + if (m_scopeStack.size() <= 1) + m_scope.clear(); + else + m_scope = m_scopeStack.back()->scope() << m_scopeStack.back()->name(); + } + + void pushScope(const ScopeModelItem &i) + { + m_scopeStack.push(i); + updateScope(); + } + + void popScope() + { + m_scopeStack.pop(); + updateScope(); + } + + bool addClass(const CXCursor &cursor, CodeModel::ClassType t); + FunctionModelItem createFunction(const CXCursor &cursor, + CodeModel::FunctionType t = CodeModel::Normal) const; + FunctionModelItem createMemberFunction(const CXCursor &cursor, + CodeModel::FunctionType t = CodeModel::Normal) const; + void qualifyConstructor(const CXCursor &cursor); + TypeInfo createTypeInfo(const CXType &type) const; + TypeInfo createTypeInfo(const CXCursor &cursor) const + { return createTypeInfo(clang_getCursorType(cursor)); } + + TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const; + TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const; + void addField(const CXCursor &cursor); + + QString cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const; + void addBaseClass(const CXCursor &cursor); + + template + void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer &item) const; + + BaseVisitor *m_baseVisitor; + CodeModel *m_model; + + QStack m_scopeStack; + QStringList m_scope; + // Store all classes by cursor so that base classes can be found and inner + // classes can be correctly parented in case of forward-declared inner classes + // (QMetaObject::Connection) + CursorClassHash m_cursorClassHash; + CursorTypedefHash m_cursorTypedefHash; + + ClassModelItem m_currentClass; + EnumModelItem m_currentEnum; + FunctionModelItem m_currentFunction; + ArgumentModelItem m_currentArgument; + VariableModelItem m_currentField; + + int m_anonymousEnumCount = 0; + CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal; +}; + +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()); + 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: + // class QMetaObject { class Connection; } + // class QMetaObject::Connection {} + const CXCursor semPar = clang_getCursorSemanticParent(cursor); + if (isClassCursor(semPar)) { + const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(semPar); + if (it == m_cursorClassHash.constEnd()) { + const QString message = QStringLiteral("Unable to find parent of inner class ") + className; + const Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + m_baseVisitor->appendDiagnostic(d); + return false; + } + const ClassModelItem &containingClass = it.value(); + containingClass->addClass(m_currentClass); + m_currentClass->setScope(containingClass->scope() << containingClass->name()); + } else { + m_currentClass->setScope(m_scope); + m_scopeStack.back()->addClass(m_currentClass); + } + pushScope(m_currentClass); + m_cursorClassHash.insert(cursor, m_currentClass); + return true; +} + +FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, + CodeModel::FunctionType t) const +{ + QString name = getCursorSpelling(cursor); + // Apply type fixes to "operator X &" -> "operator X&" + if (name.startsWith(QLatin1String("operator "))) + name = fixTypeName(name); + FunctionModelItem result(new _FunctionModelItem(m_model, name)); + setFileName(cursor, result.data()); + result->setType(createTypeInfo(clang_getCursorResultType(cursor))); + result->setFunctionType(t); + result->setScope(m_scope); + result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); + return result; +} + +FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor, + CodeModel::FunctionType t) const +{ + FunctionModelItem result = createFunction(cursor, t); + 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->setFunctionType(m_currentFunctionType); + return result; +} + +// For CXCursor_Constructor, on endToken(). +void BuilderPrivate::qualifyConstructor(const CXCursor &cursor) +{ + // Clang does not tell us whether a constructor is explicit, preventing it + // from being used for implicit conversions. Try to guess whether a + // constructor is explicit in the C++99 sense (1 parameter) by checking for + // isConvertingConstructor() == 0. Fixme: The notion of "isConvertingConstructor" + // should be used in the code model instead of "explicit" + if (clang_CXXConstructor_isDefaultConstructor(cursor) == 0 + && m_currentFunction->arguments().size() == 1 + && clang_CXXConstructor_isCopyConstructor(cursor) == 0 + && clang_CXXConstructor_isMoveConstructor(cursor) == 0) { + m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0); + } +} + +TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const +{ + return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor))); +} + +TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const +{ + TemplateParameterModelItem result = createTemplateParameter(cursor); + result->setType(createTypeInfo(cursor)); + return result; +} + +// CXCursor_VarDecl, CXCursor_FieldDecl cursors +void BuilderPrivate::addField(const CXCursor &cursor) +{ + VariableModelItem field(new _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); + m_currentField = field; + m_scopeStack.back()->addVariable(field); +} + +// Array helpers: Parse "a[2][4]" into a list of dimensions + +struct ArrayDimensionResult +{ + QVector dimensions; + int position; +}; + +static ArrayDimensionResult arrayDimensions(const QString &typeName) +{ + ArrayDimensionResult result; + result.position = typeName.indexOf(QLatin1Char('[')); + for (int openingPos = result.position; openingPos != -1; ) { + const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1); + if (closingPos == -1) + break; + result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1)); + openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1); + } + return result; +} + +// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none +static QStringList parseArrayArgs(const CXType &type, QString *typeName) +{ + const ArrayDimensionResult dimensions = arrayDimensions(*typeName); + Q_ASSERT(!dimensions.dimensions.isEmpty()); + + QStringList result; + // get first dimension from clang, preferably. + // "a[]" is seen as pointer by Clang, set special indicator "" + const long long size = clang_getArraySize(type); + result.append(size >= 0 ? QString::number(size) : QString()); + // Parse out remaining dimensions + for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i) + result.append(dimensions.dimensions.at(i).toString()); + typeName->truncate(dimensions.position); + return result; +} + +TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const +{ + if (type.kind == CXType_Pointer) { // Check for function pointers, first. + const CXType pointeeType = clang_getPointeeType(type); + const int argCount = clang_getNumArgTypes(pointeeType); + if (argCount >= 0) { + TypeInfo result = createTypeInfo(clang_getResultType(pointeeType)); + result.setFunctionPointer(true); + for (int a = 0; a < argCount; ++a) + result.addArgument(createTypeInfo(clang_getArgType(pointeeType, unsigned(a)))); + return result; + } + } + + TypeInfo typeInfo; + QString typeName = fixTypeName(getTypeName(type)); + + int indirections = 0; + // "int **" + for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections) + typeName.chop(1); + typeInfo.setIndirections(indirections); + // "int &&" + if (typeName.endsWith(QLatin1String("&&"))) { + typeName.chop(2); + typeInfo.setReferenceType(RValueReference); + } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &" + typeName.chop(1); + typeInfo.setReferenceType(LValueReference); + } + + // "int [3], int[]" + if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray + || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) { + typeInfo.setArrayElements(parseArrayArgs(type, &typeName)); + } + + bool isConstant = clang_isConstQualifiedType(type) != 0; + // A "char *const" parameter, is considered to be const-qualified by Clang, but + // not in the TypeInfo sense (corresponds to "char *" and not "const char *"). + if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) { + typeName.chop(5); + typeName = typeName.trimmed(); + isConstant = false; + } + // Clang has been observed to return false for "const int .." + if (!isConstant && typeName.startsWith(QLatin1String("const "))) { + typeName.remove(0, 6); + isConstant = true; + } + typeInfo.setConstant(isConstant); + + // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *" + if (typeName.startsWith(QLatin1String("volatile "))) { + typeName.remove(0, 9); + typeInfo.setVolatile(true); + } + + typeName = typeName.trimmed(); + + typeInfo.setQualifiedName(typeName.split(colonColon())); + // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types? + return typeInfo; +} + +// extract an expression from the cursor via source +// CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2) +QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const +{ + BaseVisitor::CodeSnippet snippet = bv->getCodeSnippet(cursor); + const char *equalSign = std::find(snippet.first, snippet.second, '='); + if (equalSign == snippet.second) + return QString(); + ++equalSign; + return QString::fromLocal8Bit(equalSign, int(snippet.second - equalSign)).trimmed(); +} + +// Add a base class to the current class from CXCursor_CXXBaseSpecifier +void BuilderPrivate::addBaseClass(const CXCursor &cursor) +{ + const CXType inheritedType = clang_getCursorType(cursor); // Note spelling has "struct baseClass", + QString baseClassName = getTypeName(inheritedType); // use type. + const CXCursor declCursor = clang_getTypeDeclaration(inheritedType); + const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor); + if (it == m_cursorClassHash.constEnd()) { + // Set unqualified name. This happens in cases like "class X : public std::list<...>" + // "template class Foo : public T" and standard types like true_type, false_type. + m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); + return; + } + // Completely qualify the class name by looking it up and taking its scope + // plus the actual baseClass stripped off any scopes. Consider: + // namespace std { + // template class vector {}; + // namespace n { + // class Foo : public vector {}; + // } + // } + // should have "std::vector" as base class (whereas the type of the base class is + // "std::vector"). + const QStringList &baseScope = it.value()->scope(); + if (!baseScope.isEmpty()) { + const int lastSep = baseClassName.lastIndexOf(colonColon()); + if (lastSep >= 0) + baseClassName.remove(0, lastSep + colonColon().size()); + baseClassName.prepend(colonColon()); + baseClassName.prepend(baseScope.join(colonColon())); + } + m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName); +} + +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 ConversionFlags; +// class QTextCodec { +// enum ConversionFlag {}; +// typedef QFlags ConversionFlags; +// struct ConverterState { +// explicit ConverterState(ConversionFlags); +// ^^ qualify to QTextCodec::ConversionFlags +// ConversionFlags m_flags; +// ^^ ditto + +template // ArgumentModelItem, VariableModelItem +void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer &item) const +{ + typedef typename CursorTypedefHash::const_iterator ConstIt; + + TypeInfo type = item->type(); + if (type.qualifiedName().size() == 1) { // item's type is unqualified. + const ConstIt 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); + } + } +} + +Builder::Builder() +{ + d = new BuilderPrivate(this); +} + +Builder::~Builder() +{ + delete d; +} + +bool Builder::visitLocation(const CXSourceLocation &location) const +{ + return !clang_Location_isInSystemHeader(location); +} + +FileModelItem Builder::dom() const +{ + Q_ASSERT(!d->m_scopeStack.isEmpty()); + return qSharedPointerDynamicCast<_FileModelItem>(d->m_scopeStack.constFirst()); +} + +static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope) +{ + return getCursorKindName(cursor.kind) + QLatin1Char(' ') + + getCursorSpelling(cursor) + QLatin1String(" encountered outside ") + + QLatin1String(expectedScope) + QLatin1Char('.'); +} + +static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind) +{ + CodeModel::ClassType result = CodeModel::Class; + if (kind == CXCursor_UnionDecl) + result = CodeModel::Union; + else if (kind == CXCursor_StructDecl) + result = CodeModel::Struct; + return result; +} + +BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + case CXCursor_CXXAccessSpecifier: + d->m_currentFunctionType = CodeModel::Normal; + break; + case CXCursor_AnnotateAttr: { + const QString annotation = getCursorSpelling(cursor); + if (annotation == QLatin1String("qt_slot")) + d->m_currentFunctionType = CodeModel::Slot; + else if (annotation == QLatin1String("qt_signal")) + d->m_currentFunctionType = CodeModel::Signal; + else + d->m_currentFunctionType = CodeModel::Normal; + } + break; + case CXCursor_CXXBaseSpecifier: + if (d->m_currentClass.isNull()) { + const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + d->addBaseClass(cursor); + break; + case CXCursor_ClassDecl: + case CXCursor_UnionDecl: + case CXCursor_StructDecl: + if (clang_isCursorDefinition(cursor) == 0) + return Skip; + if (!d->addClass(cursor, codeModelClassTypeFromCursor(cursor.kind))) + return Error; + break; + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + if (clang_isCursorDefinition(cursor) == 0) + return Skip; + d->addClass(cursor, CodeModel::Class); + d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets()); + d->m_scope.back() += templateBrackets(); + break; + case CXCursor_EnumDecl: { + QString name = getCursorSpelling(cursor); + const bool anonymous = name.isEmpty(); + if (anonymous) + name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); + d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); + setFileName(cursor, d->m_currentEnum.data()); + d->m_currentEnum->setScope(d->m_scope); + d->m_currentEnum->setAnonymous(anonymous); + if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) + d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); + d->m_scopeStack.back()->addEnum(d->m_currentEnum); + } + break; + case CXCursor_EnumConstantDecl: { + const QString name = getCursorSpelling(cursor); + if (d->m_currentEnum.isNull()) { + const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); + enumConstant->setValue(d->cursorValueExpression(this, cursor)); + d->m_currentEnum->addEnumerator(enumConstant); + } + break; + case CXCursor_VarDecl: + // static class members are seen as CXCursor_VarDecl + if (!d->m_currentClass.isNull() && isClassCursor(clang_getCursorSemanticParent(cursor))) { + d->addField(cursor); + d->m_currentField->setStatic(true); + } + break; + case CXCursor_FieldDecl: + d->addField(cursor); + break; +#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 37 // Clang 4.0 + case CXCursor_FriendDecl: + return Skip; +#endif + case CXCursor_Constructor: + case CXCursor_Destructor: // Note: Also use clang_CXXConstructor_is..Constructor? + case CXCursor_CXXMethod: + case CXCursor_ConversionFunction: + // Skip inline member functions outside class, only go by declarations inside class + if (!withinClassDeclaration(cursor)) + return Skip; + d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + // Not fully supported, currently, seen as normal function + // Note: May appear inside class (member template) or outside (free template). + case CXCursor_FunctionTemplate: { + const CXCursor semParent = clang_getCursorSemanticParent(cursor); + if (isClassCursor(semParent)) { + if (semParent == clang_getCursorLexicalParent(cursor)) { + d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + } else { + return Skip; // inline member functions outside class + } + } + } + Q_FALLTHROUGH(); // fall through to free template function. + case CXCursor_FunctionDecl: + d->m_currentFunction = d->createFunction(cursor); + d->m_scopeStack.back()->addFunction(d->m_currentFunction); + break; + case CXCursor_Namespace: { + const QString name = getCursorSpelling(cursor); + const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back()); + if (parentNamespaceItem.isNull()) { + const QString message = msgOutOfOrder(cursor, "namespace") + + QLatin1String(" (current scope: ") + d->m_scopeStack.back()->name() + QLatin1Char(')'); + const Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + // If possible, continue existing namespace (as otherwise, all headers + // where a namespace is continued show up in the type database). + NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name); + if (namespaceItem.isNull()) { + namespaceItem.reset(new _NamespaceModelItem(d->m_model, name)); + setFileName(cursor, namespaceItem.data()); + namespaceItem->setScope(d->m_scope); + parentNamespaceItem->addNamespace(namespaceItem); + } + d->pushScope(namespaceItem); + } + break; + 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()) { + const QString name = getCursorSpelling(cursor); + d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name)); + d->m_currentArgument->setType(d->createTypeInfo(cursor)); + d->m_currentFunction->addArgument(d->m_currentArgument); + QString defaultValueExpression = d->cursorValueExpression(this, cursor); + if (!defaultValueExpression.isEmpty()) { + d->m_currentArgument->setDefaultValueExpression(defaultValueExpression); + d->m_currentArgument->setDefaultValue(true); + } + } else { + return Skip; + } + break; + case CXCursor_TemplateTypeParameter: + case CXCursor_NonTypeTemplateParameter: { + const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter + ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor); + // Apply to function/member template? + if (!d->m_currentFunction.isNull()) { + d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem); + } else if (!d->m_currentClass.isNull()) { // 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 Diagnostic d(message, cursor, CXDiagnostic_Error); + qWarning() << d; + appendDiagnostic(d); + return Error; + } + d->m_currentClass->setTemplateParameters(d->m_currentClass->templateParameters() << tItem); + } + } + break; + case CXCursor_TypeAliasDecl: + case CXCursor_TypeAliasTemplateDecl: // May contain nested CXCursor_TemplateTypeParameter + return Skip; + case CXCursor_TypedefDecl: { + const QString name = getCursorSpelling(cursor); + TypeDefModelItem item(new _TypeDefModelItem(d->m_model, name)); + setFileName(cursor, item.data()); + item->setType(d->createTypeInfo(clang_getTypedefDeclUnderlyingType(cursor))); + item->setScope(d->m_scope); + d->m_scopeStack.back()->addTypeDef(item); + d->m_cursorTypedefHash.insert(cursor, item); + } + 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); + } + break; + default: + break; + } + return BaseVisitor::Recurse; +} + +bool Builder::endToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + case CXCursor_UnionDecl: + case CXCursor_ClassDecl: + case CXCursor_StructDecl: + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + d->popScope(); + // Continue in outer class after leaving inner class? + if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back())) + d->m_currentClass = lastClass; + else + d->m_currentClass.clear(); + d->m_currentFunctionType = CodeModel::Normal; + break; + case CXCursor_EnumDecl: + d->m_currentEnum.clear(); + break; + case CXCursor_VarDecl: + case CXCursor_FieldDecl: + d->m_currentField.clear(); + break; + case CXCursor_Constructor: + d->qualifyConstructor(cursor); + d->m_currentFunction.clear(); + break; + case CXCursor_Destructor: + case CXCursor_CXXMethod: + case CXCursor_FunctionDecl: + case CXCursor_FunctionTemplate: + d->m_currentFunction.clear(); + break; + case CXCursor_Namespace: + d->popScope(); + break; + case CXCursor_ParmDecl: + d->m_currentArgument.clear(); + break; + default: + break; + } + return true; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h new file mode 100644 index 000000000..c97b7d2b7 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGBUILDER_H +#define CLANGBUILDER_H + +#include "clangparser.h" + +#include + +namespace clang { + +class BuilderPrivate; + +class Builder : public BaseVisitor { +public: + Builder(); + ~Builder(); + + bool visitLocation(const CXSourceLocation &location) const override; + + StartTokenResult startToken(const CXCursor &cursor) override; + bool endToken(const CXCursor &cursor) override; + + FileModelItem dom() const; + +private: + BuilderPrivate *d; +}; + +} // namespace clang + +#endif // CLANGBUILDER_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp new file mode 100644 index 000000000..8d0fd098a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp @@ -0,0 +1,150 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangdebugutils.h" +#include "clangutils.h" + +#include +#include + +#include + +#ifndef QT_NO_DEBUG_STREAM + +#ifdef Q_OS_WIN +const char pathSep = '\\'; +#else +const char pathSep = '/'; +#endif + +static const char *baseName(const char *fileName) +{ + const char *b = strrchr(fileName, pathSep); + return b ? b + 1 : fileName; +} + +QDebug operator<<(QDebug s, const CXString &cs) +{ + s << clang_getCString(cs); + return s; +} + +QDebug operator<<(QDebug s, CXCursorKind cursorKind) // Enum +{ + const CXString kindName = clang_getCursorKindSpelling(cursorKind); + s << kindName; + clang_disposeString(kindName); + return s; +} + +static const char *accessSpecsStrings[] +{ + // CX_CXXInvalidAccessSpecifier, CX_CXXPublic, CX_CXXProtected, CX_CXXPrivate + "invalid", "public", "protected", "private" +}; + +QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac) +{ + s << accessSpecsStrings[ac]; + return s; +} + +QDebug operator<<(QDebug s, const CXType &t) +{ + CXString typeSpelling = clang_getTypeSpelling(t); + s << typeSpelling; + clang_disposeString(typeSpelling); + return s; +} + +QDebug operator<<(QDebug s, const CXCursor &cursor) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + const CXCursorKind kind = clang_getCursorKind(cursor); + s << kind; + if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid) + return s; + const CXType type = clang_getCursorType(cursor); + switch (kind) { + case CXCursor_CXXAccessSpecifier: + s << ' ' << clang_getCXXAccessSpecifier(cursor); + break; + case CXCursor_CXXBaseSpecifier: + s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"'; + break; + case CXCursor_CXXMethod: + case CXCursor_FunctionDecl: + case CXCursor_ConversionFunction: + s << ", result type=\"" << clang_getCursorResultType(cursor) << '"'; + break; + case CXCursor_TypedefDecl: + s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"'; + break; + default: + break; + } + + if (type.kind != CXType_Invalid) + s << ", type=\"" << type << '"'; + if (clang_Cursor_hasAttrs(cursor)) + s << ", [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; +} + +QDebug operator<<(QDebug s, const CXSourceLocation &location) +{ + QDebugStateSaver saver(s); + s.nospace(); + CXFile file; // void * + unsigned line; + unsigned column; + unsigned offset; + clang_getExpansionLocation(location, &file, &line, &column, &offset); + const CXString cxFileName = clang_getFileName(file); + // Has been observed to be 0 for invalid locations + if (const char *cFileName = clang_getCString(cxFileName)) + s << baseName(cFileName) << ':'; + s << line << ':' << column; + clang_disposeString(cxFileName); + return s; +} + +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h new file mode 100644 index 000000000..323efdd2a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGDEBUGUTILS_H +#define CLANGDEBUGUTILS_H + +#include + +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) +QT_FORWARD_DECLARE_CLASS(QString) + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug s, const CXString &cs); +QDebug operator<<(QDebug s, CXCursorKind cursorKind); +QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac); +QDebug operator<<(QDebug s, const CXType &t); +QDebug operator<<(QDebug s, const CXCursor &cursor); +QDebug operator<<(QDebug s, const CXSourceLocation &location); +#endif // !QT_NO_DEBUG_STREAM + +#endif // CLANGDEBUGUTILS_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp new file mode 100644 index 000000000..eb3be115c --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp @@ -0,0 +1,266 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangparser.h" +#include "clangutils.h" +#include "clangdebugutils.h" +#include "compilersupport.h" + +#include +#include +#include +#include +#include +#include + +namespace clang { + +SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor) +{ + Snippet result(nullptr, nullptr); + const SourceRange range = getCursorRange(cursor); + if (range.first.file.isEmpty() || range.second.file != range.first.file) + return result; + FileBufferCache::Iterator it = m_fileBufferCache.find(range.first.file); + if (it == m_fileBufferCache.end()) { + QFile file(range.first.file); + if (!file.open(QIODevice::ReadOnly)) { + qWarning().noquote().nospace() + << "Can't open " << QDir::toNativeSeparators(range.first.file) + << ": " << file.errorString(); + return result; + } + it = m_fileBufferCache.insert(range.first.file, file.readAll()); + } + + const unsigned pos = range.first.offset; + const unsigned end = range.second.offset; + const QByteArray &contents = it.value(); + if (end >= unsigned(contents.size())) { + qWarning().noquote().nospace() << "Range end " << end << " is above size of " + << range.first.file << " (" << contents.size() << ')'; + return result; + } + result.first = contents.constData() + pos; + result.second = contents.constData() + end; + return result; +} + +BaseVisitor::BaseVisitor() = default; +BaseVisitor::~BaseVisitor() = default; + +bool BaseVisitor::visitLocation(const CXSourceLocation &location) const +{ + return clang_Location_isFromMainFile(location) != 0; +} + +BaseVisitor::StartTokenResult BaseVisitor::cbHandleStartToken(const CXCursor &cursor) +{ + switch (cursor.kind) { + default: + break; + } + + return startToken(cursor); +} + +bool BaseVisitor::cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult) +{ + const bool result = startResult != Recurse || endToken(cursor); + switch (cursor.kind) { + default: + break; + } + + return result; +} + +BaseVisitor::CodeSnippet BaseVisitor::getCodeSnippet(const CXCursor &cursor) +{ + CodeSnippet result = m_fileCache.getCodeSnippet(cursor); + if (result.first == nullptr) + appendDiagnostic(Diagnostic(QStringLiteral("Unable to retrieve code snippet."), cursor, CXDiagnostic_Error)); + return result; +} + +QString BaseVisitor::getCodeSnippetString(const CXCursor &cursor) +{ + CodeSnippet result = m_fileCache.getCodeSnippet(cursor); + return result.first != nullptr + ? QString::fromUtf8(result.first, int(result.second - result.first)) + : QString(); +} + +static CXChildVisitResult + visitorCallback(CXCursor cursor, CXCursor /* parent */, CXClientData clientData) +{ + BaseVisitor *bv = reinterpret_cast(clientData); + + const CXSourceLocation location = clang_getCursorLocation(cursor); + if (!bv->visitLocation(location)) + return CXChildVisit_Continue; + + const BaseVisitor::StartTokenResult startResult = bv->cbHandleStartToken(cursor); + switch (startResult) { + case clang::BaseVisitor::Error: + return CXChildVisit_Break; + case clang::BaseVisitor::Skip: + break; + case clang::BaseVisitor::Recurse: + clang_visitChildren(cursor, visitorCallback, clientData); + break; + } + + if (!bv->cbHandleEndToken(cursor, startResult)) + return CXChildVisit_Break; + + return CXChildVisit_Continue; +} + +BaseVisitor::Diagnostics BaseVisitor::diagnostics() const +{ + return m_diagnostics; +} + +void BaseVisitor::setDiagnostics(const Diagnostics &d) +{ + m_diagnostics = d; +} + +void BaseVisitor::appendDiagnostic(const Diagnostic &d) +{ + m_diagnostics.append(d); +} + +static inline const char **byteArrayListToFlatArgV(const QByteArrayList &bl) +{ + const char **result = new const char *[bl.size() + 1]; + result[bl.size()] = nullptr; + std::transform(bl.cbegin(), bl.cend(), result, + [] (const QByteArray &a) { return a.constData(); }); + return result; +} + +static QByteArray msgCreateTranslationUnit(const QByteArrayList clangArgs, unsigned flags) +{ + QByteArray result = "clang_parseTranslationUnit2(0x"; + result += QByteArray::number(flags, 16); + const int count = clangArgs.size(); + result += ", cmd[" + QByteArray::number(count) + "]="; + for (int i = 0; i < count; ++i) { + const QByteArray &arg = clangArgs.at(i); + if (i) + result += ' '; + const bool quote = arg.contains(' ') || arg.contains('('); + if (quote) + result += '"'; + result += arg; + if (quote) + result += '"'; + } + result += ')'; + return result; +} + +static CXTranslationUnit createTranslationUnit(CXIndex index, + const QByteArrayList &args, + unsigned flags = 0) +{ + // courtesy qdoc + const unsigned defaultFlags = CXTranslationUnit_SkipFunctionBodies + | CXTranslationUnit_Incomplete; + + static const QByteArrayList defaultArgs = { + "-std=c++14", // ! otherwise, t.h is parsed as "C" + "-fPIC", + "-fno-exceptions", // Workaround for clang bug http://reviews.llvm.org/D17988 +#ifdef Q_OS_MACOS + "-Wno-expansion-to-defined", // Workaround for warnings in Darwin stdlib, see + // https://github.com/darlinghq/darling/issues/204 +#endif + "-Wno-constant-logical-operand" + }; + + const QByteArrayList clangArgs = emulatedCompilerOptions() + defaultArgs + args; + QScopedArrayPointer argv(byteArrayListToFlatArgV(clangArgs)); + qDebug().noquote().nospace() << msgCreateTranslationUnit(clangArgs, flags); + + CXTranslationUnit tu; + CXErrorCode err = clang_parseTranslationUnit2(index, nullptr, argv.data(), + clangArgs.size(), nullptr, 0, + defaultFlags | flags, &tu); + if (err || !tu) { + qWarning().noquote().nospace() << "Could not parse " + << clangArgs.constLast().constData() << ", error code: " << err; + return nullptr; + } + return tu; +} + +/* clangFlags are flags to clang_parseTranslationUnit2() such as + * CXTranslationUnit_KeepGoing (from CINDEX_VERSION_MAJOR/CINDEX_VERSION_MINOR 0.35) + */ + +bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &bv) +{ + CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */, + 1 /* displayDiagnostics */); + if (!index) { + qWarning() << "clang_createIndex() failed!"; + return false; + } + + CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, clangFlags); + if (!translationUnit) + return false; + + CXCursor rootCursor = clang_getTranslationUnitCursor(translationUnit); + + clang_visitChildren(rootCursor, visitorCallback, reinterpret_cast(&bv)); + + QVector diagnostics = getDiagnostics(translationUnit); + diagnostics.append(bv.diagnostics()); + bv.setDiagnostics(diagnostics); + + const bool ok = maxSeverity(diagnostics) < CXDiagnostic_Error; + if (!ok) { + QDebug debug = qWarning(); + debug.noquote(); + debug.nospace(); + debug << "Errors in " + << QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n"; + for (const Diagnostic &diagnostic : diagnostics) + debug << diagnostic << '\n'; + } + + clang_disposeTranslationUnit(translationUnit); + clang_disposeIndex(index); + return ok; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.h b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h new file mode 100644 index 000000000..ef1424f17 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGPARSER_H +#define CLANGPARSER_H + +#include + +#include +#include +#include +#include +#include + +namespace clang { + +struct Diagnostic; + +class SourceFileCache { +public: + typedef QPair Snippet; + + Snippet getCodeSnippet(const CXCursor &cursor); + +private: + typedef QHash FileBufferCache; + + FileBufferCache m_fileBufferCache; +}; + +class BaseVisitor { + Q_DISABLE_COPY(BaseVisitor) +public: + typedef QVector Diagnostics; + typedef SourceFileCache::Snippet CodeSnippet; + + enum StartTokenResult { Error, Skip, Recurse }; + + BaseVisitor(); + virtual ~BaseVisitor(); + + // Whether location should be visited. + // defaults to clang_Location_isFromMainFile() + virtual bool visitLocation(const CXSourceLocation &location) const; + + virtual StartTokenResult startToken(const CXCursor &cursor) = 0; + virtual bool endToken(const CXCursor &cursor) = 0; + + StartTokenResult cbHandleStartToken(const CXCursor &cursor); + bool cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult); + + CodeSnippet getCodeSnippet(const CXCursor &cursor); + QString getCodeSnippetString(const CXCursor &cursor); + + Diagnostics diagnostics() const; + void setDiagnostics(const Diagnostics &d); + void appendDiagnostic(const Diagnostic &d); + +private: + SourceFileCache m_fileCache; + Diagnostics m_diagnostics; +}; + +bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &ctx); + +} // namespace clang + +#endif // !CLANGPARSER_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp new file mode 100644 index 000000000..fdc8d3312 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "clangutils.h" + +#include +#include +#include +#include + +bool operator==(const CXCursor &c1, const CXCursor &c2) +{ + return c1.kind == c2.kind + && c1.xdata == c2.xdata + && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data); +} + +uint qHash(const CXCursor &c, uint seed) +{ + return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0]) + ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed; +} + +namespace clang { + +SourceLocation getExpansionLocation(const CXSourceLocation &location) +{ + SourceLocation result; + CXFile file; // void * + clang_getExpansionLocation(location, &file, &result.line, &result.column, &result.offset); + const CXString cxFileName = clang_getFileName(file); + // Has been observed to be 0 for invalid locations + if (const char *cFileName = clang_getCString(cxFileName)) + result.file = QString::fromUtf8(cFileName); + clang_disposeString(cxFileName); + return result; +} + +SourceLocation getCursorLocation(const CXCursor &cursor) +{ + const CXSourceRange extent = clang_getCursorExtent(cursor); + return getExpansionLocation(clang_getRangeStart(extent)); +} + +CXString getFileNameFromLocation(const CXSourceLocation &location) +{ + CXFile file; + unsigned line; + unsigned column; + unsigned offset; + clang_getExpansionLocation(location, &file, &line, &column, &offset); + return clang_getFileName(file); +} + +SourceRange getCursorRange(const CXCursor &cursor) +{ + const CXSourceRange extent = clang_getCursorExtent(cursor); + return qMakePair(getExpansionLocation(clang_getRangeStart(extent)), + getExpansionLocation(clang_getRangeEnd(extent))); +} + +QString getCursorKindName(CXCursorKind cursorKind) +{ + CXString kindName = clang_getCursorKindSpelling(cursorKind); + const QString result = QString::fromUtf8(clang_getCString(kindName)); + clang_disposeString(kindName); + return result; +} + +QString getCursorSpelling(const CXCursor &cursor) +{ + CXString cursorSpelling = clang_getCursorSpelling(cursor); + const QString result = QString::fromUtf8(clang_getCString(cursorSpelling)); + clang_disposeString(cursorSpelling); + return result; +} + +QString getCursorDisplayName(const CXCursor &cursor) +{ + CXString displayName = clang_getCursorDisplayName(cursor); + const QString result = QString::fromUtf8(clang_getCString(displayName)); + clang_disposeString(displayName); + return result; +} + +QString getTypeName(const CXType &type) +{ + CXString typeSpelling = clang_getTypeSpelling(type); + const QString result = QString::fromUtf8(clang_getCString(typeSpelling)); + clang_disposeString(typeSpelling); + return result; +} + +Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s) + : message(m), location(getCursorLocation(c)), source(Other), severity(s) +{ +} + +Diagnostic Diagnostic::fromCXDiagnostic(CXDiagnostic cd) +{ + Diagnostic result; + result.source = Clang; + CXString spelling = clang_getDiagnosticSpelling(cd); + result.message = QString::fromUtf8(clang_getCString(spelling)); + clang_disposeString(spelling); + result.severity = clang_getDiagnosticSeverity(cd); + result.location = getExpansionLocation(clang_getDiagnosticLocation(cd)); + + CXDiagnosticSet childDiagnostics = clang_getChildDiagnostics(cd); + if (const unsigned childCount = clang_getNumDiagnosticsInSet(childDiagnostics)) { + result.childMessages.reserve(int(childCount)); + const unsigned format = clang_defaultDiagnosticDisplayOptions(); + for (unsigned i = 0; i < childCount; ++i) { + CXDiagnostic childDiagnostic = clang_getDiagnosticInSet(childDiagnostics, i); + CXString cdm = clang_formatDiagnostic(childDiagnostic, format); + result.childMessages.append(QString::fromUtf8(clang_getCString(cdm))); + clang_disposeString(cdm); + clang_disposeDiagnostic(childDiagnostic); + } + } + + return result; +} + +QVector getDiagnostics(CXTranslationUnit tu) +{ + QVector result; + const unsigned count = clang_getNumDiagnostics(tu); + result.reserve(int(count)); + for (unsigned i = 0; i < count; ++i) { + const CXDiagnostic d = clang_getDiagnostic(tu, i); + result.append(Diagnostic::fromCXDiagnostic(d)); + clang_disposeDiagnostic(d); + } + return result; +} + +CXDiagnosticSeverity maxSeverity(const QVector &ds) +{ + CXDiagnosticSeverity result = CXDiagnostic_Ignored; + for (const Diagnostic d : ds) { + if (d.severity > result) + result = d.severity; + } + return result; +} + +#ifndef QT_NO_DEBUG_STREAM + +QDebug operator<<(QDebug s, const SourceLocation &l) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + s << QDir::toNativeSeparators(l.file) << ':' << l.line; + if (l.column) + s << ':' << l.column; + return s; +} + +// Roughly follow g++ format: +// file.cpp:214:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] +QDebug operator<<(QDebug s, const Diagnostic &d) +{ + QDebugStateSaver saver(s); + s.nospace(); + s.noquote(); + s << d.location << ": "; + switch (d.severity) { + case CXDiagnostic_Ignored: + s << "ignored"; + break; + case CXDiagnostic_Note: + s << "note"; + break; + case CXDiagnostic_Warning: + s << "warning"; + break; + case CXDiagnostic_Error: + s << "error"; + break; + case CXDiagnostic_Fatal: + s << "fatal"; + break; + } + s << ": " << d.message; + + if (d.source != Diagnostic::Clang) + s << " [other]"; + + if (const int childMessagesCount = d.childMessages.size()) { + s << '\n'; + for (int i = 0; i < childMessagesCount; ++i) + s << " " << d.childMessages.at(i) << '\n'; + } + + return s; +} + +#endif // QT_NO_DEBUG_STREAM + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h new file mode 100644 index 000000000..3437f51eb --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CLANGUTILS_H +#define CLANGUTILS_H + +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) + +bool operator==(const CXCursor &c1, const CXCursor &c2); +uint qHash(const CXCursor &c, uint seed = 0); + +namespace clang { + +QString getCursorKindName(CXCursorKind cursorKind); +QString getCursorSpelling(const CXCursor &cursor); +QString getCursorDisplayName(const CXCursor &cursor); +QString getTypeName(const CXType &type); +inline QString getCursorTypeName(const CXCursor &cursor) + { return getTypeName(clang_getCursorType(cursor)); } +inline QString getCursorResultTypeName(const CXCursor &cursor) + { return getTypeName(clang_getCursorResultType(cursor)); } + +inline bool isCursorValid(const CXCursor &c) +{ + return c.kind < CXCursor_FirstInvalid || c.kind > CXCursor_LastInvalid; +} + +struct SourceLocation +{ + int compare(const SourceLocation &rhs) const; + + QString file; + unsigned line = 0; + unsigned column = 0; + unsigned offset = 0; +}; + +SourceLocation getExpansionLocation(const CXSourceLocation &location); + +typedef QPair SourceRange; + +SourceLocation getCursorLocation(const CXCursor &cursor); +CXString getFileNameFromLocation(const CXSourceLocation &location); +SourceRange getCursorRange(const CXCursor &cursor); + +struct Diagnostic { + enum Source { Clang, Other }; + + Diagnostic() : source(Clang) {} + // Clang + static Diagnostic fromCXDiagnostic(CXDiagnostic cd); + // Other + explicit Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s = CXDiagnostic_Warning); + + QString message; + QStringList childMessages; + SourceLocation location; + Source source; + CXDiagnosticSeverity severity; +}; + +QVector getDiagnostics(CXTranslationUnit tu); +CXDiagnosticSeverity maxSeverity(const QVector &ds); + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const SourceLocation &); +QDebug operator<<(QDebug, const Diagnostic &); +#endif // QT_NO_DEBUG_STREAM +} // namespace clang + +#endif // CLANGUTILS_H diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp new file mode 100644 index 000000000..df82f9080 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "compilersupport.h" +#include "header_paths.h" + +#include +#include +#include + +#include +#include +#include + +namespace clang { + +static bool runProcess(const QString &program, const QStringList &arguments, + QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr) +{ + QProcess process; + process.start(program, arguments, QProcess::ReadWrite); + if (!process.waitForStarted()) { + qWarning().noquote().nospace() << "Unable to start " + << process.program() << ": " << process.errorString(); + return false; + } + process.closeWriteChannel(); + const bool finished = process.waitForFinished(); + const QByteArray stdErr = process.readAllStandardError(); + if (stdErrIn) + *stdErrIn = stdErr; + if (stdOutIn) + *stdOutIn = process.readAllStandardOutput(); + + if (!finished) { + qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr; + process.kill(); + return false; + } + + if (process.exitStatus() != QProcess::NormalExit) { + qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr; + return false; + } + + if (process.exitCode() != 0) { + qWarning().noquote().nospace() << process.program() << " exited " + << process.exitCode() << ": " << stdErr; + return false; + } + + return true; +} + +#if defined(Q_CC_GNU) + +static QByteArray frameworkPath() { return QByteArrayLiteral(" (framework directory)"); } + +// Determine g++'s internal include paths from the output of +// g++ -E -x c++ - -v search starts here: +// /usr/local/include +// /System/Library/Frameworks (framework directory) +// End of search list. +static HeaderPaths gppInternalIncludePaths(const QString &compiler) +{ + HeaderPaths result; + QStringList arguments; + arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++") + << QStringLiteral("-") << QStringLiteral("-v"); + QByteArray stdOut; + QByteArray stdErr; + if (!runProcess(compiler, arguments, &stdOut, &stdErr)) + return result; + const QByteArrayList stdErrLines = stdErr.split('\n'); + bool isIncludeDir = false; + for (const QByteArray &line : stdErrLines) { + if (isIncludeDir) { + if (line.startsWith(QByteArrayLiteral("End of search list"))) { + isIncludeDir = false; + } else { + HeaderPath headerPath(line.trimmed()); + if (headerPath.path.endsWith(frameworkPath())) { + headerPath.m_isFramework = true; + headerPath.path.truncate(headerPath.path.size() - frameworkPath().size()); + } + result.append(headerPath); + } + } else if (line.startsWith(QByteArrayLiteral("#include <...> search starts here"))) { + isIncludeDir = true; + } + } + return result; +} +#endif // Q_CC_MSVC + +// For MSVC, we set the MS compatibility version and let Clang figure out its own +// options and include paths. +// For the others, we pass "-nostdinc" since libclang tries to add it's own system +// include paths, which together with the clang compiler paths causes some clash +// which causes std types not being found and construct -I/-F options from the +// include paths of the host compiler. + +static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); } + +// Returns clang options needed for emulating the host compiler +QByteArrayList emulatedCompilerOptions() +{ + QByteArrayList result; +#if defined(Q_CC_MSVC) + const HeaderPaths headerPaths; + result.append(QByteArrayLiteral("-fms-compatibility-version=19")); +#elif defined(Q_CC_CLANG) + const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("clang++")); + result.append(noStandardIncludeOption()); +#elif defined(Q_CC_GNU) + const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("g++")); + result.append(noStandardIncludeOption()); +#else + const HeaderPaths headerPaths; +#endif + std::transform(headerPaths.cbegin(), headerPaths.cend(), + std::back_inserter(result), [](const HeaderPath &p) { + return HeaderPath::includeOption(p, true); + }); + return result; +} + +} // namespace clang diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h new file mode 100644 index 000000000..f556da551 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h @@ -0,0 +1,40 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COMPILERSUPPORT_H +#define COMPILERSUPPORT_H + +#include + +namespace clang { + +QByteArrayList emulatedCompilerOptions(); + +} // namespace clang + +#endif // COMPILERSUPPORT_H diff --git a/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake b/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake new file mode 100644 index 000000000..df95fb9d8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake @@ -0,0 +1,21 @@ +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") + +FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +STRING(REGEX REPLACE "\n" ";" files "${files}") +FOREACH(file ${files}) + MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + IF(EXISTS "$ENV{DESTDIR}${file}") + EXEC_PROGRAM( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + ENDIF(NOT "${rm_retval}" STREQUAL 0) + ELSE(EXISTS "$ENV{DESTDIR}${file}") + MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + ENDIF(EXISTS "$ENV{DESTDIR}${file}") +ENDFOREACH(file) diff --git a/sources/shiboken2/ApiExtractor/dependency.h b/sources/shiboken2/ApiExtractor/dependency.h new file mode 100644 index 000000000..17fbffcce --- /dev/null +++ b/sources/shiboken2/ApiExtractor/dependency.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEPENDENCY_H +#define DEPENDENCY_H + +#include +#include + +// Dependencies for topologically sorting classes +struct Dependency { + QString parent; + QString child; +}; + +typedef QVector Dependencies; + +#endif // DEPENDENCY_H diff --git a/sources/shiboken2/ApiExtractor/doc/CMakeLists.txt b/sources/shiboken2/ApiExtractor/doc/CMakeLists.txt new file mode 100644 index 000000000..d78844dc8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/CMakeLists.txt @@ -0,0 +1,10 @@ + +find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") + +if (SPHINX) + message("-- sphinx-build - found") + configure_file(conf.py.in conf.py @ONLY) + add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) +else() + message("-- sphinx-build - not found! doc target disabled") +endif() \ No newline at end of file diff --git a/sources/shiboken2/ApiExtractor/doc/_templates/index.html b/sources/shiboken2/ApiExtractor/doc/_templates/index.html new file mode 100644 index 000000000..4aa14ede5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/_templates/index.html @@ -0,0 +1,27 @@ +{% extends "layout.html" %} +{% set title = 'Overview' %} +{% block body %} + +{% endblock %} diff --git a/sources/shiboken2/ApiExtractor/doc/_templates/layout.html b/sources/shiboken2/ApiExtractor/doc/_templates/layout.html new file mode 100644 index 000000000..9dc53722d --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/_templates/layout.html @@ -0,0 +1,41 @@ +{% extends "!layout.html" %} + +# Invert sidebars +{%- block sidebar1 %}{{ sidebar() }}{%- endblock %} +{%- block sidebar2 %}{%- endblock %} + +{%- block header %} +
+
+
+ + +
+
+{%- endblock -%} + +{%- block footer %} + +
+{%- endblock %} + +# No top relbar. +{%- block relbar1 %}{%- endblock %} + +# No bottom relbar. +{%- block relbar2 %}{%- endblock %} diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/searchbox.html b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/searchbox.html new file mode 100644 index 000000000..55a972156 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/searchbox.html @@ -0,0 +1,12 @@ +{%- if pagename != "search" %} + + +{%- endif %} diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png new file mode 100644 index 000000000..843e7e2c5 Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg new file mode 100644 index 000000000..4229ae8db Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png new file mode 100644 index 000000000..b45830e00 Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg new file mode 100644 index 000000000..2a1fbe7a1 Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png new file mode 100644 index 000000000..51e868d6e Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg new file mode 100644 index 000000000..cd474efba Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png new file mode 100644 index 000000000..37800f454 Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css new file mode 100644 index 000000000..fd81f4379 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css @@ -0,0 +1,409 @@ +* { + font: 100% Verdana, Arial, Helvetica, sans-serif; + font-size:12px; +} + +html { + height: 100%; +} + +body { + margin: 0; + padding: 0; + text-align: center; + background-color: #EBEBEB; + height: 100%; + color: #333; +} + +strong { + font-weight:bold; +} + +.document { + padding-bottom: 90px; +} + +#container { + position: relative; + min-height: 100%; + background-image: url(fakebar.png); + background-repeat: repeat-y; + background-color: white; +} + +.footer { + position: absolute; + bottom: 0px; + margin-top: 50px; + text-align:center; + background-color: white; + border-top: 2px solid #e0e0e0; + white-space: nowrap; + height: 90px; + width: 100%; +} + +.footer img { + margin-left: 8px; + margin-right: 8px; +} + +.sphinxsidebar { + float: left; + width: 250px; + padding: 0px 10px 0px 10px; + text-align: left; +} + +.sphinxsidebar ul { + padding: 0px; + margin: 0px; + list-style-position: inside; +} + +.sphinxsidebar > ul { + padding: 0px; + margin: 0px; +} + +.sphinxsidebar ul li { + margin-left: 10px; + padding: 0px; +} + +.sphinxsidebar h3, .sphinxsidebar h3 a { + font-weight: bold; + color: #333; +} + +.documentwrapper { + margin-left: 270px; + text-align: left; + background-color: #ffffff; + border-left: 1px solid #989898; + font-size:18px; + padding: 10px 50px 15px 50px; + height: 100%; +} + +h1 { + font-size:18px; + padding-left: 50px; + padding-bottom: 15px; + padding-top: 15px; + border-bottom: 1px solid #c2c2c2; + text-transform:uppercase; + margin-right: -100px; + position: relative; + left: -50px; + top: -10px; +} + +h2 { + font-size:12px; + font-weight:bold; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 2px; + border-style: solid; + border-left-color: #b1b1b1; + border-right-color: #b1b1b1; + border-top-color: #b1b1b1; + border-bottom-color: #009491; + background-color: #e0e0e0; + padding:5px; + margin-top: 20px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + -khtml-border-radius:5px; +} + +h3, h4 { + font-weight: bolder; +} + +pre { + border-top: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + background-color: #fafafa; + padding: 5px; + font: 100% monospace; + overflow: auto; +} + +pre * { + font: 100% monospace; +} + +.headerlink { + font-size: 100%; + color: inherit; + float: right; + visibility: Hidden; +} + +h1 .headerlink { + padding-right: 50px; +} + +h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink { + visibility: Visible; +} + +a, a:visited { + color: #009491; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +div.note { + border: 1px solid #e3e3e3; +} + +table.docutils { + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; + border: none; +} + +table.docutils td { + border: none; +} + +table.docutils th { + border: none; + font-weight: bold; + vertical-align: top; +} + +h2 em { + float: right; + font-size: 10px; + position: relative; + top: -20px; +} + +/* Table of pymaemo components */ + +#development table.docutils td { + border-bottom: 1px solid #EBEBEB; +} + +#development th { + background-color: #EBEBEB; + color: #FC7E00; + padding: 5px; +} + +#development th:first-child { + -moz-border-radius: 20px 0px 0px 0px; + -webkit-border-radius: 20px 0px 0px 0px; + -khtml-border-radius: 20px 0px 0px 0px; + padding-left: 10px; +} +#development th:last-child { + -moz-border-radius: 0px 20px 0px 0px; + -webkit-border-radius: 0px 20px 0px 0px; + -khtml-border-radius: 0px 20px 0px 0px; + padding-right: 10px; + width: 100px; +} + +hr { + border: none; + border-bottom: 1px dashed #EBEBEB; + width: 70% +} + +.oldnews { + text-align: right; +} + +/******************* TOPO *****************************/ +.header { + background-image: url(bg_topo.jpg); + background-repeat: repeat-x; + height: 147px; +} + +.header_container { + background-image: url(bg_header.png); + background-repeat: no-repeat; + background-position: 100px 0px; +} + +.logo { + text-align: left; + margin-bottom: 10px; +} + +#searchbox { + border-top: 1px solid #989898; + padding-top: 10px; + margin-left: -10px; + margin-right: -10px; + padding-left: 10px; + padding-right: 10px; +} + +#search_button { + border: 1px solid #3A393A; + background-color: #3A393A; + color: white; + cursor: pointer; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + +} + +form { + margin: 0px; + padding: 0px; +} + +/* search field */ +form #q { + width: 136px; +/* height: 22px; */ + border: none; + margin: 0px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + margin-top: 2px; + padding: 4px; + line-height: 22px +} + +#search-results h2 { + display: none; +} + +#search-results h2 { + display: none; +} + +#search-results ul.search { + margin: 0px; + padding: 0px; +} + +ul.search div.context { + padding-left: 40px; +} + +#installation td { + text-align: center; + font-weight: bold; +} + +em { + color: inherit; + font-style:italic; +} + +/******** REL bar *********/ + +.related { + display: inline; +} + +.related ul { + padding: 0px 0px 0px 10px; + margin: 0px; + text-align: left; + background-image: url(relbar_bg.png); +} + +.related li { + display: inline; + color: white; + font-weight: bold; +} + +.related li a { + color: inherit; + line-height: 35px; + font-weight: bold; + vertical-align: middle; +} + +.related li.right { + float: right; + margin-right: 5px; +} + +.related h3 { + display: none; +} + +.align-center { + text-align: center; +} + +.contentstable { + width: 100%; +} + +.contentstable td { + padding-left: 30px; + vertical-align: top; +} + +p.biglink a { + font-size: 20px; +} + +dt:target, .highlight { + background-color: #fbe54e; +} + +img { + border: 0px; +} + +.figure .caption { + font-style:italic; +} + +table.footnote { + margin: 0px; +} diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png new file mode 100644 index 000000000..076c1057c Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png new file mode 100644 index 000000000..4036733a7 Binary files /dev/null and b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png differ diff --git a/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/theme.conf b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/theme.conf new file mode 100644 index 000000000..e0a652a5d --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/theme.conf @@ -0,0 +1,7 @@ +[theme] +inherit = default +stylesheet = pysidedocs.css +pygments_style = none + +[options] +nosidebar = false diff --git a/sources/shiboken2/ApiExtractor/doc/conf.py.in b/sources/shiboken2/ApiExtractor/doc/conf.py.in new file mode 100644 index 000000000..70750c899 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/conf.py.in @@ -0,0 +1,163 @@ +# -*- coding: utf-8 -*- +# +# ApiExtractor 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. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, 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('.')) + +# -- 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.refcounting', 'sphinx.ext.coverage'] + +rst_epilog = """ +.. |project| replace:: API Extractor +""" + +# 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' + +# The encoding of source files. +source_encoding = 'utf-8' + +# The master toctree document. +#master_doc = 'contents' + +# General information about the project. +project = u'API Extractor' +copyright = u'2009-2010, Nokia Corporation' + +# 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 = '@apiextractor_MAJOR_VERSION@.@apiextractor_MINOR_VERSION@' +# The full version, including alpha/beta/rc tags. +release = '@apiextractor_VERSION@' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'pysidedocs' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = { +#} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# 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 = None + +# 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 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = { '' : ''} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index' : 'index.html'} + +# If false, no index is generated. +html_use_index = False + +# If true, the index is split into individual pages for each letter. +html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +html_add_permalinks = True; + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + diff --git a/sources/shiboken2/ApiExtractor/doc/contents.rst b/sources/shiboken2/ApiExtractor/doc/contents.rst new file mode 100644 index 000000000..83a4889fe --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/contents.rst @@ -0,0 +1,9 @@ +Table of contents +***************** +.. toctree:: + :numbered: + :maxdepth: 3 + + overview.rst + ownership.rst + typesystem.rst diff --git a/sources/shiboken2/ApiExtractor/doc/dependency-apiextractor.svg b/sources/shiboken2/ApiExtractor/doc/dependency-apiextractor.svg new file mode 100644 index 000000000..6bec8b5a8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/dependency-apiextractor.svg @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + Boost + Qt Software + INdT/Nokia + + + + + + + + Qt 4.5 + 4.5 + headers and libraries - compile-time and run-time + GNU General Public License v3 /GNU Lesser General Public Licence v2.1 + + + + libapiextractor + 0.2 + headers and libraries - compile-time and run-time + LGPL version 2.1 + + + + boost::graph + 1.38.0 + headers and libraries - compile-time and run-time + Boost Software License 1.0 + + + diff --git a/sources/shiboken2/ApiExtractor/doc/overview.rst b/sources/shiboken2/ApiExtractor/doc/overview.rst new file mode 100644 index 000000000..471e2439b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/overview.rst @@ -0,0 +1,15 @@ +.. _gen-overview: + +********************** +API Extractor Overview +********************** + +The **API Extractor** library is used by the binding generator to parse headers +of a given library and merge this data with information provided by +typesystem (XML) files, resulting in a representation of how the API should be +exported to the chosen target language. The generation of source code for the +bindings is performed by specific generators using the API Extractor library. + +The API Extractor is based on QtScriptGenerator_ codebase. + +.. _QtScriptGenerator: http://labs.trolltech.com/page/Projects/QtScript/Generator diff --git a/sources/shiboken2/ApiExtractor/doc/ownership.rst b/sources/shiboken2/ApiExtractor/doc/ownership.rst new file mode 100644 index 000000000..760967da6 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/ownership.rst @@ -0,0 +1,85 @@ +Ownership Management +******************** + +Among the various types of instances interactions, sometimes an object +may be *owned* by another object, so that the owner is responsible for +destroying the owned object, like in Qt's object system [#]_. +This kind of relationship has a big role on interfacing with the target language, like +with Python's reference counting. + + +Ownership transfers +------------------- + +From C++ to target +^^^^^^^^^^^^^^^^^^ + + When an object that is currently owned by C++ has its ownership transfered + 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 + + + + + + +From target to C++ +^^^^^^^^^^^^^^^^^^ + + In the opposite direction,when an object ownership is transfered 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. + + .. code-block:: xml + + + + + + +Parent-child relationship +------------------------- + +One special type of relationship is the parent-child. When an object is called +the parent of another object (the child), the former is in charge of deleting its +child when deleted and the target language can trust that the child will be alive +as long as the parent is, unless some other method can take the C++ ownership away from the parent. + +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 + + + + + +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 +of the first argument using the `parent` tag. To remove ownership, just use "remove" in the action attribute. **Removing +parentship also transfers the ownership back to python.** + +Invalidation after use +---------------------- + +Sometimes an object is created as a virtual method call argument and destroyed after the +call returned. In this case, you should use the ``invalidate-after-use`` attribute in the +``modify-argument`` tag to mark the wrapper as invalid right after the virtual method returns. + + .. code-block:: xml + + + +In this example the second argument will be invalidated after this method call. + +.. [#] See *Object Trees and Object Ownership* http://doc.trolltech.com/4.5/objecttrees.html diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem.rst b/sources/shiboken2/ApiExtractor/doc/typesystem.rst new file mode 100644 index 000000000..69dda43a0 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem.rst @@ -0,0 +1,29 @@ +The API Extractor Type System +***************************** + +The typesystem is used by a binding generator or any other software using the APIExtractor library +to map a C++ library API onto a higher level language. + +The typesystem specification is a handwritten XML document listing the types +that will be available in the generated target language API; types that are not +declared in the specification will be ignored along with everything depending on +them. In addition, it is possible to manipulate and modify types and functions. +It is even possible to use the typesystem specification to inject arbitrary +code into the source files, such as an extra member function. + +Below there is a complete reference guide to the various nodes (XML tags) of the typesystem. +For usage examples, take a look at the typesystem files used to generate PySide. These files +can be found in the PySide/ directory of the PySide package. + +.. toctree:: + + typesystem_specifying_types + typesystem_manipulating_objects + typesystem_modify_function + typesystem_arguments + typesystem_solving_compilation + typesystem_templates + typesystem_conversionrule + typesystem_documentation + + diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_arguments.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_arguments.rst new file mode 100644 index 000000000..16e0678d3 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_arguments.rst @@ -0,0 +1,192 @@ +.. _modifying-arguments: + +Modifying Arguments +------------------- + +.. _conversion-rule: + +conversion-rule +^^^^^^^^^^^^^^^ + + The conversion-rule node allows you to write customized code to convert + the given argument between the target language and C++, and it is a child of the modify-argument node. + + .. code-block:: xml + + + + // the code + + + + This node is typically used in combination with the replace-type and + 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: + + .. code-block:: xml + + + bool %out = (bool) %in; + + + .. 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 `. + +remove-argument +^^^^^^^^^^^^^^^ + + The remove-argument node removes the given argument from the function's + signature, and it is a child of the modify-argument node. + + .. code-block:: xml + + + + + +rename to +^^^^^^^^^ + + The 'rename to' node is used to rename a argument and use this new name in the generated code. + + .. code-block:: xml + + + + + + +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 modify-argument node. + + .. code-block:: xml + + + + + +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 + modify-argument node. + + .. code-block:: xml + + + + + + +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 + modify-argument node. + + .. code-block:: xml + + + + + + 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 +^^^^^^^^^^^^^^^^ + + The define-ownership tag indicates that the function changes the ownership + rules of the argument object. The ``class`` attribute specifies the class of + function where to inject the ownership altering code. 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 + + + + + + +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. 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 + + + + + + + The variable-name attribute specifies the name used for the variable that + holds the reference(s). + + +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. + + .. code-block:: xml + + + + +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. + + .. code-block:: xml + + + + + + 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/shiboken2/ApiExtractor/doc/typesystem_conversionrule.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_conversionrule.rst new file mode 100644 index 000000000..c62d5bbf6 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_conversionrule.rst @@ -0,0 +1,113 @@ +.. _conversion-rule-tag: + +Conversion Rule Tag +------------------- + +.. _conversion-rule: + +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. + + .. code-block:: xml + + + + + // Code to convert a native value to a target language object. + + + + // Code to convert target language type object of type TARGETTYPEA + // to the C++ native type represented by the value/primitive/container-type. + + + // Code to convert target language type object of type TARGETTYPEB + // to the C++ native type represented by the value/primitive/container-type. + + + + + + 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. + + +.. _native-to-target: + +native-to-target +^^^^^^^^^^^^^^^^ + + The **native-to-target** tag tells how to convert a native C++ value to its + target language equivalent. 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. + ``insert-template`` tags may be used to insert commonly repeating code. + + .. code-block:: xml + + + + // Code to convert a native value to a target language object. + + + + 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"**) 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"**). + + +.. _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. 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 + + + \ + // List of target to native conversions meant to replace or expand + // the already existing implicit conversions. + + + + +.. _add-conversion: + +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. + + .. code-block:: xml + + + + // Code to convert target language type object of type TARGETTYPE_A + // to the C++ native type represented by the value/primitive/container-type. + + + + 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. + diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_documentation.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_documentation.rst new file mode 100644 index 000000000..43f72a1ba --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_documentation.rst @@ -0,0 +1,43 @@ +Manipulating Documentation +-------------------------- + +inject-documentation +^^^^^^^^^^^^^^^^^^^^ + + The inject-documentation node inserts the documentation into the generated + documentation. This node is a child of the object-type, value-type and + modify-function nodes. + + .. code-block:: xml + + + + // the documentation +
+ + + The **mode** attribute default value is *replace*. + + 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. + + At the moment the only supported backend is Sphinx. + +modify-documentation +^^^^^^^^^^^^^^^^^^^^ + + The modify-documentation node allows you to change the auto-generated + documentation. API Extractor transforms XML's from qdoc3 (the Qt documentation + tool) into .rst files to be processed later using Sphinx. So you can modify + the XML before the transformation occur. + + .. code-block:: xml + + + + + + The **xpath** attribute is the XPath to the node that you want to modify. diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_manipulating_objects.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_manipulating_objects.rst new file mode 100644 index 000000000..2838c95e1 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_manipulating_objects.rst @@ -0,0 +1,132 @@ +.. _manipulating-object-and-value-types: + +Manipulating Object and Value Types +----------------------------------- + +.. _inject-code: + +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. + + .. code-block:: xml + + + + // the code + + + + The ``class`` attribute specifies which module of the generated code that + will be affected by the code injection. The ``class`` attribute accepts the + following values: + + * native: The c++ code + * target: The binding code + * target-declaration: The code will be injected into the generated header + file containing the c++ wrapper class definition. + + 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. + + The ``since`` attribute specify the API version where this code was injected. + +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. + + .. code-block:: xml + + + + + + 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* attribute, which can mark the field + to be discarded on generation; it has the same purpose of the deprecated tag + :ref:`remove`. + +.. _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 an :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 + + + + + + The ``signature`` attribute is a normalized C++ signature, excluding return + values but including potential const declarations. + + The ``since`` attribute specify the API version when this function was modified. + + The ``remove``, ``access`` and ``rename`` attributes are *optional* attributes + for added convenience; they serve the same purpose as the deprecated tags :ref:`remove`, :ref:`access` and :ref:`rename`. + +.. _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 suposed to be a method, or :ref:`namespace` and :ref:`typesystem` if + the function is suposed to be a function inside a namespace or a global function. + + 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 + + + + + + The ``return-type`` attribute defaults to *void*, the ``access`` to *public* and the ``static`` one to *no*. + + The ``since`` attribute specify the API version when this function was added. + +.. _conversion-rule-on-types: + +conversion-rule +^^^^^^^^^^^^^^^ + + The conversion-rule node allows you to write customized code to convert the given argument between the target + language and C++, and is a child of the :ref:`value-type`, :ref:`object-type`, :ref:`primitive-type` and + :ref:`container-type` nodes. + + The code pointed by the file attribute is very tied to the generator using APIExtractor, so it don't follow any + rules, but the generator rules.. + + .. code-block:: xml + + + + + + The ``since`` attribute specify the API version when this conversion rule became valid. + + .. note:: You can also use the conversion-rule node to specify :ref:`how the conversion of a single function argument should be done in a function `. + diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_modify_function.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_modify_function.rst new file mode 100644 index 000000000..071cea4f5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_modify_function.rst @@ -0,0 +1,78 @@ +.. _modifying-functions: + +Modifying Functions +------------------- + +.. _modify-argument: + +modify-argument +^^^^^^^^^^^^^^^ + + The modify-argument node specifies which of the given function's arguments the + modification affects, and is a child of the modify-function node. Use the + remove-argument, replace-default-expression, remove-default-expression, + replace-type, reference-count and define-ownership nodes to specify the details + of the modification. + + .. code-block:: xml + + + + // modifications + + + + 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. + +.. _remove: + +remove +^^^^^^ + + The remove node removes the given method from the generated target language + API, and it is a child of the modify-function node. + + .. code-block:: xml + + + + + + .. warning:: This tag is deprecated, use the ``remove`` attribute from :ref:`modify-function` tag instead. + +.. _access: + +access +^^^^^^ + + The access node changes the access privileges of the given function in the + generated target language API, and it is a child of the modify-function node. + + .. code-block:: xml + + + + + + .. warning:: This tag is deprecated, use the ``access`` attribute from :ref:`modify-function` tag instead. + +.. _rename: + +rename +^^^^^^ + + The rename node changes the name of the given function in the generated target + language API, and it is a child of the modify-function node. + + .. code-block:: xml + + + + + + The ``to`` attribute is the new name of the function. + + .. warning:: This tag is deprecated, use the ``rename`` attribute from :ref:`modify-function` tag instead. diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_solving_compilation.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_solving_compilation.rst new file mode 100644 index 000000000..81d14a187 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_solving_compilation.rst @@ -0,0 +1,70 @@ +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 typesystem node. + + .. code-block:: xml + + + + + + 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 +^^^^^^^^^^^^^^ + + The extra-includes node contains declarations of additional include files, + and it can be a child of the interface-type, namespace-type, value-type and + object-type 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 witin the extra-include node: + + .. code-block:: xml + + + + + + + + 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 "...". + + +include +^^^^^^^ + + The include node specifies the name and location of a file that must be + included, and it is a child of the interface-type, namespace-type, value-type, + object-type or extra-includes nodes + + 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 + + + + + + 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/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst new file mode 100644 index 000000000..0d24a6d52 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst @@ -0,0 +1,371 @@ +Specifying Types +---------------- + +.. _typesystem: + +typesystem +^^^^^^^^^^ + + This is the root node containing all the type system information. It can + have a number of attributes, described below. + + .. code-block:: xml + + + + + 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". + +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 typesystem node. + + .. code-block:: xml + + + + + + 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. + + +rejection +^^^^^^^^^ + + The rejection node rejects the given class, or the specified function or + field, and it is a child of the typesystem node. + + .. code-block:: xml + + + + + + 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 \*. + +.. _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 typesystem node. Note that most + primitives are already specified in the QtCore typesystem. + + .. code-block:: xml + + + + + + The **name** attribute is the name of the primitive in C++, the optional, + **target-name** attribute is the name of the primitive type in the target + language. If the later two attributes are not specified their default value + will be the same as the **name** attribute. + + The *optional* **since** value is used to specify the API version of this type. + + 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* **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* **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*. + + +.. _namespace: + +namespace-type +^^^^^^^^^^^^^^ + + The namespace-type node maps the given C++ namespace to the target language, + and it is a child of the typesystem node. Note that within namespaces, the + generator only supports enums (i.e., no functions or classes). + + .. code-block:: xml + + + + + + The **name** attribute is the name of the namespace, e.g., "Qt". + + The *optional* **generate** attribute is used to inform if you need to prepend + the given namespace into each generated class. Its default value is **yes**. + + 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 **revision** attribute can be used to specify a revision for each type, easing the + production of ABI compatible bindings. + +enum-type +^^^^^^^^^ + + The enum-type node maps the given enum from C++ to the target language, + and it is a child of the typesystem node. Use the reject-enum-value to + reject values. + + .. code-block:: xml + + + + + + 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 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 **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 +^^^^^^^^^^^^^^^^^ + + The reject-enum-value node rejects the enum value specified by the **name** + attribute, and it is a child of the enum-type node. + + .. code-block:: xml + + + + + + 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. + + .. code-block:: xml + + + + + + 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* 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 *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 **revision** attribute can be used to specify a revision for each type, easing the + production of ABI compatible bindings. + +.. _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. + + .. code-block:: xml + + + + + + 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* 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. + +interface-type +^^^^^^^^^^^^^^ + + The interface-type node indicates that the given class is replaced by an + interface pattern when mapping from C++ to the target language. Using the + interface-type node implicitly makes the given type an :ref:`object-type`. + + .. code-block:: xml + + + + + + The **name** attribute is the fully qualified C++ class name. The *optional* + **package** attribute can be used to override the package of the type system. + If there is no C++ base class, the *optional* **default-superclass** attribute + can be used to specify a superclass in the generated target language API, for + the given class. + + The *optional* **since** value is used to specify the API version of this interface. + + The **revision** attribute can be used to specify a revision for each type, easing the + production of ABI compatible bindings. + +.. _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**. + + .. code-block:: xml + + + + + + 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: *list*, *string-list*, *linked-list*, *vector*, *stack*, + *queue*, *set*, *map*, *multi-map*, *hash*, *multi-hash* or *pair*. + + The *optional* **since** value is used to specify the API version of this container. + + +.. _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. + + .. code-block:: xml + + + + + + The **name** attribute is the name of the custom type, e.g., "PyObject". + + +.. _function: + +function +^^^^^^^^ + + The function node indicates that the given C++ global function is mapped onto + the target language. + + .. code-block:: xml + + + + + + This tag has some limitations, it doesn't support function modifications, besides you + can't add a function overload using :ref:`add-function` tag to an existent function. + These limitation will be addressed in future versions of ApiExtractor. + + The function tag has two *optional* attributes: **since**, whose value is used to specify + the API version of this function, and **rename**, to modify the function name. + diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_templates.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_templates.rst new file mode 100644 index 000000000..31b155c5a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_templates.rst @@ -0,0 +1,55 @@ +.. _using-code-templates: + +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 typesystem + node. + + .. code-block:: xml + + + + + + Use the insert-template node to insert the template code (identified by the + template's ``name`` attribute) into the generated code base. + + +insert-template +^^^^^^^^^^^^^^^ + + The insert-template node includes the code template identified by the name + attribute, and it can be a child of the inject-code, conversion-rule, template, + custom-constructor and custom-destructor nodes. + + .. code-block:: xml + + + + + + 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 insert-template node. + + .. code-block:: xml + + + + + + This node will replace the attribute ``from`` with the value pointed by + ``to``. + diff --git a/sources/shiboken2/ApiExtractor/docparser.cpp b/sources/shiboken2/ApiExtractor/docparser.cpp new file mode 100644 index 000000000..bae438f18 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/docparser.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "docparser.h" +#include "abstractmetalang.h" +#include "typesystem.h" +#include +#include +#include + +#include +#include +#include + +DocParser::DocParser() +{ + xmlSubstituteEntitiesDefault(1); +} + +DocParser::~DocParser() +{ +} + +QString DocParser::getDocumentation(QXmlQuery& xquery, const QString& query, + const DocModificationList& mods) const +{ + QString doc = execXQuery(xquery, query); + return applyDocModifications(mods, doc); +} + +QString DocParser::execXQuery(QXmlQuery& xquery, const QString& query) const +{ + QString escapedQuery(query); + // XQuery can't have invalid XML characters + escapedQuery.replace(QLatin1Char('&'), QLatin1String("&")); + escapedQuery.replace(QLatin1Char('<'), QLatin1String("<")); + xquery.setQuery(escapedQuery); + if (!xquery.isValid()) { + qWarning() << "Bad XQuery: " << escapedQuery; + return QString(); + } + + QString result; + xquery.evaluateTo(&result); + return result; +} + +namespace +{ + +struct XslResources +{ + xmlDocPtr xmlDoc; + xsltStylesheetPtr xslt; + xmlDocPtr xslResult; + + XslResources() : xmlDoc(0), xslt(0), xslResult(0) {} + + ~XslResources() + { + if (xslt) + xsltFreeStylesheet(xslt); + + if (xslResult) + xmlFreeDoc(xslResult); + + if (xmlDoc) + xmlFreeDoc(xmlDoc); + + xsltCleanupGlobals(); + xmlCleanupParser(); + } +}; + +} // namespace + +QString DocParser::applyDocModifications(const DocModificationList& mods, const QString& xml) const +{ + if (mods.isEmpty()) + return xml; + + bool hasXPathBasedModification = false; + for (const DocModification &mod : mods) { + if (mod.mode() == TypeSystem::DocModificationXPathReplace) { + hasXPathBasedModification = true; + break; + } + } + + if (!hasXPathBasedModification) + return xml; + + QString xsl = QLatin1String("\n" + "\n" + "\n" + " \n" + "\n" + "\n" + "\n" + " \n" + " \n" + "\n" + "\n" + ); + for (const DocModification &mod : mods) { + if (mod.mode() == TypeSystem::DocModificationXPathReplace) { + QString xpath = mod.xpath(); + xpath.replace(QLatin1Char('"'), QLatin1String(""")); + xsl += QLatin1String("") + + mod.code() + QLatin1String("\n"); + } + } + xsl += QLatin1String(""); + + XslResources res; + // Read XML data + QByteArray xmlData = xml.toUtf8(); + res.xmlDoc = xmlParseMemory(xmlData.constData(), xmlData.size()); + if (!res.xmlDoc) + return xml; + + // Read XSL data as a XML file + QByteArray xslData = xsl.toUtf8(); + // xsltFreeStylesheet will delete this pointer + xmlDocPtr xslDoc = xmlParseMemory(xslData.constData(), xslData.size()); + if (!xslDoc) + return xml; + + // Parse XSL data + res.xslt = xsltParseStylesheetDoc(xslDoc); + if (!res.xslt) + return xml; + + // Apply XSL + res.xslResult = xsltApplyStylesheet(res.xslt, res.xmlDoc, 0); + xmlChar* buffer = 0; + int bufferSize; + QString result; + if (!xsltSaveResultToString(&buffer, &bufferSize, res.xslResult, res.xslt)) { + result = QString::fromUtf8(reinterpret_cast(buffer), bufferSize); + std::free(buffer); + } else { + result = xml; + } + + Q_ASSERT(result != xml); + return result; +} + diff --git a/sources/shiboken2/ApiExtractor/docparser.h b/sources/shiboken2/ApiExtractor/docparser.h new file mode 100644 index 000000000..5573f6851 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/docparser.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef DOCPARSER_H +#define DOCPARSER_H + +#include "typesystem_typedefs.h" + +#include + +QT_BEGIN_NAMESPACE +class QDomDocument; +class QDomNode; +class QXmlQuery; +QT_END_NAMESPACE + +class AbstractMetaClass; +class DocModification; +class Documentation; + +class DocParser +{ +public: + DocParser(); + virtual ~DocParser(); + virtual void fillDocumentation(AbstractMetaClass* metaClass) = 0; + + /** + * Process and retrieves documentation concerning the entire + * module or library. + * \return object containing module/library documentation information + */ + virtual Documentation retrieveModuleDocumentation() = 0; + + void setDocumentationDataDirectory(const QString& dir) + { + m_docDataDir = dir; + } + + /** + * Informs the location of the XML data generated by the tool + * (e.g.: DoxyGen, qdoc) used to extract the library's documentation + * comment. + * \return the path for the directory containing the XML data created + * from the library's documentation beign parsed. + */ + QString documentationDataDirectory() const + { + return m_docDataDir; + } + + void setLibrarySourceDirectory(const QString& dir) + { + m_libSourceDir = dir; + } + /** + * Informs the location of the library being parsed. The library + * source code is parsed for the documentation comments. + * \return the path for the directory containing the source code of + * the library beign parsed. + */ + QString librarySourceDirectory() const + { + return m_libSourceDir; + } + + void setPackageName(const QString& packageName) + { + m_packageName = packageName; + } + /** + * Retrieves the name of the package (or module or library) being parsed. + * \return the name of the package (module/library) being parsed + */ + QString packageName() const + { + return m_packageName; + } + + /** + * Process and retrieves documentation concerning the entire + * module or library. + * \param name module name + * \return object containing module/library documentation information + * \todo Merge with retrieveModuleDocumentation() on next ABI change. + */ + virtual Documentation retrieveModuleDocumentation(const QString& name) = 0; + +protected: + QString getDocumentation(QXmlQuery& xquery, const QString& query, + const DocModificationList& mods) const; + +private: + QString m_packageName; + QString m_docDataDir; + QString m_libSourceDir; + + QString execXQuery(QXmlQuery& xquery, const QString& query) const; + QString applyDocModifications(const DocModificationList& mods, const QString& xml) const; +}; + +#endif // DOCPARSER_H + diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.cpp b/sources/shiboken2/ApiExtractor/doxygenparser.cpp new file mode 100644 index 000000000..6b90fe6fc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doxygenparser.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "doxygenparser.h" +#include "abstractmetalang.h" +#include "reporthandler.h" +#include "typesystem.h" + +#include +#include +#include + +namespace +{ + +QString getSectionKindAttr(const AbstractMetaFunction* func) +{ + if (func->isSignal()) { + return QLatin1String("signal"); + } else { + QString kind = func->isPublic() ? QLatin1String("public") : QLatin1String("protected"); + if (func->isStatic()) + kind += QLatin1String("-static"); + else if (func->isSlot()) + kind += QLatin1String("-slot"); + return kind; + } +} + +} + +Documentation DoxygenParser::retrieveModuleDocumentation() +{ + return retrieveModuleDocumentation(packageName()); +} + +void DoxygenParser::fillDocumentation(AbstractMetaClass* metaClass) +{ + if (!metaClass) + return; + + QString doxyFileSuffix; + if (metaClass->enclosingClass()) { + doxyFileSuffix += metaClass->enclosingClass()->name(); + doxyFileSuffix += QLatin1String("_1_1"); // FIXME: Check why _1_1!! + } + doxyFileSuffix += metaClass->name(); + doxyFileSuffix += QLatin1String(".xml"); + + const char* prefixes[] = { "class", "struct", "namespace" }; + const int numPrefixes = sizeof(prefixes) / sizeof(const char*); + bool isProperty = false; + + QString doxyFilePath; + for (int i = 0; i < numPrefixes; ++i) { + doxyFilePath = documentationDataDirectory() + QLatin1Char('/') + + QLatin1String(prefixes[i]) + doxyFileSuffix; + if (QFile::exists(doxyFilePath)) + break; + doxyFilePath.clear(); + } + + if (doxyFilePath.isEmpty()) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't find doxygen file for class " << metaClass->name() << ", tried: " + << QDir::toNativeSeparators(documentationDataDirectory()) + << "/{struct|class|namespace}"<< doxyFileSuffix; + return; + } + QXmlQuery xquery; + xquery.setFocus(QUrl(doxyFilePath)); + + // Get class documentation + QString classDoc = getDocumentation(xquery, QLatin1String("/doxygen/compounddef/detaileddescription"), + metaClass->typeEntry()->docModifications()); + if (classDoc.isEmpty()) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't find documentation for class \"" << metaClass->name() << "\"."; + } + metaClass->setDocumentation(classDoc); + + //Functions Documentation + const AbstractMetaFunctionList &funcs = metaClass->functionsInTargetLang(); + for (AbstractMetaFunction *func : funcs) { + if (!func || func->isPrivate()) + continue; + + QString query = QLatin1String("/doxygen/compounddef/sectiondef"); + // properties + if (func->isPropertyReader() || func->isPropertyWriter() + || func->isPropertyResetter()) { + query += QLatin1String("[@kind=\"property\"]/memberdef/name[text()=\"") + + func->propertySpec()->name() + QLatin1String("\"]"); + isProperty = true; + } else { // normal methods + QString kind = getSectionKindAttr(func); + query += QLatin1String("[@kind=\"") + kind + + QLatin1String("-func\"]/memberdef/name[text()=\"") + + func->originalName() + QLatin1String("\"]"); + + if (func->arguments().isEmpty()) { + QString args = func->isConstant() ? QLatin1String("() const ") : QLatin1String("()"); + query += QLatin1String("/../argsstring[text()=\"") + args + QLatin1String("\"]"); + } else { + int i = 1; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + if (!arg->type()->isPrimitive()) { + query += QLatin1String("/../param[") + QString::number(i) + + QLatin1String("]/type/ref[text()=\"") + + arg->type()->name() + QLatin1String("\"]/../.."); + } else { + query += QLatin1String("/../param[") + QString::number(i) + + QLatin1String("]/type[text()=\"") + + arg->type()->name() + QLatin1String("\"]/.."); + } + ++i; + } + } + } + if (!isProperty) { + query += QLatin1String("/../detaileddescription"); + } else { + query = QLatin1Char('(') + query; + query += QLatin1String("/../detaileddescription)[1]"); + } + QString doc = getDocumentation(xquery, query, DocModificationList()); + func->setDocumentation(doc); + isProperty = false; + } + + //Fields + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { + if (field->isPrivate()) + return; + + QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef/name[text()=\"") + + field->name() + QLatin1String("\"]/../detaileddescription"); + QString doc = getDocumentation(xquery, query, DocModificationList()); + field->setDocumentation(doc); + } + + //Enums + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *meta_enum : enums) { + QString query = QLatin1String("/doxygen/compounddef/sectiondef/memberdef[@kind=\"enum\"]/name[text()=\"") + + meta_enum->name() + QLatin1String("\"]/.."); + QString doc = getDocumentation(xquery, query, DocModificationList()); + meta_enum->setDocumentation(doc); + } + +} + +Documentation DoxygenParser::retrieveModuleDocumentation(const QString& name){ + + QString sourceFile = documentationDataDirectory() + QLatin1String("/indexpage.xml"); + + if (!QFile::exists(sourceFile)) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't find doxygen XML file for module " << name << ", tried: " + << QDir::toNativeSeparators(sourceFile); + return Documentation(); + } + + QXmlQuery xquery; + xquery.setFocus(QUrl(sourceFile)); + + // Module documentation + QString query = QLatin1String("/doxygen/compounddef/detaileddescription"); + return Documentation(getDocumentation(xquery, query, DocModificationList())); +} + diff --git a/sources/shiboken2/ApiExtractor/doxygenparser.h b/sources/shiboken2/ApiExtractor/doxygenparser.h new file mode 100644 index 000000000..3f9ca5142 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/doxygenparser.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DOXYGENPARSER_H +#define DOXYGENPARSER_H + +#include "docparser.h" + +class DoxygenParser : public DocParser +{ +public: + DoxygenParser() {} + void fillDocumentation(AbstractMetaClass *metaClass) override; + Documentation retrieveModuleDocumentation() override; + Documentation retrieveModuleDocumentation(const QString& name) override; +}; + +#endif // DOXYGENPARSER_H diff --git a/sources/shiboken2/ApiExtractor/fileout.cpp b/sources/shiboken2/ApiExtractor/fileout.cpp new file mode 100644 index 000000000..c97347fe1 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/fileout.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fileout.h" +#include "reporthandler.h" + +#include +#include +#include + +#include + +bool FileOut::dummy = false; +bool FileOut::diff = false; + +#ifdef Q_OS_LINUX +const char* colorDelete = "\033[31m"; +const char* colorAdd = "\033[32m"; +const char* colorInfo = "\033[36m"; +const char* colorReset = "\033[0m"; +#else +const char* colorDelete = ""; +const char* colorAdd = ""; +const char* colorInfo = ""; +const char* colorReset = ""; +#endif + +FileOut::FileOut(QString n): + name(n), + stream(&tmp), + isDone(false) +{} + +static int* lcsLength(QList a, QList b) +{ + const int height = a.size() + 1; + const int width = b.size() + 1; + + int *res = new int[width * height]; + + for (int row = 0; row < height; row++) + res[width * row] = 0; + + for (int col = 0; col < width; col++) + res[col] = 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; + else + res[width * row + col] = qMax(res[width * row + col-1], + res[width * (row-1) + col]); + } + } + return res; +} + +enum Type { + Add, + Delete, + Unchanged +}; + +struct Unit +{ + Unit(Type type, int pos) : + type(type), + start(pos), + end(pos) {} + + Type type; + int start; + int end; + + void print(QList a, QList b) + { + if (type == Unchanged) { + if ((end - start) > 9) { + for (int i = start; i <= start + 2; i++) + std::printf(" %s\n", a[i].data()); + std::printf("%s=\n= %d more lines\n=%s\n", colorInfo, end - start - 6, colorReset); + for (int i = end - 2; i <= end; i++) + std::printf(" %s\n", a[i].data()); + } else { + for (int i = start; i <= end; i++) + std::printf(" %s\n", a[i].data()); + } + } else if (type == Add) { + std::printf("%s", colorAdd); + for (int i = start; i <= end; i++) + std::printf("+ %s\n", b[i].data()); + std::printf("%s", colorReset); + } else if (type == Delete) { + std::printf("%s", colorDelete); + for (int i = start; i <= end; i++) + std::printf("- %s\n", a[i].data()); + std::printf("%s", colorReset); + } + } +}; + +static QList *unitAppend(QList *res, Type type, int pos) +{ + if (!res) { + res = new QList; + res->append(new Unit(type, pos)); + return res; + } + + Unit *last = res->last(); + if (last->type == type) + last->end = pos; + else + res->append(new Unit(type, pos)); + + return res; +} + +static QList *diffHelper(int *lcs, QList a, QList b, int row, int col) +{ + if (row > 0 && col > 0 && (a[row-1] == b[col-1])) { + return unitAppend(diffHelper(lcs, a, b, row - 1, col - 1), Unchanged, row - 1); + } else { + int width = b.size() + 1; + if ((col > 0) + && (row == 0 || lcs[width * row + col-1] >= lcs[width *(row-1) + col])) { + return unitAppend(diffHelper(lcs, a, b, row, col - 1), Add, col - 1); + } else if ((row > 0) + && (col == 0 || lcs[width * row + col-1] < lcs[width *(row-1) + col])) { + return unitAppend(diffHelper(lcs, a, b, row - 1, col), Delete, row - 1); + } + } + delete lcs; + return 0; +} + +static void diff(QList a, QList b) +{ + QList *res = diffHelper(lcsLength(a, b), a, b, a.size(), b.size()); + for (int i = 0; i < res->size(); i++) { + Unit *unit = res->at(i); + unit->print(a, b); + delete(unit); + } + delete(res); +} + + +FileOut::State FileOut::done() +{ + Q_ASSERT(!isDone); + if (name.isEmpty()) + return Failure; + + isDone = true; + bool fileEqual = false; + QFile fileRead(name); + QFileInfo info(fileRead); + stream.flush(); + QByteArray original; + if (info.exists() && (diff || (info.size() == tmp.size()))) { + if (!fileRead.open(QIODevice::ReadOnly)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("failed to open file '%1' for reading") + .arg(QDir::toNativeSeparators(fileRead.fileName())); + return Failure; + } + + original = fileRead.readAll(); + fileRead.close(); + fileEqual = (original == tmp); + } + + if (fileEqual) + return Unchanged; + + if (!FileOut::dummy) { + QDir dir(info.absolutePath()); + if (!dir.mkpath(dir.absolutePath())) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("unable to create directory '%1'") + .arg(QDir::toNativeSeparators(dir.absolutePath())); + return Failure; + } + + QFile fileWrite(name); + if (!fileWrite.open(QIODevice::WriteOnly)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("failed to open file '%1' for writing") + .arg(QDir::toNativeSeparators(fileWrite.fileName())); + return Failure; + } + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + stream.setCodec(codec); + stream.setDevice(&fileWrite); + stream << tmp; + } + if (diff) { + std::printf("%sFile: %s%s\n", colorInfo, qPrintable(name), colorReset); + ::diff(original.split('\n'), tmp.split('\n')); + std::printf("\n"); + } + + return Success; +} diff --git a/sources/shiboken2/ApiExtractor/fileout.h b/sources/shiboken2/ApiExtractor/fileout.h new file mode 100644 index 000000000..14ce3a251 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/fileout.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FILEOUT_H +#define FILEOUT_H + +#include +#include + +class FileOut : public QObject +{ +private: + QByteArray tmp; + QString name; + +public: + enum State { Failure, Unchanged, Success }; + + FileOut(QString name); + ~FileOut() + { + if (!isDone) + done(); + } + + State done(); + + QTextStream stream; + + static bool dummy; + static bool diff; + +private: + bool isDone; +}; + +#endif // FILEOUT_H diff --git a/sources/shiboken2/ApiExtractor/graph.cpp b/sources/shiboken2/ApiExtractor/graph.cpp new file mode 100644 index 000000000..e6ee660dc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/graph.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graph.h" +#include +#include +#include +#include +#include +#include +#include +#include + +struct Graph::GraphPrivate +{ + enum Color { WHITE, GRAY, BLACK }; + typedef QVector > Edges; + typedef QSet::const_iterator EdgeIterator; + + Edges edges; + + GraphPrivate(int numNodes) : edges(numNodes) + { + } + + void dfsVisit(int node, QLinkedList& result, QVector& colors) const + { + colors[node] = GRAY; + EdgeIterator it = edges[node].begin(); + for (; it != edges[node].end(); ++it) { + if (colors[*it] == WHITE) + dfsVisit(*it, result, colors); + else if (colors[*it] == GRAY) // This is not a DAG! + return; + } + colors[node] = BLACK; + result.push_front(node); + } +}; + +Graph::Graph(int numNodes) : m_d(new GraphPrivate(numNodes)) +{ +} + +Graph::~Graph() +{ + delete m_d; +} + +int Graph::nodeCount() const +{ + return m_d->edges.size(); +} + +QLinkedList Graph::topologicalSort() const +{ + int nodeCount = Graph::nodeCount(); + QLinkedList result; + QVector colors(nodeCount, GraphPrivate::WHITE); + + for (int i = 0; i < nodeCount; ++i) { + if (colors[i] == GraphPrivate::WHITE) + m_d->dfsVisit(i, result, colors); + } + + // Not a DAG! + if (result.size() != nodeCount) + return QLinkedList(); + return result; +} + +bool Graph::containsEdge(int from, int to) +{ + return m_d->edges[from].contains(to); +} + +void Graph::addEdge(int from, int to) +{ + Q_ASSERT(to < (int)m_d->edges.size()); + m_d->edges[from].insert(to); +} + +void Graph::removeEdge(int from, int to) +{ + m_d->edges[from].remove(to); +} + +void Graph::dump() const +{ + for (int i = 0; i < m_d->edges.size(); ++i) { + std::cout << i << " -> "; + std::copy(m_d->edges[i].begin(), m_d->edges[i].end(), std::ostream_iterator(std::cout, " ")); + std::cout << std::endl; + } +} + +void Graph::dumpDot(const QHash< int, QString >& nodeNames, const QString& fileName) const +{ + QFile output(fileName); + if (!output.open(QIODevice::WriteOnly)) + return; + QTextStream s(&output); + s << "digraph D {\n"; + for (int i = 0; i < m_d->edges.size(); ++i) { + GraphPrivate::EdgeIterator it = m_d->edges[i].begin(); + for (;it != m_d->edges[i].end(); ++it) + s << '"' << nodeNames[i] << "\" -> \"" << nodeNames[*it] << "\"\n"; + } + s << "}\n"; +} diff --git a/sources/shiboken2/ApiExtractor/graph.h b/sources/shiboken2/ApiExtractor/graph.h new file mode 100644 index 000000000..78b931320 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/graph.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GRAPH_H +#define GRAPH_H + +#include +#include +#include + +/// A graph that can have their nodes topologically sorted. +class Graph +{ +public: + /// Create a new graph with \p numNodes nodes. + Graph(int numNodes); + ~Graph(); + + /// Returns the numbed of nodes in this graph. + int nodeCount() const; + /// Returns true if the graph contains the edge from -> to + bool containsEdge(int from, int to); + /// Adds an edge to this graph. + void addEdge(int from, int to); + /// Removes an edge out of this graph. + void removeEdge(int from, int to); + /// Print this graph to stdout. + void dump() const; + /** + * Dumps a dot graph to a file named \p filename. + * \param nodeNames map used to translate node ids to human readable text. + * \param fileName file name where the output should be written. + */ + void dumpDot(const QHash& nodeNames, const QString& fileName) const; + + /** + * Topologically sort this graph. + * \return A collection with all nodes topologically sorted or an empty collection if a ciclic dependency was found. + */ + QLinkedList topologicalSort() const; +private: + + struct GraphPrivate; + GraphPrivate* m_d; +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/header_paths.h b/sources/shiboken2/ApiExtractor/header_paths.h new file mode 100644 index 000000000..3bc26efe0 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/header_paths.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HEADER_PATHS_H +#define HEADER_PATHS_H + +#include +#include +#include + +class HeaderPath { +public: + explicit HeaderPath(const QByteArray &p = QByteArray()) : path(p), m_isFramework(false) {} + explicit HeaderPath(const QString &s = QString(), bool isFramework = false) : + path(s.toLatin1()), m_isFramework(isFramework) {} + + QByteArray path; + bool m_isFramework; // macOS framework path + + static QByteArray includeOption(const HeaderPath &p, bool systemInclude = false) + { + QByteArray option; + + if (p.m_isFramework) + option = QByteArrayLiteral("-F"); + else if (systemInclude) + option = QByteArrayLiteral("-isystem"); + else + option = QByteArrayLiteral("-I"); + + return option + p.path; + } +}; + +typedef QList HeaderPaths; + +#endif // HEADER_PATHS_H diff --git a/sources/shiboken2/ApiExtractor/icecc.cmake b/sources/shiboken2/ApiExtractor/icecc.cmake new file mode 100644 index 000000000..b2bf071aa --- /dev/null +++ b/sources/shiboken2/ApiExtractor/icecc.cmake @@ -0,0 +1,11 @@ +include (CMakeForceCompiler) +option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") +if (ENABLE_ICECC) + find_program(ICECC icecc) + if (ICECC) + message(STATUS "icecc found! Distributed compilation for all!! huhuhu.") + cmake_force_cxx_compiler(${ICECC} icecc) + else(ICECC) + message(FATAL_ERROR "icecc NOT found! re-run cmake without -DENABLE_ICECC") + endif(ICECC) +endif(ENABLE_ICECC) diff --git a/sources/shiboken2/ApiExtractor/include.cpp b/sources/shiboken2/ApiExtractor/include.cpp new file mode 100644 index 000000000..deae2d2ac --- /dev/null +++ b/sources/shiboken2/ApiExtractor/include.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "include.h" +#include +#include +#include +#include + +QString Include::toString() const +{ + if (m_type == IncludePath) + return QLatin1String("#include <") + m_name + QLatin1Char('>'); + else if (m_type == LocalPath) + return QLatin1String("#include \"") + m_name + QLatin1Char('"'); + else + return QLatin1String("import ") + m_name + QLatin1Char(';'); +} + +uint qHash(const Include& inc) +{ + return qHash(inc.m_name); +} + +QTextStream& operator<<(QTextStream& out, const Include& include) +{ + if (include.isValid()) + out << include.toString() << endl; + return out; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const Include &i) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "Include("; + if (i.isValid()) + d << "type=" << i.type() << ", file=\"" << QDir::toNativeSeparators(i.name()) << '"'; + else + d << "invalid"; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/include.h b/sources/shiboken2/ApiExtractor/include.h new file mode 100644 index 000000000..dc4965e1a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/include.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INCLUDE_H +#define INCLUDE_H + +#include +#include + +QT_BEGIN_NAMESPACE +class QTextStream; +QT_END_NAMESPACE + +class Include +{ +public: + enum IncludeType { + IncludePath, + LocalPath, + TargetLangImport + }; + + Include() : m_type(IncludePath) {} + Include(IncludeType t, const QString &nam) : m_type(t), m_name(nam) {}; + + bool isValid() const + { + return !m_name.isEmpty(); + } + + IncludeType type() const + { + return m_type; + } + + QString name() const + { + return m_name; + } + + QString toString() const; + + bool operator<(const Include& other) const + { + return m_name < other.m_name; + } + + bool operator==(const Include& other) const + { + return m_type == other.m_type && m_name == other.m_name; + } + + friend uint qHash(const Include&); + private: + IncludeType m_type; + QString m_name; +}; + +uint qHash(const Include& inc); +QTextStream& operator<<(QTextStream& out, const Include& include); +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const Include &i); +#endif + +typedef QVector IncludeList; + +#endif diff --git a/sources/shiboken2/ApiExtractor/merge.xsl b/sources/shiboken2/ApiExtractor/merge.xsl new file mode 100644 index 000000000..d0b7eafa5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/merge.xsl @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp new file mode 100644 index 000000000..667e27344 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -0,0 +1,1207 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2002-2005 Roberto Raggi +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "codemodel.h" +#include +#include +#include +#include +#include + +// Predicate to find an item by name in a list of QSharedPointer +template class ModelItemNamePredicate : public std::unary_function > +{ +public: + explicit ModelItemNamePredicate(const QString &name) : m_name(name) {} + bool operator()(const QSharedPointer &item) const { return item->name() == m_name; } + +private: + const QString m_name; +}; + +template +static QSharedPointer findModelItem(const QVector > &list, const QString &name) +{ + typedef typename QVector >::const_iterator It; + const It it = std::find_if(list.begin(), list.end(), ModelItemNamePredicate(name)); + return it != list.end() ? *it : QSharedPointer(); +} + +// --------------------------------------------------------------------------- + +CodeModel::CodeModel() : m_globalNamespace(new _NamespaceModelItem(this)) +{ +} + +CodeModel::~CodeModel() +{ +} + +NamespaceModelItem CodeModel::globalNamespace() const +{ + return m_globalNamespace; +} + +void CodeModel::addFile(FileModelItem item) +{ + m_files.append(item); +} + +FileModelItem CodeModel::findFile(const QString &name) const +{ + return findModelItem(m_files, name); +} + +CodeModelItem CodeModel::findItem(const QStringList &qualifiedName, CodeModelItem scope) const +{ + for (int i = 0; i < qualifiedName.size(); ++i) { + // ### Extend to look for members etc too. + const QString &name = qualifiedName.at(i); + + if (NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(scope)) { + if (NamespaceModelItem tmp_ns = ns->findNamespace(name)) { + scope = tmp_ns; + continue; + } + } + + if (ScopeModelItem ss = qSharedPointerDynamicCast<_ScopeModelItem>(scope)) { + if (ClassModelItem cs = ss->findClass(name)) { + scope = cs; + } else if (EnumModelItem es = ss->findEnum(name)) { + if (i == qualifiedName.size() - 1) + return es; + } else if (TypeDefModelItem tp = ss->findTypeDef(name)) { + if (i == qualifiedName.size() - 1) + return tp; + } else { + // If we don't find the name in the scope chain we + // need to return an empty item to indicate failure... + return CodeModelItem(); + } + } + } + + return scope; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const CodeModel *m) +{ + QDebugStateSaver s(d); + d.noquote(); + d.nospace(); + d << "CodeModel("; + if (m) { + const NamespaceModelItem globalNamespaceP = m->globalNamespace(); + if (globalNamespaceP.data()) + globalNamespaceP->formatDebug(d); + } else { + d << '0'; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +TypeInfo TypeInfo::combine(const TypeInfo &__lhs, const TypeInfo &__rhs) +{ + TypeInfo __result = __lhs; + + __result.setConstant(__result.isConstant() || __rhs.isConstant()); + __result.setVolatile(__result.isVolatile() || __rhs.isVolatile()); + if (__rhs.referenceType() > __result.referenceType()) + __result.setReferenceType(__rhs.referenceType()); + __result.setIndirections(__result.indirections() + __rhs.indirections()); + __result.setArrayElements(__result.arrayElements() + __rhs.arrayElements()); + + return __result; +} + +TypeInfo TypeInfo::resolveType(TypeInfo const &__type, CodeModelItem __scope) +{ + CodeModel *__model = __scope->model(); + Q_ASSERT(__model != 0); + + return TypeInfo::resolveType(__model->findItem(__type.qualifiedName(), __scope), __type, __scope); +} + +TypeInfo TypeInfo::resolveType(CodeModelItem __item, TypeInfo const &__type, CodeModelItem __scope) +{ + // Copy the type and replace with the proper qualified name. This + // only makes sence to do if we're actually getting a resolved + // type with a namespace. We only get this if the returned type + // has more than 2 entries in the qualified name... This test + // could be improved by returning if the type was found or not. + TypeInfo otherType(__type); + if (__item && __item->qualifiedName().size() > 1) { + otherType.setQualifiedName(__item->qualifiedName()); + } + + if (TypeDefModelItem __typedef = qSharedPointerDynamicCast<_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()) { + std::cerr << "** WARNING Bailing out recursion of " << __FUNCTION__ + << "() on " << qPrintable(__type.qualifiedName().join(QLatin1String("::"))) + << std::endl; + return otherType; + } + return resolveType(nextItem, combined, __scope); + } + + return otherType; +} + +QString TypeInfo::toString() const +{ + QString tmp; + + tmp += m_qualifiedName.join(QLatin1String("::")); + if (isConstant()) + tmp += QLatin1String(" const"); + + if (isVolatile()) + tmp += QLatin1String(" volatile"); + + if (indirections()) + tmp += QString(indirections(), QLatin1Char('*')); + + switch (referenceType()) { + case NoReference: + break; + case LValueReference: + tmp += QLatin1Char('&'); + break; + case RValueReference: + tmp += QLatin1String("&&"); + break; + } + + if (isFunctionPointer()) { + tmp += QLatin1String(" (*)("); + for (int i = 0; i < m_arguments.count(); ++i) { + if (i != 0) + tmp += QLatin1String(", "); + + tmp += m_arguments.at(i).toString(); + } + tmp += QLatin1Char(')'); + } + + for (const QString &elt : m_arrayElements) { + tmp += QLatin1Char('['); + tmp += elt; + tmp += QLatin1Char(']'); + } + + return tmp; +} + +bool TypeInfo::operator==(const TypeInfo &other) const +{ + if (arrayElements().count() != other.arrayElements().count()) + return false; + +#if defined (RXX_CHECK_ARRAY_ELEMENTS) // ### it'll break + for (int i = 0; i < arrayElements().count(); ++i) { + QString elt1 = arrayElements().at(i).trimmed(); + QString elt2 = other.arrayElements().at(i).trimmed(); + + if (elt1 != elt2) + return false; + } +#endif + + return flags == other.flags + && m_qualifiedName == other.m_qualifiedName + && (!m_functionPointer || m_arguments == other.m_arguments); +} + +#ifndef QT_NO_DEBUG_STREAM +template +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 &d) const +{ + d << '"'; + formatSequence(d, m_qualifiedName.begin(), m_qualifiedName.end(), "\", \""); + d << '"'; + if (m_constant) + d << ", [const]"; + if (m_volatile) + d << ", [volatile]"; + if (m_indirections) + d << ", indirections=" << m_indirections; + switch (m_referenceType) { + case NoReference: + break; + case LValueReference: + d << ", [ref]"; + break; + case RValueReference: + d << ", [rvalref]"; + break; + } + if (m_functionPointer) { + d << ", function ptr("; + formatSequence(d, m_arguments.begin(), m_arguments.end()); + d << ')'; + } + if (!m_arrayElements.isEmpty()) { + d << ", array[" << m_arrayElements.size() << "]["; + formatSequence(d, m_arrayElements.begin(), m_arrayElements.end()); + d << ']'; + } +} + +QDebug operator<<(QDebug d, const TypeInfo &t) +{ + QDebugStateSaver s(d); +#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) + const int verbosity = d.verbosity(); +#else + const int verbosity = 0; +#endif + d.noquote(); + d.nospace(); + d << "TypeInfo("; + if (verbosity > 2) + t.formatDebug(d); + else + d << t.toString(); + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +_CodeModelItem::_CodeModelItem(CodeModel *model, int kind) + : m_model(model), + m_kind(kind), + m_startLine(0), + m_startColumn(0), + m_endLine(0), + m_endColumn(0) +{ +} + +_CodeModelItem::_CodeModelItem(CodeModel *model, const QString &name, int kind) + : m_model(model), + m_kind(kind), + m_startLine(0), + m_startColumn(0), + m_endLine(0), + m_endColumn(0), + m_name(name) +{ +} + +_CodeModelItem::~_CodeModelItem() +{ +} + +int _CodeModelItem::kind() const +{ + return m_kind; +} + +QStringList _CodeModelItem::qualifiedName() const +{ + QStringList q = scope(); + + if (!name().isEmpty()) + q += name(); + + return q; +} + +QString _CodeModelItem::name() const +{ + return m_name; +} + +void _CodeModelItem::setName(const QString &name) +{ + m_name = name; +} + +QStringList _CodeModelItem::scope() const +{ + return m_scope; +} + +void _CodeModelItem::setScope(const QStringList &scope) +{ + m_scope = scope; +} + +QString _CodeModelItem::fileName() const +{ + return m_fileName; +} + +void _CodeModelItem::setFileName(const QString &fileName) +{ + m_fileName = fileName; +} + +FileModelItem _CodeModelItem::file() const +{ + return model()->findFile(fileName()); +} + +void _CodeModelItem::getStartPosition(int *line, int *column) +{ + *line = m_startLine; + *column = m_startColumn; +} + +void _CodeModelItem::setStartPosition(int line, int column) +{ + m_startLine = line; + m_startColumn = column; +} + +void _CodeModelItem::getEndPosition(int *line, int *column) +{ + *line = m_endLine; + *column = m_endColumn; +} + +void _CodeModelItem::setEndPosition(int line, int column) +{ + m_endLine = line; + m_endColumn = column; +} + +#ifndef QT_NO_DEBUG_STREAM +template +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->data(); + } +} + +void _CodeModelItem::formatKind(QDebug &d, int k) +{ + switch (k) { + case Kind_Argument: + d << "ArgumentModelItem"; + break; + case Kind_Class: + d << "ClassModelItem"; + break; + case Kind_Enum: + d << "EnumModelItem"; + break; + case Kind_Enumerator: + d << "EnumeratorModelItem"; + break; + case Kind_File: + d << "FileModelItem"; + break; + case Kind_Function: + d << "FunctionModelItem"; + break; + case Kind_Member: + d << "MemberModelItem"; + break; + case Kind_Namespace: + d << "NamespaceModelItem"; + break; + case Kind_Variable: + d << "VariableModelItem"; + break; + case Kind_Scope: + d << "ScopeModelItem"; + break; + case Kind_TemplateParameter: + d << "TemplateParameter"; + break; + case Kind_TypeDef: + d << "TypeDefModelItem"; + break; + default: + d << "CodeModelItem"; + break; + } +} + +void _CodeModelItem::formatDebug(QDebug &d) const +{ + d << "(\"" << name() << '"'; + if (!m_scope.isEmpty()) { + d << ", scope="; + formatSequence(d, m_scope.cbegin(), m_scope.cend(), "::"); + } + if (!m_fileName.isEmpty()) { + d << ", file=\"" << QDir::toNativeSeparators(m_fileName); + if (m_startLine > 0) + d << ':' << m_startLine; + d << '"'; + } +} + +QDebug operator<<(QDebug d, const _CodeModelItem *t) +{ + QDebugStateSaver s(d); + d.noquote(); + d.nospace(); + if (!t) { + d << "CodeModelItem(0)"; + return d; + } + _CodeModelItem::formatKind(d, t->kind()); + t->formatDebug(d); + switch (t->kind()) { + case _CodeModelItem::Kind_Class: + d << " /* class " << t->name() << " */"; + break; + case _CodeModelItem::Kind_Namespace: + d << " /* namespace " << t->name() << " */"; + break; + } + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +_ClassModelItem::~_ClassModelItem() +{ +} + +QStringList _ClassModelItem::baseClasses() const +{ + return m_baseClasses; +} + +void _ClassModelItem::setBaseClasses(const QStringList &baseClasses) +{ + m_baseClasses = baseClasses; +} + +TemplateParameterList _ClassModelItem::templateParameters() const +{ + return m_templateParameters; +} + +void _ClassModelItem::setTemplateParameters(const TemplateParameterList &templateParameters) +{ + m_templateParameters = templateParameters; +} + +void _ClassModelItem::addBaseClass(const QString &baseClass) +{ + m_baseClasses.append(baseClass); +} + +bool _ClassModelItem::extendsClass(const QString &name) const +{ + return m_baseClasses.contains(name); +} + +void _ClassModelItem::setClassType(CodeModel::ClassType type) +{ + m_classType = type; +} + +CodeModel::ClassType _ClassModelItem::classType() const +{ + return m_classType; +} + +void _ClassModelItem::addPropertyDeclaration(const QString &propertyDeclaration) +{ + m_propertyDeclarations << propertyDeclaration; +} + +#ifndef QT_NO_DEBUG_STREAM +template +static void formatModelItemList(QDebug &d, const char *prefix, const List &l, + const char *separator = ", ") +{ + if (const int size = l.size()) { + d << prefix << '[' << size << "]("; + for (int i = 0; i < size; ++i) { + if (i) + d << separator; + l.at(i)->formatDebug(d); + } + d << ')'; + } +} + +void _ClassModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + if (!m_baseClasses.isEmpty()) + d << ", inherits=" << m_baseClasses; + formatModelItemList(d, ", templateParameters=", m_templateParameters); + formatScopeItemsDebug(d); +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +FunctionModelItem _ScopeModelItem::declaredFunction(FunctionModelItem item) +{ + for (const FunctionModelItem &fun : qAsConst(m_functions)) { + if (fun->name() == item->name() && fun->isSimilar(item)) + return fun; + + } + return FunctionModelItem(); +} + +_ScopeModelItem::~_ScopeModelItem() +{ +} + +void _ScopeModelItem::addEnumsDeclaration(const QString &enumsDeclaration) +{ + m_enumsDeclarations << enumsDeclaration; +} + +void _ScopeModelItem::addClass(ClassModelItem item) +{ + m_classes.append(item); +} + +void _ScopeModelItem::addFunction(FunctionModelItem item) +{ + m_functions.append(item); +} + +void _ScopeModelItem::addVariable(VariableModelItem item) +{ + m_variables.append(item); +} + +void _ScopeModelItem::addTypeDef(TypeDefModelItem item) +{ + m_typeDefs.append(item); +} + +void _ScopeModelItem::addEnum(EnumModelItem item) +{ + m_enums.append(item); +} + +#ifndef QT_NO_DEBUG_STREAM +template +static void formatScopeHash(QDebug &d, const char *prefix, const Hash &h, + const char *separator = ", ", + bool trailingNewLine = false) +{ + typedef typename Hash::ConstIterator HashIterator; + if (!h.isEmpty()) { + d << prefix << '[' << h.size() << "]("; + const HashIterator begin = h.begin(); + const HashIterator end = h.end(); + for (HashIterator it = begin; it != end; ++it) { // Omit the names as they are repeated + if (it != begin) + d << separator; + d << it.value().data(); + } + d << ')'; + if (trailingNewLine) + d << '\n'; + } +} + +template +static void formatScopeList(QDebug &d, const char *prefix, const List &l, + const char *separator = ", ", + bool trailingNewLine = false) +{ + if (!l.isEmpty()) { + d << prefix << '[' << l.size() << "]("; + formatPtrSequence(d, l.begin(), l.end(), separator); + d << ')'; + if (trailingNewLine) + d << '\n'; + } +} + +void _ScopeModelItem::formatScopeItemsDebug(QDebug &d) const +{ + formatScopeList(d, ", classes=", m_classes, "\n", true); + formatScopeList(d, ", enums=", m_enums, "\n", true); + formatScopeList(d, ", aliases=", m_typeDefs, "\n", true); + formatScopeList(d, ", functions=", m_functions, "\n", true); + formatScopeList(d, ", variables=", m_variables); +} + +void _ScopeModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + formatScopeItemsDebug(d); +} +#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" (as seen for methods +// from within the class "Vector"). +class ClassNamePredicate : public std::unary_function +{ +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()) == QLatin1Char('<'); + } + +private: + const QString m_name; +}; +} // namespace + +ClassModelItem _ScopeModelItem::findClass(const QString &name) const +{ + // A fully qualified template is matched by name only + const ClassList::const_iterator it = name.contains(QLatin1Char('<')) + ? std::find_if(m_classes.begin(), m_classes.end(), ModelItemNamePredicate<_ClassModelItem>(name)) + : std::find_if(m_classes.begin(), m_classes.end(), ClassNamePredicate(name)); + return it != m_classes.end() ? *it : ClassModelItem(); +} + +VariableModelItem _ScopeModelItem::findVariable(const QString &name) const +{ + return findModelItem(m_variables, name); +} + +TypeDefModelItem _ScopeModelItem::findTypeDef(const QString &name) const +{ + return findModelItem(m_typeDefs, name); +} + +EnumModelItem _ScopeModelItem::findEnum(const QString &name) const +{ + return findModelItem(m_enums, name); +} + +FunctionList _ScopeModelItem::findFunctions(const QString &name) const +{ + FunctionList result; + for (const FunctionModelItem &func : m_functions) { + if (func->name() == name) + result.append(func); + } + return result; +} + +// --------------------------------------------------------------------------- +_NamespaceModelItem::~_NamespaceModelItem() +{ +} + +QSet _NamespaceModelItem::uniqueNamespaces() const +{ + QSet result; + for (const NamespaceModelItem &n : m_namespaces) + result.insert(n); + return result; +} + +void _NamespaceModelItem::addNamespace(NamespaceModelItem item) +{ + m_namespaces.append(item); +} + +NamespaceModelItem _NamespaceModelItem::findNamespace(const QString &name) const +{ + return findModelItem(m_namespaces, name); +} + +_FileModelItem::~_FileModelItem() +{ +} + +#ifndef QT_NO_DEBUG_STREAM +void _NamespaceModelItem::formatDebug(QDebug &d) const +{ + _ScopeModelItem::formatDebug(d); + formatScopeList(d, ", namespaces=", m_namespaces); +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +_ArgumentModelItem::~_ArgumentModelItem() +{ +} + +TypeInfo _ArgumentModelItem::type() const +{ + return m_type; +} + +void _ArgumentModelItem::setType(const TypeInfo &type) +{ + m_type = type; +} + +bool _ArgumentModelItem::defaultValue() const +{ + return m_defaultValue; +} + +void _ArgumentModelItem::setDefaultValue(bool defaultValue) +{ + m_defaultValue = defaultValue; +} + +#ifndef QT_NO_DEBUG_STREAM +void _ArgumentModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + d << ", type=" << m_type; + if (m_defaultValue) + d << ", defaultValue=\"" << m_defaultValueExpression << '"'; +} +#endif // !QT_NO_DEBUG_STREAM +// --------------------------------------------------------------------------- +_FunctionModelItem::~_FunctionModelItem() +{ +} + +bool _FunctionModelItem::isSimilar(FunctionModelItem other) const +{ + if (name() != other->name()) + return false; + + if (isConstant() != other->isConstant()) + return false; + + if (isVariadics() != other->isVariadics()) + return false; + + if (arguments().count() != other->arguments().count()) + return false; + + // ### check the template parameters + + for (int i = 0; i < arguments().count(); ++i) { + ArgumentModelItem arg1 = arguments().at(i); + ArgumentModelItem arg2 = other->arguments().at(i); + + if (arg1->type() != arg2->type()) + return false; + } + + return true; +} + +ArgumentList _FunctionModelItem::arguments() const +{ + return m_arguments; +} + +void _FunctionModelItem::addArgument(ArgumentModelItem item) +{ + m_arguments.append(item); +} + +CodeModel::FunctionType _FunctionModelItem::functionType() const +{ + return m_functionType; +} + +void _FunctionModelItem::setFunctionType(CodeModel::FunctionType functionType) +{ + m_functionType = functionType; +} + +bool _FunctionModelItem::isVariadics() const +{ + return m_isVariadics; +} + +void _FunctionModelItem::setVariadics(bool isVariadics) +{ + m_isVariadics = isVariadics; +} + +bool _FunctionModelItem::isVirtual() const +{ + return m_isVirtual; +} + +void _FunctionModelItem::setVirtual(bool isVirtual) +{ + m_isVirtual = isVirtual; +} + +bool _FunctionModelItem::isInline() const +{ + return m_isInline; +} + +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::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; +} + +#ifndef QT_NO_DEBUG_STREAM +void _FunctionModelItem::formatDebug(QDebug &d) const +{ + _MemberModelItem::formatDebug(d); + d << ", type=" << m_functionType; + if (m_isInline) + d << " [inline]"; + if (m_isAbstract) + d << " [abstract]"; + if (m_isExplicit) + d << " [explicit]"; + if (m_isInvokable) + d << " [invokable]"; + formatModelItemList(d, ", arguments=", m_arguments); + if (m_isVariadics) + d << ",..."; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +TypeInfo _TypeDefModelItem::type() const +{ + return m_type; +} + +void _TypeDefModelItem::setType(const TypeInfo &type) +{ + m_type = type; +} + +#ifndef QT_NO_DEBUG_STREAM +void _TypeDefModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + d << ", type=" << m_type; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +CodeModel::AccessPolicy _EnumModelItem::accessPolicy() const +{ + return m_accessPolicy; +} + +_EnumModelItem::~_EnumModelItem() +{ +} + +void _EnumModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy) +{ + m_accessPolicy = accessPolicy; +} + +EnumeratorList _EnumModelItem::enumerators() const +{ + return m_enumerators; +} + +void _EnumModelItem::addEnumerator(EnumeratorModelItem item) +{ + m_enumerators.append(item); +} + +bool _EnumModelItem::isAnonymous() const +{ + return m_anonymous; +} + +void _EnumModelItem::setAnonymous(bool anonymous) +{ + m_anonymous = anonymous; +} + +#ifndef QT_NO_DEBUG_STREAM +void _EnumModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + if (m_anonymous) + d << " (anonymous)"; + formatModelItemList(d, ", enumerators=", m_enumerators); +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +_EnumeratorModelItem::~_EnumeratorModelItem() +{ +} + +QString _EnumeratorModelItem::value() const +{ + return m_value; +} + +void _EnumeratorModelItem::setValue(const QString &value) +{ + m_value = value; +} + +#ifndef QT_NO_DEBUG_STREAM +void _EnumeratorModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + if (!m_value.isEmpty()) + d << ", value=\"" << m_value << '"'; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +_TemplateParameterModelItem::~_TemplateParameterModelItem() +{ +} + +TypeInfo _TemplateParameterModelItem::type() const +{ + return m_type; +} + +void _TemplateParameterModelItem::setType(const TypeInfo &type) +{ + m_type = type; +} + +bool _TemplateParameterModelItem::defaultValue() const +{ + return m_defaultValue; +} + +void _TemplateParameterModelItem::setDefaultValue(bool defaultValue) +{ + m_defaultValue = defaultValue; +} + +#ifndef QT_NO_DEBUG_STREAM +void _TemplateParameterModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + d << ", type=" << m_type; + if (m_defaultValue) + d << " [defaultValue]"; +} +#endif // !QT_NO_DEBUG_STREAM + +// --------------------------------------------------------------------------- +TypeInfo _MemberModelItem::type() const +{ + return m_type; +} + +void _MemberModelItem::setType(const TypeInfo &type) +{ + m_type = type; +} + +CodeModel::AccessPolicy _MemberModelItem::accessPolicy() const +{ + return m_accessPolicy; +} + +_MemberModelItem::~_MemberModelItem() +{ +} + +void _MemberModelItem::setAccessPolicy(CodeModel::AccessPolicy accessPolicy) +{ + m_accessPolicy = accessPolicy; +} + +bool _MemberModelItem::isStatic() const +{ + return m_isStatic; +} + +void _MemberModelItem::setStatic(bool isStatic) +{ + m_isStatic = isStatic; +} + +bool _MemberModelItem::isConstant() const +{ + return m_isConstant; +} + +void _MemberModelItem::setConstant(bool isConstant) +{ + m_isConstant = isConstant; +} + +bool _MemberModelItem::isVolatile() const +{ + return m_isVolatile; +} + +void _MemberModelItem::setVolatile(bool isVolatile) +{ + m_isVolatile = isVolatile; +} + +bool _MemberModelItem::isAuto() const +{ + return m_isAuto; +} + +void _MemberModelItem::setAuto(bool isAuto) +{ + m_isAuto = isAuto; +} + +bool _MemberModelItem::isFriend() const +{ + return m_isFriend; +} + +void _MemberModelItem::setFriend(bool isFriend) +{ + m_isFriend = isFriend; +} + +bool _MemberModelItem::isRegister() const +{ + return m_isRegister; +} + +void _MemberModelItem::setRegister(bool isRegister) +{ + m_isRegister = isRegister; +} + +bool _MemberModelItem::isExtern() const +{ + return m_isExtern; +} + +void _MemberModelItem::setExtern(bool isExtern) +{ + m_isExtern = isExtern; +} + +bool _MemberModelItem::isMutable() const +{ + return m_isMutable; +} + +void _MemberModelItem::setMutable(bool isMutable) +{ + m_isMutable = isMutable; +} + +#ifndef QT_NO_DEBUG_STREAM +void _MemberModelItem::formatDebug(QDebug &d) const +{ + _CodeModelItem::formatDebug(d); + switch (m_accessPolicy) { + case CodeModel::Public: + d << ", public"; + break; + case CodeModel::Protected: + d << ", protected"; + break; + case CodeModel::Private: + d << ", private"; + break; + } + d << ", type="; + if (m_isConstant) + d << "const "; + if (m_isVolatile) + d << "volatile "; + if (m_isStatic) + d << "static "; + if (m_isAuto) + d << "auto "; + if (m_isFriend) + d << "friend "; + if (m_isRegister) + d << "register "; + if (m_isExtern) + d << "extern "; + if (m_isMutable) + d << "mutable "; + d << m_type; + formatScopeList(d, ", templateParameters", m_templateParameters); +} +#endif // !QT_NO_DEBUG_STREAM + +// kate: space-indent on; indent-width 2; replace-tabs on; + diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h new file mode 100644 index 000000000..ea16e6912 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -0,0 +1,687 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2002-2005 Roberto Raggi +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef CODEMODEL_H +#define CODEMODEL_H + +#include "codemodel_fwd.h" +#include "codemodel_enums.h" + +#include +#include +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) + +#define DECLARE_MODEL_NODE(k) \ + enum { __node_kind = Kind_##k }; + +class CodeModel +{ +public: + enum AccessPolicy { + Public, + Protected, + Private + }; + + enum FunctionType { + Normal, + Signal, + Slot + }; + + enum ClassType { + Class, + Struct, + Union + }; + +public: + CodeModel(); + virtual ~CodeModel(); + + FileList files() const { return m_files; } + NamespaceModelItem globalNamespace() const; + + void addFile(FileModelItem item); + FileModelItem findFile(const QString &name) const; + + CodeModelItem findItem(const QStringList &qualifiedName, CodeModelItem scope) const; + +private: + FileList m_files; + NamespaceModelItem m_globalNamespace; + +private: + CodeModel(const CodeModel &other); + void operator = (const CodeModel &other); +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const CodeModel *m); +#endif + +class TypeInfo +{ +public: + TypeInfo() : flags(0), m_referenceType(NoReference) {} + + QStringList qualifiedName() const + { + return m_qualifiedName; + } + + void setQualifiedName(const QStringList &qualified_name) + { + m_qualifiedName = qualified_name; + } + + bool isConstant() const + { + return m_constant; + } + + void setConstant(bool is) + { + m_constant = is; + } + + bool isVolatile() const + { + return m_volatile; + } + + void setVolatile(bool is) + { + m_volatile = is; + } + + ReferenceType referenceType() const { return m_referenceType; } + void setReferenceType(ReferenceType r) { m_referenceType = r; } + + int indirections() const + { + return m_indirections; + } + + void setIndirections(int indirections) + { + m_indirections = indirections; + } + + bool isFunctionPointer() const + { + return m_functionPointer; + } + void setFunctionPointer(bool is) + { + m_functionPointer = is; + } + + QStringList arrayElements() const + { + return m_arrayElements; + } + void setArrayElements(const QStringList &arrayElements) + { + m_arrayElements = arrayElements; + } + + QVector arguments() const { return m_arguments; } + + void setArguments(const QVector &arguments); + + void addArgument(const TypeInfo &arg) + { + m_arguments.append(arg); + } + + bool operator==(const TypeInfo &other) const; + + bool operator!=(const TypeInfo &other) const + { + return !(*this == other); + } + + // ### arrays and templates?? + + QString toString() const; + + static TypeInfo combine(const TypeInfo &__lhs, const TypeInfo &__rhs); + static TypeInfo resolveType(TypeInfo const &__type, CodeModelItem __scope); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const; +#endif + +private: + static TypeInfo resolveType(CodeModelItem item, TypeInfo const &__type, CodeModelItem __scope); + + QStringList m_qualifiedName; + QStringList m_arrayElements; + QVector m_arguments; + + union { + uint flags; + + struct { + uint m_constant: 1; + uint m_volatile: 1; + uint m_functionPointer: 1; + uint m_indirections: 6; + uint m_padding: 23; + }; + }; + + ReferenceType m_referenceType; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeInfo &t); +#endif + +class _CodeModelItem +{ + Q_DISABLE_COPY(_CodeModelItem) +public: + enum Kind { + /* These are bit-flags resembling inheritance */ + Kind_Scope = 0x1, + Kind_Namespace = 0x2 | Kind_Scope, + Kind_Member = 0x4, + Kind_Function = 0x8 | Kind_Member, + KindMask = 0xf, + + /* These are for classes that are not inherited from */ + FirstKind = 0x8, + Kind_Argument = 1 << FirstKind, + Kind_Class = 2 << FirstKind | Kind_Scope, + Kind_Enum = 3 << FirstKind, + Kind_Enumerator = 4 << FirstKind, + Kind_File = 5 << FirstKind | Kind_Namespace, + Kind_TemplateParameter = 7 << FirstKind, + Kind_TypeDef = 8 << FirstKind, + Kind_Variable = 9 << FirstKind | Kind_Member + }; + +public: + virtual ~_CodeModelItem(); + + int kind() const; + + QStringList qualifiedName() const; + + QString name() const; + void setName(const QString &name); + + QStringList scope() const; + void setScope(const QStringList &scope); + + QString fileName() const; + void setFileName(const QString &fileName); + + FileModelItem file() const; + + void getStartPosition(int *line, int *column); + void setStartPosition(int line, int column); + + void getEndPosition(int *line, int *column); + void setEndPosition(int line, int column); + + inline CodeModel *model() const { return m_model; } + +#ifndef QT_NO_DEBUG_STREAM + static void formatKind(QDebug &d, int k); + virtual void formatDebug(QDebug &d) const; +#endif + +protected: + explicit _CodeModelItem(CodeModel *model, int kind); + explicit _CodeModelItem(CodeModel *model, const QString &name, int kind); + +private: + CodeModel *m_model; + int m_kind; + int m_startLine; + int m_startColumn; + int m_endLine; + int m_endColumn; + QString m_name; + QString m_fileName; + QStringList m_scope; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const _CodeModelItem *t); +#endif + +class _ScopeModelItem: public _CodeModelItem +{ +public: + DECLARE_MODEL_NODE(Scope) + + ~_ScopeModelItem(); + + ClassList classes() const { return m_classes; } + EnumList enums() const { return m_enums; } + inline FunctionList functions() const { return m_functions; } + TypeDefList typeDefs() const { return m_typeDefs; } + VariableList variables() const { return m_variables; } + + void addClass(ClassModelItem item); + void addEnum(EnumModelItem item); + void addFunction(FunctionModelItem item); + void addTypeDef(TypeDefModelItem item); + void addVariable(VariableModelItem item); + + ClassModelItem findClass(const QString &name) const; + EnumModelItem findEnum(const QString &name) const; + FunctionList findFunctions(const QString &name) const; + TypeDefModelItem findTypeDef(const QString &name) const; + VariableModelItem findVariable(const QString &name) const; + + void addEnumsDeclaration(const QString &enumsDeclaration); + QStringList enumsDeclarations() const { return m_enumsDeclarations; } + + FunctionModelItem declaredFunction(FunctionModelItem item); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#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) {} + +#ifndef QT_NO_DEBUG_STREAM + void formatScopeItemsDebug(QDebug &d) const; +#endif + +private: + ClassList m_classes; + EnumList m_enums; + TypeDefList m_typeDefs; + VariableList m_variables; + FunctionList m_functions; + +private: + QStringList m_enumsDeclarations; +}; + +class _ClassModelItem: public _ScopeModelItem +{ +public: + DECLARE_MODEL_NODE(Class) + + 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) {} + ~_ClassModelItem(); + + QStringList baseClasses() const; + + void setBaseClasses(const QStringList &baseClasses); + void addBaseClass(const QString &baseClass); + + TemplateParameterList templateParameters() const; + void setTemplateParameters(const TemplateParameterList &templateParameters); + + bool extendsClass(const QString &name) const; + + void setClassType(CodeModel::ClassType type); + CodeModel::ClassType classType() const; + + void addPropertyDeclaration(const QString &propertyDeclaration); + QStringList propertyDeclarations() const { return m_propertyDeclarations; } + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + QStringList m_baseClasses; + TemplateParameterList m_templateParameters; + CodeModel::ClassType m_classType; + + QStringList m_propertyDeclarations; +}; + +class _NamespaceModelItem: public _ScopeModelItem +{ +public: + 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) {} + ~_NamespaceModelItem(); + + NamespaceList namespaces() const { return m_namespaces; } + QSet uniqueNamespaces() const; + + void addNamespace(NamespaceModelItem item); + + NamespaceModelItem findNamespace(const QString &name) const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + NamespaceList m_namespaces; +}; + +class _FileModelItem: public _NamespaceModelItem +{ +public: + 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) {} + ~_FileModelItem(); +}; + +class _ArgumentModelItem: public _CodeModelItem +{ +public: + 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) {} + ~_ArgumentModelItem(); + + TypeInfo type() const; + void setType(const TypeInfo &type); + + bool defaultValue() const; + void setDefaultValue(bool defaultValue); + + QString defaultValueExpression() const { return m_defaultValueExpression; } + void setDefaultValueExpression(const QString &expr) { m_defaultValueExpression = expr; } + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + TypeInfo m_type; + QString m_defaultValueExpression; + bool m_defaultValue; +}; + +class _MemberModelItem: public _CodeModelItem +{ +public: + DECLARE_MODEL_NODE(Member) + + explicit _MemberModelItem(CodeModel *model, int kind = __node_kind) + : _CodeModelItem(model, kind), m_accessPolicy(CodeModel::Public), m_flags(0) {} + explicit _MemberModelItem(CodeModel *model, const QString &name, int kind = __node_kind) + : _CodeModelItem(model, name, kind), m_accessPolicy(CodeModel::Public), m_flags(0) {} + ~_MemberModelItem(); + + bool isConstant() const; + void setConstant(bool isConstant); + + bool isVolatile() const; + void setVolatile(bool isVolatile); + + bool isStatic() const; + void setStatic(bool isStatic); + + bool isAuto() const; + void setAuto(bool isAuto); + + bool isFriend() const; + void setFriend(bool isFriend); + + bool isRegister() const; + void setRegister(bool isRegister); + + bool isExtern() const; + void setExtern(bool isExtern); + + bool isMutable() const; + void setMutable(bool isMutable); + + CodeModel::AccessPolicy accessPolicy() const; + void setAccessPolicy(CodeModel::AccessPolicy accessPolicy); + + TemplateParameterList templateParameters() const { return m_templateParameters; } + void setTemplateParameters(const TemplateParameterList &templateParameters) { m_templateParameters = templateParameters; } + + TypeInfo type() const; + void setType(const TypeInfo &type); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + TemplateParameterList m_templateParameters; + TypeInfo m_type; + CodeModel::AccessPolicy m_accessPolicy; + union { + struct { + uint m_isConstant: 1; + uint m_isVolatile: 1; + uint m_isStatic: 1; + uint m_isAuto: 1; + uint m_isFriend: 1; + uint m_isRegister: 1; + uint m_isExtern: 1; + uint m_isMutable: 1; + }; + uint m_flags; + }; + +}; + +class _FunctionModelItem: public _MemberModelItem +{ +public: + 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) {} + ~_FunctionModelItem(); + + ArgumentList arguments() const; + + void addArgument(ArgumentModelItem item); + + CodeModel::FunctionType functionType() const; + void setFunctionType(CodeModel::FunctionType functionType); + + bool isVirtual() const; + void setVirtual(bool isVirtual); + + bool isInline() const; + void setInline(bool isInline); + + bool isExplicit() const; + void setExplicit(bool isExplicit); + + bool isInvokable() const; // Qt + void setInvokable(bool isInvokable); // Qt + + bool isAbstract() const; + void setAbstract(bool isAbstract); + + bool isVariadics() const; + void setVariadics(bool isVariadics); + + bool isSimilar(FunctionModelItem other) const; + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + ArgumentList m_arguments; + CodeModel::FunctionType m_functionType; + union { + struct { + uint m_isVirtual: 1; + uint m_isInline: 1; + uint m_isAbstract: 1; + uint m_isExplicit: 1; + uint m_isVariadics: 1; + uint m_isInvokable : 1; // Qt + }; + uint m_flags; + }; +}; + +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) {} +}; + +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) {} + + TypeInfo type() const; + void setType(const TypeInfo &type); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + TypeInfo m_type; +}; + +class _EnumModelItem: public _CodeModelItem +{ +public: + DECLARE_MODEL_NODE(Enum) + + explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) + : _CodeModelItem(model, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} + explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) + : _CodeModelItem(model, name, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} + ~_EnumModelItem(); + + CodeModel::AccessPolicy accessPolicy() const; + void setAccessPolicy(CodeModel::AccessPolicy accessPolicy); + + EnumeratorList enumerators() const; + void addEnumerator(EnumeratorModelItem item); + bool isAnonymous() const; + void setAnonymous(bool anonymous); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + CodeModel::AccessPolicy m_accessPolicy; + EnumeratorList m_enumerators; + bool m_anonymous; +}; + +class _EnumeratorModelItem: public _CodeModelItem +{ +public: + 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) {} + ~_EnumeratorModelItem(); + + QString value() const; + void setValue(const QString &value); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + QString m_value; +}; + +class _TemplateParameterModelItem: public _CodeModelItem +{ +public: + 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) {} + ~_TemplateParameterModelItem(); + + TypeInfo type() const; + void setType(const TypeInfo &type); + + bool defaultValue() const; + void setDefaultValue(bool defaultValue); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const override; +#endif + +private: + TypeInfo m_type; + bool m_defaultValue; +}; + +#endif // CODEMODEL_H + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h new file mode 100644 index 000000000..aa8b051d8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -0,0 +1,38 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CODEMODEL_ENUMS_H +#define CODEMODEL_ENUMS_H + +enum ReferenceType { + NoReference, + LValueReference, + RValueReference +}; + +#endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h new file mode 100644 index 000000000..d5a9f2850 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2002-2005 Roberto Raggi +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef CODEMODEL_FWD_H +#define CODEMODEL_FWD_H + +#include +#include + +// forward declarations +class CodeModel; +class _ArgumentModelItem; +class _ClassModelItem; +class _CodeModelItem; +class _EnumModelItem; +class _EnumeratorModelItem; +class _FileModelItem; +class _FunctionModelItem; +class _NamespaceModelItem; +class _ScopeModelItem; +class _TemplateParameterModelItem; +class _TypeDefModelItem; +class _VariableModelItem; +class _MemberModelItem; +class TypeInfo; + +typedef QSharedPointer<_ArgumentModelItem> ArgumentModelItem; +typedef QSharedPointer<_ClassModelItem> ClassModelItem; +typedef QSharedPointer<_CodeModelItem> CodeModelItem; +typedef QSharedPointer<_EnumModelItem> EnumModelItem; +typedef QSharedPointer<_EnumeratorModelItem> EnumeratorModelItem; +typedef QSharedPointer<_FileModelItem> FileModelItem; +typedef QSharedPointer<_FunctionModelItem> FunctionModelItem; +typedef QSharedPointer<_NamespaceModelItem> NamespaceModelItem; +typedef QSharedPointer<_ScopeModelItem> ScopeModelItem; +typedef QSharedPointer<_TemplateParameterModelItem> TemplateParameterModelItem; +typedef QSharedPointer<_TypeDefModelItem> TypeDefModelItem; +typedef QSharedPointer<_VariableModelItem> VariableModelItem; +typedef QSharedPointer<_MemberModelItem> MemberModelItem; + +typedef QVector ArgumentList; +typedef QVector ClassList; +typedef QVector ItemList; +typedef QVector EnumList; +typedef QVector EnumeratorList; +typedef QVector FileList; +typedef QVector FunctionList; +typedef QVector NamespaceList; +typedef QVector ScopeList; +typedef QVector TemplateParameterList; +typedef QVector TypeDefList; +typedef QVector VariableList; +typedef QVector MemberList; + +#endif // CODEMODEL_FWD_H diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp new file mode 100644 index 000000000..00e2384f0 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtdocparser.h" +#include "abstractmetalang.h" +#include "reporthandler.h" +#include "typesystem.h" + +#include +#include +#include +#include + +Documentation QtDocParser::retrieveModuleDocumentation() +{ + return retrieveModuleDocumentation(packageName()); +} + +void QtDocParser::fillDocumentation(AbstractMetaClass* metaClass) +{ + if (!metaClass) + return; + + QString scope = metaClass->name(); + const AbstractMetaClass* context = metaClass->enclosingClass(); + while(context) { + if (context->enclosingClass() == 0) + break; + context = context->enclosingClass(); + } + + QString filename = metaClass->qualifiedCppName().toLower(); + filename.replace(QLatin1String("::"), QLatin1String("-")); + QString sourceFile = documentationDataDirectory() + QLatin1Char('/') + + filename + QLatin1String(".xml"); + if (metaClass->enclosingClass()) + sourceFile.replace(QLatin1String("::"), QLatin1String("-")); + + if (!QFile::exists(sourceFile)) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't find qdoc3 file for class " << metaClass->name() << ", tried: " + << QDir::toNativeSeparators(sourceFile); + return; + } + + QXmlQuery xquery; + xquery.setFocus(QUrl(sourceFile)); + + QString className = metaClass->name(); + + // Class/Namespace documentation + QString type = metaClass->isNamespace() ? QLatin1String("namespace") : QLatin1String("class"); + QString query = QLatin1String("/WebXML/document/") + type + QLatin1String("[@name=\"") + + className + QLatin1String("\"]/description"); + + 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); + } + + Documentation doc(getDocumentation(xquery, query, classModifs)); + metaClass->setDocumentation(doc); + + + //Functions Documentation + const AbstractMetaFunctionList &funcs = metaClass->functionsInTargetLang(); + for (AbstractMetaFunction *func : funcs) { + if (!func || func->isPrivate()) + continue; + + QString query = QLatin1String("/WebXML/document/") + type + + QLatin1String("[@name=\"") + className + QLatin1String("\"]"); + // properties + if (func->isPropertyReader() || func->isPropertyWriter() || func->isPropertyResetter()) { + query += QLatin1String("/property[@name=\"") + func->propertySpec()->name() + + QLatin1String("\"]"); + } else { // normal methods + QString isConst = func->isConstant() ? QLatin1String("true") : QLatin1String("false"); + query += QLatin1String("/function[@name=\"") + func->originalName() + + QLatin1String("\" and count(parameter)=") + + QString::number(func->arguments().count()) + + QLatin1String(" and @const=\"") + isConst + QLatin1String("\"]"); + + const AbstractMetaArgumentList &arguments = func->arguments(); + for (int i = 0, size = arguments.size(); i < size; ++i) { + const AbstractMetaArgument *arg = arguments.at(i); + QString type = arg->type()->name(); + + if (arg->type()->isConstant()) + type.prepend(QLatin1String("const ")); + + if (arg->type()->referenceType() == LValueReference) { + type += QLatin1String(" &"); + } else if (arg->type()->referenceType() == RValueReference) { + type += QLatin1String(" &&"); + } else if (arg->type()->indirections()) { + type += QLatin1Char(' '); + for (int j = 0, max = arg->type()->indirections(); j < max; ++j) + type += QLatin1Char('*'); + } + query += QLatin1String("/parameter[") + QString::number(i + 1) + + QLatin1String("][@left=\"") + type + QLatin1String("\"]/.."); + } + } + query += QLatin1String("/description"); + DocModificationList funcModifs; + for (const DocModification &funcModif : qAsConst(signedModifs)) { + if (funcModif.signature() == func->minimalSignature()) + funcModifs.append(funcModif); + } + doc.setValue(getDocumentation(xquery, query, funcModifs)); + func->setDocumentation(doc); + } +#if 0 + // Fields + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { + if (field->isPrivate()) + return; + + QString query = "/doxygen/compounddef/sectiondef/memberdef/name[text()=\"" + field->name() + "\"]/.."; + Documentation doc = getDocumentation(DocModificationList(), xquery, query); + field->setDocumentation(doc); + } +#endif + // Enums + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *meta_enum : enums) { + QString query = QLatin1String("/WebXML/document/") + type + + QLatin1String("[@name=\"") + + className + QLatin1String("\"]/enum[@name=\"") + + meta_enum->name() + QLatin1String("\"]/description"); + doc.setValue(getDocumentation(xquery, query, DocModificationList())); + meta_enum->setDocumentation(doc); + } +} + +Documentation QtDocParser::retrieveModuleDocumentation(const QString& name) +{ + // TODO: This method of acquiring the module name supposes that the target language uses + // dots as module separators in package names. Improve this. + QString moduleName = name; + moduleName.remove(0, name.lastIndexOf(QLatin1Char('.')) + 1); + QString sourceFile = documentationDataDirectory() + QLatin1Char('/') + + moduleName.toLower() + QLatin1String(".xml"); + + if (!QFile::exists(sourceFile)) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't find qdoc3 file for module " << name << ", tried: " + << QDir::toNativeSeparators(sourceFile); + return Documentation(); + } + + QXmlQuery xquery; + xquery.setFocus(QUrl(sourceFile)); + + // Module documentation + QString query = QLatin1String("/WebXML/document/page[@name=\"") + moduleName + QLatin1String("\"]/description"); + return Documentation(getDocumentation(xquery, query, DocModificationList())); +} diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.h b/sources/shiboken2/ApiExtractor/qtdocparser.h new file mode 100644 index 000000000..f6bd479cd --- /dev/null +++ b/sources/shiboken2/ApiExtractor/qtdocparser.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTDOCPARSER_H +#define QTDOCPARSER_H + +#include "docparser.h" + +class QtDocParser : public DocParser +{ +public: + QtDocParser() {} + void fillDocumentation(AbstractMetaClass* metaClass) override; + Documentation retrieveModuleDocumentation() override; + Documentation retrieveModuleDocumentation(const QString& name) override; +}; + +#endif // QTDOCPARSER_H + diff --git a/sources/shiboken2/ApiExtractor/reporthandler.cpp b/sources/shiboken2/ApiExtractor/reporthandler.cpp new file mode 100644 index 000000000..8abea42c6 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/reporthandler.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "reporthandler.h" +#include "typesystem.h" +#include "typedatabase.h" +#include +#include +#include +#include + +#if _WINDOWS || NOCOLOR + #define COLOR_END "" + #define COLOR_WHITE "" + #define COLOR_YELLOW "" + #define COLOR_GREEN "" +#else + #define COLOR_END "\033[0m" + #define COLOR_WHITE "\033[1;37m" + #define COLOR_YELLOW "\033[1;33m" + #define COLOR_GREEN "\033[0;32m" +#endif + +static bool m_silent = false; +static int m_warningCount = 0; +static int m_suppressedCount = 0; +static ReportHandler::DebugLevel m_debugLevel = ReportHandler::NoDebug; +static QSet m_reportedWarnings; +static QString m_progressBuffer; +static int m_step_size = 0; +static int m_step = -1; +static int m_step_warning = 0; + +Q_LOGGING_CATEGORY(lcShiboken, "qt.shiboken") + +static void printProgress() +{ + std::printf("%s", m_progressBuffer.toUtf8().data()); + std::fflush(stdout); + m_progressBuffer.clear(); +} + +void ReportHandler::install() +{ + qInstallMessageHandler(ReportHandler::messageOutput); +} + +ReportHandler::DebugLevel ReportHandler::debugLevel() +{ + return m_debugLevel; +} + +void ReportHandler::setDebugLevel(ReportHandler::DebugLevel level) +{ + m_debugLevel = level; +} + +int ReportHandler::suppressedCount() +{ + return m_suppressedCount; +} + +int ReportHandler::warningCount() +{ + return m_warningCount; +} + +void ReportHandler::setProgressReference(int max) +{ + m_step_size = max; + m_step = -1; +} + +bool ReportHandler::isSilent() +{ + return m_silent; +} + +void ReportHandler::setSilent(bool silent) +{ + m_silent = silent; +} + +void ReportHandler::messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &text) +{ + if (type == QtWarningMsg) { + if (m_silent || m_reportedWarnings.contains(text)) + return; + const TypeDatabase *db = TypeDatabase::instance(); + if (db && db->isSuppressedWarning(text)) { + ++m_suppressedCount; + return; + } + ++m_warningCount; + ++m_step_warning; + m_reportedWarnings.insert(text); + } + fprintf(stderr, "%s\n", qPrintable(qFormatLogMessage(type, context, text))); +} + +void ReportHandler::progress(const QString& str, ...) +{ + if (m_silent) + return; + + if (m_step == -1) { + QTextStream buf(&m_progressBuffer); + buf.setFieldWidth(45); + buf.setFieldAlignment(QTextStream::AlignLeft); + buf << str; + printProgress(); + m_step = 0; + } + m_step++; + if (m_step >= m_step_size) { + if (m_step_warning == 0) { + m_progressBuffer = QLatin1String("[" COLOR_GREEN "OK" COLOR_END "]\n"); + } else { + m_progressBuffer = QLatin1String("[" COLOR_YELLOW "WARNING" COLOR_END "]\n"); + } + printProgress(); + m_step_warning = 0; + } +} diff --git a/sources/shiboken2/ApiExtractor/reporthandler.h b/sources/shiboken2/ApiExtractor/reporthandler.h new file mode 100644 index 000000000..6896d6e86 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/reporthandler.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef REPORTHANDLER_H +#define REPORTHANDLER_H + +#include +#include + +Q_DECLARE_LOGGING_CATEGORY(lcShiboken) + +class ReportHandler +{ +public: + enum DebugLevel { NoDebug, SparseDebug, MediumDebug, FullDebug }; + + static void install(); + + static DebugLevel debugLevel(); + static void setDebugLevel(DebugLevel level); + + static int warningCount(); + + static int suppressedCount(); + + template + static void setProgressReference(T collection) + { + setProgressReference(collection.count()); + } + + static void setProgressReference(int max); + + static void progress(const QString &str, ...); + + static bool isDebug(DebugLevel level) + { return debugLevel() >= level; } + + static bool isSilent(); + static void setSilent(bool silent); + +private: + static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); +}; + +#endif // REPORTHANDLER_H diff --git a/sources/shiboken2/ApiExtractor/symbols.filter b/sources/shiboken2/ApiExtractor/symbols.filter new file mode 100644 index 000000000..af6c744dd --- /dev/null +++ b/sources/shiboken2/ApiExtractor/symbols.filter @@ -0,0 +1,7 @@ +{ +local: +_ZSt*; +_ZNSt*; +_ZNSs*; +_ZNKSt*; +}; diff --git a/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt new file mode 100644 index 000000000..860a37d9d --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt @@ -0,0 +1,74 @@ +find_package(Qt5Core) +find_package(Qt5Gui) +find_package(Qt5Test) +find_package(Qt5Xml) +find_package(Qt5XmlPatterns) + +macro(declare_test testname) + # gone: qt4_automoc("${testname}.cpp") + if (EXISTS "${testname}.h") + add_executable(${testname} "${testname}.h ${testname}.cpp") + else () + add_executable(${testname} "${testname}.cpp") + endif () + include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${apiextractor_SOURCE_DIR} + ${Qt5Test_INCLUDE_DIRS} + ) + link_directories(${APIEXTRACTOR_EXTRA_LINK_DIRECTORIES}) + target_link_libraries(${testname} + ${Qt5XmlPatterns_LIBRARIES} + ${Qt5Test_LIBRARIES} + ${Qt5Core_LIBRARIES} + ${Qt5Gui_LIBRARIES} + apiextractor) + add_test(${testname} ${testname}) + if (INSTALL_TESTS) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${testname} + DESTINATION share/apiextractor${apiextractor_SUFFIX}/tests) + endif() +endmacro(declare_test testname) + +declare_test(testabstractmetaclass) +declare_test(testabstractmetatype) +declare_test(testaddfunction) +declare_test(testarrayargument) +declare_test(testcodeinjection) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/utf8code.txt" + "${CMAKE_CURRENT_BINARY_DIR}/utf8code.txt" COPYONLY) +declare_test(testcontainer) +declare_test(testconversionoperator) +declare_test(testconversionruletag) +declare_test(testctorinformation) +declare_test(testdroptypeentries) +declare_test(testdtorinformation) +declare_test(testenum) +declare_test(testextrainclude) +declare_test(testfunctiontag) +declare_test(testimplicitconversions) +declare_test(testinserttemplate) +declare_test(testmodifyfunction) +declare_test(testmultipleinheritance) +declare_test(testnamespace) +declare_test(testnestedtypes) +declare_test(testnumericaltypedef) +declare_test(testprimitivetypetag) +declare_test(testrefcounttag) +declare_test(testreferencetopointer) +declare_test(testremovefield) +declare_test(testremoveimplconv) +declare_test(testremoveoperatormethod) +declare_test(testresolvetype) +declare_test(testreverseoperators) +declare_test(testtemplates) +declare_test(testtoposort) +declare_test(testvaluetypedefaultctortag) +declare_test(testvoidarg) +declare_test(testtyperevision) +if (NOT DISABLE_DOCSTRINGS) + declare_test(testmodifydocumentation) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/a.xml" + "${CMAKE_CURRENT_BINARY_DIR}/a.xml" COPYONLY) +endif() + diff --git a/sources/shiboken2/ApiExtractor/tests/a.xml b/sources/shiboken2/ApiExtractor/tests/a.xml new file mode 100644 index 000000000..1c6d62a17 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/a.xml @@ -0,0 +1,13 @@ + + + + + + oi + Paragraph number 1 + Paragraph number 2 + Paragraph number 3 + + + + diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp new file mode 100644 index 000000000..423b8d9ff --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp @@ -0,0 +1,527 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testabstractmetaclass.h" +#include "abstractmetabuilder.h" +#include +#include "testutil.h" +#include +#include + +void TestAbstractMetaClass::testClassName() +{ + const char* cppCode ="class ClassName {};"; + const char* xmlCode = ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + QCOMPARE(classes[0]->name(), QLatin1String("ClassName")); +} + +void TestAbstractMetaClass::testClassNameUnderNamespace() +{ + const char* cppCode ="namespace Namespace { class ClassName {}; }\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); // 1 namespace + 1 class + if (classes.first()->name() != QLatin1String("ClassName")) + qSwap(classes[0], classes[1]); + + QCOMPARE(classes[0]->name(), QLatin1String("ClassName")); + QCOMPARE(classes[0]->qualifiedCppName(), QLatin1String("Namespace::ClassName")); + QCOMPARE(classes[1]->name(), QLatin1String("Namespace")); + QVERIFY(classes[1]->isNamespace()); + + // Check ctors info + QVERIFY(classes[0]->hasConstructors()); + QCOMPARE(classes[0]->functions().size(), 2); // default ctor + copy ctor + + AbstractMetaFunctionList ctors = classes[0]->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + if (ctors.first()->minimalSignature() != QLatin1String("ClassName()")) + qSwap(ctors[0], ctors[1]); + + QCOMPARE(ctors[0]->arguments().size(), 0); + QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("ClassName()")); + QCOMPARE(ctors[1]->arguments().size(), 1); + QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("ClassName(Namespace::ClassName)")); + + QVERIFY(!classes[0]->hasPrivateDestructor()); + QVERIFY(classes[0]->hasCloneOperator()); // implicit default copy ctor + QVERIFY(!classes[0]->hasHashFunction()); + + // This method is buggy and nobody wants to fix it or needs it fixed :-/ + // QVERIFY(classes[0]->hasNonPrivateConstructor()); +} + +void TestAbstractMetaClass::testVirtualMethods() +{ + const char* cppCode ="\ + class A {\n\ + public:\n\ + virtual int pureVirtual() const = 0;\n\ + };\n\ + class B : public A {};\n\ + class C : public B {\n\ + public:\n\ + int pureVirtual() const { return 0; }\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + AbstractMetaClass* a = AbstractMetaClass::findClass(classes, QLatin1String("A")); + AbstractMetaClass* b = AbstractMetaClass::findClass(classes, QLatin1String("B")); + AbstractMetaClass* c = AbstractMetaClass::findClass(classes, QLatin1String("C")); + + AbstractMetaClass* no_class = 0; + + QCOMPARE(a->baseClass(), no_class); + QCOMPARE(b->baseClass(), a); + QCOMPARE(c->baseClass(), b); + + QCOMPARE(a->functions().size(), 2); // default ctor + the pure virtual method + QCOMPARE(b->functions().size(), 2); + QCOMPARE(c->functions().size(), 2); + + // implementing class, ownclass, declaringclass + AbstractMetaFunction* ctorA = a->queryFunctions(AbstractMetaClass::Constructors).first(); + AbstractMetaFunction* ctorB = b->queryFunctions(AbstractMetaClass::Constructors).first(); + AbstractMetaFunction* ctorC = c->queryFunctions(AbstractMetaClass::Constructors).first(); + QVERIFY(ctorA->isConstructor()); + QVERIFY(!ctorA->isVirtual()); + QVERIFY(ctorB->isConstructor()); + QVERIFY(!ctorB->isVirtual()); + QVERIFY(ctorC->isConstructor()); + QVERIFY(!ctorC->isVirtual()); + QCOMPARE(ctorA->implementingClass(), a); + QCOMPARE(ctorA->ownerClass(), a); + QCOMPARE(ctorA->declaringClass(), a); + + QCOMPARE(a->virtualFunctions().size(), 1); // Add a pureVirtualMethods method !? + QCOMPARE(b->virtualFunctions().size(), 1); + QCOMPARE(c->virtualFunctions().size(), 1); + + AbstractMetaFunction* funcA = a->virtualFunctions().first(); + AbstractMetaFunction* funcB = b->virtualFunctions().first(); + AbstractMetaFunction* funcC = c->virtualFunctions().first(); + + QCOMPARE(funcA->ownerClass(), a); + QCOMPARE(funcB->ownerClass(), b); + QCOMPARE(funcC->ownerClass(), c); + + QCOMPARE(funcA->declaringClass(), a); + QCOMPARE(funcB->declaringClass(), a); + QCOMPARE(funcC->declaringClass(), a); + + // The next two tests could return null, because it makes more sense. + // But we have too many code written relying on this behaviour where + // implementingClass is equals to declaringClass on pure virtual functions + QCOMPARE(funcA->implementingClass(), a); + QCOMPARE(funcB->implementingClass(), a); + QCOMPARE(funcC->implementingClass(), c); +} + +void TestAbstractMetaClass::testDefaultValues() +{ + const char* cppCode ="\ + struct A {\n\ + class B {};\n\ + void method(B b = B());\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->queryFunctionsByName(QLatin1String("method")).count(), 1); + AbstractMetaFunction* method = classA->queryFunctionsByName(QLatin1String("method")).first(); + AbstractMetaArgument* arg = method->arguments().first(); + QCOMPARE(arg->defaultValueExpression(), arg->originalDefaultValueExpression()); +} + +void TestAbstractMetaClass::testModifiedDefaultValues() +{ + const char* cppCode ="\ + struct A {\n\ + class B {};\n\ + void method(B b = B());\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->queryFunctionsByName(QLatin1String("method")).count(), 1); + AbstractMetaFunction* method = classA->queryFunctionsByName(QLatin1String("method")).first(); + AbstractMetaArgument* arg = method->arguments().first(); + QCOMPARE(arg->defaultValueExpression(), QLatin1String("Hello")); + QCOMPARE(arg->originalDefaultValueExpression(), QLatin1String("A::B()")); +} + +void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne() +{ + const char* cppCode ="\ + struct A {\n\ + class B {};\n\ + virtual void method();\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QVERIFY(classA->isPolymorphic()); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("A::B")); + QVERIFY(classB); + QVERIFY(!classB->isPolymorphic()); +} + +void TestAbstractMetaClass::testForwardDeclaredInnerClass() +{ + const char cppCode[] ="\ + class A {\n\ + class B;\n\ + };\n\ + class A::B {\n\ + public:\n\ + void foo();\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("A::B")); + QVERIFY(classB); + const AbstractMetaFunction *fooF = classB->findFunction(QLatin1String("foo")); + QVERIFY(fooF); +} + +void TestAbstractMetaClass::testSpecialFunctions() +{ + const char cppCode[] ="\ + struct A {\n\ + A();\n\ + A(const A&);\n\ + A &operator=(const A&);\n\ + };\n\ + struct B {\n\ + B();\n\ + B(const B &);\n\ + B &operator=(B);\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); + QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); + AbstractMetaFunctionList assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); + QCOMPARE(assigmentOps.size(), 1); + QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); + + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + ctors = classB->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); + QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); + assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); + QCOMPARE(assigmentOps.size(), 1); + QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); +} + +void TestAbstractMetaClass::testClassDefaultConstructors() +{ + const char* cppCode ="\ + struct A {};\n\ + \n\ + struct B {\n\ + B();\n\ + private: \n\ + B(const B&);\n\ + };\n\ + \n\ + struct C {\n\ + C(const C&);\n\ + };\n\ + \n\ + struct D {\n\ + private: \n\ + D(const D&);\n\ + };\n\ + \n\ + struct E {\n\ + private: \n\ + ~E();\n\ + };\n\ + \n\ + struct F {\n\ + F(int, int);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 6); + + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().size(), 2); + + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + if (ctors.first()->minimalSignature() != QLatin1String("A()")) + qSwap(ctors[0], ctors[1]); + + QCOMPARE(ctors[0]->arguments().size(), 0); + QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); + QCOMPARE(ctors[1]->arguments().size(), 1); + QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("A(A)")); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + QCOMPARE(classB->functions().size(), 2); + QCOMPARE(classB->functions().first()->minimalSignature(), QLatin1String("B()")); + + AbstractMetaClass* classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); + QVERIFY(classC); + QCOMPARE(classC->functions().size(), 1); + QCOMPARE(classC->functions().first()->minimalSignature(), QLatin1String("C(C)")); + + AbstractMetaClass* classD = AbstractMetaClass::findClass(classes, QLatin1String("D")); + QVERIFY(classD); + QCOMPARE(classD->functions().size(), 1); + QCOMPARE(classD->functions().first()->minimalSignature(), QLatin1String("D(D)")); + QVERIFY(classD->functions().first()->isPrivate()); + + AbstractMetaClass* classE = AbstractMetaClass::findClass(classes, QLatin1String("E")); + QVERIFY(classE); + QVERIFY(classE->hasPrivateDestructor()); + QCOMPARE(classE->functions().size(), 0); + + AbstractMetaClass* classF = AbstractMetaClass::findClass(classes, QLatin1String("F")); + QVERIFY(classF); + + ctors = classF->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + if (ctors.first()->minimalSignature() != QLatin1String("F(int,int)")) + qSwap(ctors[0], ctors[1]); + + QCOMPARE(ctors[0]->arguments().size(), 2); + QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("F(int,int)")); + QCOMPARE(ctors[1]->arguments().size(), 1); + QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("F(F)")); +} + +void TestAbstractMetaClass::testClassInheritedDefaultConstructors() +{ + const char* cppCode ="\ + struct A {\n\ + A();\n\ + private: \n\ + A(const A&);\n\ + };\n\ + struct B : public A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + if (ctors.first()->minimalSignature() != QLatin1String("A()")) + qSwap(ctors[0], ctors[1]); + + QCOMPARE(ctors[0]->arguments().size(), 0); + QCOMPARE(ctors[0]->minimalSignature(), QLatin1String("A()")); + QCOMPARE(ctors[1]->arguments().size(), 1); + QCOMPARE(ctors[1]->minimalSignature(), QLatin1String("A(A)")); + QVERIFY(ctors[1]->isPrivate()); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + + ctors = classB->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 1); + QCOMPARE(ctors.first()->arguments().size(), 0); + QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("B()")); +} + +void TestAbstractMetaClass::testAbstractClassDefaultConstructors() +{ + const char* cppCode ="\ + struct A {\n\ + virtual void method() = 0;\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 1); + QCOMPARE(ctors.first()->arguments().size(), 0); + QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("A()")); +} + +void TestAbstractMetaClass::testObjectTypesMustNotHaveCopyConstructors() +{ + const char* cppCode ="struct A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 1); + QCOMPARE(ctors.first()->arguments().size(), 0); + QCOMPARE(ctors.first()->minimalSignature(), QLatin1String("A()")); +} + +void TestAbstractMetaClass::testIsPolymorphic() +{ + const char* cppCode = "\ + class A\n\ + {\n\ + public:\n\ + A();\n\ + inline bool abc() const {}\n\ + };\n\ + \n\ + class B : public A\n\ + {\n\ + public:\n\ + B();\n\ + inline bool abc() const {}\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* b = AbstractMetaClass::findClass(classes, QLatin1String("A")); + + QVERIFY(!b->isPolymorphic()); + AbstractMetaClass* a = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(!a->isPolymorphic()); +} + +QTEST_APPLESS_MAIN(TestAbstractMetaClass) diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h new file mode 100644 index 000000000..811bf5a10 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTABSTRACTMETACLASS_H +#define TESTABSTRACTMETACLASS_H + +#include + +class AbstractMetaBuilder; + +class TestAbstractMetaClass : public QObject +{ + Q_OBJECT +private slots: + void testClassName(); + void testClassNameUnderNamespace(); + void testVirtualMethods(); + void testDefaultValues(); + void testModifiedDefaultValues(); + void testInnerClassOfAPolymorphicOne(); + void testForwardDeclaredInnerClass(); + void testSpecialFunctions(); + void testClassDefaultConstructors(); + void testClassInheritedDefaultConstructors(); + void testAbstractClassDefaultConstructors(); + void testObjectTypesMustNotHaveCopyConstructors(); + void testIsPolymorphic(); +}; + +#endif // TESTABSTRACTMETACLASS_H diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp new file mode 100644 index 000000000..1d52c1e41 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp @@ -0,0 +1,216 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testabstractmetatype.h" +#include +#include "testutil.h" +#include +#include + +void TestAbstractMetaType::testConstCharPtrType() +{ + const char* cppCode ="const char* justAtest();\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + QCOMPARE(builder->globalFunctions().size(), 1); + AbstractMetaFunction* func = builder->globalFunctions().first(); + AbstractMetaType* rtype = func->type(); + // Test properties of const char* + QVERIFY(rtype); + QCOMPARE(rtype->package(), QLatin1String("Foo")); + QCOMPARE(rtype->name(), QLatin1String("char")); + QVERIFY(rtype->isConstant()); + QVERIFY(!rtype->isArray()); + QVERIFY(!rtype->isContainer()); + QVERIFY(!rtype->isObject()); + QVERIFY(!rtype->isPrimitive()); // const char* differs from char, so it's not considered a primitive type by apiextractor + QVERIFY(rtype->isNativePointer()); + QVERIFY(!rtype->isQObject()); + QCOMPARE(rtype->referenceType(), NoReference); + QVERIFY(!rtype->isValue()); + QVERIFY(!rtype->isValuePointer()); +} + +void TestAbstractMetaType::testApiVersionSupported() +{ + const char* cppCode ="class foo {}; class foo2 {};\n\ + void justAtest(); void justAtest3();\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "1.0")); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 2); + + + AbstractMetaFunctionList functions = builder->globalFunctions(); + QCOMPARE(functions.size(), 2); +} + + +void TestAbstractMetaType::testApiVersionNotSupported() +{ + const char* cppCode ="class object {};\n"; + const char* xmlCode = "\n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 1); +} + +void TestAbstractMetaType::testCharType() +{ + const char* cppCode ="char justAtest(); class A {};\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 1); + QCOMPARE(classes.first()->package(), QLatin1String("Foo")); + + AbstractMetaFunctionList functions = builder->globalFunctions(); + QCOMPARE(functions.size(), 1); + AbstractMetaFunction* func = functions.first(); + AbstractMetaType* rtype = func->type(); + // Test properties of const char* + QVERIFY(rtype); + QCOMPARE(rtype->package(), QLatin1String("Foo")); + QCOMPARE(rtype->name(), QLatin1String("char")); + QVERIFY(!rtype->isConstant()); + QVERIFY(!rtype->isArray()); + QVERIFY(!rtype->isContainer()); + QVERIFY(!rtype->isObject()); + QVERIFY(rtype->isPrimitive()); + QVERIFY(!rtype->isNativePointer()); + QVERIFY(!rtype->isQObject()); + QCOMPARE(rtype->referenceType(), NoReference); + QVERIFY(!rtype->isValue()); + QVERIFY(!rtype->isValuePointer()); +} + +void TestAbstractMetaType::testTypedef() +{ + const char* cppCode ="\ + struct A {\n\ + void someMethod();\n\ + };\n\ + typedef A B;\n\ + typedef B C;\n"; + const char* xmlCode = "\n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 1); + const AbstractMetaClass *c = AbstractMetaClass::findClass(classes, QLatin1String("C")); + QVERIFY(c); + QVERIFY(c->isTypeDef()); +} + +void TestAbstractMetaType::testTypedefWithTemplates() +{ + const char* cppCode ="\ + template\n\ + class A {};\n\ + \n\ + class B {};\n\ + typedef A C;\n\ + \n\ + void func(C c);\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 1); + AbstractMetaFunctionList functions = builder->globalFunctions(); + QCOMPARE(functions.count(), 1); + AbstractMetaFunction* function = functions.first(); + AbstractMetaArgumentList args = function->arguments(); + QCOMPARE(args.count(), 1); + AbstractMetaArgument* arg = args.first(); + AbstractMetaType* metaType = arg->type(); + QCOMPARE(metaType->cppSignature(), QLatin1String("A")); +} + + +void TestAbstractMetaType::testObjectTypeUsedAsValue() +{ + const char* cppCode ="\ + class A {\n\ + void method(A);\n\ + };\n"; + const char* xmlCode = "\n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.size(), 1); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + AbstractMetaFunctionList overloads = classA->queryFunctionsByName(QLatin1String("method")); + QCOMPARE(overloads.count(), 1); + AbstractMetaFunction* method = overloads.first(); + QVERIFY(method); + AbstractMetaArgumentList args = method->arguments(); + QCOMPARE(args.count(), 1); + AbstractMetaArgument* arg = args.first(); + AbstractMetaType* metaType = arg->type(); + QCOMPARE(metaType->cppSignature(), QLatin1String("A")); + QVERIFY(metaType->isValue()); + QVERIFY(metaType->typeEntry()->isObject()); +} + +QTEST_APPLESS_MAIN(TestAbstractMetaType) diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h new file mode 100644 index 000000000..a806d36e3 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTABSTRACTMETATYPE_H +#define TESTABSTRACTMETATYPE_H + +#include + +class TestAbstractMetaType : public QObject +{ + Q_OBJECT +private slots: + void testConstCharPtrType(); + void testCharType(); + void testTypedef(); + void testTypedefWithTemplates(); + void testApiVersionSupported(); + void testApiVersionNotSupported(); + void testObjectTypeUsedAsValue(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp new file mode 100644 index 000000000..bcc5238bc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp @@ -0,0 +1,453 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testaddfunction.h" +#include +#include "testutil.h" +#include +#include + +void TestAddFunction::testParsingFuncNameAndConstness() +{ + // generic test... + const char sig1[] = "func(type1, const type2, const type3* const)"; + AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + QCOMPARE(f1.name(), QLatin1String("func")); + QCOMPARE(f1.arguments().count(), 3); + AddedFunction::TypeInfo retval = f1.returnType(); + QCOMPARE(retval.name, QLatin1String("void")); + QCOMPARE(retval.indirections, 0); + QCOMPARE(retval.isConstant, false); + QCOMPARE(retval.isReference, false); + + // test with a ugly template as argument and other ugly stuff + const char sig2[] = " _fu__nc_ ( type1, const type2, const Abc * > * *, const type3* const ) const "; + AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc * > * *"), 0); + QCOMPARE(f2.name(), QLatin1String("_fu__nc_")); + QVector< AddedFunction::TypeInfo > args = f2.arguments(); + QCOMPARE(args.count(), 4); + retval = f2.returnType(); + QCOMPARE(retval.name, QLatin1String("Abc * >")); + QCOMPARE(retval.indirections, 2); + QCOMPARE(retval.isConstant, true); + QCOMPARE(retval.isReference, false); + retval = args[2]; + QCOMPARE(retval.name, QLatin1String("Abc * >")); + QCOMPARE(retval.indirections, 2); + QCOMPARE(retval.isConstant, true); + QCOMPARE(retval.isReference, false); + + // function with no args. + const char sig3[] = "func()"; + AddedFunction f3(QLatin1String(sig3), QLatin1String("void"), 0); + QCOMPARE(f3.name(), QLatin1String("func")); + QCOMPARE(f3.arguments().count(), 0); +} + +void TestAddFunction::testAddFunction() +{ + const char cppCode[] = "struct B {}; struct A { void a(int); };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + TypeDatabase* typeDb = TypeDatabase::instance(); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 4); // default ctor, default copy ctor, func a() and the added function + + AbstractMetaFunction* addedFunc = classA->functions().last(); + QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Protected); + QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); + QVERIFY(addedFunc->isUserAdded()); + QCOMPARE(addedFunc->ownerClass(), classA); + QCOMPARE(addedFunc->implementingClass(), classA); + QCOMPARE(addedFunc->declaringClass(), classA); + QVERIFY(!addedFunc->isVirtual()); + QVERIFY(!addedFunc->isSignal()); + QVERIFY(!addedFunc->isSlot()); + QVERIFY(!addedFunc->isStatic()); + + AbstractMetaType* returnType = addedFunc->type(); + QCOMPARE(returnType->typeEntry(), typeDb->findPrimitiveType(QLatin1String("int"))); + AbstractMetaArgumentList args = addedFunc->arguments(); + QCOMPARE(args.count(), 3); + QCOMPARE(args[0]->type()->typeEntry(), returnType->typeEntry()); + QCOMPARE(args[1]->defaultValueExpression(), QLatin1String("4.6")); + QCOMPARE(args[2]->type()->typeEntry(), typeDb->findType(QLatin1String("B"))); +} + +void TestAddFunction::testAddFunctionConstructor() +{ + const char cppCode[] = "struct A { A() {} };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 3); // default and added ctors + AbstractMetaFunction* addedFunc = classA->functions().last(); + QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); + QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::ConstructorFunction); + QCOMPARE(addedFunc->arguments().size(), 1); + QVERIFY(addedFunc->isUserAdded()); + QVERIFY(!addedFunc->type()); +} + +void TestAddFunction::testAddFunctionTagDefaultValues() +{ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 3); // default ctor, default copy ctor and the added function + AbstractMetaFunction* addedFunc = classA->functions().last(); + QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); + QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); + QVERIFY(addedFunc->isUserAdded()); + QVERIFY(!addedFunc->type()); +} + +void TestAddFunction::testAddFunctionCodeSnippets() +{ + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + Hi!, I am the code.\n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + AbstractMetaFunction* addedFunc = classA->functions().last(); + QVERIFY(addedFunc->hasInjectedCode()); +} + +void TestAddFunction::testAddFunctionWithoutParenteses() +{ + const char sig1[] = "func"; + AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + + QCOMPARE(f1.name(), QLatin1String("func")); + QCOMPARE(f1.arguments().count(), 0); + QCOMPARE(f1.isConstant(), false); + + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + Hi!, I am the code.\n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); + QVERIFY(addedFunc); + QVERIFY(addedFunc->hasInjectedCode()); + QCOMPARE(addedFunc->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode).count(), 1); +} + +void TestAddFunction::testAddFunctionWithDefaultArgs() +{ + const char sig1[] = "func"; + AddedFunction f1(QLatin1String(sig1), QLatin1String("void"), 0); + + QCOMPARE(f1.name(), QLatin1String("func")); + QCOMPARE(f1.arguments().count(), 0); + QCOMPARE(f1.isConstant(), false); + + const char cppCode[] = "struct A { };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); + QVERIFY(addedFunc); + AbstractMetaArgument *arg = addedFunc->arguments()[1]; + QCOMPARE(arg->defaultValueExpression(), QLatin1String("2")); +} + +void TestAddFunction::testAddFunctionAtModuleLevel() +{ + const char cppCode[] = "struct A { };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + TypeDatabase* typeDb = TypeDatabase::instance(); + + AddedFunctionList addedFuncs = typeDb->findGlobalUserFunctions(QLatin1String("func")); + + QCOMPARE(addedFuncs.size(), 1); + + FunctionModificationList mods = typeDb->functionModifications(QLatin1String("func(int,int)")); + + QCOMPARE(mods.size(), 1); + QVERIFY(mods.first().isCodeInjection()); + CodeSnip snip = mods.first().snips.first(); + QCOMPARE(snip.code(), QLatin1String("custom_code();")); +} + +void TestAddFunction::testAddFunctionWithVarargs() +{ + const char sig1[] = "func(int,char,...)"; + AddedFunction f1( QLatin1String(sig1), QLatin1String("void"), 0); + + QCOMPARE(f1.name(), QLatin1String("func")); + QCOMPARE(f1.arguments().count(), 3); + QVERIFY(!f1.isConstant()); + + const char cppCode[] = "struct A {};\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); + QVERIFY(addedFunc); + const AbstractMetaArgument* arg = addedFunc->arguments().last(); + QVERIFY(arg->type()->isVarargs()); + QVERIFY(arg->type()->typeEntry()->isVarargs()); +} + +void TestAddFunction::testAddStaticFunction() +{ + const char cppCode[] = "struct A { };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("func")); + QVERIFY(addedFunc); + QVERIFY(addedFunc->isStatic()); +} + +void TestAddFunction::testAddGlobalFunction() +{ + const char cppCode[] = "struct A { };struct B {};\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); + QCOMPARE(globalFuncs.count(), 2); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(builder->classes(), QLatin1String("B")); + QVERIFY(classB); + QVERIFY(!classB->findFunction(QLatin1String("globalFunc"))); + QVERIFY(!classB->findFunction(QLatin1String("globalFunc2"))); + QVERIFY(!globalFuncs[0]->injectedCodeSnips().isEmpty()); + QVERIFY(!globalFuncs[1]->injectedCodeSnips().isEmpty()); +} + +void TestAddFunction::testAddFunctionWithApiVersion() +{ + const char cppCode[] = ""; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QVERIFY(!builder.isNull()); + AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); + QCOMPARE(globalFuncs.count(), 1); +} + +void TestAddFunction::testModifyAddedFunction() +{ + const char cppCode[] = "class Foo { };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("Foo")); + const AbstractMetaFunction* method = foo->findFunction(QLatin1String("method")); + QCOMPARE(method->arguments().size(), 2); + AbstractMetaArgument* arg = method->arguments().at(1); + QCOMPARE(arg->defaultValueExpression(), QLatin1String("0")); + QCOMPARE(arg->name(), QLatin1String("varName")); + QCOMPARE(method->argumentName(2), QLatin1String("varName")); +} + +void TestAddFunction::testAddFunctionOnTypedef() +{ + const char cppCode[] = "template class Foo { }; typedef Foo FooInt;\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + custom_code();\n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("FooInt")); + QVERIFY(foo); + QVERIFY(foo->hasNonPrivateConstructor()); + const AbstractMetaFunctionList &lst = foo->queryFunctions(AbstractMetaClass::Constructors); + for (const AbstractMetaFunction *f : lst) + QVERIFY(f->signature().startsWith(f->name())); + QCOMPARE(lst.size(), 2); + const AbstractMetaFunction* method = foo->findFunction(QLatin1String("method")); + QVERIFY(method); +} + +void TestAddFunction::testAddFunctionWithTemplateArg() +{ + const char cppCode[] = "template class Foo { };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + QCOMPARE(builder->globalFunctions().size(), 1); + AbstractMetaFunction* func = builder->globalFunctions().first(); + AbstractMetaArgument* arg = func->arguments().first(); + QCOMPARE(arg->type()->instantiations().count(), 1); +} + +QTEST_APPLESS_MAIN(TestAddFunction) + diff --git a/sources/shiboken2/ApiExtractor/tests/testaddfunction.h b/sources/shiboken2/ApiExtractor/tests/testaddfunction.h new file mode 100644 index 000000000..16a4ede09 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testaddfunction.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTADDFUNCTION_H +#define TESTADDFUNCTION_H +#include + +class TestAddFunction : public QObject +{ + Q_OBJECT +private slots: + void testParsingFuncNameAndConstness(); + void testAddFunction(); + void testAddFunctionConstructor(); + void testAddFunctionTagDefaultValues(); + void testAddFunctionCodeSnippets(); + void testAddFunctionWithoutParenteses(); + void testAddFunctionWithDefaultArgs(); + void testAddFunctionAtModuleLevel(); + void testAddFunctionWithVarargs(); + void testAddStaticFunction(); + void testAddGlobalFunction(); + void testAddFunctionWithApiVersion(); + void testModifyAddedFunction(); + void testAddFunctionOnTypedef(); + void testAddFunctionWithTemplateArg(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp new file mode 100644 index 000000000..4d46d44bc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testarrayargument.h" +#include +#include "testutil.h" +#include +#include + +void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger() +{ + const char* cppCode ="\ + struct A {\n\ + enum SomeEnum { Value0, Value1, NValues };\n\ + void method(double[3]);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); + QVERIFY(arg->type()->isArray()); + QCOMPARE(arg->type()->arrayElementCount(), 3); + QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); +} + +void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() +{ + const char* cppCode ="\ + struct A {\n\ + enum SomeEnum { Value0, Value1, NValues };\n\ + void method(double[NValues]);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaEnum* someEnum = classA->findEnum(QLatin1String("SomeEnum")); + QVERIFY(someEnum); + AbstractMetaEnumValue* nvalues = classA->findEnumValue(QLatin1String("NValues"), someEnum); + QVERIFY(nvalues); + + const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); + QVERIFY(arg->type()->isArray()); + QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); + QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); +}; + +void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum() +{ + const char* cppCode ="\ + enum SomeEnum { Value0, Value1, NValues };\n\ + struct A {\n\ + void method(double[NValues]);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaEnum* someEnum = builder->globalEnums().first(); + QVERIFY(someEnum); + AbstractMetaEnumValue* nvalues = 0; + const AbstractMetaEnumValueList &values = someEnum->values(); + for (AbstractMetaEnumValue *enumValue : values) { + if (enumValue->name() == QLatin1String("NValues")) { + nvalues = enumValue; + break; + } + } + QVERIFY(nvalues); + + const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); + QVERIFY(arg->type()->isArray()); + QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); + QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); +}; + +QTEST_APPLESS_MAIN(TestArrayArgument) diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.h b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h new file mode 100644 index 000000000..b50232ef4 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTARRAYARGUMENT_H +#define TESTARRAYARGUMENT_H +#include + +class TestArrayArgument : public QObject +{ + Q_OBJECT +private slots: + void testArrayArgumentWithSizeDefinedByInteger(); + void testArrayArgumentWithSizeDefinedByEnumValue(); + void testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnum(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp new file mode 100644 index 000000000..ad245633e --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testcodeinjection.h" +#include +#include +#include +#include "testutil.h" +#include +#include + +void TestCodeInjections::testReadFileUtf8() +{ + const char* cppCode ="struct A {};\n"; + int argc = 0; + char *argv[] = {NULL}; + QCoreApplication app(argc, argv); + QString filePath = QDir::currentPath(); + QString xmlCode = QLatin1String("\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"); + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().constData())); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); + QString code = classA->typeEntry()->codeSnips().first().code(); + QString utf8Data = QString::fromUtf8("\xC3\xA1\xC3\xA9\xC3\xAD\xC3\xB3\xC3\xBA"); + QVERIFY(code.indexOf(utf8Data) != -1); + code = classA->typeEntry()->conversionRule(); + QVERIFY(code.indexOf(utf8Data) != -1); +} + +void TestCodeInjections::testInjectWithValidApiVersion() +{ + const char* cppCode ="struct A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + test Inject code\n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "1.0")); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); +} + +void TestCodeInjections::testInjectWithInvalidApiVersion() +{ + const char* cppCode ="struct A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + test Inject code\n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->typeEntry()->codeSnips().count(), 0); +} + + + +QTEST_APPLESS_MAIN(TestCodeInjections) diff --git a/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h new file mode 100644 index 000000000..56c1c7cba --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testcodeinjection.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCODEINJECTIONS_H +#define TESTCODEINJECTIONS_H + +#include + +class AbstractMetaBuilder; + +class TestCodeInjections : public QObject +{ + Q_OBJECT +private slots: + void testReadFileUtf8(); + void testInjectWithValidApiVersion(); + void testInjectWithInvalidApiVersion(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp b/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp new file mode 100644 index 000000000..1c79a5a7a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testcontainer.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testcontainer.h" +#include +#include "testutil.h" +#include +#include + +void TestContainer::testContainerType() +{ + const char* cppCode ="\ + namespace std {\n\ + template\n\ + class list {\n\ + T get(int x) { return 0; }\n\ + };\n\ + }\n\ + class A : public std::list {\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + //search for class A + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QVERIFY(classA->typeEntry()->baseContainerType()); + QCOMPARE(reinterpret_cast(classA->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::ListContainer); +} + +void TestContainer::testListOfValueType() +{ + const char* cppCode ="\ + namespace std {\n\ + template\n\ + class list {\n\ + T get(int x) { return 0; }\n\ + };\n\ + }\n\ + class ValueType {};\n\ + class A : public std::list {\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->templateBaseClassInstantiations().count(), 1); + const AbstractMetaType* templateInstanceType = classA->templateBaseClassInstantiations().first(); + QVERIFY(templateInstanceType); + + QCOMPARE(templateInstanceType->indirections(), 0); + QVERIFY(!templateInstanceType->typeEntry()->isObject()); + QVERIFY(templateInstanceType->typeEntry()->isValue()); + QCOMPARE(templateInstanceType->referenceType(), NoReference); + QVERIFY(!templateInstanceType->isObject()); + QVERIFY(!templateInstanceType->isValuePointer()); + QVERIFY(templateInstanceType->isValue()); +} + +QTEST_APPLESS_MAIN(TestContainer) + diff --git a/sources/shiboken2/ApiExtractor/tests/testcontainer.h b/sources/shiboken2/ApiExtractor/tests/testcontainer.h new file mode 100644 index 000000000..f154ea212 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testcontainer.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCONTAINER_H +#define TESTCONTAINER_H +#include + +class TestContainer : public QObject +{ + Q_OBJECT +private slots: + void testContainerType(); + void testListOfValueType(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp new file mode 100644 index 000000000..86f571328 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testconversionoperator.h" +#include +#include "testutil.h" +#include +#include + +void TestConversionOperator::testConversionOperator() +{ + const char cppCode[] = "\ + struct A {\n\ + };\n\ + struct B {\n\ + operator A() const;\n\ + };\n\ + struct C {\n\ + operator A() const;\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); + QVERIFY(classA); + QVERIFY(classB); + QVERIFY(classC); + QCOMPARE(classA->functions().count(), 2); + QCOMPARE(classB->functions().count(), 3); + QCOMPARE(classC->functions().count(), 3); + QCOMPARE(classA->externalConversionOperators().count(), 2); + + AbstractMetaFunction* convOp = 0; + for (AbstractMetaFunction *func : classB->functions()) { + if (func->isConversionOperator()) { + convOp = func; + break; + } + } + QVERIFY(convOp); + QVERIFY(classA->externalConversionOperators().contains(convOp)); +} + +void TestConversionOperator::testConversionOperatorOfDiscardedClass() +{ + const char cppCode[] = "\ + struct A {\n\ + };\n\ + struct B {\n\ + operator A() const;\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->externalConversionOperators().count(), 0); +} + +void TestConversionOperator::testRemovedConversionOperator() +{ + const char cppCode[] = "\ + struct A {\n\ + };\n\ + struct B {\n\ + operator A() const;\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classA); + QVERIFY(classB); + QCOMPARE(classA->functions().count(), 2); + QCOMPARE(classB->functions().count(), 3); + QCOMPARE(classA->externalConversionOperators().count(), 0); + QCOMPARE(classA->implicitConversions().count(), 0); +} + +void TestConversionOperator::testConversionOperatorReturningReference() +{ + const char cppCode[] = "\ + struct A {};\n\ + struct B {\n\ + operator A&() const;\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classA); + QVERIFY(classB); + QCOMPARE(classA->functions().count(), 2); + QCOMPARE(classB->functions().count(), 3); + QCOMPARE(classA->externalConversionOperators().count(), 1); + QCOMPARE(classA->externalConversionOperators().first()->type()->cppSignature(), QLatin1String("A")); + QCOMPARE(classA->externalConversionOperators().first()->ownerClass()->name(), QLatin1String("B")); + QCOMPARE(classA->implicitConversions().count(), 1); + QCOMPARE(classA->implicitConversions().first()->type()->cppSignature(), QLatin1String("A")); + QCOMPARE(classA->implicitConversions().first()->ownerClass()->name(), QLatin1String("B")); +} + +void TestConversionOperator::testConversionOperatorReturningConstReference() +{ + const char cppCode[] = "\ + struct A {};\n\ + struct B {\n\ + operator const A&() const;\n\ + };\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classA); + QVERIFY(classB); + QCOMPARE(classA->functions().count(), 2); + QCOMPARE(classB->functions().count(), 3); + QCOMPARE(classA->externalConversionOperators().count(), 1); + QCOMPARE(classA->externalConversionOperators().first()->type()->cppSignature(), QLatin1String("A")); + QCOMPARE(classA->externalConversionOperators().first()->ownerClass()->name(), QLatin1String("B")); + QCOMPARE(classA->implicitConversions().count(), 1); + QCOMPARE(classA->implicitConversions().first()->type()->cppSignature(), QLatin1String("A")); + QCOMPARE(classA->implicitConversions().first()->ownerClass()->name(), QLatin1String("B")); +} + +QTEST_APPLESS_MAIN(TestConversionOperator) diff --git a/sources/shiboken2/ApiExtractor/tests/testconversionoperator.h b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.h new file mode 100644 index 000000000..f28747ab5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testconversionoperator.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCONVERSIONOPERATOR_H +#define TESTCONVERSIONOPERATOR_H +#include + +class TestConversionOperator : public QObject +{ + Q_OBJECT +private slots: + void testConversionOperator(); + void testConversionOperatorOfDiscardedClass(); + void testRemovedConversionOperator(); + void testConversionOperatorReturningReference(); + void testConversionOperatorReturningConstReference(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testconversionruletag.cpp b/sources/shiboken2/ApiExtractor/tests/testconversionruletag.cpp new file mode 100644 index 000000000..fb9290795 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testconversionruletag.cpp @@ -0,0 +1,250 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testconversionruletag.h" +#include +#include "testutil.h" +#include +#include +#include +#include + +void TestConversionRuleTag::testConversionRuleTagWithFile() +{ + // temp file used later + const char conversionData[] = "Hi! I'm a conversion rule."; + QTemporaryFile file; + file.open(); + QCOMPARE(file.write(conversionData), qint64(sizeof(conversionData)-1)); + file.close(); + + const char cppCode[] = "struct A {};\n"; + QString xmlCode = QLatin1String("\ + \n\ + \n\ + \n\ + \n\ + \n"); + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode.toLocal8Bit().data())); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const ComplexTypeEntry* typeEntry = classA->typeEntry(); + QVERIFY(typeEntry->hasConversionRule()); + QCOMPARE(typeEntry->conversionRule(), QLatin1String(conversionData)); +} + +void TestConversionRuleTag::testConversionRuleTagReplace() +{ + const char cppCode[] = "\ + struct A {\n\ + A();\n\ + A(const char*, int);\n\ + };\n\ + struct B {\n\ + A createA();\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + DoThis();\n\ + return ConvertFromCppToPython(%IN);\n\ + \n\ + \n\ + \n\ + DoThat();\n\ + DoSomething();\n\ + %OUT = A();\n\ + \n\ + \n\ + %OUT = %IN.createA();\n\ + \n\ + \n\ + %OUT = new A(String_AsString(%IN), String_GetSize(%IN));\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + TypeDatabase* typeDb = TypeDatabase::instance(); + PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(QLatin1String("A")); + QVERIFY(typeA); + + CustomConversion* conversion = typeA->customConversion(); + QVERIFY(conversion); + + QCOMPARE(typeA, conversion->ownerType()); + QCOMPARE(conversion->nativeToTargetConversion().simplified(), + QLatin1String("DoThis(); return ConvertFromCppToPython(%IN);")); + + QVERIFY(conversion->replaceOriginalTargetToNativeConversions()); + QVERIFY(conversion->hasTargetToNativeConversions()); + QCOMPARE(conversion->targetToNativeConversions().size(), 3); + + CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().at(0); + QVERIFY(toNative); + QCOMPARE(toNative->sourceTypeName(), QLatin1String("TargetNone")); + QVERIFY(toNative->isCustomType()); + QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); + QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("%IN == Target_None")); + QCOMPARE(toNative->conversion().simplified(), + QLatin1String("DoThat(); DoSomething(); %OUT = A();")); + + toNative = conversion->targetToNativeConversions().at(1); + QVERIFY(toNative); + QCOMPARE(toNative->sourceTypeName(), QLatin1String("B")); + QVERIFY(!toNative->isCustomType()); + TypeEntry* typeB = typeDb->findType(QLatin1String("B")); + QVERIFY(typeB); + QCOMPARE(toNative->sourceType(), typeB); + QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("CheckIfInputObjectIsB(%IN)")); + QCOMPARE(toNative->conversion().trimmed(), QLatin1String("%OUT = %IN.createA();")); + + toNative = conversion->targetToNativeConversions().at(2); + QVERIFY(toNative); + QCOMPARE(toNative->sourceTypeName(), QLatin1String("String")); + QVERIFY(toNative->isCustomType()); + QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); + QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("String_Check(%IN)")); + QCOMPARE(toNative->conversion().trimmed(), QLatin1String("%OUT = new A(String_AsString(%IN), String_GetSize(%IN));")); +} + +void TestConversionRuleTag::testConversionRuleTagAdd() +{ + const char cppCode[] = "\ + struct Date {\n\ + Date();\n\ + Date(int, int, int);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ +if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\ +%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));\n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("Date")); + QVERIFY(classA); + + CustomConversion* conversion = classA->typeEntry()->customConversion(); + QVERIFY(conversion); + + QCOMPARE(conversion->nativeToTargetConversion(), QString()); + + QVERIFY(!conversion->replaceOriginalTargetToNativeConversions()); + QVERIFY(conversion->hasTargetToNativeConversions()); + QCOMPARE(conversion->targetToNativeConversions().size(), 1); + + CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().first(); + QVERIFY(toNative); + QCOMPARE(toNative->sourceTypeName(), QLatin1String("TargetDate")); + QVERIFY(toNative->isCustomType()); + QCOMPARE(toNative->sourceType(), (const TypeEntry*)0); + QCOMPARE(toNative->sourceTypeCheck(), QLatin1String("TargetDate_Check(%IN)")); + QCOMPARE(toNative->conversion().trimmed(), + QLatin1String("if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));")); +} + +void TestConversionRuleTag::testConversionRuleTagWithInsertTemplate() +{ + const char cppCode[] = "struct A {};"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + const char nativeToTargetExpected[] = + "// TEMPLATE - native_to_target - START\n" + "return ConvertFromCppToPython(%IN);\n" + "// TEMPLATE - native_to_target - END"; + + const char targetToNativeExpected[] = + "// TEMPLATE - target_to_native - START\n" + "%OUT = %IN.createA();\n" + "// TEMPLATE - target_to_native - END"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + TypeDatabase* typeDb = TypeDatabase::instance(); + PrimitiveTypeEntry* typeA = typeDb->findPrimitiveType(QLatin1String("A")); + QVERIFY(typeA); + + CustomConversion* conversion = typeA->customConversion(); + QVERIFY(conversion); + + QCOMPARE(typeA, conversion->ownerType()); + QCOMPARE(conversion->nativeToTargetConversion().trimmed(), + QLatin1String(nativeToTargetExpected)); + + QVERIFY(conversion->hasTargetToNativeConversions()); + QCOMPARE(conversion->targetToNativeConversions().size(), 1); + + CustomConversion::TargetToNativeConversion* toNative = conversion->targetToNativeConversions().first(); + QVERIFY(toNative); + QCOMPARE(toNative->conversion().trimmed(), + QLatin1String(targetToNativeExpected)); +} + +QTEST_APPLESS_MAIN(TestConversionRuleTag) diff --git a/sources/shiboken2/ApiExtractor/tests/testconversionruletag.h b/sources/shiboken2/ApiExtractor/tests/testconversionruletag.h new file mode 100644 index 000000000..c02a9708b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testconversionruletag.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCONVERSIONRULE_H +#define TESTCONVERSIONRULE_H +#include + +class TestConversionRuleTag : public QObject +{ + Q_OBJECT +private slots: + void testConversionRuleTagWithFile(); + void testConversionRuleTagReplace(); + void testConversionRuleTagAdd(); + void testConversionRuleTagWithInsertTemplate(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testctorinformation.cpp b/sources/shiboken2/ApiExtractor/tests/testctorinformation.cpp new file mode 100644 index 000000000..a4b4c2388 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testctorinformation.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testctorinformation.h" +#include "abstractmetabuilder.h" +#include +#include "testutil.h" +#include +#include + +void TestCtorInformation::testCtorIsPrivate() +{ + const char* cppCode = "class Control { public: Control() {} };\n\ + class Subject { private: Subject() {} };\n\ + class CtorLess { };\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasNonPrivateConstructor(), true); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasNonPrivateConstructor(), false); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("CtorLess"))->hasNonPrivateConstructor(), true); +} + +void TestCtorInformation::testHasNonPrivateCtor() +{ + const char* cppCode = "template\n\ + struct Base { Base(double) {} };\n\ + typedef Base Derived;\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + const AbstractMetaClass *base = AbstractMetaClass::findClass(classes, QLatin1String("Base")); + QCOMPARE(base->hasNonPrivateConstructor(), true); + const AbstractMetaClass *derived = AbstractMetaClass::findClass(classes, QLatin1String("Derived")); + QCOMPARE(derived->hasNonPrivateConstructor(), true); +} + +QTEST_APPLESS_MAIN(TestCtorInformation) diff --git a/sources/shiboken2/ApiExtractor/tests/testctorinformation.h b/sources/shiboken2/ApiExtractor/tests/testctorinformation.h new file mode 100644 index 000000000..f5ffe5501 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testctorinformation.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTCTORINFORMATION_H +#define TESTCTORINFORMATION_H + +#include + +class AbstractMetaBuilder; + +class TestCtorInformation: public QObject +{ + Q_OBJECT +private slots: + void testCtorIsPrivate(); + void testHasNonPrivateCtor(); +}; + +#endif // TESTCTORINFORMATION_H diff --git a/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp new file mode 100644 index 000000000..6b6c5d011 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testdroptypeentries.h" +#include +#include "testutil.h" +#include +#include + +static const char* cppCode ="\ + struct ValueA {};\n\ + struct ValueB {};\n\ + struct ObjectA {};\n\ + struct ObjectB {};\n\ + namespace NamespaceA {\n\ + struct InnerClassA {};\n\ + namespace InnerNamespaceA {}\n\ + }\n\ + namespace NamespaceB {}\n\ + enum EnumA { Value0 };\n\ + enum EnumB { Value1 };\n\ + void funcA();\n\ + void funcB();\n"; + +static const char* xmlCode = "\ +\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ +\n"; + +void TestDropTypeEntries::testDropEntries() +{ + QStringList droppedEntries(QLatin1String("Foo.ValueB")); + droppedEntries << QLatin1String("Foo.ObjectB") << QLatin1String("Foo.NamespaceA.InnerClassA"); + droppedEntries << QLatin1String("Foo.NamespaceB") << QLatin1String("Foo.EnumB") << QLatin1String("Foo.funcB()"); + droppedEntries << QLatin1String("Foo.NamespaceA.InnerNamespaceA"); + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, Q_NULLPTR, droppedEntries)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueA"))); + QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("ValueB"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectA"))); + QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("ObjectB"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA"))); + QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA::InnerClassA"))); + QVERIFY(!AbstractMetaClass::findClass(classes, QLatin1String("NamespaceB"))); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QCOMPARE(globalEnums.count(), 1); + QCOMPARE(globalEnums.first()->name(), QLatin1String("EnumA")); + + TypeDatabase* td = TypeDatabase::instance(); + QVERIFY(td->findType(QLatin1String("funcA"))); + QVERIFY(!td->findType(QLatin1String("funcB"))); +} + +void TestDropTypeEntries::testDontDropEntries() +{ + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueA"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ValueB"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectA"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("ObjectB"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceA::InnerClassA"))); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("NamespaceB"))); + + QCOMPARE(builder->globalEnums().size(), 2); + + TypeDatabase* td = TypeDatabase::instance(); + QVERIFY(td->findType(QLatin1String("funcA"))); + QVERIFY(td->findType(QLatin1String("funcB"))); +} + +static const char* cppCode2 ="\ + struct ValueA {\n\ + void func();\n\ + };\n"; + +static const char* xmlCode2 = "\ +\n\ + \n\ + \n\ + \n\ + \n\ + \n\ +\n"; + +void TestDropTypeEntries::testDropEntryWithChildTags() +{ + QStringList droppedEntries(QLatin1String("Foo.ValueA")); + QScopedPointer builder(TestUtil::parse(cppCode2, xmlCode2, false, Q_NULLPTR, droppedEntries)); + QVERIFY(!builder.isNull()); + QVERIFY(!AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA"))); +} + + +void TestDropTypeEntries::testDontDropEntryWithChildTags() +{ + QScopedPointer builder(TestUtil::parse(cppCode2, xmlCode2, false)); + QVERIFY(!builder.isNull()); + QVERIFY(AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA"))); +} + +QTEST_APPLESS_MAIN(TestDropTypeEntries) diff --git a/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.h b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.h new file mode 100644 index 000000000..d04c6dc92 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testdroptypeentries.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTDROPTYPEENTRIES_H +#define TESTDROPTYPEENTRIES_H + +#include + +class TestDropTypeEntries : public QObject +{ + Q_OBJECT + private slots: + void testDropEntries(); + void testDontDropEntries(); + void testDropEntryWithChildTags(); + void testDontDropEntryWithChildTags(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testdtorinformation.cpp b/sources/shiboken2/ApiExtractor/tests/testdtorinformation.cpp new file mode 100644 index 000000000..63b745c12 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testdtorinformation.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testdtorinformation.h" +#include "abstractmetabuilder.h" +#include +#include "testutil.h" +#include +#include + +void TestDtorInformation::testDtorIsPrivate() +{ + const char* cppCode ="class Control { public: ~Control() {} }; class Subject { private: ~Subject() {} };"; + const char* xmlCode = ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasPrivateDestructor(), false); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasPrivateDestructor(), true); +} + +void TestDtorInformation::testDtorIsProtected() +{ + const char* cppCode ="class Control { public: ~Control() {} }; class Subject { protected: ~Subject() {} };"; + const char* xmlCode = ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasProtectedDestructor(), false); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasProtectedDestructor(), true); +} + +void TestDtorInformation::testDtorIsVirtual() +{ + const char* cppCode ="class Control { public: ~Control() {} }; class Subject { protected: virtual ~Subject() {} };"; + const char* xmlCode = ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->hasVirtualDestructor(), false); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->hasVirtualDestructor(), true); +} + +void TestDtorInformation::testClassWithVirtualDtorIsPolymorphic() +{ + const char* cppCode ="class Control { public: virtual ~Control() {} }; class Subject { protected: virtual ~Subject() {} };"; + const char* xmlCode = ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Control"))->isPolymorphic(), true); + QCOMPARE(AbstractMetaClass::findClass(classes, QLatin1String("Subject"))->isPolymorphic(), true); +} + +QTEST_APPLESS_MAIN(TestDtorInformation) + + diff --git a/sources/shiboken2/ApiExtractor/tests/testdtorinformation.h b/sources/shiboken2/ApiExtractor/tests/testdtorinformation.h new file mode 100644 index 000000000..21a3b1822 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testdtorinformation.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTDTORINFORMATION_H +#define TESTDTORINFORMATION_H + +#include + +class AbstractMetaBuilder; + +class TestDtorInformation: public QObject +{ + Q_OBJECT +private slots: + void testDtorIsPrivate(); + void testDtorIsProtected(); + void testDtorIsVirtual(); + void testClassWithVirtualDtorIsPolymorphic(); +}; + +#endif // TESTDTORINFORMATION_H diff --git a/sources/shiboken2/ApiExtractor/tests/testenum.cpp b/sources/shiboken2/ApiExtractor/tests/testenum.cpp new file mode 100644 index 000000000..98e56b86e --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testenum.cpp @@ -0,0 +1,416 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testenum.h" +#include +#include "testutil.h" +#include +#include + +void TestEnum::testEnumCppSignature() +{ + const char* cppCode ="\ + enum GlobalEnum { A, B };\n\ + \n\ + struct A {\n\ + enum ClassEnum { CA, CB };\n\ + void method(ClassEnum);\n\ + };\n\ + void func(A::ClassEnum);\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QCOMPARE(globalEnums.count(), 1); + QCOMPARE(globalEnums.first()->name(), QLatin1String("GlobalEnum")); + + // enum as parameter of a function + AbstractMetaFunctionList functions = builder->globalFunctions(); + QCOMPARE(functions.count(), 1); + QCOMPARE(functions.first()->arguments().count(), 1); + QCOMPARE(functions.first()->arguments().first()->type()->cppSignature(), QLatin1String("A::ClassEnum")); + + // enum as parameter of a method + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QCOMPARE(classA->enums().count(), 1); + AbstractMetaFunctionList funcs = classA->queryFunctionsByName(QLatin1String("method")); + QVERIFY(!funcs.isEmpty()); + AbstractMetaFunction* method = funcs.first(); + QVERIFY(method); + AbstractMetaArgument* arg = method->arguments().first(); + QCOMPARE(arg->type()->name(), QLatin1String("ClassEnum")); + QCOMPARE(arg->type()->cppSignature(), QLatin1String("A::ClassEnum")); + QCOMPARE(functions.first()->arguments().count(), 1); + arg = functions.first()->arguments().first(); + QCOMPARE(arg->type()->name(), QLatin1String("ClassEnum")); + QCOMPARE(arg->type()->cppSignature(), QLatin1String("A::ClassEnum")); + + AbstractMetaEnumList classEnums = classA->enums(); + QCOMPARE(classEnums.first()->name(), QLatin1String("ClassEnum")); +} + +void TestEnum::testEnumWithApiVersion() +{ + const char* cppCode ="\ + struct A {\n\ + enum ClassEnum { EnumA, EnumB };\n\ + enum ClassEnum2 { EnumC, EnumD };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true, "0.1")); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + QCOMPARE(classes[0]->enums().count(), 1); +} + +void TestEnum::testAnonymousEnum() +{ + const char* cppCode ="\ + enum { Global0, Global1 };\n\ + struct A {\n\ + enum { A0, A1 };\n\ + enum { isThis = true, isThat = false };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QCOMPARE(globalEnums.count(), 1); + QCOMPARE(globalEnums.first()->typeEntry()->qualifiedCppName(), QLatin1String("Global0")); + QVERIFY(globalEnums.first()->isAnonymous()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + QCOMPARE(classes[0]->enums().count(), 2); + + AbstractMetaEnum* anonEnumA1 = classes[0]->findEnum(QLatin1String("A1")); + QVERIFY(anonEnumA1); + QVERIFY(anonEnumA1->isAnonymous()); + QCOMPARE(anonEnumA1->typeEntry()->qualifiedCppName(), QLatin1String("A::A1")); + + AbstractMetaEnumValue* enumValueA0 = anonEnumA1->values().first(); + QCOMPARE(enumValueA0->name(), QLatin1String("A0")); + QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->stringValue(), QString()); + + AbstractMetaEnumValue* enumValueA1 = anonEnumA1->values().last(); + QCOMPARE(enumValueA1->name(), QLatin1String("A1")); + QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->stringValue(), QString()); + + AbstractMetaEnum* anonEnumIsThis = classes[0]->findEnum(QLatin1String("isThis")); + QVERIFY(anonEnumIsThis); + QVERIFY(anonEnumIsThis->isAnonymous()); + QCOMPARE(anonEnumIsThis->typeEntry()->qualifiedCppName(), QLatin1String("A::isThis")); + + AbstractMetaEnumValue* enumValueIsThis = anonEnumIsThis->values().first(); + QCOMPARE(enumValueIsThis->name(), QLatin1String("isThis")); + QCOMPARE(enumValueIsThis->value(), static_cast(true)); + QCOMPARE(enumValueIsThis->stringValue(), QLatin1String("true")); + + AbstractMetaEnumValue* enumValueIsThat = anonEnumIsThis->values().last(); + QCOMPARE(enumValueIsThat->name(), QLatin1String("isThat")); + QCOMPARE(enumValueIsThat->value(), static_cast(false)); + QCOMPARE(enumValueIsThat->stringValue(), QLatin1String("false")); +} + +void TestEnum::testGlobalEnums() +{ + const char* cppCode ="\ + enum EnumA { A0, A1 };\n\ + enum EnumB { B0 = 2, B1 = 0x4 };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QCOMPARE(globalEnums.count(), 2); + + AbstractMetaEnum* enumA = globalEnums.first(); + QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("EnumA")); + + AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); + QCOMPARE(enumValueA0->name(), QLatin1String("A0")); + QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->stringValue(), QString()); + + AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); + QCOMPARE(enumValueA1->name(), QLatin1String("A1")); + QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->stringValue(), QString()); + + AbstractMetaEnum* enumB = globalEnums.last(); + QCOMPARE(enumB->typeEntry()->qualifiedCppName(), QLatin1String("EnumB")); + + AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); + QCOMPARE(enumValueB0->name(), QLatin1String("B0")); + QCOMPARE(enumValueB0->value(), 2); + QCOMPARE(enumValueB0->stringValue(), QLatin1String("2")); + + AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); + QCOMPARE(enumValueB1->name(), QLatin1String("B1")); + QCOMPARE(enumValueB1->value(), 4); + QCOMPARE(enumValueB1->stringValue(), QLatin1String("0x4")); +} + +void TestEnum::testEnumValueFromNeighbourEnum() +{ + const char* cppCode ="\ + namespace A {\n\ + enum EnumA { ValueA0, ValueA1 };\n\ + enum EnumB { ValueB0 = A::ValueA1, ValueB1 = ValueA0 };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + QCOMPARE(classes[0]->enums().count(), 2); + + AbstractMetaEnum* enumA = classes[0]->findEnum(QLatin1String("EnumA")); + QVERIFY(enumA); + QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumA")); + + AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); + QCOMPARE(enumValueA0->name(), QLatin1String("ValueA0")); + QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->stringValue(), QString()); + + AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); + QCOMPARE(enumValueA1->name(), QLatin1String("ValueA1")); + QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->stringValue(), QString()); + + AbstractMetaEnum* enumB = classes[0]->findEnum(QLatin1String("EnumB")); + QVERIFY(enumB); + QCOMPARE(enumB->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumB")); + + AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); + QCOMPARE(enumValueB0->name(), QLatin1String("ValueB0")); + QCOMPARE(enumValueB0->value(), 1); + QCOMPARE(enumValueB0->stringValue(), QLatin1String("A::ValueA1")); + + AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); + QCOMPARE(enumValueB1->name(), QLatin1String("ValueB1")); + QCOMPARE(enumValueB1->value(), 0); + QCOMPARE(enumValueB1->stringValue(), QLatin1String("ValueA0")); +} + +void TestEnum::testEnumValueFromExpression() +{ + const char* cppCode ="\ + struct A {\n\ + enum EnumA {\n\ + ValueA0 = 3u,\n\ + ValueA1 = ~3u,\n\ + ValueA2 = ~3,\n\ + ValueA3 = 0xf0,\n\ + ValueA4 = 8 |ValueA3,\n\ + ValueA5 = ValueA3|32,\n\ + ValueA6 = ValueA3 >> 1,\n\ + ValueA7 = ValueA3 << 1\n\ + };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + AbstractMetaEnum* enumA = classA->findEnum(QLatin1String("EnumA")); + QVERIFY(enumA); + QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumA")); + + AbstractMetaEnumValue* valueA0 = enumA->values().at(0); + QCOMPARE(valueA0->name(), QLatin1String("ValueA0")); + QCOMPARE(valueA0->stringValue(), QLatin1String("3u")); + QCOMPARE(valueA0->value(), (int) 3u); + + AbstractMetaEnumValue* valueA1 = enumA->values().at(1); + QCOMPARE(valueA1->name(), QLatin1String("ValueA1")); + QCOMPARE(valueA1->stringValue(), QLatin1String("~3u")); + QCOMPARE(valueA1->value(), (int) ~3u); + + AbstractMetaEnumValue* valueA2 = enumA->values().at(2); + QCOMPARE(valueA2->name(), QLatin1String("ValueA2")); + QCOMPARE(valueA2->stringValue(), QLatin1String("~3")); + QCOMPARE(valueA2->value(), ~3); + + AbstractMetaEnumValue* valueA3 = enumA->values().at(3); + QCOMPARE(valueA3->name(), QLatin1String("ValueA3")); + QCOMPARE(valueA3->stringValue(), QLatin1String("0xf0")); + QCOMPARE(valueA3->value(), 0xf0); + + AbstractMetaEnumValue* valueA4 = enumA->values().at(4); + QCOMPARE(valueA4->name(), QLatin1String("ValueA4")); + QCOMPARE(valueA4->stringValue(), QLatin1String("8 |ValueA3")); + QCOMPARE(valueA4->value(), 8|0xf0); + + AbstractMetaEnumValue* valueA5 = enumA->values().at(5); + QCOMPARE(valueA5->name(), QLatin1String("ValueA5")); + QCOMPARE(valueA5->stringValue(), QLatin1String("ValueA3|32")); + QCOMPARE(valueA5->value(), 0xf0|32); + + AbstractMetaEnumValue* valueA6 = enumA->values().at(6); + QCOMPARE(valueA6->name(), QLatin1String("ValueA6")); + QCOMPARE(valueA6->stringValue(), QLatin1String("ValueA3 >> 1")); + QCOMPARE(valueA6->value(), 0xf0 >> 1); + + AbstractMetaEnumValue* valueA7 = enumA->values().at(7); + QCOMPARE(valueA7->name(), QLatin1String("ValueA7")); + QCOMPARE(valueA7->stringValue(), QLatin1String("ValueA3 << 1")); + QCOMPARE(valueA7->value(), 0xf0 << 1); +} + +void TestEnum::testPrivateEnum() +{ + 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 = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->enums().count(), 2); + + AbstractMetaEnum* privateEnum = classA->findEnum(QLatin1String("PrivateEnum")); + QVERIFY(privateEnum); + QVERIFY(privateEnum->isPrivate()); + QCOMPARE(privateEnum->typeEntry()->qualifiedCppName(), QLatin1String("A::PrivateEnum")); + + AbstractMetaEnum* publicEnum = classA->findEnum(QLatin1String("PublicEnum")); + QVERIFY(publicEnum); + QCOMPARE(publicEnum->typeEntry()->qualifiedCppName(), QLatin1String("A::PublicEnum")); + + AbstractMetaEnumValue* pub0 = publicEnum->values().first(); + QCOMPARE(pub0->name(), QLatin1String("Pub0")); + QCOMPARE(pub0->value(), 0x0f); + QCOMPARE(pub0->stringValue(), QLatin1String("Priv0")); + + AbstractMetaEnumValue* pub1 = publicEnum->values().last(); + QCOMPARE(pub1->name(), QLatin1String("Pub1")); + QCOMPARE(pub1->value(), 0xf0); + QCOMPARE(pub1->stringValue(), QLatin1String("A::Priv1")); +} + +void TestEnum::testTypedefEnum() +{ + const char* cppCode ="\ + typedef enum EnumA {\n\ + A0,\n\ + A1,\n\ + } EnumA;\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaEnumList globalEnums = builder->globalEnums(); + QEXPECT_FAIL("", "APIExtractor does not handle typedef enum correctly yet", Abort); + QCOMPARE(globalEnums.count(), 1); + + AbstractMetaEnum* enumA = globalEnums.first(); + QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("EnumA")); + + AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); + QCOMPARE(enumValueA0->name(), QLatin1String("A0")); + QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->stringValue(), QLatin1String("")); + + AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); + QCOMPARE(enumValueA1->name(), QLatin1String("A1")); + QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->stringValue(), QString()); +} + +QTEST_APPLESS_MAIN(TestEnum) diff --git a/sources/shiboken2/ApiExtractor/tests/testenum.h b/sources/shiboken2/ApiExtractor/tests/testenum.h new file mode 100644 index 000000000..8b46b1bd6 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testenum.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTENUM_H +#define TESTENUM_H +#include + +class TestEnum : public QObject +{ + Q_OBJECT +private slots: + void testEnumCppSignature(); + void testEnumWithApiVersion(); + void testAnonymousEnum(); + void testGlobalEnums(); + void testEnumValueFromNeighbourEnum(); + void testEnumValueFromExpression(); + void testPrivateEnum(); + void testTypedefEnum(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp new file mode 100644 index 000000000..97f0d568e --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testextrainclude.h" +#include +#include "testutil.h" +#include +#include + +void TestExtraInclude::testClassExtraInclude() +{ + const char* cppCode ="struct A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + + QVector includes = classA->typeEntry()->extraIncludes(); + QCOMPARE(includes.count(), 1); + QCOMPARE(includes.first().name(), QLatin1String("header.h")); +} + +void TestExtraInclude::testGlobalExtraIncludes() +{ + const char* cppCode ="struct A {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QVERIFY(AbstractMetaClass::findClass(classes, QLatin1String("A"))); + + TypeDatabase* td = TypeDatabase::instance(); + TypeEntry* module = td->findType(QLatin1String("Foo")); + QVERIFY(module); + + QVector includes = module->extraIncludes(); + QCOMPARE(includes.count(), 2); + QCOMPARE(includes.first().name(), QLatin1String("header1.h")); + QCOMPARE(includes.last().name(), QLatin1String("header2.h")); +} + +QTEST_APPLESS_MAIN(TestExtraInclude) diff --git a/sources/shiboken2/ApiExtractor/tests/testextrainclude.h b/sources/shiboken2/ApiExtractor/tests/testextrainclude.h new file mode 100644 index 000000000..c569901e1 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testextrainclude.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTEXTRAINCLUDE_H +#define TESTEXTRAINCLUDE_H + +#include + +class TestExtraInclude : public QObject +{ + Q_OBJECT + private slots: + void testClassExtraInclude(); + void testGlobalExtraIncludes(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testfunctiontag.cpp b/sources/shiboken2/ApiExtractor/tests/testfunctiontag.cpp new file mode 100644 index 000000000..a29d740bf --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testfunctiontag.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testfunctiontag.h" +#include +#include "testutil.h" +#include +#include + +void TestFunctionTag::testFunctionTagForSpecificSignature() +{ + const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("globalFunction")); + QVERIFY(func); + QCOMPARE(builder->globalFunctions().size(), 1); +} + +void TestFunctionTag::testFunctionTagForAllSignatures() +{ + const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();\n"; + const char xmlCode[] = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("globalFunction")); + QVERIFY(func); + QCOMPARE(builder->globalFunctions().size(), 2); +} + +void TestFunctionTag::testRenameGlobalFunction() +{ + const char* cppCode ="void global_function_with_ugly_name();\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + const TypeEntry *func = TypeDatabase::instance()->findType(QLatin1String("global_function_with_ugly_name")); + QVERIFY(func); + + QCOMPARE(builder->globalFunctions().size(), 1); + const AbstractMetaFunction* metaFunc = builder->globalFunctions().first(); + + QVERIFY(metaFunc); + QCOMPARE(metaFunc->modifications().size(), 1); + QVERIFY(metaFunc->modifications().first().isRenameModifier()); + QCOMPARE(metaFunc->modifications().first().renamedTo(), QLatin1String("smooth")); + + QCOMPARE(metaFunc->name(), QLatin1String("smooth")); + QCOMPARE(metaFunc->originalName(), QLatin1String("global_function_with_ugly_name")); + QCOMPARE(metaFunc->minimalSignature(), QLatin1String("global_function_with_ugly_name()")); +} + +QTEST_APPLESS_MAIN(TestFunctionTag) + diff --git a/sources/shiboken2/ApiExtractor/tests/testfunctiontag.h b/sources/shiboken2/ApiExtractor/tests/testfunctiontag.h new file mode 100644 index 000000000..d4b6c7d2c --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testfunctiontag.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTFUNCTIONTAG_H +#define TESTFUNCTIONTAG_H +#include + +class TestFunctionTag : public QObject +{ + Q_OBJECT +private slots: + void testFunctionTagForSpecificSignature(); + void testFunctionTagForAllSignatures(); + void testRenameGlobalFunction(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp new file mode 100644 index 000000000..7e8db42f3 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testimplicitconversions.h" +#include "testutil.h" +#include +#include +#include + +void TestImplicitConversions::testWithPrivateCtors() +{ + const char* cppCode ="\ + class B;\n\ + class C;\n\ + class A {\n\ + A(const B&);\n\ + public:\n\ + A(const C&);\n\ + };\n\ + class B {};\n\ + class C {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); + AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); + QCOMPARE(implicitConvs.count(), 1); + QCOMPARE(implicitConvs.first()->arguments().first()->type()->typeEntry(), classC->typeEntry()); +} + +void TestImplicitConversions::testWithModifiedVisibility() +{ + const char* cppCode ="\ + class B;\n\ + class A {\n\ + public:\n\ + A(const B&);\n\ + };\n\ + class B {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); + QCOMPARE(implicitConvs.count(), 1); + QCOMPARE(implicitConvs.first()->arguments().first()->type()->typeEntry(), classB->typeEntry()); +} + + +void TestImplicitConversions::testWithAddedCtor() +{ + const char* cppCode ="\ + class B;\n\ + class A {\n\ + public:\n\ + A(const B&);\n\ + };\n\ + class B {};\n\ + class C {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); + QCOMPARE(implicitConvs.count(), 2); + + // Added constructors with custom types should never result in implicit converters. + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + implicitConvs = classB->implicitConversions(); + QCOMPARE(implicitConvs.count(), 0); +} + +void TestImplicitConversions::testWithExternalConversionOperator() +{ + const char* cppCode ="\ + class A {};\n\ + struct B {\n\ + operator A() const;\n\ + };\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + AbstractMetaFunctionList implicitConvs = classA->implicitConversions(); + QCOMPARE(implicitConvs.count(), 1); + AbstractMetaFunctionList externalConvOps = classA->externalConversionOperators(); + QCOMPARE(externalConvOps.count(), 1); + + const AbstractMetaFunction* convOp = 0; + for (const AbstractMetaFunction *func : classB->functions()) { + if (func->isConversionOperator()) + convOp = func; + } + QVERIFY(convOp); + QCOMPARE(implicitConvs.first(), convOp); +} + +QTEST_APPLESS_MAIN(TestImplicitConversions) diff --git a/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.h b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.h new file mode 100644 index 000000000..657c1a558 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testimplicitconversions.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTIMPLICITCONVERSIONS_H +#define TESTIMPLICITCONVERSIONS_H + +#include + +class AbstractMetaBuilder; + +class TestImplicitConversions : public QObject +{ + Q_OBJECT +private slots: + void testWithPrivateCtors(); + void testWithModifiedVisibility(); + void testWithAddedCtor(); + void testWithExternalConversionOperator(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp new file mode 100644 index 000000000..ecadf311b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testinserttemplate.h" +#include +#include "testutil.h" +#include +#include + +void TestInsertTemplate::testInsertTemplateOnClassInjectCode() +{ + const char* cppCode ="struct A{};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->typeEntry()->codeSnips().count(), 1); + QString code = classA->typeEntry()->codeSnips().first().code(); + QVERIFY(code.contains(QLatin1String("code template content"))); +} + +void TestInsertTemplate::testInsertTemplateOnModuleInjectCode() +{ + const char* cppCode =""; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QVERIFY(classes.isEmpty()); + + TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); + QVERIFY(module); + QCOMPARE(module->codeSnips().count(), 1); + QString code = module->codeSnips().first().code().trimmed(); + QVERIFY(code.contains(QLatin1String("code template content"))); +} + +void TestInsertTemplate::testInvalidTypeSystemTemplate() +{ + const char* cppCode =""; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QVERIFY(classes.isEmpty()); + + TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); + QVERIFY(module); + QCOMPARE(module->codeSnips().count(), 1); + QString code = module->codeSnips().first().code().trimmed(); + QVERIFY(code.isEmpty()); +} + +void TestInsertTemplate::testValidAndInvalidTypeSystemTemplate() +{ + const char* cppCode =""; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QVERIFY(classes.isEmpty()); + + TypeEntry* module = TypeDatabase::instance()->findType(QLatin1String("Foo")); + QVERIFY(module); + QCOMPARE(module->codeSnips().count(), 1); + QString code = module->codeSnips().first().code().trimmed(); + QVERIFY(code.contains(QLatin1String("code template content"))); +} + +QTEST_APPLESS_MAIN(TestInsertTemplate) diff --git a/sources/shiboken2/ApiExtractor/tests/testinserttemplate.h b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.h new file mode 100644 index 000000000..0e2a882fe --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testinserttemplate.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTINSERTTEMPLATE_H +#define TESTINSERTTEMPLATE_H + +#include + +class TestInsertTemplate : public QObject +{ + Q_OBJECT + private slots: + void testInsertTemplateOnClassInjectCode(); + void testInsertTemplateOnModuleInjectCode(); + void testInvalidTypeSystemTemplate(); + void testValidAndInvalidTypeSystemTemplate(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp new file mode 100644 index 000000000..96bd0251b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testmodifydocumentation.h" + +#include +#include +#include "testutil.h" +#include +#include +#include + +void TestModifyDocumentation::testModifyDocumentation() +{ + const char* cppCode ="struct B { void b(); }; class A {};\n"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + <para>Some changed contents here</para>\n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + DocModificationList docMods = classA->typeEntry()->docModifications(); + QCOMPARE(docMods.count(), 1); + QCOMPARE(docMods[0].code().trimmed(), QLatin1String("Some changed contents here")); + QCOMPARE(docMods[0].signature(), QString()); + QtDocParser docParser; + docParser.setDocumentationDataDirectory(QDir::currentPath()); + docParser.fillDocumentation(classA); + + QVERIFY(!classA->documentation().value().trimmed().isEmpty()); + QCOMPARE(classA->documentation().value(), QLatin1String("\n\ +oi\n\ + Paragraph number 1\n\ + Paragraph number 2\n\ + Some changed contents here\n\ +\n")); +} + +// 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 +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + TestModifyDocumentation tc; + return QTest::qExec(&tc, argc, argv); +} diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.h b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.h new file mode 100644 index 000000000..fb8f6fc01 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTMODIFYDOCUMENTATION_H +#define TESTMODIFYDOCUMENTATION_H + +#include + +class TestModifyDocumentation : public QObject +{ +Q_OBJECT +private slots: + void testModifyDocumentation(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp new file mode 100644 index 000000000..3d4ef9c89 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp @@ -0,0 +1,249 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testmodifyfunction.h" +#include +#include "testutil.h" +#include +#include + +void TestModifyFunction::testRenameArgument() +{ + const char* cppCode ="\ + struct A {\n\ + void method(int=0);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + const AbstractMetaFunction* func = classA->findFunction(QLatin1String("method")); + Q_ASSERT(func); + + QCOMPARE(func->argumentName(1), QLatin1String("otherArg")); +} + +void TestModifyFunction::testOwnershipTransfer() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {\n\ + virtual A* method();\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("method")); + + QCOMPARE(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0), TypeSystem::CppOwnership); +} + + +void TestModifyFunction::invalidateAfterUse() +{ + const char* cppCode ="\ + struct A {\n\ + virtual void call(int *a);\n\ + };\n\ + struct B : A {\n\ + };\n\ + struct C : B {\n\ + virtual void call2(int *a);\n\ + };\n\ + struct D : C {\n\ + virtual void call2(int *a);\n\ + };\n\ + struct E : D {\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("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, QLatin1String("C")); + QVERIFY(classC); + func = classC->findFunction(QLatin1String("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(QLatin1String("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, QLatin1String("D")); + QVERIFY(classD); + func = classD->findFunction(QLatin1String("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(QLatin1String("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, QLatin1String("E")); + QVERIFY(classE); + func = classE->findFunction(QLatin1String("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(QLatin1String("call2")); + 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); +} + +void TestModifyFunction::testWithApiVersion() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {\n\ + virtual A* method();\n\ + virtual B* methodB();\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("method")); + + QCOMPARE(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0), TypeSystem::CppOwnership); + + func = classB->findFunction(QLatin1String("methodB")); + QVERIFY(func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0) != TypeSystem::CppOwnership); +} + +void TestModifyFunction::testGlobalFunctionModification() +{ + const char* cppCode ="\ + struct A {};\n\ + void function(A* a = 0);\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + QCOMPARE(builder->globalFunctions().size(), 1); + + FunctionModificationList mods = TypeDatabase::instance()->functionModifications(QLatin1String("function(A*)")); + QCOMPARE(mods.count(), 1); + QVector argMods = mods.first().argument_mods; + QCOMPARE(argMods.count(), 1); + ArgumentModification argMod = argMods.first(); + QCOMPARE(argMod.replacedDefaultExpression, QLatin1String("A()")); + + const AbstractMetaFunction* func = builder->globalFunctions().first(); + QVERIFY(func); + QCOMPARE(func->arguments().count(), 1); + const AbstractMetaArgument* arg = func->arguments().first(); + QCOMPARE(arg->type()->cppSignature(), QLatin1String("A *")); + QCOMPARE(arg->originalDefaultValueExpression(), QLatin1String("0")); + QCOMPARE(arg->defaultValueExpression(), QLatin1String("A()")); +} + +QTEST_APPLESS_MAIN(TestModifyFunction) diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h new file mode 100644 index 000000000..fcaa0f9db --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTABSTRACTMETACLASS_H +#define TESTABSTRACTMETACLASS_H + +#include + +class TestModifyFunction : public QObject +{ + Q_OBJECT + private slots: + void testOwnershipTransfer(); + void testWithApiVersion(); + void testRenameArgument(); + void invalidateAfterUse(); + void testGlobalFunctionModification(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp new file mode 100644 index 000000000..b78e6ec01 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testmultipleinheritance.h" +#include +#include "testutil.h" +#include +#include + +void TestMultipleInheritance::testVirtualClass() +{ + const char* cppCode ="\ + struct A {\n\ + virtual ~A();\n\ + virtual void theBug();\n\ + };\n\ + struct B {\n\ + virtual ~B();\n\ + };\n\ + struct C : A, B {\n\ + };\n\ + struct D : C {\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 4); + + const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, QLatin1String("D")); + bool functionFound = false; + const AbstractMetaFunctionList &functions = classD->functions(); + for (AbstractMetaFunction *f : functions) { + if (f->name() == QLatin1String("theBug")) { + functionFound = true; + break; + } + } + QVERIFY(functionFound); + +} + +QTEST_APPLESS_MAIN(TestMultipleInheritance) diff --git a/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.h b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.h new file mode 100644 index 000000000..2313073bb --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTMULTIPLEINHERITANCE_H +#define TESTMULTIPLEINHERITANCE_H + +#include + +class AbstractMetaBuilder; + +class TestMultipleInheritance : public QObject +{ + Q_OBJECT + private slots: + void testVirtualClass(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testnamespace.cpp b/sources/shiboken2/ApiExtractor/tests/testnamespace.cpp new file mode 100644 index 000000000..ca6ce0589 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnamespace.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testnamespace.h" +#include +#include "testutil.h" +#include +#include + +void NamespaceTest::testNamespaceMembers() +{ + const char* cppCode = "\ + namespace Namespace\n\ + {\n\ + enum Option {\n\ + OpZero,\n\ + OpOne\n\ + };\n\ + void foo(Option opt);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass *ns = AbstractMetaClass::findClass(classes, QLatin1String("Namespace")); + QVERIFY(ns); + const AbstractMetaEnum* metaEnum = ns->findEnum(QLatin1String("Option")); + QVERIFY(metaEnum); + const AbstractMetaFunction* func = ns->findFunction(QLatin1String("foo")); + QVERIFY(func); +} + +void NamespaceTest::testNamespaceInnerClassMembers() +{ + const char* cppCode = "\ + namespace OuterNamespace\n\ + {\n\ + namespace InnerNamespace {\n\ + struct SomeClass {\n\ + void method();\n\ + };\n\ + };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace")); + QVERIFY(ons); + const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace")); + QVERIFY(ins); + const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); + QVERIFY(sc); + const AbstractMetaFunction* meth = sc->findFunction(QLatin1String("method")); + QVERIFY(meth); +} + +QTEST_APPLESS_MAIN(NamespaceTest) + diff --git a/sources/shiboken2/ApiExtractor/tests/testnamespace.h b/sources/shiboken2/ApiExtractor/tests/testnamespace.h new file mode 100644 index 000000000..d4451a938 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnamespace.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTNAMESPACE_H +#define TESTNAMESPACE_H + +#include + +// The class is named 'NamespaceTest' to avoid clashes with Qt COIN using +// '-qtnamespace TestNamespace'. +class NamespaceTest : public QObject +{ + Q_OBJECT + private slots: + void testNamespaceMembers(); + void testNamespaceInnerClassMembers(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp new file mode 100644 index 000000000..296aa4385 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testnestedtypes.h" +#include +#include "testutil.h" +#include +#include + +void TestNestedTypes::testNestedTypesModifications() +{ + const char* cppCode ="\ + namespace OuterNamespace {\n\ + namespace InnerNamespace {\n\ + struct SomeClass {\n\ + void method() {}\n\ + };\n\ + };\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + custom_code1();\n\ + \n\ + custom_code2();\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + const AbstractMetaClass *ons = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace")); + QVERIFY(ons); + + const AbstractMetaClass *ins = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace")); + QVERIFY(ins); + QCOMPARE(ins->functions().count(), 1); + QCOMPARE(ins->typeEntry()->codeSnips().count(), 1); + CodeSnip snip = ins->typeEntry()->codeSnips().first(); + QCOMPARE(snip.code(), QLatin1String("custom_code1();")); + + AbstractMetaFunction* addedFunc = ins->functions().first(); + QVERIFY(addedFunc->isUserAdded()); + QCOMPARE(addedFunc->visibility(), AbstractMetaFunction::Public); + QCOMPARE(addedFunc->functionType(), AbstractMetaFunction::NormalFunction); + QCOMPARE(addedFunc->type()->minimalSignature(), QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); + + QCOMPARE(addedFunc->modifications().size(), 1); + QVERIFY(addedFunc->modifications().first().isCodeInjection()); + snip = addedFunc->modifications().first().snips.first(); + QCOMPARE(snip.code(), QLatin1String("custom_code2();")); + + const AbstractMetaClass *sc = AbstractMetaClass::findClass(classes, QLatin1String("OuterNamespace::InnerNamespace::SomeClass")); + QVERIFY(ins); + QCOMPARE(sc->functions().count(), 2); // default constructor and removed method + AbstractMetaFunction* removedFunc = sc->functions().last(); + QVERIFY(removedFunc->isModifiedRemoved()); +} + + +void TestNestedTypes::testDuplicationOfNestedTypes() +{ + const char* cppCode ="\ + namespace Namespace {\n\ + class SomeClass {};\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 2); + const AbstractMetaClass *nspace = AbstractMetaClass::findClass(classes, QLatin1String("Namespace")); + QVERIFY(nspace); + const AbstractMetaClass *cls1 = AbstractMetaClass::findClass(classes, QLatin1String("SomeClass")); + QVERIFY(cls1); + const AbstractMetaClass *cls2 = AbstractMetaClass::findClass(classes, QLatin1String("Namespace::SomeClass")); + QVERIFY(cls2); + QCOMPARE(cls1, cls2); + QCOMPARE(cls1->name(), QLatin1String("SomeClass")); + QCOMPARE(cls1->qualifiedCppName(), QLatin1String("Namespace::SomeClass")); + + TypeEntry* t1 = TypeDatabase::instance()->findType(QLatin1String("Namespace::SomeClass")); + QVERIFY(t1); + TypeEntry* t2 = TypeDatabase::instance()->findType(QLatin1String("SomeClass")); + QVERIFY(!t2); +} + +QTEST_APPLESS_MAIN(TestNestedTypes) diff --git a/sources/shiboken2/ApiExtractor/tests/testnestedtypes.h b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.h new file mode 100644 index 000000000..737e81fab --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnestedtypes.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTNESTEDTYPES_H +#define TESTNESTEDTYPES_H +#include + +class TestNestedTypes : public QObject +{ + Q_OBJECT +private slots: + void testNestedTypesModifications(); + void testDuplicationOfNestedTypes(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.cpp b/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.cpp new file mode 100644 index 000000000..3491d5cb4 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testnumericaltypedef.h" +#include +#include "testutil.h" +#include +#include + +void TestNumericalTypedef::testNumericalTypedef() +{ + const char* cppCode ="\ + typedef double real;\n\ + void funcDouble(double);\n\ + void funcReal(real);\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + QCOMPARE(builder->globalFunctions().size(), 2); + const AbstractMetaFunction* funcDouble = builder->globalFunctions().first(); + QVERIFY(funcDouble); + const AbstractMetaFunction* funcReal = builder->globalFunctions().last(); + QVERIFY(funcReal); + + if (funcDouble->name() == QLatin1String("funcReal")) + std::swap(funcDouble, funcReal); + + QCOMPARE(funcDouble->minimalSignature(), QLatin1String("funcDouble(double)")); + QCOMPARE(funcReal->minimalSignature(), QLatin1String("funcReal(real)")); + + const AbstractMetaType* doubleType = funcDouble->arguments().first()->type(); + QVERIFY(doubleType); + QCOMPARE(doubleType->cppSignature(), QLatin1String("double")); + QVERIFY(doubleType->isPrimitive()); + QVERIFY(doubleType->typeEntry()->isCppPrimitive()); + + const AbstractMetaType* realType = funcReal->arguments().first()->type(); + QVERIFY(realType); + QCOMPARE(realType->cppSignature(), QLatin1String("real")); + QVERIFY(realType->isPrimitive()); + QVERIFY(realType->typeEntry()->isCppPrimitive()); +} + +void TestNumericalTypedef::testUnsignedNumericalTypedef() +{ + const char* cppCode ="\ + typedef unsigned short ushort;\n\ + void funcUnsignedShort(unsigned short);\n\ + void funcUShort(ushort);\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + QCOMPARE(builder->globalFunctions().size(), 2); + const AbstractMetaFunction* funcUnsignedShort = builder->globalFunctions().first(); + QVERIFY(funcUnsignedShort); + const AbstractMetaFunction* funcUShort = builder->globalFunctions().last(); + QVERIFY(funcUShort); + + if (funcUnsignedShort->name() == QLatin1String("funcUShort")) + std::swap(funcUnsignedShort, funcUShort); + + QCOMPARE(funcUnsignedShort->minimalSignature(), QLatin1String("funcUnsignedShort(unsigned short)")); + QCOMPARE(funcUShort->minimalSignature(), QLatin1String("funcUShort(ushort)")); + + const AbstractMetaType* unsignedShortType = funcUnsignedShort->arguments().first()->type(); + QVERIFY(unsignedShortType); + QCOMPARE(unsignedShortType->cppSignature(), QLatin1String("unsigned short")); + QVERIFY(unsignedShortType->isPrimitive()); + QVERIFY(unsignedShortType->typeEntry()->isCppPrimitive()); + + const AbstractMetaType* ushortType = funcUShort->arguments().first()->type(); + QVERIFY(ushortType); + QCOMPARE(ushortType->cppSignature(), QLatin1String("ushort")); + QVERIFY(ushortType->isPrimitive()); + QVERIFY(ushortType->typeEntry()->isCppPrimitive()); +} + +QTEST_APPLESS_MAIN(TestNumericalTypedef) + diff --git a/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.h b/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.h new file mode 100644 index 000000000..e8af1fa8e --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTNUMERICALTYPEDEF_H +#define TESTNUMERICALTYPEDEF_H + +#include + +class TestNumericalTypedef : public QObject +{ + Q_OBJECT + private slots: + void testNumericalTypedef(); + void testUnsignedNumericalTypedef(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.cpp b/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.cpp new file mode 100644 index 000000000..7646dd23a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testprimitivetypetag.h" +#include +#include "testutil.h" +#include +#include + +void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {};\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + + PrimitiveTypeEntry* typeEntry = TypeDatabase::instance()->findPrimitiveType(QLatin1String("A")); + QVERIFY(typeEntry); + QVERIFY(typeEntry->hasDefaultConstructor()); + QCOMPARE(typeEntry->defaultConstructor(), QLatin1String("A()")); +} + +QTEST_APPLESS_MAIN(TestPrimitiveTypeTag) + diff --git a/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.h b/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.h new file mode 100644 index 000000000..ea9276de3 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTPRIMITIVETYPETAG_H +#define TESTPRIMITIVETYPETAG_H + +#include + +class TestPrimitiveTypeTag : public QObject +{ + Q_OBJECT + private slots: + void testPrimitiveTypeDefaultConstructor(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp new file mode 100644 index 000000000..e9f9f0ab7 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testrefcounttag.h" +#include +#include "testutil.h" +#include +#include + +void TestRefCountTag::testReferenceCountTag() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {\n\ + void keepObject(B* b);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("keepObject")); + QVERIFY(func); + ReferenceCount refCount = func->modifications().first().argument_mods.first().referenceCounts.first(); + QCOMPARE(refCount.action, ReferenceCount::Add); +} + +void TestRefCountTag::testWithApiVersion() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {\n\ + void keepObject(B*, B*);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false, "0.1")); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("keepObject")); + QVERIFY(func); + ReferenceCount refCount = func->modifications().first().argument_mods.first().referenceCounts.first(); + QCOMPARE(refCount.action, ReferenceCount::Add); + + QCOMPARE(func->modifications().size(), 1); +} + + +QTEST_APPLESS_MAIN(TestRefCountTag) + + diff --git a/sources/shiboken2/ApiExtractor/tests/testrefcounttag.h b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.h new file mode 100644 index 000000000..a95661293 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testrefcounttag.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREFCOUNTTAG_H +#define TESTREFCOUNTTAG_H + +#include + +class TestRefCountTag : public QObject +{ + Q_OBJECT + private slots: + void testReferenceCountTag(); + void testWithApiVersion(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.cpp b/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.cpp new file mode 100644 index 000000000..f594cdd25 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testreferencetopointer.h" +#include +#include "testutil.h" +#include +#include + +void TestReferenceToPointer::testReferenceToPointerArgument() +{ + const char* cppCode ="\ + struct A {};\n\ + struct B {\n\ + void dummy(A*&);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("dummy")); + QVERIFY(func); + QCOMPARE(func->arguments().first()->type()->minimalSignature(), QLatin1String("A*&")); +} + +QTEST_APPLESS_MAIN(TestReferenceToPointer) + + diff --git a/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.h b/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.h new file mode 100644 index 000000000..83b0b6fad --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testreferencetopointer.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREFERENCETOPOINTER_H +#define TESTREFERENCETOPOINTER_H + +#include + +class TestReferenceToPointer : public QObject +{ + Q_OBJECT + private slots: + void testReferenceToPointerArgument(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testremovefield.cpp b/sources/shiboken2/ApiExtractor/tests/testremovefield.cpp new file mode 100644 index 000000000..7ebe49160 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremovefield.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testremovefield.h" +#include +#include "testutil.h" +#include +#include + +void TestRemoveField::testRemoveField() +{ + const char* cppCode ="\ + struct A {\n\ + int fieldA;\n\ + int fieldB;\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->fields().size(), 1); + const AbstractMetaField* fieldA = classA->fields().first(); + QVERIFY(fieldA); + QCOMPARE(fieldA->name(), QLatin1String("fieldA")); +} + +QTEST_APPLESS_MAIN(TestRemoveField) + + diff --git a/sources/shiboken2/ApiExtractor/tests/testremovefield.h b/sources/shiboken2/ApiExtractor/tests/testremovefield.h new file mode 100644 index 000000000..ea103e0cc --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremovefield.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREMOVEFIELD_H +#define TESTREMOVEFIELD_H + +#include + +class TestRemoveField : public QObject +{ + Q_OBJECT + private slots: + void testRemoveField(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.cpp b/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.cpp new file mode 100644 index 000000000..a81380873 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testremoveimplconv.h" +#include "testutil.h" +#include +#include +#include + +// 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 ="\ + struct A {};\n\ + struct B {};\n\ + struct C {\n\ + C(const A&);\n\ + C(const B&);\n\ + };\n"; + const char* xmlCode = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + const AbstractMetaClass *classC = AbstractMetaClass::findClass(classes, QLatin1String("C")); + QVERIFY(classC); + AbstractMetaFunctionList implConv = classC->implicitConversions(); + QCOMPARE(implConv.count(), 1); + QCOMPARE(implConv.first()->arguments().first()->type()->typeEntry(), classB->typeEntry()); +} + +QTEST_APPLESS_MAIN(TestRemoveImplConv) diff --git a/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.h b/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.h new file mode 100644 index 000000000..62d5f74e6 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremoveimplconv.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREMOVEIMPLCONV_H +#define TESTREMOVEIMPLCONV_H + +#include + +class TestRemoveImplConv : public QObject +{ +Q_OBJECT +private slots: + void testRemoveImplConv(); +}; + +#endif // TESTREMOVEIMPLCONV_H diff --git a/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp new file mode 100644 index 000000000..508cff586 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testremoveoperatormethod.h" +#include +#include "testutil.h" +#include +#include + +void TestRemoveOperatorMethod::testRemoveOperatorMethod() +{ + const char* cppCode ="\ + #include \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 = "\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().size(), 14); + QStringList removedSignatures; + removedSignatures.append(QLatin1String("operator>>(char&)")); + removedSignatures.append(QLatin1String("operator>>(char*)")); + removedSignatures.append(QLatin1String("operator>>(short&)")); + removedSignatures.append(QLatin1String("operator>>(unsigned short&)")); + removedSignatures.append(QLatin1String("operator>>(int&)")); + removedSignatures.append(QLatin1String("operator>>(unsigned int&)")); + removedSignatures.append(QLatin1String("operator>>(int64_t&)")); + removedSignatures.append(QLatin1String("operator>>(uint64_t&)")); + removedSignatures.append(QLatin1String("operator>>(float&)")); + removedSignatures.append(QLatin1String("operator>>(double&)")); + removedSignatures.append(QLatin1String("operator>>(Char&)")); + removedSignatures.append(QLatin1String("operator>>(String&)")); + int notRemoved = classA->functions().size(); + const AbstractMetaFunctionList &functions = classA->functions(); + for (const AbstractMetaFunction *f : functions) { + QCOMPARE(f->isModifiedRemoved(), bool(removedSignatures.contains(f->minimalSignature()))); + notRemoved -= int(f->isModifiedRemoved()); + } + QCOMPARE(notRemoved, 2); +} + +QTEST_APPLESS_MAIN(TestRemoveOperatorMethod) + diff --git a/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.h b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.h new file mode 100644 index 000000000..17ff75d74 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREMOVEOPERATORMETHOD_H +#define TESTREMOVEOPERATORMETHOD_H + +#include + +class TestRemoveOperatorMethod : public QObject +{ + Q_OBJECT + private slots: + void testRemoveOperatorMethod(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testresolvetype.cpp b/sources/shiboken2/ApiExtractor/tests/testresolvetype.cpp new file mode 100644 index 000000000..69691e860 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testresolvetype.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testresolvetype.h" +#include +#include "testutil.h" +#include +#include + +void TestResolveType::testResolveReturnTypeFromParentScope() +{ + const char* cppCode = "\n\ + namespace A {\n\ + struct B {\n\ + struct C {};\n\ + };\n\ + struct D : public B::C {\n\ + C* foo = 0;\n\ + C* method();\n\ + };\n\ + };"; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classD = AbstractMetaClass::findClass(classes, QLatin1String("A::D")); + QVERIFY(classD); + const AbstractMetaFunction* meth = classD->findFunction(QLatin1String("method")); + QVERIFY(meth); +} + +QTEST_APPLESS_MAIN(TestResolveType) + diff --git a/sources/shiboken2/ApiExtractor/tests/testresolvetype.h b/sources/shiboken2/ApiExtractor/tests/testresolvetype.h new file mode 100644 index 000000000..6164d0074 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testresolvetype.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTRESOLVETYPE_H +#define TESTRESOLVETYPE_H + +#include + +class TestResolveType : public QObject +{ + Q_OBJECT + private slots: + void testResolveReturnTypeFromParentScope(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp new file mode 100644 index 000000000..18d6902c2 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testreverseoperators.h" +#include +#include "testutil.h" +#include +#include + +void TestReverseOperators::testReverseSum() +{ + const char cppCode[] = "struct A {\n\ + A& operator+(int);\n\ + };\n\ + A& operator+(int, const A&);"; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClass* classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 4); + + const AbstractMetaFunction* reverseOp = 0; + const AbstractMetaFunction* normalOp = 0; + for (const AbstractMetaFunction *func : classA->functions()) { + if (func->name() == QLatin1String("operator+")) { + if (func->isReverseOperator()) + reverseOp = func; + else + normalOp = func; + } + } + + QVERIFY(normalOp); + QVERIFY(!normalOp->isReverseOperator()); + QCOMPARE(normalOp->arguments().count(), 1); + QVERIFY(reverseOp); + QVERIFY(reverseOp->isReverseOperator()); + QCOMPARE(reverseOp->arguments().count(), 1); +} + +void TestReverseOperators::testReverseSumWithAmbiguity() +{ + const char cppCode[] = "\n\ + struct A { A operator+(int); };\n\ + A operator+(int, const A&);\n\ + struct B {};\n\ + B operator+(const A&, const B&);\n\ + B operator+(const B&, const A&);\n\ + int operator-(int, const A*);\n\ + int operator/(const A*, int);\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QEXPECT_FAIL("", "Clang: Does not compile", Abort); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QCOMPARE(classA->functions().count(), 6); + + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + QCOMPARE(classB->functions().count(), 4); + + const AbstractMetaFunction* reverseOp = 0; + const AbstractMetaFunction* normalOp = 0; + for (const AbstractMetaFunction *func : classB->functions()) { + if (func->name() == QLatin1String("operator+")) { + if (func->isReverseOperator()) + reverseOp = func; + else + normalOp = func; + } + } + QVERIFY(normalOp); + QVERIFY(!normalOp->isReverseOperator()); + QCOMPARE(normalOp->arguments().count(), 1); + QCOMPARE(normalOp->minimalSignature(), QLatin1String("operator+(B,A)")); + QVERIFY(reverseOp); + QVERIFY(reverseOp->isReverseOperator()); + QCOMPARE(reverseOp->arguments().count(), 1); + QCOMPARE(reverseOp->minimalSignature(), QLatin1String("operator+(A,B)")); + + reverseOp = classA->findFunction(QLatin1String("operator-")); + QVERIFY(reverseOp); + QCOMPARE(reverseOp->arguments().count(), 1); + QVERIFY(reverseOp->isPointerOperator()); + QVERIFY(reverseOp->isReverseOperator()); + + normalOp = classA->findFunction(QLatin1String("operator/")); + QVERIFY(normalOp); + QCOMPARE(normalOp->arguments().count(), 1); + QVERIFY(normalOp->isPointerOperator()); + QVERIFY(!normalOp->isReverseOperator()); + +} + + + +QTEST_APPLESS_MAIN(TestReverseOperators) + diff --git a/sources/shiboken2/ApiExtractor/tests/testreverseoperators.h b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.h new file mode 100644 index 000000000..3bd65fb85 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTREVERSEOPERATORS_H +#define TESTREVERSEOPERATORS_H +#include + +class TestReverseOperators : public QObject +{ + Q_OBJECT +private slots: + void testReverseSum(); + void testReverseSumWithAmbiguity(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp new file mode 100644 index 000000000..4a66264d8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp @@ -0,0 +1,439 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testtemplates.h" +#include +#include +#include "testutil.h" +#include +#include + +void TestTemplates::testTemplateWithNamespace() +{ + const char cppCode[] = "\n\ + template struct QList {}; \n\ + struct Url {\n\ + void name();\n\ + };\n\ + namespace Internet {\n\ + struct Url{};\n\ + struct Bookmarks {\n\ + QList list();\n\ + };\n\ + }"; + const char xmlCode0[] = "\n\ + \n\ + \n\ + "; + + QTemporaryFile file; + QVERIFY(file.open()); + file.write(xmlCode0); + file.close(); + + QString xmlCode1 = QString::fromLatin1("\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + ").arg(file.fileName()); + + QScopedPointer builder(TestUtil::parse(cppCode, qPrintable(xmlCode1), false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Bookmarks")); + QVERIFY(classB); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("list")); + AbstractMetaType* funcType = func->type(); + QVERIFY(funcType); + QCOMPARE(funcType->cppSignature(), QLatin1String("QList")); +} + +void TestTemplates::testTemplateOnContainers() +{ + const char cppCode[] = "\n\ + struct Base {};\n\ + template struct QList {}; \n\ + namespace Namespace {\n\ + enum SomeEnum { E1, E2 };\n\ + template struct A {\n\ + A foo(const QList >& a);\n\ + };\n\ + typedef A B;\n\ + }\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + QVERIFY(!classB->baseClass()); + QVERIFY(classB->baseClassName().isNull()); + const AbstractMetaFunction* func = classB->findFunction(QLatin1String("foo")); + AbstractMetaType* argType = func->arguments().first()->type(); + QCOMPARE(argType->instantiations().count(), 1); + QCOMPARE(argType->typeEntry()->qualifiedCppName(), QLatin1String("QList")); + + const AbstractMetaType* instance1 = argType->instantiations().first(); + QCOMPARE(instance1->instantiations().count(), 1); + QCOMPARE(instance1->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::A")); + + const AbstractMetaType* instance2 = instance1->instantiations().first(); + QCOMPARE(instance2->instantiations().count(), 0); + QCOMPARE(instance2->typeEntry()->qualifiedCppName(), QLatin1String("Namespace::E1")); +} + +void TestTemplates::testTemplateValueAsArgument() +{ + const char cppCode[] = "\n\ + template struct List {};\n\ + void func(List arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); + QCOMPARE(globalFuncs.count(), 1); + + AbstractMetaFunction* func = globalFuncs.first(); + QCOMPARE(func->minimalSignature(), QLatin1String("func(List)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List")); +} + +void TestTemplates::testTemplatePointerAsArgument() +{ + const char cppCode[] = "\n\ + template struct List {};\n\ + void func(List* arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); + QCOMPARE(globalFuncs.count(), 1); + + AbstractMetaFunction* func = globalFuncs.first(); + QCOMPARE(func->minimalSignature(), QLatin1String("func(List*)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List *")); +} + +void TestTemplates::testTemplateReferenceAsArgument() +{ + const char cppCode[] = "\n\ + template struct List {};\n\ + void func(List& arg) {}\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaFunctionList globalFuncs = builder->globalFunctions(); + QCOMPARE(globalFuncs.count(), 1); + + AbstractMetaFunction* func = globalFuncs.first(); + QCOMPARE(func->minimalSignature(), QLatin1String("func(List&)")); + QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List &")); +} + +void TestTemplates::testTemplateParameterFixup() +{ + const char cppCode[] = "\n\ + template\n\ + struct List {\n\ + struct Iterator {};\n\ + void append(List l);\n\ + void erase(List::Iterator it);\n\ + };\n"; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n"; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + const AbstractMetaClassList templates = builder->templates(); + + QCOMPARE(templates.count(), 1); + const AbstractMetaClass *list = templates.first(); + // Verify that the parameter of "void append(List l)" gets fixed to "List" + const AbstractMetaFunction *append = list->findFunction(QStringLiteral("append")); + QVERIFY(append); + QCOMPARE(append->arguments().size(), 1); + QCOMPARE(append->arguments().at(0)->type()->cppSignature(), QLatin1String("List")); + // Verify that the parameter of "void erase(Iterator)" is not modified + const AbstractMetaFunction *erase = list->findFunction(QStringLiteral("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(), QLatin1String("List::Iterator")); +} + +void TestTemplates::testInheritanceFromContainterTemplate() +{ + const char cppCode[] = "\n\ + template\n\ + struct ListContainer {\n\ + inline void push_front(const T& t);\n\ + inline T& front();\n\ + };\n\ + struct FooBar {};\n\ + struct FooBars : public ListContainer {};\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + AbstractMetaClassList templates = builder->templates(); + QCOMPARE(classes.count(), 2); + QCOMPARE(templates.count(), 1); + + const AbstractMetaClass* foobars = AbstractMetaClass::findClass(classes, QLatin1String("FooBars")); + QCOMPARE(foobars->functions().count(), 4); + + const AbstractMetaClass* lc = templates.first(); + QCOMPARE(lc->functions().count(), 2); +} + +void TestTemplates::testTemplateInheritanceMixedWithForwardDeclaration() +{ + const char cppCode[] = "\n\ + enum SomeEnum { E1, E2 };\n\ + template struct Future;\n\ + template\n\ + struct A {\n\ + A();\n\ + void method();\n\ + friend struct Future;\n\ + };\n\ + typedef A B;\n\ + template struct Future {};\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + QVERIFY(!classB->baseClass()); + QVERIFY(classB->baseClassName().isNull()); + // 3 functions: simple constructor, copy constructor and "method()". + QCOMPARE(classB->functions().count(), 3); +} + +void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration() +{ + const char cppCode[] = "\n\ + namespace Namespace {\n\ + enum SomeEnum { E1, E2 };\n\ + template struct Future;\n\ + template\n\ + struct A {\n\ + A();\n\ + void method();\n\ + friend struct Future;\n\ + };\n\ + typedef A B;\n\ + template struct Future {};\n\ + };\n\ + "; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + + AbstractMetaClass* classB = AbstractMetaClass::findClass(classes, QLatin1String("Namespace::B")); + QVERIFY(classB); + QVERIFY(!classB->baseClass()); + QVERIFY(classB->baseClassName().isNull()); + // 3 functions: simple constructor, copy constructor and "method()". + QCOMPARE(classB->functions().count(), 3); +} + +void TestTemplates::testTypedefOfInstantiationOfTemplateClass() +{ + const char cppCode[] = "\n\ + namespace NSpace {\n\ + enum ClassType {\n\ + TypeOne\n\ + };\n\ + template\n\ + struct BaseTemplateClass {\n\ + inline ClassType getClassType() const { CLASS_TYPE; }\n\ + };\n\ + typedef BaseTemplateClass TypeOneClass;\n\ + }\n\ + "; + + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 3); + + const AbstractMetaClass* base = AbstractMetaClass::findClass(classes, QLatin1String("BaseTemplateClass")); + QVERIFY(base); + const AbstractMetaClass* one = AbstractMetaClass::findClass(classes, QLatin1String("TypeOneClass")); + QVERIFY(one); + QCOMPARE(one->templateBaseClass(), base); + QCOMPARE(one->functions().count(), base->functions().count()); + QVERIFY(one->isTypeDef()); + const ComplexTypeEntry* oneType = one->typeEntry(); + const ComplexTypeEntry* baseType = base->typeEntry(); + QCOMPARE(oneType->baseContainerType(), baseType); + QCOMPARE(one->baseClassNames(), QStringList(QLatin1String("BaseTemplateClass"))); + + QVERIFY(one->hasTemplateBaseClassInstantiations()); + AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); + QCOMPARE(instantiations.count(), 1); + const AbstractMetaType* inst = instantiations.first(); + QVERIFY(inst); + QVERIFY(!inst->isEnum()); + QVERIFY(!inst->typeEntry()->isEnum()); + QVERIFY(inst->typeEntry()->isEnumValue()); + QCOMPARE(inst->cppSignature(), QLatin1String("NSpace::TypeOne")); +} + +void TestTemplates::testContainerTypeIncompleteArgument() +{ + const char* cppCode ="\n\ + template\n\ + class Vector {\n\ + void method(const Vector& vector);\n\ + Vector otherMethod();\n\ + };\n\ + template \n\ + void Vector::method(const Vector& vector) {}\n\ + template \n\ + Vector Vector::otherMethod() { return Vector(); }\n\ + typedef Vector IntVector;\n\ + "; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + "; + + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, true)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + QCOMPARE(classes.count(), 1); + + AbstractMetaClass* vector = AbstractMetaClass::findClass(classes, QLatin1String("IntVector")); + QVERIFY(vector); + QVERIFY(vector->typeEntry()->baseContainerType()); + QCOMPARE(reinterpret_cast(vector->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::VectorContainer); + QCOMPARE(vector->functions().count(), 4); + + const AbstractMetaFunction* method = vector->findFunction(QLatin1String("method")); + QVERIFY(method); + QCOMPARE(method->signature(), QLatin1String("method(const Vector & vector)")); + + const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod")); + QVERIFY(otherMethod); + QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()")); + QVERIFY(otherMethod->type()); + QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector")); +} + +QTEST_APPLESS_MAIN(TestTemplates) diff --git a/sources/shiboken2/ApiExtractor/tests/testtemplates.h b/sources/shiboken2/ApiExtractor/tests/testtemplates.h new file mode 100644 index 000000000..7b0d0f3b3 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTTEMPLATES_H +#define TESTTEMPLATES_H + +#include + +class TestTemplates : public QObject +{ + Q_OBJECT +private slots: + void testTemplateOnContainers(); + void testTemplateWithNamespace(); + void testTemplateValueAsArgument(); + void testTemplatePointerAsArgument(); + void testTemplateReferenceAsArgument(); + void testTemplateParameterFixup(); + void testInheritanceFromContainterTemplate(); + void testTemplateInheritanceMixedWithForwardDeclaration(); + void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); + void testTypedefOfInstantiationOfTemplateClass(); + void testContainerTypeIncompleteArgument(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp b/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp new file mode 100644 index 000000000..30d368a8a --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtoposort.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testtoposort.h" +#include +#include "graph.h" +#include + +void TestTopoSort::testTopoSort() +{ + QLinkedList result; + { + Graph g(3); + g.addEdge(1, 2); + g.addEdge(0, 1); + result = g.topologicalSort(); + QCOMPARE(result.size(), 3); + QLinkedList::iterator it = result.begin(); + QCOMPARE(*it, 0); + QCOMPARE(*(++it), 1); + QCOMPARE(*(++it), 2); + } + { + Graph g(2); + result = g.topologicalSort(); + QCOMPARE(result.size(), 2); + QLinkedList::iterator it = result.begin(); + QCOMPARE(*it, 1); + QCOMPARE(*(++it), 0); + } +} + +void TestTopoSort::testCiclicGraph() +{ + Graph g(3); + g.addEdge(0, 1); + g.addEdge(1, 2); + g.addEdge(2, 0); + QLinkedList result = g.topologicalSort(); + QVERIFY(result.isEmpty()); +} + +QTEST_APPLESS_MAIN(TestTopoSort) + diff --git a/sources/shiboken2/ApiExtractor/tests/testtoposort.h b/sources/shiboken2/ApiExtractor/tests/testtoposort.h new file mode 100644 index 000000000..ae8a2bab8 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtoposort.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTTOPOSORT_H +#define TESTTOPOSORT_H + +#include + +class TestTopoSort : public QObject +{ +Q_OBJECT +private slots: + void testTopoSort(); + void testCiclicGraph(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp new file mode 100644 index 000000000..804683140 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testtyperevision.h" +#include +#include "testutil.h" +#include +#include + +void TestTypeRevision::testRevisionAttr() +{ + const char* cppCode = "class Rev_0 {};" + "class Rev_1 {};" + "class Rev_2 { public: enum Rev_3 { X }; enum Rev_5 { Y }; };"; + const char* xmlCode = "" + "" + "" + "" + " " + " " + "" + ""; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *rev0 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_0")); + QCOMPARE(getTypeRevision(rev0->typeEntry()), 0); + + const AbstractMetaClass *rev1 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_1")); + QCOMPARE(getTypeRevision(rev1->typeEntry()), 1); + + AbstractMetaClass *rev2 = AbstractMetaClass::findClass(classes, QLatin1String("Rev_2")); + QCOMPARE(getTypeRevision(rev2->typeEntry()), 2); + + AbstractMetaEnum* rev3 = rev2->findEnum(QLatin1String("Rev_3")); + QCOMPARE(getTypeRevision(rev3->typeEntry()), 3); + FlagsTypeEntry* rev4 = rev3->typeEntry()->flags(); + QCOMPARE(getTypeRevision(rev4), 4); + AbstractMetaEnum* rev5 = rev2->findEnum(QLatin1String("Rev_5")); + QCOMPARE(getTypeRevision(rev5->typeEntry()), 5); + QCOMPARE(getTypeRevision(rev5->typeEntry()->flags()), 5); +} + +QTEST_APPLESS_MAIN(TestTypeRevision) + + diff --git a/sources/shiboken2/ApiExtractor/tests/testtyperevision.h b/sources/shiboken2/ApiExtractor/tests/testtyperevision.h new file mode 100644 index 000000000..dcb2d8794 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testtyperevision.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTTYPEREVISION_H +#define TESTTYPEREVISION_H + +#include + +class TestTypeRevision : public QObject +{ + Q_OBJECT + +private slots: + void testRevisionAttr(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testutil.h b/sources/shiboken2/ApiExtractor/tests/testutil.h new file mode 100644 index 000000000..200fdb104 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testutil.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTUTIL_H +#define TESTUTIL_H +#include +#include +#include +#include +#include "abstractmetabuilder.h" +#include "reporthandler.h" +#include "typedatabase.h" + +namespace TestUtil +{ + static AbstractMetaBuilder *parse(const char *cppCode, const char *xmlCode, + bool silent = true, + const char *apiVersion = Q_NULLPTR, + const QStringList &dropTypeEntries = QStringList()) + { + ReportHandler::setSilent(silent); + TypeDatabase* td = TypeDatabase::instance(true); + if (apiVersion && !td->setApiVersion(QLatin1String("*"), QLatin1String(apiVersion))) + return Q_NULLPTR; + td->setDropTypeEntries(dropTypeEntries); + QBuffer buffer; + // parse typesystem + buffer.setData(xmlCode); + if (!buffer.open(QIODevice::ReadOnly)) + return Q_NULLPTR; + td->parseFile(&buffer); + buffer.close(); + // parse C++ code + QTemporaryFile tempSource(QDir::tempPath() + QLatin1String("/st_XXXXXX_main.cpp")); + if (!tempSource.open()) { + qWarning().noquote().nospace() << "Creation of temporary file failed: " + << tempSource.errorString(); + return nullptr; + } + QByteArrayList arguments; + arguments.append(QFile::encodeName(tempSource.fileName())); + tempSource.write(cppCode, qint64(strlen(cppCode))); + tempSource.close(); + AbstractMetaBuilder *builder = new AbstractMetaBuilder; + if (!builder->build(arguments, 0)) { + delete builder; + return Q_NULLPTR; + } + return builder; + } +} // namespace TestUtil + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.cpp b/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.cpp new file mode 100644 index 000000000..627255d37 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testvaluetypedefaultctortag.h" +#include +#include "testutil.h" +#include +#include + +void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument() +{ + const char* cppCode ="\n\ + struct A {\n\ + A(int,int);\n\ + };\n\ + struct B {};\n\ + "; + const char* xmlCode = "\n\ + \n\ + \n\ + \n\ + \n\ + "; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + AbstractMetaClassList classes = builder->classes(); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + QVERIFY(classA->typeEntry()->hasDefaultConstructor()); + QCOMPARE(classA->typeEntry()->defaultConstructor(), QLatin1String("A(0, 0)")); + + const AbstractMetaClass *classB = AbstractMetaClass::findClass(classes, QLatin1String("B")); + QVERIFY(classB); + QVERIFY(!classB->typeEntry()->hasDefaultConstructor()); +} + +QTEST_APPLESS_MAIN(TestValueTypeDefaultCtorTag) diff --git a/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.h b/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.h new file mode 100644 index 000000000..2d2efe79d --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.h @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTVALUETYPEDEFAULTCTORTAG_H +#define TESTVALUETYPEDEFAULTCTORTAG_H + +#include + +class TestValueTypeDefaultCtorTag : public QObject +{ + Q_OBJECT + private slots: + void testValueTypeDefaultCtorTagArgument(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/testvoidarg.cpp b/sources/shiboken2/ApiExtractor/tests/testvoidarg.cpp new file mode 100644 index 000000000..5f0b47389 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testvoidarg.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "testvoidarg.h" +#include +#include "testutil.h" +#include +#include + +void TestVoidArg::testVoidParsedFunction() +{ + const char cppCode[] = "struct A { void a(void); };"; + const char xmlCode[] = "\n\ + \n\ + \n\ + "; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); + QCOMPARE(addedFunc->arguments().count(), 0); +} + +void TestVoidArg::testVoidAddedFunction() +{ + const char cppCode[] = "struct A { };"; + const char xmlCode[] = "\n\ + \n\ + \n\ + \n\ + \n\ + "; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); + QCOMPARE(addedFunc->arguments().count(), 0); + +} + +void TestVoidArg::testVoidPointerParsedFunction() +{ + const char cppCode[] = "struct A { void a(void*); };"; + const char xmlCode[] = "\n\ + \n\ + \n\ + "; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode)); + QVERIFY(!builder.isNull()); + AbstractMetaClassList classes = builder->classes(); + const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A")); + QVERIFY(classA); + const AbstractMetaFunction* addedFunc = classA->findFunction(QLatin1String("a")); + QCOMPARE(addedFunc->arguments().count(), 1); + +} + +QTEST_APPLESS_MAIN(TestVoidArg) diff --git a/sources/shiboken2/ApiExtractor/tests/testvoidarg.h b/sources/shiboken2/ApiExtractor/tests/testvoidarg.h new file mode 100644 index 000000000..40d96a4ff --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/testvoidarg.h @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TESTVOIDARG_H +#define TESTVOIDARG_H +#include + +class TestVoidArg : public QObject +{ + Q_OBJECT +private slots: + void testVoidParsedFunction(); + void testVoidPointerParsedFunction(); + void testVoidAddedFunction(); +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/tests/utf8code.txt b/sources/shiboken2/ApiExtractor/tests/utf8code.txt new file mode 100644 index 000000000..6d5fa9dcf --- /dev/null +++ b/sources/shiboken2/ApiExtractor/tests/utf8code.txt @@ -0,0 +1 @@ +áéíóú \ No newline at end of file diff --git a/sources/shiboken2/ApiExtractor/typedatabase.cpp b/sources/shiboken2/ApiExtractor/typedatabase.cpp new file mode 100644 index 000000000..a1b28070b --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp @@ -0,0 +1,745 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "typedatabase.h" +#include "typesystem.h" +#include "typesystem_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "reporthandler.h" +// #include +#include + +// package -> api-version + +static QString wildcardToRegExp(QString w) +{ + w.replace(QLatin1Char('?'), QLatin1Char('.')); + w.replace(QLatin1Char('*'), QStringLiteral(".*")); + return w; +} + +typedef QPair ApiVersion; +typedef QVector ApiVersions; + +Q_GLOBAL_STATIC(ApiVersions, apiVersions) + +TypeDatabase::TypeDatabase() : m_suppressWarnings(true) +{ + addType(new VoidTypeEntry()); + addType(new VarargsTypeEntry()); +} + +TypeDatabase::~TypeDatabase() +{ +} + +TypeDatabase* TypeDatabase::instance(bool newInstance) +{ + static TypeDatabase* db = 0; + if (!db || newInstance) { + if (db) + delete db; + db = new TypeDatabase; + } + return db; +} + +// A list of regex/replacements to fix int types like "ushort" to "unsigned short" +// unless present in TypeDatabase +struct IntTypeNormalizationEntry +{ + QRegularExpression regex; + QString replacement; +}; + +typedef QVector IntTypeNormalizationEntries; + +static const IntTypeNormalizationEntries &intTypeNormalizationEntries() +{ + static IntTypeNormalizationEntries result; + static bool firstTime = true; + if (firstTime) { + firstTime = false; + static const char *intTypes[] = {"char", "short", "int", "long"}; + const size_t size = sizeof(intTypes) / sizeof(intTypes[0]); + for (size_t i = 0; i < size; ++i) { + const QString intType = QLatin1String(intTypes[i]); + if (!TypeDatabase::instance()->findType(QLatin1Char('u') + intType)) { + IntTypeNormalizationEntry entry; + entry.replacement = QStringLiteral("unsigned ") + intType; + entry.regex.setPattern(QStringLiteral("\\bu") + intType + QStringLiteral("\\b")); + Q_ASSERT(entry.regex.isValid()); + result.append(entry); + } + } + } + return result; +} + +QString TypeDatabase::normalizedSignature(const QString &signature) +{ + QString normalized = QLatin1String(QMetaObject::normalizedSignature(signature.toUtf8().constData())); + + if (instance() && signature.contains(QLatin1String("unsigned"))) { + const IntTypeNormalizationEntries &entries = intTypeNormalizationEntries(); + for (int i = 0, size = entries.size(); i < size; ++i) + normalized.replace(entries.at(i).regex, entries.at(i).replacement); + } + + return normalized; +} + +QStringList TypeDatabase::requiredTargetImports() const +{ + return m_requiredTargetImports; +} + +void TypeDatabase::addRequiredTargetImport(const QString& moduleName) +{ + if (!m_requiredTargetImports.contains(moduleName)) + 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 + m_typesystemPaths += typesystem_paths.split(QLatin1Char(path_splitter)); +} + +IncludeList TypeDatabase::extraIncludes(const QString& className) const +{ + ComplexTypeEntry* typeEntry = findComplexType(className); + if (typeEntry) + return typeEntry->extraIncludes(); + else + return IncludeList(); +} + +ContainerTypeEntry* TypeDatabase::findContainerType(const QString &name) const +{ + QString template_name = name; + + int pos = name.indexOf(QLatin1Char('<')); + if (pos > 0) + template_name = name.left(pos); + + TypeEntry* type_entry = findType(template_name); + if (type_entry && type_entry->isContainer()) + return static_cast(type_entry); + return 0; +} + +FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const +{ + TypeEntry* entry = findType(name); + if (entry && entry->type() == TypeEntry::FunctionType) + return static_cast(entry); + return 0; +} + +TypeEntry* TypeDatabase::findType(const QString& name) const +{ + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { + if (entry && + (!entry->isPrimitive() || static_cast(entry)->preferredTargetLangType())) { + return entry; + } + } + return 0; +} + +TypeEntryList TypeDatabase::findTypes(const QString &name) const +{ + return m_entries.value(name); +} + +SingleTypeEntryHash TypeDatabase::entries() const +{ + TypeEntryHash entries = allEntries(); + + SingleTypeEntryHash returned; + for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) + returned.insert(it.key(), findType(it.key())); + + return returned; +} + +PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const +{ + TypeEntryHash entries = allEntries(); + PrimitiveTypeEntryList returned; + for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { + for (TypeEntry *typeEntry : it.value()) { + if (typeEntry->isPrimitive()) + returned.append(static_cast(typeEntry)); + } + } + return returned; +} + +ContainerTypeEntryList TypeDatabase::containerTypes() const +{ + TypeEntryHash entries = allEntries(); + ContainerTypeEntryList returned; + for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) { + for (TypeEntry *typeEntry : it.value()) { + if (typeEntry->isContainer()) + returned.append(static_cast(typeEntry)); + } + } + return returned; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeRejection &r) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeRejection(type=" << r.matchType << ", class=" + << r.className.pattern() << ", pattern=" << r.pattern.pattern() << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +void TypeDatabase::addRejection(const TypeRejection &r) +{ + m_rejections << r; +} + +static inline QString msgRejectReason(const TypeRejection &r, const QString &needle = QString()) +{ + QString result; + QTextStream str(&result); + switch (r.matchType) { + case TypeRejection::ExcludeClass: + str << " matches class exclusion \"" << r.className.pattern() << '"'; + break; + case TypeRejection::Function: + case TypeRejection::Field: + case TypeRejection::Enum: + str << " matches class \"" << r.className.pattern() << "\" and \"" << r.pattern.pattern() << '"'; + break; + case TypeRejection::ArgumentType: + case TypeRejection::ReturnType: + str << " matches class \"" << r.className.pattern() << "\" and \"" << needle + << "\" matches \"" << r.pattern.pattern() << '"'; + break; + } + return result; +} + +// Match class name only +bool TypeDatabase::isClassRejected(const QString& className, QString *reason) const +{ + for (const TypeRejection& r : m_rejections) { + if (r.matchType == TypeRejection::ExcludeClass && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r); + return true; + } + } + return false; +} + +// Match class name and function/enum/field +static bool findRejection(const QVector &rejections, + TypeRejection::MatchType matchType, + const QString& className, const QString& name, + QString *reason = nullptr) +{ + Q_ASSERT(matchType != TypeRejection::ExcludeClass); + for (const TypeRejection& r : rejections) { + if (r.matchType == matchType && r.pattern.match(name).hasMatch() + && r.className.match(className).hasMatch()) { + if (reason) + *reason = msgRejectReason(r, name); + return true; + } + } + return false; +} + +bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName, QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Enum, className, enumName, reason); +} + +void TypeDatabase::addType(TypeEntry *e) +{ + m_entries[e->qualifiedCppName()].append(e); +} + +bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Function, className, functionName, reason); +} + +bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::Field, className, fieldName, reason); +} + +bool TypeDatabase::isArgumentTypeRejected(const QString& className, const QString& typeName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::ArgumentType, className, typeName, reason); +} + +bool TypeDatabase::isReturnTypeRejected(const QString& className, const QString& typeName, + QString *reason) const +{ + return findRejection(m_rejections, TypeRejection::ReturnType, className, typeName, reason); +} + +FlagsTypeEntry* TypeDatabase::findFlagsType(const QString &name) const +{ + TypeEntry *fte = findType(name); + if (!fte) { + fte = m_flagsEntries.value(name); + if (!fte) { + //last hope, search for flag without scope inside of flags hash + for (SingleTypeEntryHash::const_iterator it = m_flagsEntries.cbegin(), end = m_flagsEntries.cend(); it != end; ++it) { + if (it.key().endsWith(name)) { + fte = it.value(); + break; + } + } + } + } + return static_cast(fte); +} + +void TypeDatabase::addFlagsType(FlagsTypeEntry *fte) +{ + m_flagsEntries[fte->originalName()] = fte; +} + +void TypeDatabase::addTemplate(TemplateEntry *t) +{ + m_templates[t->name()] = t; +} + +void TypeDatabase::addGlobalUserFunctions(const AddedFunctionList &functions) +{ + m_globalUserFunctions << functions; +} + +AddedFunctionList TypeDatabase::findGlobalUserFunctions(const QString& name) const +{ + AddedFunctionList addedFunctions; + for (const AddedFunction &func : m_globalUserFunctions) { + if (func.name() == name) + addedFunctions.append(func); + } + return addedFunctions; +} + +void TypeDatabase::addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications) +{ + m_functionMods << functionModifications; +} + +QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) +{ + return QLatin1String("Global"); +} + +FunctionModificationList TypeDatabase::functionModifications(const QString& signature) const +{ + FunctionModificationList lst; + for (int i = 0; i < m_functionMods.count(); ++i) { + const FunctionModification& mod = m_functionMods.at(i); + if (mod.signature == signature) + lst << mod; + } + + return lst; +} + +void TypeDatabase::addSuppressedWarning(const QString &s) +{ + m_suppressedWarnings.append(s); +} + +bool TypeDatabase::isSuppressedWarning(const QString& s) const +{ + if (!m_suppressWarnings) + return false; + + for (QString warning : m_suppressedWarnings) { + warning.replace(QLatin1String("\\*"), QLatin1String("&place_holder_for_asterisk;")); + + QStringList segs = warning.split(QLatin1Char('*'), QString::SkipEmptyParts); + if (!segs.size()) + continue; + + int i = 0; + int pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*"))); + //qDebug() << "s == " << s << ", warning == " << segs; + while (pos != -1) { + if (i == segs.size()) + return true; + pos = s.indexOf(QString(segs.at(i++)).replace(QLatin1String("&place_holder_for_asterisk;"), QLatin1String("*")), pos); + } + } + + return false; +} + +QString TypeDatabase::modifiedTypesystemFilepath(const QString& tsFile) const +{ + const QFileInfo tsFi(tsFile); + if (tsFi.isAbsolute()) // No point in further lookups + return tsFi.absoluteFilePath(); + if (tsFi.isFile()) // Make path absolute + return tsFi.absoluteFilePath(); + const QString fileName = tsFi.fileName(); + for (const QString &path : m_typesystemPaths) { + const QFileInfo fi(path + QLatin1Char('/') + fileName); + if (fi.isFile()) + return fi.absoluteFilePath(); + } + return tsFile; +} + +bool TypeDatabase::parseFile(const QString &filename, bool generate) +{ + QString filepath = modifiedTypesystemFilepath(filename); + if (m_parsedTypesystemFiles.contains(filepath)) + return m_parsedTypesystemFiles[filepath]; + + m_parsedTypesystemFiles[filepath] = true; // Prevent recursion when including self. + + QFile file(filepath); + if (!file.exists()) { + m_parsedTypesystemFiles[filepath] = false; + qCWarning(lcShiboken).noquote().nospace() + << "Can't find " << filename << ", typesystem paths: " << m_typesystemPaths.join(QLatin1String(", ")); + return false; + } + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_parsedTypesystemFiles[filepath] = false; + qCWarning(lcShiboken).noquote().nospace() + << "Can't open " << QDir::toNativeSeparators(filename) << ": " << file.errorString(); + return false; + } + + int count = m_entries.size(); + bool ok = parseFile(&file, generate); + m_parsedTypesystemFiles[filepath] = ok; + int newCount = m_entries.size(); + + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + qCDebug(lcShiboken) + << QStringLiteral("Parsed: '%1', %2 new entries").arg(filename).arg(newCount - count); + } + return ok; +} + +bool TypeDatabase::parseFile(QIODevice* device, bool generate) +{ + QXmlStreamReader reader(device); + Handler handler(this, generate); + return handler.parse(reader); +} + +PrimitiveTypeEntry *TypeDatabase::findPrimitiveType(const QString& name) const +{ + const TypeEntryList &entries = findTypes(name); + + for (TypeEntry *entry : entries) { + if (entry && entry->isPrimitive() && static_cast(entry)->preferredTargetLangType()) + return static_cast(entry); + } + + return 0; +} + +ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const +{ + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { + if (entry && entry->isComplex()) + return static_cast(entry); + } + return 0; +} + +ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const +{ + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { + if (entry && entry->isObject()) + return static_cast(entry); + } + return 0; +} + +NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const +{ + const TypeEntryList &entries = findTypes(name); + for (TypeEntry *entry : entries) { + if (entry && entry->isNamespace()) + return static_cast(entry); + } + return 0; +} + +bool TypeDatabase::shouldDropTypeEntry(const QString& fullTypeName) const +{ + return m_dropTypeEntries.contains(fullTypeName); +} + +void TypeDatabase::setDropTypeEntries(QStringList dropTypeEntries) +{ + m_dropTypeEntries = dropTypeEntries; + m_dropTypeEntries.sort(); +} + +// Using std::pair to save some memory +// the pair means (revision, typeIndex) +// This global variable exists only because we can't break the ABI +typedef QHash > TypeRevisionMap; +Q_GLOBAL_STATIC(TypeRevisionMap, typeEntryFields); +static bool computeTypeIndexes = true; +static int maxTypeIndex; + +int getTypeRevision(const TypeEntry* typeEntry) +{ + return typeEntryFields()->value(typeEntry).first; +} + +void setTypeRevision(TypeEntry* typeEntry, int revision) +{ + (*typeEntryFields())[typeEntry].first = revision; + computeTypeIndexes = true; +} + +static bool compareTypeEntriesByName(const TypeEntry* t1, const TypeEntry* t2) +{ + return t1->qualifiedCppName() < t2->qualifiedCppName(); +} + +static void _computeTypeIndexes() +{ + TypeDatabase* tdb = TypeDatabase::instance(); + typedef QMap GroupedTypeEntries; + GroupedTypeEntries groupedEntries; + + // Group type entries by revision numbers + const TypeEntryHash &allEntries = tdb->allEntries(); + for (TypeEntryHash::const_iterator tit = allEntries.cbegin(), end = allEntries.cend(); tit != end; ++tit) { + for (TypeEntry *entry : tit.value()) { + if (entry->isPrimitive() + || entry->isContainer() + || entry->isFunction() + || !entry->generateCode() + || entry->isEnumValue() + || entry->isVarargs() + || entry->isTypeSystem() + || entry->isVoid() + || entry->isCustom()) + continue; + groupedEntries[getTypeRevision(entry)] << entry; + } + } + + maxTypeIndex = 0; + GroupedTypeEntries::iterator it = groupedEntries.begin(); + for (; it != groupedEntries.end(); ++it) { + // Remove duplicates + TypeEntryList::iterator newEnd = std::unique(it.value().begin(), it.value().end()); + it.value().erase(newEnd, it.value().end()); + // Sort the type entries by name + qSort(it.value().begin(), newEnd, compareTypeEntriesByName); + + for (TypeEntry *entry : qAsConst(it.value())) { + (*typeEntryFields())[entry].second = maxTypeIndex++; + } + } + computeTypeIndexes = false; +} + +int getTypeIndex(const TypeEntry* typeEntry) +{ + if (computeTypeIndexes) + _computeTypeIndexes(); + return typeEntryFields()->value(typeEntry).second; +} + +int getMaxTypeIndex() +{ + if (computeTypeIndexes) + _computeTypeIndexes(); + return maxTypeIndex; +} + +bool TypeDatabase::setApiVersion(const QString& packageWildcardPattern, const QString &version) +{ + const QString packagePattern = wildcardToRegExp(packageWildcardPattern.trimmed()); + const QVersionNumber versionNumber = QVersionNumber::fromString(version); + if (versionNumber.isNull()) + return false; + ApiVersions &versions = *apiVersions(); + for (int i = 0, size = versions.size(); i < size; ++i) { + if (versions.at(i).first.pattern() == packagePattern) { + versions[i].second = versionNumber; + return true; + } + } + const QRegularExpression packageRegex(packagePattern); + if (!packageRegex.isValid()) + return false; + versions.append(qMakePair(packageRegex, versionNumber)); + return true; +} + +bool TypeDatabase::checkApiVersion(const QString& package, const QString& version) const +{ + const QVersionNumber versionNumber = QVersionNumber::fromString(version); + if (versionNumber.isNull()) { + qCWarning(lcShiboken).noquote().nospace() + << "checkApiVersion: Invalid version \"" << version << "\" specified for package " + << package << '.'; + return false; + } + const ApiVersions &versions = *apiVersions(); + for (int i = 0, size = versions.size(); i < size; ++i) { + if (versions.at(i).first.match(package).hasMatch()) + return versions.at(i).second >= versionNumber; + } + return false; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeEntry *te) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeEntry("; + if (te) { + d << '"' << te->qualifiedCppName() << "\", type=" << te->type(); + if (te->include().isValid()) + d << ", include=" << te->include(); + const IncludeList &extraIncludes = te->extraIncludes(); + if (const int count = extraIncludes.size()) { + d << ", extraIncludes[" << count << "]="; + for (int i = 0; i < count; ++i) { + if (i) + d << ", "; + d << extraIncludes.at(i); + } + } + } else { + d << '0'; + } + d << ')'; + return d; +} + +QDebug operator<<(QDebug d, const TemplateEntry *te) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TemplateEntry("; + if (te) { + d << '"' << te->name() << "\", version=" << te->version(); + } else { + d << '0'; + } + d << ')'; + return d; +} + +void TypeDatabase::formatDebug(QDebug &d) const +{ + typedef TypeEntryHash::ConstIterator Eit; + typedef SingleTypeEntryHash::ConstIterator Sit; + typedef TemplateEntryHash::ConstIterator TplIt; + d << "TypeDatabase(" + << "entries[" << m_entries.size() << "]="; + for (Eit it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { + const int count = it.value().size(); + d << '"' << it.key() << "\" [" << count << "]: ("; + for (int t = 0; t < count; ++t) { + if (t) + d << ", "; + d << it.value().at(t); + } + d << ")\n"; + } + if (!m_templates.isEmpty()) { + d << "templates[" << m_templates.size() << "]=("; + const TplIt begin = m_templates.cbegin(); + for (TplIt it = begin, end = m_templates.cend(); it != end; ++it) { + if (it != begin) + d << ", "; + d << it.value(); + } + d << ")\n"; + } + if (!m_flagsEntries.isEmpty()) { + d << "flags[" << m_flagsEntries.size() << "]=("; + const Sit begin = m_flagsEntries.cbegin(); + for (Sit it = begin, end = m_flagsEntries.cend(); it != end; ++it) { + if (it != begin) + d << ", "; + d << it.value(); + } + d << ")\n"; + } + d <<"\nglobalUserFunctions=" << m_globalUserFunctions << ')'; +} + +QDebug operator<<(QDebug d, const TypeDatabase &db) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + db.formatDebug(d); + return d; +} +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/typedatabase.h b/sources/shiboken2/ApiExtractor/typedatabase.h new file mode 100644 index 000000000..86f933448 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typedatabase.h @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPEDATABASE_H +#define TYPEDATABASE_H + +#include "apiextractormacros.h" +#include "include.h" +#include "typedatabase_typedefs.h" +#include "typesystem_enums.h" +#include "typesystem_typedefs.h" + +#include + +QT_FORWARD_DECLARE_CLASS(QIODevice) + +class ComplexTypeEntry; +class ContainerTypeEntry; +class FlagsTypeEntry; +class FunctionTypeEntry; +class NamespaceTypeEntry; +class ObjectTypeEntry; +class TemplateEntry; +class TypeEntry; + +struct TypeRejection; + +QT_FORWARD_DECLARE_CLASS(QDebug) + +void setTypeRevision(TypeEntry* typeEntry, int revision); +int getTypeRevision(const TypeEntry* typeEntry); +int getTypeIndex(const TypeEntry* typeEntry); +int getMaxTypeIndex(); + +class ContainerTypeEntry; +class PrimitiveTypeEntry; +class TypeDatabase +{ + TypeDatabase(); + Q_DISABLE_COPY(TypeDatabase) +public: + ~TypeDatabase(); + + /** + * Return the type system instance. + * \param newInstance This parameter is useful just for unit testing, because singletons causes + * too many side effects on unit testing. + */ + static TypeDatabase* instance(bool newInstance = false); + + static QString normalizedSignature(const QString &signature); + + QStringList requiredTargetImports() const; + + void addRequiredTargetImport(const QString& moduleName); + + void addTypesystemPath(const QString& typesystem_paths); + + IncludeList extraIncludes(const QString& className) const; + + PrimitiveTypeEntry* findPrimitiveType(const QString& name) const; + ComplexTypeEntry* findComplexType(const QString& name) const; + ObjectTypeEntry* findObjectType(const QString& name) const; + NamespaceTypeEntry* findNamespaceType(const QString& name) const; + ContainerTypeEntry* findContainerType(const QString& name) const; + FunctionTypeEntry* findFunctionType(const QString& name) const; + + TypeEntry* findType(const QString& name) const; + + TypeEntryHash allEntries() const { return m_entries; } + + SingleTypeEntryHash entries() const; + + PrimitiveTypeEntryList primitiveTypes() const; + + ContainerTypeEntryList containerTypes() const; + + void addRejection(const TypeRejection &); + bool isClassRejected(const QString& className, QString *reason = nullptr) const; + bool isFunctionRejected(const QString& className, const QString& functionName, + QString *reason = nullptr) const; + bool isFieldRejected(const QString& className, const QString& fieldName, + QString *reason = nullptr) const; + bool isEnumRejected(const QString& className, const QString& enumName, + QString *reason = nullptr) const; + bool isArgumentTypeRejected(const QString& className, const QString& typeName, + QString *reason = nullptr) const; + bool isReturnTypeRejected(const QString& className, const QString& typeName, + QString *reason = nullptr) const; + + void addType(TypeEntry* e); + + FlagsTypeEntry* findFlagsType(const QString& name) const; + void addFlagsType(FlagsTypeEntry* fte); + + TemplateEntry *findTemplate(const QString& name) const { return m_templates[name]; } + + void addTemplate(TemplateEntry* t); + + AddedFunctionList globalUserFunctions() const { return m_globalUserFunctions; } + + void addGlobalUserFunctions(const AddedFunctionList &functions); + + AddedFunctionList findGlobalUserFunctions(const QString& name) const; + + void addGlobalUserFunctionModifications(const FunctionModificationList &functionModifications); + + FunctionModificationList functionModifications(const QString& signature) const; + + void setSuppressWarnings(bool on) { m_suppressWarnings = on; } + + void addSuppressedWarning(const QString &s); + + bool isSuppressedWarning(const QString& s) const; + + static QString globalNamespaceClassName(const TypeEntry *te); + + bool parseFile(const QString &filename, bool generate = true); + bool parseFile(QIODevice* device, bool generate = true); + + bool setApiVersion(const QString& package, const QString& version); + + bool checkApiVersion(const QString& package, const QString &version) const; + + bool hasDroppedTypeEntries() const { return !m_dropTypeEntries.isEmpty(); } + + bool shouldDropTypeEntry(const QString& fullTypeName) const; + + void setDropTypeEntries(QStringList dropTypeEntries); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &d) const; +#endif +private: + TypeEntryList findTypes(const QString &name) const; + QString modifiedTypesystemFilepath(const QString &tsFile) const; + + bool m_suppressWarnings; + TypeEntryHash m_entries; + SingleTypeEntryHash m_flagsEntries; + TemplateEntryHash m_templates; + QStringList m_suppressedWarnings; + + AddedFunctionList m_globalUserFunctions; + FunctionModificationList m_functionMods; + + QStringList m_requiredTargetImports; + + QStringList m_typesystemPaths; + QHash m_parsedTypesystemFiles; + + QVector m_rejections; + + QStringList m_dropTypeEntries; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeEntry *te); +QDebug operator<<(QDebug d, const TypeDatabase &db); +#endif +#endif // TYPEDATABASE_H diff --git a/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h new file mode 100644 index 000000000..95859a399 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typedatabase_typedefs.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPEDATABASE_TYPEDEFS_H +#define TYPEDATABASE_TYPEDEFS_H + +#include +#include +#include + +class ContainerTypeEntry; +class PrimitiveTypeEntry; +class TemplateEntry; +class TypeEntry; + +typedef QVector TypeEntryList; +typedef QHash TypeEntryHash; +typedef QHash SingleTypeEntryHash; +typedef QHash TemplateEntryHash; + +typedef QVector ContainerTypeEntryList; +typedef QVector PrimitiveTypeEntryList; + +#endif // TYPEDATABASE_TYPEDEFS_H diff --git a/sources/shiboken2/ApiExtractor/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp new file mode 100644 index 000000000..8165bfe44 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typeparser.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "typeparser.h" + +#include +#include +#include + +class Scanner +{ +public: + enum Token { + StarToken, + AmpersandToken, + LessThanToken, + ColonToken, + CommaToken, + OpenParenToken, + CloseParenToken, + SquareBegin, + SquareEnd, + GreaterThanToken, + + ConstToken, + Identifier, + NoToken, + InvalidToken + }; + + Scanner(const QString &s) + : m_pos(0), m_length(s.length()), m_chars(s.constData()) + { + } + + Token nextToken(QString *errorMessage = Q_NULLPTR); + QString identifier() const; + + QString msgParseError(const QString &why) const; + +private: + int m_pos; + int m_length; + int m_tokenStart; + const QChar *m_chars; +}; + +QString Scanner::identifier() const +{ + return QString(m_chars + m_tokenStart, m_pos - m_tokenStart); +} + +Scanner::Token Scanner::nextToken(QString *errorMessage) +{ + Token tok = NoToken; + + // remove whitespace + while (m_pos < m_length && m_chars[m_pos] == QLatin1Char(' ')) + ++m_pos; + + m_tokenStart = m_pos; + + while (m_pos < m_length) { + + const QChar &c = m_chars[m_pos]; + + if (tok == NoToken) { + switch (c.toLatin1()) { + case '*': tok = StarToken; break; + case '&': tok = AmpersandToken; break; + case '<': tok = LessThanToken; break; + case '>': tok = GreaterThanToken; break; + case ',': tok = CommaToken; break; + case '(': tok = OpenParenToken; break; + case ')': tok = CloseParenToken; break; + case '[': tok = SquareBegin; break; + case ']' : tok = SquareEnd; break; + case ':': + tok = ColonToken; + Q_ASSERT(m_pos + 1 < m_length); + ++m_pos; + break; + default: + if (c.isLetterOrNumber() || c == QLatin1Char('_')) { + tok = Identifier; + } else { + QString message; + QTextStream (&message) << ": Unrecognized character in lexer at " + << m_pos << " : '" << c << '\''; + message = msgParseError(message); + if (errorMessage) + *errorMessage = message; + else + qWarning().noquote().nospace() << message; + return InvalidToken; + } + break; + } + } + + if (tok <= GreaterThanToken) { + ++m_pos; + break; + } + + if (tok == Identifier) { + if (c.isLetterOrNumber() || c == QLatin1Char('_')) + ++m_pos; + else + break; + } + } + + if (tok == Identifier && m_pos - m_tokenStart == 5) { + if (m_chars[m_tokenStart] == QLatin1Char('c') + && m_chars[m_tokenStart + 1] == QLatin1Char('o') + && m_chars[m_tokenStart + 2] == QLatin1Char('n') + && m_chars[m_tokenStart + 3] == QLatin1Char('s') + && m_chars[m_tokenStart + 4] == QLatin1Char('t')) + tok = ConstToken; + } + + return tok; + +} + +QString Scanner::msgParseError(const QString &why) const +{ + return QStringLiteral("TypeParser: Unable to parse \"") + + QString(m_chars, m_length) + QStringLiteral("\": ") + why; +} + +static TypeParser::Info invalidInfo() +{ + TypeParser::Info result; + result.is_busted = true; + return result; +} + +TypeParser::Info TypeParser::parse(const QString &str, QString *errorMessage) +{ + Scanner scanner(str); + + Info info; + QStack stack; + stack.push(&info); + + bool colon_prefix = false; + bool in_array = false; + QString array; + + Scanner::Token tok = scanner.nextToken(errorMessage); + while (tok != Scanner::NoToken) { + if (tok == Scanner::InvalidToken) + return invalidInfo(); + +// switch (tok) { +// case Scanner::StarToken: printf(" - *\n"); break; +// case Scanner::AmpersandToken: printf(" - &\n"); break; +// case Scanner::LessThanToken: printf(" - <\n"); break; +// case Scanner::GreaterThanToken: printf(" - >\n"); break; +// case Scanner::ColonToken: printf(" - ::\n"); break; +// case Scanner::CommaToken: printf(" - ,\n"); break; +// case Scanner::ConstToken: printf(" - const\n"); break; +// case Scanner::SquareBegin: printf(" - [\n"); break; +// case Scanner::SquareEnd: printf(" - ]\n"); break; +// case Scanner::Identifier: printf(" - '%s'\n", qPrintable(scanner.identifier())); break; +// default: +// break; +// } + + switch (tok) { + + case Scanner::StarToken: + ++stack.top()->indirections; + break; + + case Scanner::AmpersandToken: + switch (stack.top()->referenceType) { + case NoReference: + stack.top()->referenceType = LValueReference; + break; + case LValueReference: + stack.top()->referenceType = RValueReference; + break; + case RValueReference: + const QString message = scanner.msgParseError(QStringLiteral("Too many '&' qualifiers")); + if (errorMessage) + *errorMessage = message; + else + qWarning().noquote().nospace() << message; + return invalidInfo(); + } + break; + case Scanner::LessThanToken: + stack.top()->template_instantiations << Info(); + stack.push(&stack.top()->template_instantiations.last()); + break; + + case Scanner::CommaToken: + stack.pop(); + stack.top()->template_instantiations << Info(); + stack.push(&stack.top()->template_instantiations.last()); + break; + + case Scanner::GreaterThanToken: + stack.pop(); + break; + + case Scanner::ColonToken: + colon_prefix = true; + break; + + case Scanner::ConstToken: + stack.top()->is_constant = true; + break; + + case Scanner::OpenParenToken: // function pointers not supported + case Scanner::CloseParenToken: { + const QString message = scanner.msgParseError(QStringLiteral("Function pointers are not supported")); + if (errorMessage) + *errorMessage = message; + else + qWarning().noquote().nospace() << message; + return invalidInfo(); + } + + case Scanner::Identifier: + if (in_array) { + array = scanner.identifier(); + } else if (colon_prefix || stack.top()->qualified_name.isEmpty()) { + stack.top()->qualified_name << scanner.identifier(); + colon_prefix = false; + } else { + stack.top()->qualified_name.last().append(QLatin1Char(' ') + scanner.identifier()); + } + break; + + case Scanner::SquareBegin: + in_array = true; + break; + + case Scanner::SquareEnd: + in_array = false; + stack.top()->arrays += array; + break; + + + default: + break; + } + + tok = scanner.nextToken(); + } + + return info; +} + +QString TypeParser::Info::instantiationName() const +{ + QString s(qualified_name.join(QLatin1String("::"))); + if (!template_instantiations.isEmpty()) { + QStringList insts; + for (const Info &info : template_instantiations) + insts << info.toString(); + s += QLatin1String("< ") + insts.join(QLatin1String(", ")) + QLatin1String(" >"); + } + + return s; +} + +QString TypeParser::Info::toString() const +{ + QString s; + + if (is_constant) + s += QLatin1String("const "); + s += instantiationName(); + for (int i = 0; i < arrays.size(); ++i) + s += QLatin1Char('[') + arrays.at(i) + QLatin1Char(']'); + s += QString(indirections, QLatin1Char('*')); + switch (referenceType) { + case NoReference: + break; + case LValueReference: + s += QLatin1Char('&'); + break; + case RValueReference: + s += QLatin1String("&&"); + break; + } + return s; +} diff --git a/sources/shiboken2/ApiExtractor/typeparser.h b/sources/shiboken2/ApiExtractor/typeparser.h new file mode 100644 index 000000000..f42c42a5e --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typeparser.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPEPARSER_H +#define TYPEPARSER_H + +#include "parser/codemodel_enums.h" + +#include +#include +#include +#include + +class TypeParser +{ +public: + struct Info + { + Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { } + QStringList qualified_name; + QStringList arrays; + QVector template_instantiations; + ReferenceType referenceType; + uint is_constant : 1; + uint is_busted : 1; + uint indirections : 6; + + QString toString() const; + QString instantiationName() const; + }; + + static Info parse(const QString &str, QString *errorMessage = Q_NULLPTR); +}; + +#endif // TYPEPARSER_H diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp new file mode 100644 index 000000000..3ec82c56d --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -0,0 +1,2737 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "typesystem.h" +#include "typesystem_p.h" +#include "typedatabase.h" +#include "reporthandler.h" +#include +#include +#include +#include +#include + +static QString strings_Object = QLatin1String("Object"); +static QString strings_String = QLatin1String("String"); +static QString strings_char = QLatin1String("char"); +static QString strings_jchar = QLatin1String("jchar"); +static QString strings_jobject = QLatin1String("jobject"); + +static inline QString colonColon() { return QStringLiteral("::"); } +static inline QString quoteAfterLineAttribute() { return QStringLiteral("quote-after-line"); } +static inline QString quoteBeforeLineAttribute() { return QStringLiteral("quote-before-line"); } +static inline QString nameAttribute() { return QStringLiteral("name"); } +static inline QString sinceAttribute() { return QStringLiteral("since"); } +static inline QString flagsAttribute() { return QStringLiteral("flags"); } +static inline QString classAttribute() { return QStringLiteral("class"); } +static inline QString functionNameAttribute() { return QStringLiteral("function-name"); } +static inline QString fieldNameAttribute() { return QStringLiteral("field-name"); } +static inline QString enumNameAttribute() { return QStringLiteral("enum-name"); } +static inline QString argumentTypeAttribute() { return QStringLiteral("argument-type"); } +static inline QString returnTypeAttribute() { return QStringLiteral("return-type"); } + +static QVector customConversionsForReview; + +// Set a regular expression for rejection from text. By legacy, those are fixed +// strings, except for '*' meaning 'match all'. Enclosing in "^..$" +// indicates regular expression. +static bool setRejectionRegularExpression(const QString &patternIn, + QRegularExpression *re, + QString *errorMessage) +{ + QString pattern; + if (patternIn.startsWith(QLatin1Char('^')) && patternIn.endsWith(QLatin1Char('$'))) + pattern = patternIn; + else if (patternIn == QLatin1String("*")) + pattern = QStringLiteral("^.*$"); + else + pattern = QLatin1Char('^') + QRegularExpression::escape(patternIn) + QLatin1Char('$'); + re->setPattern(pattern); + if (!re->isValid()) { + *errorMessage = QLatin1String("Invalid pattern \"") + patternIn + + QLatin1String("\": ") + re->errorString(); + return false; + } + return true; +} + +static bool addRejection(TypeDatabase *database, const QHash &attributes, + QString *errorMessage) +{ + typedef QPair AttributeMatchTypePair; + + TypeRejection rejection; + + const QString className = attributes.value(classAttribute()); + if (!setRejectionRegularExpression(className, &rejection.className, errorMessage)) + return false; + + static const AttributeMatchTypePair attributeMatchTypeMapping[] = + {{functionNameAttribute(), TypeRejection::Function}, + {fieldNameAttribute(), TypeRejection::Field}, + {enumNameAttribute(), TypeRejection::Enum}, + {argumentTypeAttribute(), TypeRejection::ArgumentType}, + {returnTypeAttribute(), TypeRejection::ReturnType} + }; + + // Search for non-empty attribute (function, field, enum) + const auto aend = attributes.cend(); + for (const AttributeMatchTypePair &mapping : attributeMatchTypeMapping) { + const auto it = attributes.constFind(mapping.first); + if (it != aend && !it.value().isEmpty()) { + if (!setRejectionRegularExpression(it.value(), &rejection.pattern, errorMessage)) + return false; + rejection.matchType = mapping.second; + database->addRejection(rejection); + return true; + } + } + + // Special case: When all fields except class are empty, completely exclude class + if (className == QLatin1String("*")) { + *errorMessage = QLatin1String("bad reject entry, neither 'class', 'function-name'" + " nor 'field' specified"); + return false; + } + rejection.matchType = TypeRejection::ExcludeClass; + database->addRejection(rejection); + return true; +} + + +Handler::Handler(TypeDatabase* database, bool generate) + : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass) +{ + m_currentEnum = 0; + m_current = 0; + m_currentDroppedEntry = 0; + m_currentDroppedEntryDepth = 0; + m_ignoreDepth = 0; + + tagNames.insert(QLatin1String("rejection"), StackElement::Rejection); + tagNames.insert(QLatin1String("custom-type"), StackElement::CustomTypeEntry); + tagNames.insert(QLatin1String("primitive-type"), StackElement::PrimitiveTypeEntry); + tagNames.insert(QLatin1String("container-type"), StackElement::ContainerTypeEntry); + tagNames.insert(QLatin1String("object-type"), StackElement::ObjectTypeEntry); + tagNames.insert(QLatin1String("value-type"), StackElement::ValueTypeEntry); + tagNames.insert(QLatin1String("interface-type"), StackElement::InterfaceTypeEntry); + tagNames.insert(QLatin1String("namespace-type"), StackElement::NamespaceTypeEntry); + tagNames.insert(QLatin1String("enum-type"), StackElement::EnumTypeEntry); + tagNames.insert(QLatin1String("smart-pointer-type"), StackElement::SmartPointerTypeEntry); + tagNames.insert(QLatin1String("function"), StackElement::FunctionTypeEntry); + tagNames.insert(QLatin1String("extra-includes"), StackElement::ExtraIncludes); + tagNames.insert(QLatin1String("include"), StackElement::Include); + tagNames.insert(QLatin1String("inject-code"), StackElement::InjectCode); + tagNames.insert(QLatin1String("modify-function"), StackElement::ModifyFunction); + tagNames.insert(QLatin1String("modify-field"), StackElement::ModifyField); + tagNames.insert(QLatin1String("access"), StackElement::Access); + tagNames.insert(QLatin1String("remove"), StackElement::Removal); + tagNames.insert(QLatin1String("rename"), StackElement::Rename); + tagNames.insert(QLatin1String("typesystem"), StackElement::Root); + tagNames.insert(QLatin1String("custom-constructor"), StackElement::CustomMetaConstructor); + tagNames.insert(QLatin1String("custom-destructor"), StackElement::CustomMetaDestructor); + tagNames.insert(QLatin1String("argument-map"), StackElement::ArgumentMap); + tagNames.insert(QLatin1String("suppress-warning"), StackElement::SuppressedWarning); + tagNames.insert(QLatin1String("load-typesystem"), StackElement::LoadTypesystem); + tagNames.insert(QLatin1String("define-ownership"), StackElement::DefineOwnership); + tagNames.insert(QLatin1String("replace-default-expression"), StackElement::ReplaceDefaultExpression); + tagNames.insert(QLatin1String("reject-enum-value"), StackElement::RejectEnumValue); + tagNames.insert(QLatin1String("replace-type"), StackElement::ReplaceType); + tagNames.insert(QLatin1String("conversion-rule"), StackElement::ConversionRule); + tagNames.insert(QLatin1String("native-to-target"), StackElement::NativeToTarget); + tagNames.insert(QLatin1String("target-to-native"), StackElement::TargetToNative); + tagNames.insert(QLatin1String("add-conversion"), StackElement::AddConversion); + tagNames.insert(QLatin1String("modify-argument"), StackElement::ModifyArgument); + tagNames.insert(QLatin1String("remove-argument"), StackElement::RemoveArgument); + tagNames.insert(QLatin1String("remove-default-expression"), StackElement::RemoveDefaultExpression); + tagNames.insert(QLatin1String("template"), StackElement::Template); + tagNames.insert(QLatin1String("insert-template"), StackElement::TemplateInstanceEnum); + tagNames.insert(QLatin1String("replace"), StackElement::Replace); + tagNames.insert(QLatin1String("no-null-pointer"), StackElement::NoNullPointers); + tagNames.insert(QLatin1String("reference-count"), StackElement::ReferenceCount); + tagNames.insert(QLatin1String("parent"), StackElement::ParentOwner); + tagNames.insert(QLatin1String("inject-documentation"), StackElement::InjectDocumentation); + tagNames.insert(QLatin1String("modify-documentation"), StackElement::ModifyDocumentation); + tagNames.insert(QLatin1String("add-function"), StackElement::AddFunction); +} + +static QString msgReaderError(const QXmlStreamReader &reader, const QString &what) +{ + QString message; + QTextStream str(&message); + str << "Error: "; + if (const QFile *file = qobject_cast(reader.device())) + str << "file=" << QDir::toNativeSeparators(file->fileName()) << ", "; + str << "line=" << reader.lineNumber() << ", column=" << reader.columnNumber() + << ", message=" << what; + return message; +} + +static QString msgReaderError(const QXmlStreamReader &reader) +{ + return msgReaderError(reader, reader.errorString()); +} + +bool Handler::parse(QXmlStreamReader &reader) +{ + m_error.clear(); + while (!reader.atEnd()) { + switch (reader.readNext()) { + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + qCWarning(lcShiboken).noquote().nospace() << msgReaderError(reader); + return false; + case QXmlStreamReader::StartElement: + if (!startElement(reader.name(), reader.attributes())) { + m_error = msgReaderError(reader, m_error); + return false; + } + + break; + case QXmlStreamReader::EndElement: + if (!endElement(reader.name())) { + m_error = msgReaderError(reader, m_error); + return false; + } + break; + case QXmlStreamReader::Characters: + if (!characters(reader.text())) { + m_error = msgReaderError(reader, m_error); + return false; + } + break; + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::EndDocument: + case QXmlStreamReader::Comment: + case QXmlStreamReader::DTD: + case QXmlStreamReader::EntityReference: + case QXmlStreamReader::ProcessingInstruction: + break; + } + } + return true; +} + +void Handler::fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts, + QHash *acceptedAttributes) +{ + Q_ASSERT(acceptedAttributes); + + for (int i = 0; i < atts.length(); ++i) { + const QString key = atts.at(i).name().toString().toLower(); + if (!acceptedAttributes->contains(key)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Unknown attribute for '%1': '%2'").arg(name, key); + } else { + acceptedAttributes->insert(key, atts.at(i).value().toString()); + } + } +} + +bool Handler::endElement(const QStringRef &localName) +{ + if (m_ignoreDepth) { + --m_ignoreDepth; + return true; + } + + if (m_currentDroppedEntry) { + if (m_currentDroppedEntryDepth == 1) { + m_current = m_currentDroppedEntry->parent; + delete m_currentDroppedEntry; + m_currentDroppedEntry = 0; + m_currentDroppedEntryDepth = 0; + } else { + ++m_currentDroppedEntryDepth; + } + return true; + } + + if (!localName.compare(QLatin1String("import-file"), Qt::CaseInsensitive)) + return true; + + if (!m_current) + return true; + + switch (m_current->type) { + case StackElement::Root: + if (m_generate == TypeEntry::GenerateAll) { + TypeDatabase::instance()->addGlobalUserFunctions(m_contextStack.top()->addedFunctions); + TypeDatabase::instance()->addGlobalUserFunctionModifications(m_contextStack.top()->functionMods); + for (CustomConversion *customConversion : qAsConst(customConversionsForReview)) { + const CustomConversion::TargetToNativeConversions &toNatives = customConversion->targetToNativeConversions(); + for (CustomConversion::TargetToNativeConversion *toNative : toNatives) + toNative->setSourceType(m_database->findType(toNative->sourceTypeName())); + } + } + break; + case StackElement::ObjectTypeEntry: + case StackElement::ValueTypeEntry: + case StackElement::InterfaceTypeEntry: + case StackElement::NamespaceTypeEntry: { + ComplexTypeEntry *centry = static_cast(m_current->entry); + centry->setAddedFunctions(m_contextStack.top()->addedFunctions); + centry->setFunctionModifications(m_contextStack.top()->functionMods); + centry->setFieldModifications(m_contextStack.top()->fieldMods); + centry->setCodeSnips(m_contextStack.top()->codeSnips); + centry->setDocModification(m_contextStack.top()->docModifications); + + if (centry->designatedInterface()) { + centry->designatedInterface()->setCodeSnips(m_contextStack.top()->codeSnips); + centry->designatedInterface()->setFunctionModifications(m_contextStack.top()->functionMods); + } + } + break; + case StackElement::NativeToTarget: + case StackElement::AddConversion: { + CustomConversion* customConversion = static_cast(m_current->entry)->customConversion(); + if (!customConversion) { + m_error = QLatin1String("CustomConversion object is missing."); + return false; + } + + QString code = m_contextStack.top()->codeSnips.takeLast().code(); + if (m_current->type == StackElement::AddConversion) { + if (customConversion->targetToNativeConversions().isEmpty()) { + m_error = QLatin1String("CustomConversion's target to native conversions missing."); + return false; + } + customConversion->targetToNativeConversions().last()->setConversion(code); + } else { + customConversion->setNativeToTargetConversion(code); + } + } + break; + case StackElement::CustomMetaConstructor: { + m_current->entry->setCustomConstructor(*m_current->value.customFunction); + delete m_current->value.customFunction; + } + break; + case StackElement::CustomMetaDestructor: { + m_current->entry->setCustomDestructor(*m_current->value.customFunction); + delete m_current->value.customFunction; + } + break; + case StackElement::EnumTypeEntry: + m_current->entry->setDocModification(m_contextStack.top()->docModifications); + m_contextStack.top()->docModifications = DocModificationList(); + m_currentEnum = 0; + break; + case StackElement::Template: + m_database->addTemplate(m_current->value.templateEntry); + break; + case StackElement::TemplateInstanceEnum: + switch (m_current->parent->type) { + case StackElement::InjectCode: + if (m_current->parent->parent->type == StackElement::Root) { + CodeSnipList snips = m_current->parent->entry->codeSnips(); + CodeSnip snip = snips.takeLast(); + snip.addTemplateInstance(m_current->value.templateInstance); + snips.append(snip); + m_current->parent->entry->setCodeSnips(snips); + break; + } + case StackElement::NativeToTarget: + case StackElement::AddConversion: + m_contextStack.top()->codeSnips.last().addTemplateInstance(m_current->value.templateInstance); + break; + case StackElement::Template: + m_current->parent->value.templateEntry->addTemplateInstance(m_current->value.templateInstance); + break; + case StackElement::CustomMetaConstructor: + case StackElement::CustomMetaDestructor: + m_current->parent->value.customFunction->addTemplateInstance(m_current->value.templateInstance); + break; + case StackElement::ConversionRule: + m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.last().addTemplateInstance(m_current->value.templateInstance); + break; + case StackElement::InjectCodeInFunction: + m_contextStack.top()->functionMods.last().snips.last().addTemplateInstance(m_current->value.templateInstance); + break; + default: + break; // nada + }; + break; + default: + break; + } + + if (m_current->type == StackElement::Root + || m_current->type == StackElement::NamespaceTypeEntry + || m_current->type == StackElement::InterfaceTypeEntry + || m_current->type == StackElement::ObjectTypeEntry + || m_current->type == StackElement::ValueTypeEntry + || m_current->type == StackElement::PrimitiveTypeEntry) { + StackElementContext* context = m_contextStack.pop(); + delete context; + } + + StackElement *child = m_current; + m_current = m_current->parent; + delete(child); + + return true; +} + +template // QString/QStringRef +bool Handler::characters(const String &ch) +{ + if (m_currentDroppedEntry || m_ignoreDepth) + return true; + + if (m_current->type == StackElement::Template) { + m_current->value.templateEntry->addCode(ch); + return true; + } + + if (m_current->type == StackElement::CustomMetaConstructor || m_current->type == StackElement::CustomMetaDestructor) { + m_current->value.customFunction->addCode(ch); + return true; + } + + if (m_current->type == StackElement::ConversionRule + && m_current->parent->type == StackElement::ModifyArgument) { + m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.last().addCode(ch); + return true; + } + + if (m_current->type == StackElement::NativeToTarget || m_current->type == StackElement::AddConversion) { + m_contextStack.top()->codeSnips.last().addCode(ch); + return true; + } + + if (m_current->parent) { + if ((m_current->type & StackElement::CodeSnipMask)) { + CodeSnipList snips; + switch (m_current->parent->type) { + case StackElement::Root: + snips = m_current->parent->entry->codeSnips(); + snips.last().addCode(ch); + m_current->parent->entry->setCodeSnips(snips); + break; + case StackElement::ModifyFunction: + case StackElement::AddFunction: + m_contextStack.top()->functionMods.last().snips.last().addCode(ch); + m_contextStack.top()->functionMods.last().modifiers |= FunctionModification::CodeInjection; + break; + case StackElement::NamespaceTypeEntry: + case StackElement::ObjectTypeEntry: + case StackElement::ValueTypeEntry: + case StackElement::InterfaceTypeEntry: + m_contextStack.top()->codeSnips.last().addCode(ch); + break; + default: + Q_ASSERT(false); + }; + return true; + } + } + + if (m_current->type & StackElement::DocumentationMask) + m_contextStack.top()->docModifications.last().setCode(ch); + + return true; +} + +bool Handler::importFileElement(const QXmlStreamAttributes &atts) +{ + const QString fileName = atts.value(nameAttribute()).toString(); + if (fileName.isEmpty()) { + m_error = QLatin1String("Required attribute 'name' missing for include-file tag."); + return false; + } + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + file.setFileName(QLatin1String(":/trolltech/generator/") + fileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + m_error = QString::fromLatin1("Could not open file: '%1'").arg(QDir::toNativeSeparators(fileName)); + return false; + } + } + + const QStringRef quoteFrom = atts.value(quoteAfterLineAttribute()); + bool foundFromOk = quoteFrom.isEmpty(); + bool from = quoteFrom.isEmpty(); + + const QStringRef quoteTo = atts.value(quoteBeforeLineAttribute()); + bool foundToOk = quoteTo.isEmpty(); + bool to = true; + + QTextStream in(&file); + while (!in.atEnd()) { + QString line = in.readLine(); + if (from && to && line.contains(quoteTo)) { + to = false; + foundToOk = true; + break; + } + if (from && to) + characters(line + QLatin1Char('\n')); + if (!from && line.contains(quoteFrom)) { + from = true; + foundFromOk = true; + } + } + 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); + + if (!foundToOk) + m_error = toError; + if (!foundFromOk) + m_error = fromError; + if (!foundFromOk && !foundToOk) + m_error = fromError + QLatin1Char(' ') + toError; + return false; + } + + return true; +} + +bool Handler::convertBoolean(const QString &_value, const QString &attributeName, bool defaultValue) +{ + QString value = _value.toLower(); + if (value == QLatin1String("true") || value == QLatin1String("yes")) + return true; + else if (value == QLatin1String("false") || value == QLatin1String("no")) + return false; + else { + QString warn = QStringLiteral("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") + .arg(value, attributeName, + defaultValue ? QLatin1String("yes") : QLatin1String("no")); + + qCWarning(lcShiboken).noquote().nospace() << warn; + return defaultValue; + } +} + +static bool convertRemovalAttribute(const QString& removalAttribute, Modification& mod, QString& errorMsg) +{ + QString remove = removalAttribute.toLower(); + if (!remove.isEmpty()) { + if (remove == QLatin1String("all")) { + mod.removal = TypeSystem::All; + } else if (remove == QLatin1String("target")) { + mod.removal = TypeSystem::TargetLangAndNativeCode; + } else { + errorMsg = QString::fromLatin1("Bad removal type '%1'").arg(remove); + return false; + } + } + return true; +} + +static void getNamePrefixRecursive(StackElement* element, QStringList& names) +{ + if (!element->parent || !element->parent->entry) + return; + getNamePrefixRecursive(element->parent, names); + names << element->parent->entry->name(); +} + +static QString getNamePrefix(StackElement* element) +{ + QStringList names; + getNamePrefixRecursive(element, names); + return names.join(QLatin1Char('.')); +} + +// Returns empty string if there's no error. +static QString checkSignatureError(const QString& signature, const QString& tag) +{ + QString funcName = signature.left(signature.indexOf(QLatin1Char('('))).trimmed(); + static const QRegularExpression whiteSpace(QStringLiteral("\\s")); + Q_ASSERT(whiteSpace.isValid()); + if (!funcName.startsWith(QLatin1String("operator ")) && funcName.contains(whiteSpace)) { + return QString::fromLatin1("Error in <%1> tag signature attribute '%2'.\n" + "White spaces aren't allowed in function names, " + "and return types should not be part of the signature.") + .arg(tag, signature); + } + return QString(); +} + +void Handler::addFlags(const QString &name, QString flagName, + const QHash &attributes, double since) +{ + FlagsTypeEntry *ftype = new FlagsTypeEntry(QLatin1String("QFlags<") + name + QLatin1Char('>'), since); + ftype->setOriginator(m_currentEnum); + // Try to get the guess the qualified flag name + const int lastSepPos = name.lastIndexOf(colonColon()); + if (lastSepPos >= 0 && !flagName.contains(colonColon())) + flagName.prepend(name.left(lastSepPos + 2)); + + ftype->setOriginalName(flagName); + ftype->setCodeGeneration(m_generate); + QString n = ftype->originalName(); + + QStringList lst = n.split(colonColon()); + if (QStringList(lst.mid(0, lst.size() - 1)).join(colonColon()) != m_currentEnum->targetLangQualifier()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("enum %1 and flags %2 differ in qualifiers") + // avoid constFirst to stay Qt 5.5 compatible + .arg(m_currentEnum->targetLangQualifier(), lst.first()); + } + + ftype->setFlagsName(lst.last()); + m_currentEnum->setFlags(ftype); + + m_database->addFlagsType(ftype); + m_database->addType(ftype); + + QString revision = attributes.value(QLatin1String("flags-revision")); + if (revision.isEmpty()) + revision = attributes.value(QLatin1String("revision")); + setTypeRevision(ftype, revision.toInt()); +} + +bool Handler::handleSmartPointerEntry(StackElement *element, + QHash &attributes, + const QString &name, + double since) +{ + QString smartPointerType = attributes[QLatin1String("type")]; + if (smartPointerType.isEmpty()) { + m_error = QLatin1String("No type specified for the smart pointer. Currently supported types: 'shared',"); + return false; + } + if (smartPointerType != QLatin1String("shared")) { + m_error = QLatin1String("Currently only the 'shared' type is supported."); + return false; + } + + QString getter = attributes[QLatin1String("getter")]; + if (getter.isEmpty()) { + m_error = QLatin1String("No function getter name specified for getting the raw pointer held by the smart pointer."); + return false; + } + + QString refCountMethodName = attributes[QLatin1String("ref-count-method")]; + QString signature = getter + QLatin1String("()"); + + signature = TypeDatabase::normalizedSignature(signature); + if (signature.isEmpty()) { + m_error = QLatin1String("No signature for the smart pointer getter found."); + return false; + } + + QString errorString = checkSignatureError(signature, + QLatin1String("smart-pointer-type")); + if (!errorString.isEmpty()) { + m_error = errorString; + return false; + } + + SmartPointerTypeEntry *type = new SmartPointerTypeEntry(name, + getter, + smartPointerType, + refCountMethodName, + since); + type->setTargetLangPackage(m_defaultPackage); + type->setCodeGeneration(m_generate); + element->entry = type; + return true; +} + +bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts) +{ + if (m_ignoreDepth) { + ++m_ignoreDepth; + return true; + } + + if (!m_defaultPackage.isEmpty() && atts.hasAttribute(sinceAttribute())) { + TypeDatabase* td = TypeDatabase::instance(); + if (!td->checkApiVersion(m_defaultPackage, atts.value(sinceAttribute()).toString())) { + ++m_ignoreDepth; + return true; + } + } + + const QString tagName = n.toString().toLower(); + if (tagName == QLatin1String("import-file")) + return importFileElement(atts); + + const QHash::const_iterator tit = tagNames.constFind(tagName); + if (tit == tagNames.constEnd()) { + m_error = QStringLiteral("Unknown tag name: '%1'").arg(tagName); + return false; + } + + if (m_currentDroppedEntry) { + ++m_currentDroppedEntryDepth; + return true; + } + + StackElement* element = new StackElement(m_current); + element->type = tit.value(); + + if (element->type == StackElement::Root && m_generate == TypeEntry::GenerateAll) + customConversionsForReview.clear(); + + if (element->type == StackElement::Root + || element->type == StackElement::NamespaceTypeEntry + || element->type == StackElement::InterfaceTypeEntry + || element->type == StackElement::ObjectTypeEntry + || element->type == StackElement::ValueTypeEntry + || element->type == StackElement::PrimitiveTypeEntry) { + m_contextStack.push(new StackElementContext()); + } + + if (element->type & StackElement::TypeEntryMask) { + QHash attributes; + attributes.insert(nameAttribute(), QString()); + attributes.insert(QLatin1String("revision"), QLatin1String("0")); + attributes.insert(sinceAttribute(), QLatin1String("0")); + + switch (element->type) { + case StackElement::PrimitiveTypeEntry: + attributes.insert(QLatin1String("target-lang-name"), QString()); + attributes.insert(QLatin1String("target-lang-api-name"), QString()); + attributes.insert(QLatin1String("preferred-conversion"), QLatin1String("yes")); + attributes.insert(QLatin1String("preferred-target-lang-type"), QLatin1String("yes")); + attributes.insert(QLatin1String("default-constructor"), QString()); + break; + case StackElement::ContainerTypeEntry: + attributes.insert(QLatin1String("type"), QString()); + break; + case StackElement::SmartPointerTypeEntry: + attributes.insert(QLatin1String("type"), QString()); + attributes.insert(QLatin1String("getter"), QString()); + attributes.insert(QLatin1String("ref-count-method"), QString()); + break; + case StackElement::EnumTypeEntry: + attributes.insert(flagsAttribute(), QString()); + attributes.insert(QLatin1String("flags-revision"), QString()); + attributes.insert(QLatin1String("upper-bound"), QString()); + attributes.insert(QLatin1String("lower-bound"), QString()); + attributes.insert(QLatin1String("force-integer"), QLatin1String("no")); + attributes.insert(QLatin1String("extensible"), QLatin1String("no")); + attributes.insert(QLatin1String("identified-by-value"), QString()); + break; + case StackElement::ValueTypeEntry: + attributes.insert(QLatin1String("default-constructor"), QString()); + // fall throooough + case StackElement::ObjectTypeEntry: + attributes.insert(QLatin1String("force-abstract"), QLatin1String("no")); + attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); + attributes.insert(QLatin1String("hash-function"), QString()); + attributes.insert(QLatin1String("stream"), QLatin1String("no")); + // fall throooough + case StackElement::InterfaceTypeEntry: + attributes[QLatin1String("default-superclass")] = m_defaultSuperclass; + attributes.insert(QLatin1String("polymorphic-id-expression"), QString()); + attributes.insert(QLatin1String("delete-in-main-thread"), QLatin1String("no")); + attributes.insert(QLatin1String("held-type"), QString()); + attributes.insert(QLatin1String("copyable"), QString()); + // fall through + case StackElement::NamespaceTypeEntry: + attributes.insert(QLatin1String("target-lang-name"), QString()); + attributes[QLatin1String("package")] = m_defaultPackage; + attributes.insert(QLatin1String("expense-cost"), QLatin1String("1")); + attributes.insert(QLatin1String("expense-limit"), QLatin1String("none")); + attributes.insert(QLatin1String("polymorphic-base"), QLatin1String("no")); + attributes.insert(QLatin1String("generate"), QLatin1String("yes")); + attributes.insert(QLatin1String("target-type"), QString()); + attributes.insert(QLatin1String("generic-class"), QLatin1String("no")); + break; + case StackElement::FunctionTypeEntry: + attributes.insert(QLatin1String("signature"), QString()); + attributes.insert(QLatin1String("rename"), QString()); + break; + default: + { } // nada + }; + + fetchAttributeValues(tagName, atts, &attributes); + QString name = attributes[nameAttribute()]; + double since = attributes[sinceAttribute()].toDouble(); + + if (m_database->hasDroppedTypeEntries()) { + QString identifier = getNamePrefix(element) + QLatin1Char('.'); + identifier += (element->type == StackElement::FunctionTypeEntry ? attributes[QLatin1String("signature")] : name); + if (m_database->shouldDropTypeEntry(identifier)) { + m_currentDroppedEntry = element; + m_currentDroppedEntryDepth = 1; + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) { + qCDebug(lcShiboken) + << QStringLiteral("Type system entry '%1' was intentionally dropped from generation.").arg(identifier); + } + return true; + } + } + + // The top level tag 'function' has only the 'signature' tag + // and we should extract the 'name' value from it. + if (element->type == StackElement::FunctionTypeEntry) { + QString signature = attributes[QLatin1String("signature")]; + name = signature.left(signature.indexOf(QLatin1Char('('))).trimmed(); + QString errorString = checkSignatureError(signature, QLatin1String("function")); + if (!errorString.isEmpty()) { + m_error = errorString; + return false; + } + QString rename = attributes[QLatin1String("rename")]; + if (!rename.isEmpty()) { + static const QRegularExpression functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$")); + Q_ASSERT(functionNameRegExp.isValid()); + if (!functionNameRegExp.match(rename).hasMatch()) { + m_error = QLatin1String("can not rename '") + signature + QLatin1String("', '") + + rename + QLatin1String("' is not a valid function name"); + return false; + } + FunctionModification mod(since); + mod.signature = signature; + mod.renamedToName = attributes[QLatin1String("rename")]; + mod.modifiers |= Modification::Rename; + m_contextStack.top()->functionMods << mod; + } + } + + // We need to be able to have duplicate primitive type entries, + // or it's not possible to cover all primitive target language + // types (which we need to do in order to support fake meta objects) + if (element->type != StackElement::PrimitiveTypeEntry + && element->type != StackElement::FunctionTypeEntry) { + TypeEntry *tmp = m_database->findType(name); + if (tmp) + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Duplicate type entry: '%1'").arg(name); + } + + if (element->type == StackElement::EnumTypeEntry) { + if (name.isEmpty()) { + name = attributes[QLatin1String("identified-by-value")]; + } else if (!attributes[QLatin1String("identified-by-value")].isEmpty()) { + m_error = QLatin1String("can't specify both 'name' and 'identified-by-value' attributes"); + return false; + } + } + + // Fix type entry name using nesting information. + if (element->type & StackElement::TypeEntryMask + && element->parent && element->parent->type != StackElement::Root) { + name = element->parent->entry->name() + colonColon() + name; + } + + + if (name.isEmpty()) { + m_error = QLatin1String("no 'name' attribute specified"); + return false; + } + + switch (element->type) { + case StackElement::CustomTypeEntry: + element->entry = new TypeEntry(name, TypeEntry::CustomType, since); + break; + case StackElement::PrimitiveTypeEntry: { + QString targetLangName = attributes[QLatin1String("target-lang-name")]; + QString targetLangApiName = attributes[QLatin1String("target-lang-api-name")]; + QString preferredConversion = attributes[QLatin1String("preferred-conversion")].toLower(); + QString preferredTargetLangType = attributes[QLatin1String("preferred-target-lang-type")].toLower(); + QString defaultConstructor = attributes[QLatin1String("default-constructor")]; + + if (targetLangName.isEmpty()) + targetLangName = name; + if (targetLangApiName.isEmpty()) + targetLangApiName = name; + + PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name, since); + type->setCodeGeneration(m_generate); + type->setTargetLangName(targetLangName); + type->setTargetLangApiName(targetLangApiName); + type->setTargetLangPackage(m_defaultPackage); + type->setDefaultConstructor(defaultConstructor); + + bool preferred; + preferred = convertBoolean(preferredConversion, QLatin1String("preferred-conversion"), true); + type->setPreferredConversion(preferred); + preferred = convertBoolean(preferredTargetLangType, + QLatin1String("preferred-target-lang-type"), true); + type->setPreferredTargetLangType(preferred); + + element->entry = type; + } + break; + + case StackElement::ContainerTypeEntry: { + QString typeName = attributes[QLatin1String("type")]; + ContainerTypeEntry::Type containerType = + ContainerTypeEntry::containerTypeFromString(typeName); + if (typeName.isEmpty()) { + m_error = QLatin1String("no 'type' attribute specified"); + return false; + } else if (containerType == ContainerTypeEntry::NoContainer) { + m_error = QLatin1String("there is no container of type ") + typeName; + return false; + } + + ContainerTypeEntry *type = new ContainerTypeEntry(name, containerType, since); + type->setCodeGeneration(m_generate); + element->entry = type; + } + break; + + case StackElement::SmartPointerTypeEntry: { + bool result = handleSmartPointerEntry(element, attributes, name, since); + if (!result) + return result; + } + break; + + case StackElement::EnumTypeEntry: { + QStringList names = name.split(colonColon()); + if (names.size() == 1) + m_currentEnum = new EnumTypeEntry(QString(), name, since); + else + m_currentEnum = + new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join(colonColon()), + names.last(), since); + m_currentEnum->setAnonymous(!attributes[QLatin1String("identified-by-value")].isEmpty()); + element->entry = m_currentEnum; + m_currentEnum->setCodeGeneration(m_generate); + m_currentEnum->setTargetLangPackage(m_defaultPackage); + m_currentEnum->setUpperBound(attributes[QLatin1String("upper-bound")]); + m_currentEnum->setLowerBound(attributes[QLatin1String("lower-bound")]); + m_currentEnum->setForceInteger(convertBoolean(attributes[QLatin1String("force-integer")], QLatin1String("force-integer"), false)); + m_currentEnum->setExtensible(convertBoolean(attributes[QLatin1String("extensible")], QLatin1String("extensible"), false)); + + // put in the flags parallel... + const QString flagNames = attributes.value(flagsAttribute()); + if (!flagNames.isEmpty()) { + const QStringList &flagNameList = flagNames.split(QLatin1Char(',')); + for (const QString &flagName : flagNameList) + addFlags(name, flagName.trimmed(), attributes, since); + } + } + break; + + case StackElement::InterfaceTypeEntry: { + ObjectTypeEntry *otype = new ObjectTypeEntry(name, since); + QString targetLangName = attributes[QLatin1String("target-lang-name")]; + if (targetLangName.isEmpty()) + targetLangName = name; + InterfaceTypeEntry *itype = + new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(targetLangName), since); + + if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true)) + itype->setCodeGeneration(TypeEntry::GenerateForSubclass); + else + itype->setCodeGeneration(m_generate); + otype->setDesignatedInterface(itype); + itype->setOrigin(otype); + element->entry = otype; + } + // fall through + case StackElement::ValueTypeEntry: { + if (!element->entry) { + ValueTypeEntry* typeEntry = new ValueTypeEntry(name, since); + QString defaultConstructor = attributes[QLatin1String("default-constructor")]; + if (!defaultConstructor.isEmpty()) + typeEntry->setDefaultConstructor(defaultConstructor); + element->entry = typeEntry; + } + + // fall through + case StackElement::NamespaceTypeEntry: + if (!element->entry) + element->entry = new NamespaceTypeEntry(name, since); + + // fall through + case StackElement::ObjectTypeEntry: + if (!element->entry) + element->entry = new ObjectTypeEntry(name, since); + + element->entry->setStream(attributes[QLatin1String("stream")] == QLatin1String("yes")); + + ComplexTypeEntry *ctype = static_cast(element->entry); + ctype->setTargetLangPackage(attributes[QLatin1String("package")]); + ctype->setDefaultSuperclass(attributes[QLatin1String("default-superclass")]); + ctype->setGenericClass(convertBoolean(attributes[QLatin1String("generic-class")], QLatin1String("generic-class"), false)); + + if (!convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true)) + element->entry->setCodeGeneration(TypeEntry::GenerateForSubclass); + else + element->entry->setCodeGeneration(m_generate); + + QString targetLangName = attributes[QLatin1String("target-lang-name")]; + if (!targetLangName.isEmpty()) + ctype->setTargetLangName(targetLangName); + + // The expense policy + QString limit = attributes[QLatin1String("expense-limit")]; + if (!limit.isEmpty() && limit != QLatin1String("none")) { + ExpensePolicy ep; + ep.limit = limit.toInt(); + ep.cost = attributes[QLatin1String("expense-cost")]; + ctype->setExpensePolicy(ep); + } + + + ctype->setIsPolymorphicBase(convertBoolean(attributes[QLatin1String("polymorphic-base")], QLatin1String("polymorphic-base"), false)); + ctype->setPolymorphicIdValue(attributes[QLatin1String("polymorphic-id-expression")]); + //Copyable + if (attributes[QLatin1String("copyable")].isEmpty()) + ctype->setCopyable(ComplexTypeEntry::Unknown); + else { + if (convertBoolean(attributes[QLatin1String("copyable")], QLatin1String("copyable"), false)) + ctype->setCopyable(ComplexTypeEntry::CopyableSet); + else + ctype->setCopyable(ComplexTypeEntry::NonCopyableSet); + + } + + if (element->type == StackElement::ObjectTypeEntry || element->type == StackElement::ValueTypeEntry) + ctype->setHashFunction(attributes[QLatin1String("hash-function")]); + + + ctype->setHeldType(attributes[QLatin1String("held-type")]); + + if (element->type == StackElement::ObjectTypeEntry + || element->type == StackElement::ValueTypeEntry) { + if (convertBoolean(attributes[QLatin1String("force-abstract")], QLatin1String("force-abstract"), false)) + ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract); + if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false)) + ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); + } + + if (element->type == StackElement::InterfaceTypeEntry + || element->type == StackElement::ValueTypeEntry + || element->type == StackElement::ObjectTypeEntry) { + if (convertBoolean(attributes[QLatin1String("delete-in-main-thread")], QLatin1String("delete-in-main-thread"), false)) + ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread); + } + + QString targetType = attributes[QLatin1String("target-type")]; + if (!targetType.isEmpty() && element->entry->isComplex()) + static_cast(element->entry)->setTargetType(targetType); + + // ctype->setInclude(Include(Include::IncludePath, ctype->name())); + ctype = ctype->designatedInterface(); + if (ctype) + ctype->setTargetLangPackage(attributes[QLatin1String("package")]); + + } + break; + case StackElement::FunctionTypeEntry: { + QString signature = attributes[QLatin1String("signature")]; + signature = TypeDatabase::normalizedSignature(signature); + element->entry = m_database->findType(name); + if (element->entry) { + if (element->entry->type() == TypeEntry::FunctionType) { + reinterpret_cast(element->entry)->addSignature(signature); + } else { + 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); + return false; + } + } else { + element->entry = new FunctionTypeEntry(name, signature, since); + element->entry->setCodeGeneration(m_generate); + } + } + break; + default: + Q_ASSERT(false); + }; + + if (element->entry) { + m_database->addType(element->entry); + setTypeRevision(element->entry, attributes[QLatin1String("revision")].toInt()); + } else { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Type: %1 was rejected by typesystem").arg(name); + } + + } else if (element->type == StackElement::InjectDocumentation) { + // check the XML tag attributes + QHash attributes; + attributes.insert(QLatin1String("mode"), QLatin1String("replace")); + attributes.insert(QLatin1String("format"), QLatin1String("native")); + attributes.insert(sinceAttribute(), QLatin1String("0")); + + fetchAttributeValues(tagName, atts, &attributes); + double since = attributes[sinceAttribute()].toDouble(); + + const int validParent = StackElement::TypeEntryMask + | StackElement::ModifyFunction + | StackElement::ModifyField; + if (m_current->parent && m_current->parent->type & validParent) { + QString modeName = attributes[QLatin1String("mode")]; + TypeSystem::DocModificationMode mode; + if (modeName == QLatin1String("append")) { + mode = TypeSystem::DocModificationAppend; + } else if (modeName == QLatin1String("prepend")) { + mode = TypeSystem::DocModificationPrepend; + } else if (modeName == QLatin1String("replace")) { + mode = TypeSystem::DocModificationReplace; + } else { + m_error = QLatin1String("Unknow documentation injection mode: ") + modeName; + return false; + } + + static QHash languageNames; + if (languageNames.isEmpty()) { + languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; + languageNames[QLatin1String("native")] = TypeSystem::NativeCode; + } + + QString format = attributes[QLatin1String("format")].toLower(); + TypeSystem::Language lang = languageNames.value(format, TypeSystem::NoLanguage); + if (lang == TypeSystem::NoLanguage) { + m_error = QStringLiteral("unsupported class attribute: '%1'").arg(format); + return false; + } + + QString signature = m_current->type & StackElement::TypeEntryMask ? QString() : m_currentSignature; + DocModification mod(mode, signature, since); + mod.format = lang; + m_contextStack.top()->docModifications << mod; + } else { + m_error = QLatin1String("inject-documentation must be inside modify-function, " + "modify-field or other tags that creates a type"); + return false; + } + } else if (element->type == StackElement::ModifyDocumentation) { + // check the XML tag attributes + QHash attributes; + attributes.insert(QLatin1String("xpath"), QString()); + attributes.insert(sinceAttribute(), QLatin1String("0")); + fetchAttributeValues(tagName, atts, &attributes); + double since = attributes[sinceAttribute()].toDouble(); + + const int validParent = StackElement::TypeEntryMask + | StackElement::ModifyFunction + | StackElement::ModifyField; + if (m_current->parent && m_current->parent->type & validParent) { + QString signature = (m_current->type & StackElement::TypeEntryMask) ? QString() : m_currentSignature; + m_contextStack.top()->docModifications << DocModification(attributes[QLatin1String("xpath")], signature, since); + } else { + m_error = QLatin1String("modify-documentation must be inside modify-function, " + "modify-field or other tags that creates a type"); + return false; + } + } else if (element->type != StackElement::None) { + bool topLevel = element->type == StackElement::Root + || element->type == StackElement::SuppressedWarning + || element->type == StackElement::Rejection + || element->type == StackElement::LoadTypesystem + || element->type == StackElement::InjectCode + || element->type == StackElement::ExtraIncludes + || element->type == StackElement::ConversionRule + || element->type == StackElement::AddFunction + || element->type == StackElement::Template; + + if (!topLevel && m_current->type == StackElement::Root) { + m_error = QStringLiteral("Tag requires parent: '%1'").arg(tagName); + return false; + } + + StackElement topElement = !m_current ? StackElement(0) : *m_current; + element->entry = topElement.entry; + + QHash attributes; + attributes.insert(sinceAttribute(), QLatin1String("0")); + switch (element->type) { + case StackElement::Root: + attributes.insert(QLatin1String("package"), QString()); + attributes.insert(QLatin1String("default-superclass"), QString()); + break; + case StackElement::LoadTypesystem: + attributes.insert(nameAttribute(), QString()); + attributes.insert(QLatin1String("generate"), QLatin1String("yes")); + break; + case StackElement::NoNullPointers: + attributes.insert(QLatin1String("default-value"), QString()); + break; + case StackElement::SuppressedWarning: + attributes.insert(QLatin1String("text"), QString()); + break; + case StackElement::ReplaceDefaultExpression: + attributes.insert(QLatin1String("with"), QString()); + break; + case StackElement::DefineOwnership: + attributes.insert(QLatin1String("class"), QLatin1String("target")); + attributes.insert(QLatin1String("owner"), QString()); + break; + case StackElement::AddFunction: + attributes.insert(QLatin1String("signature"), QString()); + attributes.insert(QLatin1String("return-type"), QLatin1String("void")); + attributes.insert(QLatin1String("access"), QLatin1String("public")); + attributes.insert(QLatin1String("static"), QLatin1String("no")); + break; + case StackElement::ModifyFunction: + attributes.insert(QLatin1String("signature"), QString()); + attributes.insert(QLatin1String("access"), QString()); + attributes.insert(QLatin1String("remove"), QString()); + attributes.insert(QLatin1String("rename"), QString()); + attributes.insert(QLatin1String("deprecated"), QLatin1String("no")); + attributes.insert(QLatin1String("associated-to"), QString()); + attributes.insert(QLatin1String("virtual-slot"), QLatin1String("no")); + attributes.insert(QLatin1String("thread"), QLatin1String("no")); + attributes.insert(QLatin1String("allow-thread"), QLatin1String("no")); + break; + case StackElement::ModifyArgument: + attributes.insert(QLatin1String("index"), QString()); + attributes.insert(QLatin1String("replace-value"), QString()); + attributes.insert(QLatin1String("invalidate-after-use"), QLatin1String("no")); + break; + case StackElement::ModifyField: + attributes.insert(nameAttribute(), QString()); + attributes.insert(QLatin1String("write"), QLatin1String("true")); + attributes.insert(QLatin1String("read"), QLatin1String("true")); + attributes.insert(QLatin1String("remove"), QString()); + break; + case StackElement::Access: + attributes.insert(QLatin1String("modifier"), QString()); + break; + case StackElement::Include: + attributes.insert(QLatin1String("file-name"), QString()); + attributes.insert(QLatin1String("location"), QString()); + break; + case StackElement::CustomMetaConstructor: + attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_create"); + attributes.insert(QLatin1String("param-name"), QLatin1String("copy")); + break; + case StackElement::CustomMetaDestructor: + attributes[nameAttribute()] = topElement.entry->name().toLower() + QLatin1String("_delete"); + attributes.insert(QLatin1String("param-name"), QLatin1String("copy")); + break; + case StackElement::ReplaceType: + attributes.insert(QLatin1String("modified-type"), QString()); + break; + case StackElement::InjectCode: + attributes.insert(QLatin1String("class"), QLatin1String("target")); + attributes.insert(QLatin1String("position"), QLatin1String("beginning")); + attributes.insert(QLatin1String("file"), QString()); + break; + case StackElement::ConversionRule: + attributes.insert(QLatin1String("class"), QString()); + attributes.insert(QLatin1String("file"), QString()); + break; + case StackElement::TargetToNative: + attributes.insert(QLatin1String("replace"), QLatin1String("yes")); + break; + case StackElement::AddConversion: + attributes.insert(QLatin1String("type"), QString()); + attributes.insert(QLatin1String("check"), QString()); + break; + case StackElement::RejectEnumValue: + attributes.insert(nameAttribute(), QString()); + break; + case StackElement::ArgumentMap: + attributes.insert(QLatin1String("index"), QLatin1String("1")); + attributes.insert(QLatin1String("meta-name"), QString()); + break; + case StackElement::Rename: + attributes.insert(QLatin1String("to"), QString()); + break; + case StackElement::Rejection: + attributes.insert(classAttribute(), QString()); + attributes.insert(functionNameAttribute(), QString()); + attributes.insert(fieldNameAttribute(), QString()); + attributes.insert(enumNameAttribute(), QString()); + attributes.insert(argumentTypeAttribute(), QString()); + attributes.insert(returnTypeAttribute(), QString()); + break; + case StackElement::Removal: + attributes.insert(QLatin1String("class"), QLatin1String("all")); + break; + case StackElement::Template: + attributes.insert(nameAttribute(), QString()); + break; + case StackElement::TemplateInstanceEnum: + attributes.insert(nameAttribute(), QString()); + break; + case StackElement::Replace: + attributes.insert(QLatin1String("from"), QString()); + attributes.insert(QLatin1String("to"), QString()); + break; + case StackElement::ReferenceCount: + attributes.insert(QLatin1String("action"), QString()); + attributes.insert(QLatin1String("variable-name"), QString()); + break; + case StackElement::ParentOwner: + attributes.insert(QLatin1String("index"), QString()); + attributes.insert(QLatin1String("action"), QString()); + default: + { }; + }; + + double since = 0; + if (attributes.count() > 0) { + fetchAttributeValues(tagName, atts, &attributes); + since = attributes[sinceAttribute()].toDouble(); + } + + switch (element->type) { + case StackElement::Root: + m_defaultPackage = attributes[QLatin1String("package")]; + m_defaultSuperclass = attributes[QLatin1String("default-superclass")]; + element->type = StackElement::Root; + { + TypeSystemTypeEntry* moduleEntry = reinterpret_cast( + m_database->findType(m_defaultPackage)); + element->entry = moduleEntry ? moduleEntry : new TypeSystemTypeEntry(m_defaultPackage, since); + element->entry->setCodeGeneration(m_generate); + } + + if ((m_generate == TypeEntry::GenerateForSubclass || + m_generate == TypeEntry::GenerateNothing) && !m_defaultPackage.isEmpty()) + TypeDatabase::instance()->addRequiredTargetImport(m_defaultPackage); + + if (!element->entry->qualifiedCppName().isEmpty()) + m_database->addType(element->entry); + break; + case StackElement::LoadTypesystem: { + QString name = attributes[nameAttribute()]; + if (name.isEmpty()) { + m_error = QLatin1String("No typesystem name specified"); + return false; + } + bool generateChild = (convertBoolean(attributes[QLatin1String("generate")], QLatin1String("generate"), true) && (m_generate == TypeEntry::GenerateAll)); + if (!m_database->parseFile(name, generateChild)) { + m_error = QStringLiteral("Failed to parse: '%1'").arg(name); + return false; + } + } + break; + case StackElement::RejectEnumValue: { + if (!m_currentEnum) { + m_error = QLatin1String(" node must be used inside a node"); + return false; + } + QString name = attributes[nameAttribute()]; + } break; + case StackElement::ReplaceType: { + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("Type replacement can only be specified for argument modifications"); + return false; + } + + if (attributes[QLatin1String("modified-type")].isEmpty()) { + m_error = QLatin1String("Type replacement requires 'modified-type' attribute"); + return false; + } + + m_contextStack.top()->functionMods.last().argument_mods.last().modified_type = attributes[QLatin1String("modified-type")]; + } + break; + case StackElement::ConversionRule: { + if (topElement.type != StackElement::ModifyArgument + && topElement.type != StackElement::ValueTypeEntry + && topElement.type != StackElement::PrimitiveTypeEntry + && topElement.type != StackElement::ContainerTypeEntry) { + m_error = QLatin1String("Conversion rules can only be specified for argument modification, " + "value-type, primitive-type or container-type conversion."); + return false; + } + + static QHash languageNames; + if (languageNames.isEmpty()) { + languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; + languageNames[QLatin1String("native")] = TypeSystem::NativeCode; + } + + QString languageAttribute = attributes[QLatin1String("class")].toLower(); + TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); + + if (topElement.type == StackElement::ModifyArgument) { + if (lang == TypeSystem::NoLanguage) { + m_error = QStringLiteral("unsupported class attribute: '%1'").arg(lang); + return false; + } + + CodeSnip snip(since); + snip.language = lang; + m_contextStack.top()->functionMods.last().argument_mods.last().conversion_rules.append(snip); + } else { + if (topElement.entry->hasConversionRule() || topElement.entry->hasCustomConversion()) { + m_error = QLatin1String("Types can have only one conversion rule"); + return false; + } + + // The old conversion rule tag that uses a file containing the conversion + // will be kept temporarily for compatibility reasons. + QString sourceFile = attributes[QLatin1String("file")]; + if (!sourceFile.isEmpty()) { + if (m_generate != TypeEntry::GenerateForSubclass + && m_generate != TypeEntry::GenerateNothing) { + + const char* conversionFlag = NATIVE_CONVERSION_RULE_FLAG; + if (lang == TypeSystem::TargetLangCode) + conversionFlag = TARGET_CONVERSION_RULE_FLAG; + + QFile conversionSource(sourceFile); + if (conversionSource.open(QIODevice::ReadOnly | QIODevice::Text)) { + topElement.entry->setConversionRule(QLatin1String(conversionFlag) + QString::fromUtf8(conversionSource.readAll())); + } else { + qCWarning(lcShiboken).noquote().nospace() + << "File containing conversion code for " + << topElement.entry->name() << " type does not exist or is not readable: " + << sourceFile; + } + } + } + + CustomConversion* customConversion = new CustomConversion(static_cast(m_current->entry)); + customConversionsForReview.append(customConversion); + } + } + break; + case StackElement::NativeToTarget: { + if (topElement.type != StackElement::ConversionRule) { + m_error = QLatin1String("Native to Target conversion code can only be specified for custom conversion rules."); + return false; + } + m_contextStack.top()->codeSnips << CodeSnip(0); + } + break; + case StackElement::TargetToNative: { + if (topElement.type != StackElement::ConversionRule) { + m_error = QLatin1String("Target to Native conversions can only be specified for custom conversion rules."); + return false; + } + bool replace = attributes[QLatin1String("replace")] == QLatin1String("yes"); + static_cast(m_current->entry)->customConversion()->setReplaceOriginalTargetToNativeConversions(replace); + } + break; + case StackElement::AddConversion: { + if (topElement.type != StackElement::TargetToNative) { + m_error = QLatin1String("Target to Native conversions can only be added inside 'target-to-native' tags."); + return false; + } + QString sourceTypeName = attributes[QLatin1String("type")]; + if (sourceTypeName.isEmpty()) { + m_error = QLatin1String("Target to Native conversions must specify the input type with the 'type' attribute."); + return false; + } + QString typeCheck = attributes[QLatin1String("check")]; + static_cast(m_current->entry)->customConversion()->addTargetToNativeConversion(sourceTypeName, typeCheck); + m_contextStack.top()->codeSnips << CodeSnip(0); + } + break; + case StackElement::ModifyArgument: { + if (topElement.type != StackElement::ModifyFunction + && topElement.type != StackElement::AddFunction) { + m_error = QString::fromLatin1("argument modification requires function" + " modification as parent, was %1") + .arg(topElement.type, 0, 16); + return false; + } + + QString index = attributes[QLatin1String("index")]; + if (index == QLatin1String("return")) + index = QLatin1String("0"); + else if (index == QLatin1String("this")) + index = QLatin1String("-1"); + + bool ok = false; + int idx = index.toInt(&ok); + if (!ok) { + m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index); + return false; + } + + QString replace_value = attributes[QLatin1String("replace-value")]; + + if (!replace_value.isEmpty() && idx) { + m_error = QLatin1String("replace-value is only supported for return values (index=0)."); + return false; + } + + ArgumentModification argumentModification = ArgumentModification(idx, since); + argumentModification.replace_value = replace_value; + argumentModification.resetAfterUse = convertBoolean(attributes[QLatin1String("invalidate-after-use")], QLatin1String("invalidate-after-use"), false); + m_contextStack.top()->functionMods.last().argument_mods.append(argumentModification); + } + break; + case StackElement::NoNullPointers: { + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("no-null-pointer requires argument modification as parent"); + return false; + } + + m_contextStack.top()->functionMods.last().argument_mods.last().noNullPointers = true; + if (!m_contextStack.top()->functionMods.last().argument_mods.last().index) + m_contextStack.top()->functionMods.last().argument_mods.last().nullPointerDefaultValue = attributes[QLatin1String("default-value")]; + else if (!attributes[QLatin1String("default-value")].isEmpty()) + qCWarning(lcShiboken) << "default values for null pointer guards are only effective for return values"; + + } + break; + case StackElement::DefineOwnership: { + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("define-ownership requires argument modification as parent"); + return false; + } + + static QHash languageNames; + if (languageNames.isEmpty()) { + languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; + languageNames[QLatin1String("native")] = TypeSystem::NativeCode; + } + + QString classAttribute = attributes[QLatin1String("class")].toLower(); + TypeSystem::Language lang = languageNames.value(classAttribute, TypeSystem::NoLanguage); + if (lang == TypeSystem::NoLanguage) { + m_error = QStringLiteral("unsupported class attribute: '%1'").arg(classAttribute); + return false; + } + + static QHash ownershipNames; + if (ownershipNames.isEmpty()) { + ownershipNames[QLatin1String("target")] = TypeSystem::TargetLangOwnership; + ownershipNames[QLatin1String("c++")] = TypeSystem::CppOwnership; + ownershipNames[QLatin1String("default")] = TypeSystem::DefaultOwnership; + } + + QString ownershipAttribute = attributes[QLatin1String("owner")].toLower(); + TypeSystem::Ownership owner = ownershipNames.value(ownershipAttribute, TypeSystem::InvalidOwnership); + if (owner == TypeSystem::InvalidOwnership) { + m_error = QStringLiteral("unsupported owner attribute: '%1'").arg(ownershipAttribute); + return false; + } + + m_contextStack.top()->functionMods.last().argument_mods.last().ownerships[lang] = owner; + } + break; + case StackElement::SuppressedWarning: + if (attributes[QLatin1String("text")].isEmpty()) + qCWarning(lcShiboken) << "Suppressed warning with no text specified"; + else + m_database->addSuppressedWarning(attributes[QLatin1String("text")]); + break; + case StackElement::ArgumentMap: { + if (!(topElement.type & StackElement::CodeSnipMask)) { + m_error = QLatin1String("Argument maps requires code injection as parent"); + return false; + } + + bool ok; + int pos = attributes[QLatin1String("index")].toInt(&ok); + if (!ok) { + m_error = QStringLiteral("Can't convert position '%1' to integer") + .arg(attributes[QLatin1String("position")]); + return false; + } + + if (pos <= 0) { + m_error = QStringLiteral("Argument position %1 must be a positive number").arg(pos); + return false; + } + + QString meta_name = attributes[QLatin1String("meta-name")]; + if (meta_name.isEmpty()) + qCWarning(lcShiboken) << "Empty meta name in argument map"; + + + if (topElement.type == StackElement::InjectCodeInFunction) + m_contextStack.top()->functionMods.last().snips.last().argumentMap[pos] = meta_name; + else { + qCWarning(lcShiboken) << "Argument maps are only useful for injection of code " + "into functions."; + } + } + break; + case StackElement::Removal: { + if (topElement.type != StackElement::ModifyFunction) { + m_error = QLatin1String("Function modification parent required"); + return false; + } + + static QHash languageNames; + if (languageNames.isEmpty()) { + languageNames.insert(QLatin1String("target"), TypeSystem::TargetLangAndNativeCode); + languageNames.insert(QLatin1String("all"), TypeSystem::All); + } + + QString languageAttribute = attributes[QLatin1String("class")].toLower(); + TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); + if (lang == TypeSystem::NoLanguage) { + m_error = QStringLiteral("unsupported class attribute: '%1'").arg(languageAttribute); + return false; + } + + m_contextStack.top()->functionMods.last().removal = lang; + } + break; + case StackElement::Rename: + case StackElement::Access: { + if (topElement.type != StackElement::ModifyField + && topElement.type != StackElement::ModifyFunction + && topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("Function, field or argument modification parent required"); + return false; + } + + Modification *mod = 0; + if (topElement.type == StackElement::ModifyFunction) + mod = &m_contextStack.top()->functionMods.last(); + else if (topElement.type == StackElement::ModifyField) + mod = &m_contextStack.top()->fieldMods.last(); + + QString modifier; + if (element->type == StackElement::Rename) { + modifier = QLatin1String("rename"); + QString renamed_to = attributes[QLatin1String("to")]; + if (renamed_to.isEmpty()) { + m_error = QLatin1String("Rename modifier requires 'to' attribute"); + return false; + } + + if (topElement.type == StackElement::ModifyFunction) + mod->setRenamedTo(renamed_to); + else if (topElement.type == StackElement::ModifyField) + mod->setRenamedTo(renamed_to); + else + m_contextStack.top()->functionMods.last().argument_mods.last().renamed_to = renamed_to; + } else + modifier = attributes[QLatin1String("modifier")].toLower(); + + + if (modifier.isEmpty()) { + m_error = QLatin1String("No access modification specified"); + return false; + } + + static QHash modifierNames; + if (modifierNames.isEmpty()) { + modifierNames[QLatin1String("private")] = Modification::Private; + modifierNames[QLatin1String("public")] = Modification::Public; + modifierNames[QLatin1String("protected")] = Modification::Protected; + modifierNames[QLatin1String("friendly")] = Modification::Friendly; + modifierNames[QLatin1String("rename")] = Modification::Rename; + modifierNames[QLatin1String("final")] = Modification::Final; + modifierNames[QLatin1String("non-final")] = Modification::NonFinal; + } + + if (!modifierNames.contains(modifier)) { + m_error = QStringLiteral("Unknown access modifier: '%1'").arg(modifier); + return false; + } + + if (mod) + mod->modifiers |= modifierNames[modifier]; + } + break; + case StackElement::RemoveArgument: + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("Removing argument requires argument modification as parent"); + return false; + } + + m_contextStack.top()->functionMods.last().argument_mods.last().removed = true; + break; + + case StackElement::ModifyField: { + QString name = attributes[nameAttribute()]; + if (name.isEmpty()) + break; + FieldModification fm; + fm.name = name; + fm.modifiers = 0; + + if (!convertRemovalAttribute(attributes[QLatin1String("remove")], fm, m_error)) + return false; + + QString read = attributes[QLatin1String("read")]; + QString write = attributes[QLatin1String("write")]; + + if (read == QLatin1String("true")) fm.modifiers |= FieldModification::Readable; + if (write == QLatin1String("true")) fm.modifiers |= FieldModification::Writable; + + m_contextStack.top()->fieldMods << fm; + } + break; + case StackElement::AddFunction: { + if (!(topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::Root))) { + m_error = QString::fromLatin1("Add function requires a complex type or a root tag as parent" + ", was=%1").arg(topElement.type, 0, 16); + return false; + } + QString signature = attributes[QLatin1String("signature")]; + + signature = TypeDatabase::normalizedSignature(signature); + if (signature.isEmpty()) { + m_error = QLatin1String("No signature for the added function"); + return false; + } + + QString errorString = checkSignatureError(signature, QLatin1String("add-function")); + if (!errorString.isEmpty()) { + m_error = errorString; + return false; + } + + AddedFunction func(signature, attributes[QLatin1String("return-type")], since); + func.setStatic(attributes[QLatin1String("static")] == QLatin1String("yes")); + if (!signature.contains(QLatin1Char('('))) + signature += QLatin1String("()"); + m_currentSignature = signature; + + QString access = attributes[QLatin1String("access")].toLower(); + if (!access.isEmpty()) { + if (access == QLatin1String("protected")) { + func.setAccess(AddedFunction::Protected); + } else if (access == QLatin1String("public")) { + func.setAccess(AddedFunction::Public); + } else { + m_error = QString::fromLatin1("Bad access type '%1'").arg(access); + return false; + } + } + + m_contextStack.top()->addedFunctions << func; + + FunctionModification mod(since); + mod.signature = m_currentSignature; + m_contextStack.top()->functionMods << mod; + } + break; + case StackElement::ModifyFunction: { + if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { + m_error = QString::fromLatin1("Modify function requires complex type as parent" + ", was=%1").arg(topElement.type, 0, 16); + return false; + } + QString signature = attributes[QLatin1String("signature")]; + + signature = TypeDatabase::normalizedSignature(signature); + if (signature.isEmpty()) { + m_error = QLatin1String("No signature for modified function"); + return false; + } + + QString errorString = checkSignatureError(signature, QLatin1String("modify-function")); + if (!errorString.isEmpty()) { + m_error = errorString; + return false; + } + + FunctionModification mod(since); + m_currentSignature = mod.signature = signature; + + QString access = attributes[QLatin1String("access")].toLower(); + if (!access.isEmpty()) { + if (access == QLatin1String("private")) + mod.modifiers |= Modification::Private; + else if (access == QLatin1String("protected")) + mod.modifiers |= Modification::Protected; + else if (access == QLatin1String("public")) + mod.modifiers |= Modification::Public; + else if (access == QLatin1String("final")) + mod.modifiers |= Modification::Final; + else if (access == QLatin1String("non-final")) + mod.modifiers |= Modification::NonFinal; + else { + m_error = QString::fromLatin1("Bad access type '%1'").arg(access); + return false; + } + } + + if (convertBoolean(attributes[QLatin1String("deprecated")], QLatin1String("deprecated"), false)) + mod.modifiers |= Modification::Deprecated; + + if (!convertRemovalAttribute(attributes[QLatin1String("remove")], mod, m_error)) + return false; + + QString rename = attributes[QLatin1String("rename")]; + if (!rename.isEmpty()) { + mod.renamedToName = rename; + mod.modifiers |= Modification::Rename; + } + + QString association = attributes[QLatin1String("associated-to")]; + if (!association.isEmpty()) + mod.association = association; + + mod.setIsThread(convertBoolean(attributes[QLatin1String("thread")], QLatin1String("thread"), false)); + mod.setAllowThread(convertBoolean(attributes[QLatin1String("allow-thread")], QLatin1String("allow-thread"), false)); + + mod.modifiers |= (convertBoolean(attributes[QLatin1String("virtual-slot")], QLatin1String("virtual-slot"), false) ? Modification::VirtualSlot : 0); + + m_contextStack.top()->functionMods << mod; + } + break; + case StackElement::ReplaceDefaultExpression: + if (!(topElement.type & StackElement::ModifyArgument)) { + m_error = QLatin1String("Replace default expression only allowed as child of argument modification"); + return false; + } + + if (attributes[QLatin1String("with")].isEmpty()) { + m_error = QLatin1String("Default expression replaced with empty string. Use remove-default-expression instead."); + return false; + } + + m_contextStack.top()->functionMods.last().argument_mods.last().replacedDefaultExpression = attributes[QLatin1String("with")]; + break; + case StackElement::RemoveDefaultExpression: + m_contextStack.top()->functionMods.last().argument_mods.last().removedDefaultExpression = true; + break; + case StackElement::CustomMetaConstructor: + case StackElement::CustomMetaDestructor: { + CustomFunction *func = new CustomFunction(attributes[nameAttribute()]); + func->paramName = attributes[QLatin1String("param-name")]; + element->value.customFunction = func; + } + break; + case StackElement::ReferenceCount: { + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("reference-count must be child of modify-argument"); + return false; + } + + ReferenceCount rc; + + static QHash actions; + if (actions.isEmpty()) { + actions[QLatin1String("add")] = ReferenceCount::Add; + actions[QLatin1String("add-all")] = ReferenceCount::AddAll; + actions[QLatin1String("remove")] = ReferenceCount::Remove; + actions[QLatin1String("set")] = ReferenceCount::Set; + actions[QLatin1String("ignore")] = ReferenceCount::Ignore; + } + rc.action = actions.value(attributes[QLatin1String("action")].toLower(), ReferenceCount::Invalid); + rc.varName = attributes[QLatin1String("variable-name")]; + + if (rc.action == ReferenceCount::Invalid) { + m_error = QLatin1String("unrecognized value for action attribute. supported actions:"); + for (QHash::const_iterator it = actions.cbegin(), end = actions.cend(); it != end; ++it) + m_error += QLatin1Char(' ') + it.key(); + } + + m_contextStack.top()->functionMods.last().argument_mods.last().referenceCounts.append(rc); + } + break; + + case StackElement::ParentOwner: { + if (topElement.type != StackElement::ModifyArgument) { + m_error = QLatin1String("parent-policy must be child of modify-argument"); + return false; + } + + ArgumentOwner ao; + + QString index = attributes[QLatin1String("index")]; + if (index == QLatin1String("return")) + index = QLatin1String("0"); + else if (index == QLatin1String("this")) + index = QLatin1String("-1"); + + bool ok = false; + int idx = index.toInt(&ok); + if (!ok) { + m_error = QStringLiteral("Cannot convert '%1' to integer").arg(index); + return false; + } + + static QHash actions; + if (actions.isEmpty()) { + actions[QLatin1String("add")] = ArgumentOwner::Add; + actions[QLatin1String("remove")] = ArgumentOwner::Remove; + } + + ao.action = actions.value(attributes[QLatin1String("action")].toLower(), ArgumentOwner::Invalid); + if (!ao.action) { + m_error = QLatin1String("Invalid parent actionr"); + return false; + } + ao.index = idx; + m_contextStack.top()->functionMods.last().argument_mods.last().owner = ao; + } + break; + + + case StackElement::InjectCode: { + if (!(topElement.type & StackElement::ComplexTypeEntryMask) + && (topElement.type != StackElement::AddFunction) + && (topElement.type != StackElement::ModifyFunction) + && (topElement.type != StackElement::Root)) { + m_error = QLatin1String("wrong parent type for code injection"); + return false; + } + + static QHash languageNames; + if (languageNames.isEmpty()) { + languageNames[QLatin1String("target")] = TypeSystem::TargetLangCode; // em algum lugar do cpp + languageNames[QLatin1String("native")] = TypeSystem::NativeCode; // em algum lugar do cpp + languageNames[QLatin1String("shell")] = TypeSystem::ShellCode; // coloca no header, mas antes da declaracao da classe + languageNames[QLatin1String("shell-declaration")] = TypeSystem::ShellDeclaration; // coloca no header, dentro da declaracao da classe + languageNames[QLatin1String("library-initializer")] = TypeSystem::PackageInitializer; + languageNames[QLatin1String("destructor-function")] = TypeSystem::DestructorFunction; + languageNames[QLatin1String("constructors")] = TypeSystem::Constructors; + languageNames[QLatin1String("interface")] = TypeSystem::Interface; + } + + QString className = attributes[QLatin1String("class")].toLower(); + if (!languageNames.contains(className)) { + m_error = QStringLiteral("Invalid class specifier: '%1'").arg(className); + return false; + } + + + static QHash positionNames; + if (positionNames.isEmpty()) { + positionNames.insert(QLatin1String("beginning"), TypeSystem::CodeSnipPositionBeginning); + positionNames.insert(QLatin1String("end"), TypeSystem::CodeSnipPositionEnd); + // QtScript + positionNames.insert(QLatin1String("declaration"), TypeSystem::CodeSnipPositionDeclaration); + positionNames.insert(QLatin1String("prototype-initialization"), TypeSystem::CodeSnipPositionPrototypeInitialization); + positionNames.insert(QLatin1String("constructor-initialization"), TypeSystem::CodeSnipPositionConstructorInitialization); + positionNames.insert(QLatin1String("constructor"), TypeSystem::CodeSnipPositionConstructor); + } + + QString position = attributes[QLatin1String("position")].toLower(); + if (!positionNames.contains(position)) { + m_error = QStringLiteral("Invalid position: '%1'").arg(position); + return false; + } + + CodeSnip snip(since); + snip.language = languageNames[className]; + snip.position = positionNames[position]; + bool in_file = false; + + QString file_name = attributes[QLatin1String("file")]; + + //Handler constructor.... + if (m_generate != TypeEntry::GenerateForSubclass && + m_generate != TypeEntry::GenerateNothing && + !file_name.isEmpty()) { + if (QFile::exists(file_name)) { + QFile codeFile(file_name); + if (codeFile.open(QIODevice::Text | QIODevice::ReadOnly)) { + QString content = QLatin1String("// ========================================================================\n" + "// START of custom code block [file: "); + content += file_name; + content += QLatin1String("]\n"); + content += QString::fromUtf8(codeFile.readAll()); + content += QLatin1String("\n// END of custom code block [file: "); + content += file_name; + content += QLatin1String("]\n// ========================================================================\n"); + snip.addCode(content); + in_file = true; + } + } else { + qCWarning(lcShiboken).noquote().nospace() + << "File for inject code not exist: " << QDir::toNativeSeparators(file_name); + } + + } + + if (snip.language == TypeSystem::Interface && topElement.type != StackElement::InterfaceTypeEntry) { + m_error = QLatin1String("Interface code injections must be direct child of an interface type entry"); + return false; + } + + if (topElement.type == StackElement::ModifyFunction || topElement.type == StackElement::AddFunction) { + FunctionModification mod = m_contextStack.top()->functionMods.last(); + if (snip.language == TypeSystem::ShellDeclaration) { + m_error = QLatin1String("no function implementation in shell declaration in which to inject code"); + return false; + } + + m_contextStack.top()->functionMods.last().snips << snip; + if (in_file) + m_contextStack.top()->functionMods.last().modifiers |= FunctionModification::CodeInjection; + element->type = StackElement::InjectCodeInFunction; + } else if (topElement.type == StackElement::Root) { + element->entry->addCodeSnip(snip); + } else if (topElement.type != StackElement::Root) { + m_contextStack.top()->codeSnips << snip; + } + + } + break; + case StackElement::Include: { + QString location = attributes[QLatin1String("location")].toLower(); + + static QHash locationNames; + if (locationNames.isEmpty()) { + locationNames[QLatin1String("global")] = Include::IncludePath; + locationNames[QLatin1String("local")] = Include::LocalPath; + locationNames[QLatin1String("target")] = Include::TargetLangImport; + } + + if (!locationNames.contains(location)) { + m_error = QStringLiteral("Location not recognized: '%1'").arg(location); + return false; + } + + Include::IncludeType loc = locationNames[location]; + Include inc(loc, attributes[QLatin1String("file-name")]); + + ComplexTypeEntry *ctype = static_cast(element->entry); + if (topElement.type & (StackElement::ComplexTypeEntryMask | StackElement::PrimitiveTypeEntry)) { + element->entry->setInclude(inc); + } else if (topElement.type == StackElement::ExtraIncludes) { + element->entry->addExtraInclude(inc); + } else { + m_error = QLatin1String("Only supported parent tags are primitive-type, complex types or extra-includes"); + return false; + } + + inc = ctype->include(); + IncludeList lst = ctype->extraIncludes(); + ctype = ctype->designatedInterface(); + if (ctype) { + ctype->setExtraIncludes(lst); + ctype->setInclude(inc); + } + } + break; + case StackElement::Rejection: + if (!addRejection(m_database, attributes, &m_error)) + return false; + break; + case StackElement::Template: + element->value.templateEntry = new TemplateEntry(attributes[nameAttribute()], since); + break; + case StackElement::TemplateInstanceEnum: + if (!(topElement.type & StackElement::CodeSnipMask) && + (topElement.type != StackElement::Template) && + (topElement.type != StackElement::CustomMetaConstructor) && + (topElement.type != StackElement::CustomMetaDestructor) && + (topElement.type != StackElement::NativeToTarget) && + (topElement.type != StackElement::AddConversion) && + (topElement.type != StackElement::ConversionRule)) { + m_error = QLatin1String("Can only insert templates into code snippets, templates, custom-constructors, "\ + "custom-destructors, conversion-rule, native-to-target or add-conversion tags."); + return false; + } + element->value.templateInstance = new TemplateInstance(attributes[nameAttribute()], since); + break; + case StackElement::Replace: + if (topElement.type != StackElement::TemplateInstanceEnum) { + m_error = QLatin1String("Can only insert replace rules into insert-template."); + return false; + } + element->parent->value.templateInstance->addReplaceRule(attributes[QLatin1String("from")], attributes[QLatin1String("to")]); + break; + default: + break; // nada + }; + } + + m_current = element; + return true; +} + +PrimitiveTypeEntry *PrimitiveTypeEntry::basicReferencedTypeEntry() const +{ + if (!m_referencedTypeEntry) + return 0; + + PrimitiveTypeEntry *baseReferencedTypeEntry = m_referencedTypeEntry->basicReferencedTypeEntry(); + if (baseReferencedTypeEntry) + return baseReferencedTypeEntry; + else + return m_referencedTypeEntry; +} + +typedef QHash PrimitiveTypeEntryTargetLangPackageMap; +Q_GLOBAL_STATIC(PrimitiveTypeEntryTargetLangPackageMap, primitiveTypeEntryTargetLangPackages); + +void PrimitiveTypeEntry::setTargetLangPackage(const QString& package) +{ + primitiveTypeEntryTargetLangPackages()->insert(this, package); +} +QString PrimitiveTypeEntry::targetLangPackage() const +{ + if (!primitiveTypeEntryTargetLangPackages()->contains(this)) + return this->::TypeEntry::targetLangPackage(); + return primitiveTypeEntryTargetLangPackages()->value(this); +} + +CodeSnipList TypeEntry::codeSnips() const +{ + return m_codeSnips; +} + +QString Modification::accessModifierString() const +{ + if (isPrivate()) return QLatin1String("private"); + if (isProtected()) return QLatin1String("protected"); + if (isPublic()) return QLatin1String("public"); + if (isFriendly()) return QLatin1String("friendly"); + return QString(); +} + +FunctionModificationList ComplexTypeEntry::functionModifications(const QString &signature) const +{ + FunctionModificationList lst; + for (int i = 0; i < m_functionMods.count(); ++i) { + const FunctionModification &mod = m_functionMods.at(i); + if (mod.signature == signature) + lst << mod; + } + return lst; +} + +FieldModification ComplexTypeEntry::fieldModification(const QString &name) const +{ + for (int i = 0; i < m_fieldMods.size(); ++i) + if (m_fieldMods.at(i).name == name) + return m_fieldMods.at(i); + FieldModification mod; + mod.name = name; + mod.modifiers = FieldModification::Readable | FieldModification::Writable; + return mod; +} + +// The things we do not to break the ABI... +typedef QHash ComplexTypeEntryDefaultConstructorMap; +Q_GLOBAL_STATIC(ComplexTypeEntryDefaultConstructorMap, complexTypeEntryDefaultConstructors); + +void ComplexTypeEntry::setDefaultConstructor(const QString& defaultConstructor) +{ + if (!defaultConstructor.isEmpty()) + complexTypeEntryDefaultConstructors()->insert(this, defaultConstructor); +} +QString ComplexTypeEntry::defaultConstructor() const +{ + if (!complexTypeEntryDefaultConstructors()->contains(this)) + return QString(); + return complexTypeEntryDefaultConstructors()->value(this); +} +bool ComplexTypeEntry::hasDefaultConstructor() const +{ + return complexTypeEntryDefaultConstructors()->contains(this); +} + +QString ContainerTypeEntry::targetLangPackage() const +{ + return QString(); +} + +QString ContainerTypeEntry::targetLangName() const +{ + + switch (m_type) { + case StringListContainer: return QLatin1String("QStringList"); + case ListContainer: return QLatin1String("QList"); + case LinkedListContainer: return QLatin1String("QLinkedList"); + case VectorContainer: return QLatin1String("QVector"); + case StackContainer: return QLatin1String("QStack"); + case QueueContainer: return QLatin1String("QQueue"); + case SetContainer: return QLatin1String("QSet"); + case MapContainer: return QLatin1String("QMap"); + case MultiMapContainer: return QLatin1String("QMultiMap"); + case HashContainer: return QLatin1String("QHash"); + case MultiHashContainer: return QLatin1String("QMultiHash"); + case PairContainer: return QLatin1String("QPair"); + default: + qWarning("bad type... %d", m_type); + break; + } + return QString(); +} + +QString ContainerTypeEntry::qualifiedCppName() const +{ + if (m_type == StringListContainer) + return QLatin1String("QStringList"); + return ComplexTypeEntry::qualifiedCppName(); +} + +QString EnumTypeEntry::targetLangQualifier() const +{ + TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier); + if (te) + return te->targetLangName(); + else + return m_qualifier; +} + +QString EnumTypeEntry::targetLangApiName() const +{ + return QLatin1String("jint"); +} + +QString FlagsTypeEntry::targetLangApiName() const +{ + return QLatin1String("jint"); +} + +void EnumTypeEntry::addEnumValueRedirection(const QString &rejected, const QString &usedValue) +{ + m_enumRedirections << EnumValueRedirection(rejected, usedValue); +} + +QString EnumTypeEntry::enumValueRedirection(const QString &value) const +{ + for (int i = 0; i < m_enumRedirections.size(); ++i) + if (m_enumRedirections.at(i).rejected == value) + return m_enumRedirections.at(i).used; + return QString(); +} + +QString FlagsTypeEntry::qualifiedTargetLangName() const +{ + return targetLangPackage() + QLatin1Char('.') + m_enum->targetLangQualifier() + + QLatin1Char('.') + targetLangName(); +} + +/*! + * The Visual Studio 2002 compiler doesn't support these symbols, + * which our typedefs unforntuatly expand to. + */ +QString fixCppTypeName(const QString &name) +{ + if (name == QLatin1String("long long")) + return QLatin1String("qint64"); + else if (name == QLatin1String("unsigned long long")) + return QLatin1String("quint64"); + return name; +} + +QString TemplateInstance::expandCode() const +{ + TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name); + if (templateEntry) { + typedef QHash::const_iterator ConstIt; + QString code = templateEntry->code(); + for (ConstIt it = replaceRules.begin(), end = replaceRules.end(); it != end; ++it) + code.replace(it.key(), it.value()); + while (!code.isEmpty() && code.at(code.size() - 1).isSpace()) + code.chop(1); + QString result = QLatin1String("// TEMPLATE - ") + m_name + QLatin1String(" - START"); + if (!code.startsWith(QLatin1Char('\n'))) + result += QLatin1Char('\n'); + result += code; + result += QLatin1String("\n// TEMPLATE - ") + m_name + QLatin1String(" - END"); + return result; + } else { + qCWarning(lcShiboken).noquote().nospace() + << "insert-template referring to non-existing template '" << m_name << '\''; + } + + return QString(); +} + + +QString CodeSnipAbstract::code() const +{ + QString res; + for (const CodeSnipFragment &codeFrag : codeList) + res.append(codeFrag.code()); + + return res; +} + +QString CodeSnipFragment::code() const +{ + if (m_instance) + return m_instance->expandCode(); + else + return m_code; +} + +QString FunctionModification::toString() const +{ + QString str = signature + QLatin1String("->"); + if (modifiers & AccessModifierMask) { + switch (modifiers & AccessModifierMask) { + case Private: str += QLatin1String("private"); break; + case Protected: str += QLatin1String("protected"); break; + case Public: str += QLatin1String("public"); break; + case Friendly: str += QLatin1String("friendly"); break; + } + } + + if (modifiers & Final) str += QLatin1String("final"); + if (modifiers & NonFinal) str += QLatin1String("non-final"); + + if (modifiers & Readable) str += QLatin1String("readable"); + if (modifiers & Writable) str += QLatin1String("writable"); + + if (modifiers & CodeInjection) { + for (const CodeSnip &s : snips) { + str += QLatin1String("\n//code injection:\n"); + str += s.code(); + } + } + + if (modifiers & Rename) str += QLatin1String("renamed:") + renamedToName; + + if (modifiers & Deprecated) str += QLatin1String("deprecate"); + + if (modifiers & ReplaceExpression) str += QLatin1String("replace-expression"); + + return str; +} + +bool FunctionModification::operator!=(const FunctionModification& other) const +{ + return !(*this == other); +} + +bool FunctionModification::operator==(const FunctionModification& other) const +{ + if (signature != other.signature) + return false; + + if (association != other.association) + return false; + + if (modifiers != other.modifiers) + return false; + + if (removal != other.removal) + return false; + + if (m_thread != other.m_thread) + return false; + + if (m_allowThread != other.m_allowThread) + return false; + + if (m_version != other.m_version) + return false; + + return true; +} + +static AddedFunction::TypeInfo parseType(const QString& signature, int startPos = 0, int* endPos = 0) +{ + AddedFunction::TypeInfo result; + static const QRegularExpression regex(QLatin1String("\\w")); + Q_ASSERT(regex.isValid()); + int length = signature.length(); + int start = signature.indexOf(regex, startPos); + if (start == -1) { + if (signature.midRef(startPos + 1, 3) == QLatin1String("...")) { // varargs + if (endPos) + *endPos = startPos + 4; + result.name = QLatin1String("..."); + } else { // error + if (endPos) + *endPos = length; + } + return result; + } + + int cantStop = 0; + QString paramString; + QChar c; + int i = start; + for (; i < length; ++i) { + c = signature[i]; + if (c == QLatin1Char('<')) + cantStop++; + if (c == QLatin1Char('>')) + cantStop--; + if (cantStop < 0) + break; // FIXME: report error? + if ((c == QLatin1Char(')') || c == QLatin1Char(',')) && !cantStop) + break; + paramString += signature[i]; + } + if (endPos) + *endPos = i; + + // Check default value + if (paramString.contains(QLatin1Char('='))) { + QStringList lst = paramString.split(QLatin1Char('=')); + paramString = lst[0].trimmed(); + result.defaultValue = lst[1].trimmed(); + } + + // check constness + if (paramString.startsWith(QLatin1String("const "))) { + result.isConstant = true; + paramString.remove(0, sizeof("const")/sizeof(char)); + paramString = paramString.trimmed(); + } + // check reference + if (paramString.endsWith(QLatin1Char('&'))) { + result.isReference = true; + paramString.chop(1); + paramString = paramString.trimmed(); + } + // check Indirections + while (paramString.endsWith(QLatin1Char('*'))) { + result.indirections++; + paramString.chop(1); + paramString = paramString.trimmed(); + } + result.name = paramString; + + return result; +} + +AddedFunction::AddedFunction(QString signature, QString returnType, double vr) : m_access(Public), m_version(vr) +{ + Q_ASSERT(!returnType.isEmpty()); + m_returnType = parseType(returnType); + signature = signature.trimmed(); + int endPos = signature.indexOf(QLatin1Char('(')); + if (endPos < 0) { + m_isConst = false; + m_name = signature; + } else { + m_name = signature.left(endPos).trimmed(); + int signatureLength = signature.length(); + while (endPos < signatureLength) { + TypeInfo arg = parseType(signature, endPos, &endPos); + if (!arg.name.isEmpty()) + m_arguments.append(arg); + // end of parameters... + if (signature[endPos] == QLatin1Char(')')) + break; + } + // is const? + m_isConst = signature.right(signatureLength - endPos).contains(QLatin1String("const")); + } +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "TypeInfo("; + if (ti.isConstant) + d << "const"; + if (ti.indirections) + d << QByteArray(ti.indirections, '*'); + if (ti.isReference) + d << " &"; + d << ti.name; + if (!ti.defaultValue.isEmpty()) + d << " = " << ti.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"; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +AddedFunction::TypeInfo AddedFunction::TypeInfo::fromSignature(const QString& signature) +{ + return parseType(signature); +} + +QString ComplexTypeEntry::targetLangApiName() const +{ + return strings_jobject; +} +QString StringTypeEntry::targetLangApiName() const +{ + return strings_jobject; +} +QString StringTypeEntry::targetLangName() const +{ + return strings_String; +} +QString StringTypeEntry::targetLangPackage() const +{ + return QString(); +} +QString CharTypeEntry::targetLangApiName() const +{ + return strings_jchar; +} +QString CharTypeEntry::targetLangName() const +{ + return strings_char; +} +QString VariantTypeEntry::targetLangApiName() const +{ + return strings_jobject; +} +QString VariantTypeEntry::targetLangName() const +{ + return strings_Object; +} +QString VariantTypeEntry::targetLangPackage() const +{ + return QString(); +} + +QString ContainerTypeEntry::typeName() const +{ + switch(m_type) { + case LinkedListContainer: + return QLatin1String("linked-list"); + case ListContainer: + return QLatin1String("list"); + case StringListContainer: + return QLatin1String("string-list"); + case VectorContainer: + return QLatin1String("vector"); + case StackContainer: + return QLatin1String("stack"); + case QueueContainer: + return QLatin1String("queue"); + case SetContainer: + return QLatin1String("set"); + case MapContainer: + return QLatin1String("map"); + case MultiMapContainer: + return QLatin1String("multi-map"); + case HashContainer: + return QLatin1String("hash"); + case MultiHashContainer: + return QLatin1String("multi-hash"); + case PairContainer: + return QLatin1String("pair"); + case NoContainer: + default: + return QLatin1String("?"); + } +} + +static bool strLess(const char* a, const char* b) +{ + return ::strcmp(a, b) < 0; +} + +bool TypeEntry::isCppPrimitive() const +{ + if (!isPrimitive()) + return false; + + const PrimitiveTypeEntry *referencedType = + static_cast(this)->basicReferencedTypeEntry(); + QByteArray typeName = (referencedType ? referencedType->name() : m_name).toUtf8(); + + if (typeName.contains(' ') || m_type == VoidType) + return true; + // Keep this sorted!! + static const char* cppTypes[] = { "bool", "char", "double", "float", "int", "long", "long long", "short", "wchar_t" }; + const int N = sizeof(cppTypes)/sizeof(char*); + + const char** res = qBinaryFind(&cppTypes[0], &cppTypes[N], typeName.constData(), strLess); + + return res != &cppTypes[N]; +} + +// Again, stuff to avoid ABI breakage. +typedef QHash TypeEntryCustomConversionMap; +Q_GLOBAL_STATIC(TypeEntryCustomConversionMap, typeEntryCustomConversionMap); + +TypeEntry::~TypeEntry() +{ + if (typeEntryCustomConversionMap()->contains(this)) { + CustomConversion* customConversion = typeEntryCustomConversionMap()->value(this); + typeEntryCustomConversionMap()->remove(this); + delete customConversion; + } +} + +bool TypeEntry::hasCustomConversion() const +{ + return typeEntryCustomConversionMap()->contains(this); +} +void TypeEntry::setCustomConversion(CustomConversion* customConversion) +{ + if (customConversion) + typeEntryCustomConversionMap()->insert(this, customConversion); + else if (typeEntryCustomConversionMap()->contains(this)) + typeEntryCustomConversionMap()->remove(this); +} +CustomConversion* TypeEntry::customConversion() const +{ + if (typeEntryCustomConversionMap()->contains(this)) + return typeEntryCustomConversionMap()->value(this); + return 0; +} + +/* +static void injectCode(ComplexTypeEntry *e, + const char *signature, + const QByteArray &code, + const ArgumentMap &args) +{ + CodeSnip snip; + snip.language = TypeSystem::NativeCode; + snip.position = CodeSnip::Beginning; + snip.addCode(QString::fromLatin1(code)); + snip.argumentMap = args; + + FunctionModification mod; + mod.signature = QMetaObject::normalizedSignature(signature); + mod.snips << snip; + mod.modifiers = Modification::CodeInjection; +} +*/ + +struct CustomConversion::CustomConversionPrivate +{ + CustomConversionPrivate(const TypeEntry* ownerType) + : ownerType(ownerType), replaceOriginalTargetToNativeConversions(false) + { + } + const TypeEntry* ownerType; + QString nativeToTargetConversion; + bool replaceOriginalTargetToNativeConversions; + TargetToNativeConversions targetToNativeConversions; +}; + +struct CustomConversion::TargetToNativeConversion::TargetToNativeConversionPrivate +{ + TargetToNativeConversionPrivate() + : sourceType(0) + { + } + const TypeEntry* sourceType; + QString sourceTypeName; + QString sourceTypeCheck; + QString conversion; +}; + +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() +{ + return m_d->targetToNativeConversions; +} + +const CustomConversion::TargetToNativeConversions& CustomConversion::targetToNativeConversions() const +{ + return m_d->targetToNativeConversions; +} + +void CustomConversion::addTargetToNativeConversion(const QString& sourceTypeName, + const QString& sourceTypeCheck, + const QString& conversion) +{ + m_d->targetToNativeConversions.append(new TargetToNativeConversion(sourceTypeName, sourceTypeCheck, conversion)); +} + +CustomConversion::TargetToNativeConversion::TargetToNativeConversion(const QString& sourceTypeName, + const QString& sourceTypeCheck, + const QString& conversion) +{ + m_d = new TargetToNativeConversionPrivate; + m_d->sourceTypeName = sourceTypeName; + m_d->sourceTypeCheck = sourceTypeCheck; + m_d->conversion = conversion; +} + +CustomConversion::TargetToNativeConversion::~TargetToNativeConversion() +{ + delete m_d; +} + +const TypeEntry* CustomConversion::TargetToNativeConversion::sourceType() const +{ + return m_d->sourceType; +} + +void CustomConversion::TargetToNativeConversion::setSourceType(const TypeEntry* sourceType) +{ + m_d->sourceType = sourceType; +} + +bool CustomConversion::TargetToNativeConversion::isCustomType() const +{ + return !(m_d->sourceType); +} + +QString CustomConversion::TargetToNativeConversion::sourceTypeName() const +{ + return m_d->sourceTypeName; +} + +QString CustomConversion::TargetToNativeConversion::sourceTypeCheck() const +{ + return m_d->sourceTypeCheck; +} + +QString CustomConversion::TargetToNativeConversion::conversion() const +{ + return m_d->conversion; +} + +void CustomConversion::TargetToNativeConversion::setConversion(const QString& conversion) +{ + m_d->conversion = conversion; +} diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h new file mode 100644 index 000000000..b75da48ba --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -0,0 +1,1975 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPESYSTEM_H +#define TYPESYSTEM_H + +#include "typesystem_enums.h" +#include "typesystem_typedefs.h" +#include "include.h" + +#include +#include +#include +#include +#include +#include +#include + +//Used to identify the conversion rule to avoid break API +#define TARGET_CONVERSION_RULE_FLAG "0" +#define NATIVE_CONVERSION_RULE_FLAG "1" + +class Indentor; + +class AbstractMetaType; +QT_BEGIN_NAMESPACE +class QDebug; +class QTextStream; +QT_END_NAMESPACE + +class EnumTypeEntry; +class FlagsTypeEntry; + +typedef QMap ArgumentMap; + +class TemplateInstance; + +struct ReferenceCount +{ + ReferenceCount() {} + enum Action { // 0x01 - 0xff + Invalid = 0x00, + Add = 0x01, + AddAll = 0x02, + Remove = 0x04, + Set = 0x08, + Ignore = 0x10, + + ActionsMask = 0xff, + + Padding = 0xffffffff + }; + + Action action; + QString varName; +}; + +struct ArgumentOwner +{ + enum Action { + Invalid = 0x00, + Add = 0x01, + Remove = 0x02 + }; + enum { + InvalidIndex = -2, + ThisIndex = -1, + ReturnIndex = 0, + FirstArgumentIndex = 1 + }; + ArgumentOwner() : action(ArgumentOwner::Invalid), index(ArgumentOwner::InvalidIndex) {} + + Action action; + int index; +}; + +class CodeSnipFragment +{ +private: + QString m_code; + TemplateInstance *m_instance; + +public: + CodeSnipFragment() : m_instance(0) {} + CodeSnipFragment(const QString &code) + : m_code(code), + m_instance(0) {} + + CodeSnipFragment(TemplateInstance *instance) + : m_instance(instance) {} + + QString code() const; +}; + +class CodeSnipAbstract +{ +public: + QString code() const; + + void addCode(const QString &code) { codeList.append(CodeSnipFragment(code)); } + void addCode(const QStringRef &code) { addCode(code.toString()); } + + void addTemplateInstance(TemplateInstance *ti) + { + codeList.append(CodeSnipFragment(ti)); + } + + QVector codeList; +}; + +class CustomFunction : public CodeSnipAbstract +{ +public: + CustomFunction(const QString &n = QString()) : name(n) { } + + QString name; + QString paramName; +}; + +class TemplateEntry : public CodeSnipAbstract +{ +public: + TemplateEntry(const QString &name, double vr) + : m_name(name), m_version(vr) + { + }; + + QString name() const + { + return m_name; + }; + + double version() const + { + return m_version; + } + +private: + QString m_name; + double m_version; +}; + +class TemplateInstance +{ +public: + TemplateInstance(const QString &name, double vr) + : m_name(name), m_version(vr) {} + + void addReplaceRule(const QString &name, const QString &value) + { + replaceRules[name] = value; + } + + QString expandCode() const; + + QString name() const + { + return m_name; + } + + double version() const + { + return m_version; + } + +private: + const QString m_name; + double m_version; + QHash replaceRules; +}; + + +class CodeSnip : public CodeSnipAbstract +{ +public: + CodeSnip() : language(TypeSystem::TargetLangCode), version(0) {} + CodeSnip(double vr) : language(TypeSystem::TargetLangCode), version(vr) { } + CodeSnip(double vr, TypeSystem::Language lang) : language(lang), version(vr) { } + + TypeSystem::Language language; + TypeSystem::CodeSnipPosition position; + ArgumentMap argumentMap; + double version; +}; + +struct ArgumentModification +{ + ArgumentModification() : removedDefaultExpression(false), removed(false), + noNullPointers(false), index(-1), version(0) {} + ArgumentModification(int idx, double vr) + : removedDefaultExpression(false), removed(false), + noNullPointers(false), index(idx), version(vr) {} + + // Should the default expression be removed? + uint removedDefaultExpression : 1; + uint removed : 1; + uint noNullPointers : 1; + uint resetAfterUse : 1; + + // The index of this argument + int index; + + // Reference count flags for this argument + QVector referenceCounts; + + // The text given for the new type of the argument + QString modified_type; + + QString replace_value; + + // The code to be used to construct a return value when noNullPointers is true and + // the returned value is null. If noNullPointers is true and this string is + // empty, then the base class implementation will be used (or a default construction + // if there is no implementation) + QString nullPointerDefaultValue; + + // The text of the new default expression of the argument + QString replacedDefaultExpression; + + // The new definition of ownership for a specific argument + QHash ownerships; + + // Different conversion rules + CodeSnipList conversion_rules; + + //QObject parent(owner) of this argument + ArgumentOwner owner; + + //Api version + double version; + + //New name + QString renamed_to; +}; + +struct Modification +{ + enum Modifiers { + Private = 0x0001, + Protected = 0x0002, + Public = 0x0003, + Friendly = 0x0004, + AccessModifierMask = 0x000f, + + Final = 0x0010, + NonFinal = 0x0020, + FinalMask = Final | NonFinal, + + Readable = 0x0100, + Writable = 0x0200, + + CodeInjection = 0x1000, + Rename = 0x2000, + Deprecated = 0x4000, + ReplaceExpression = 0x8000, + VirtualSlot = 0x10000 | NonFinal + }; + + Modification() : modifiers(0), removal(TypeSystem::NoLanguage) { } + + bool isAccessModifier() const + { + return modifiers & AccessModifierMask; + } + Modifiers accessModifier() const + { + return Modifiers(modifiers & AccessModifierMask); + } + bool isPrivate() const + { + return accessModifier() == Private; + } + bool isProtected() const + { + return accessModifier() == Protected; + } + bool isPublic() const + { + return accessModifier() == Public; + } + bool isFriendly() const + { + return accessModifier() == Friendly; + } + bool isFinal() const + { + return modifiers & Final; + } + bool isNonFinal() const + { + return modifiers & NonFinal; + } + bool isVirtualSlot() const + { + return (modifiers & VirtualSlot) == VirtualSlot; + } + QString accessModifierString() const; + + bool isDeprecated() const + { + return modifiers & Deprecated; + } + + void setRenamedTo(const QString &name) + { + renamedToName = name; + } + QString renamedTo() const + { + return renamedToName; + } + bool isRenameModifier() const + { + return modifiers & Rename; + } + + bool isRemoveModifier() const + { + return removal != TypeSystem::NoLanguage; + } + + uint modifiers; + QString renamedToName; + TypeSystem::Language removal; +}; + +struct FunctionModification: public Modification +{ + FunctionModification() : m_thread(false), m_allowThread(false), m_version(0) {} + FunctionModification(double vr) : m_thread(false), m_allowThread(false), m_version(vr) {} + + bool isCodeInjection() const + { + return modifiers & CodeInjection; + } + void setIsThread(bool flag) + { + m_thread = flag; + } + bool isThread() const + { + return m_thread; + } + bool allowThread() const + { + return m_allowThread; + } + void setAllowThread(bool allow) + { + m_allowThread = allow; + } + double version() const + { + return m_version; + } + + bool operator!=(const FunctionModification& other) const; + bool operator==(const FunctionModification& other) const; + + + QString toString() const; + + QString signature; + QString association; + CodeSnipList snips; + + QVector argument_mods; + +private: + bool m_thread; + bool m_allowThread; + double m_version; + + +}; + +struct FieldModification: public Modification +{ + bool isReadable() const + { + return modifiers & Readable; + } + bool isWritable() const + { + return modifiers & Writable; + } + + QString name; +}; + +/** +* \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 +{ + /// Function access types. + enum Access { + Protected = 0x1, + Public = 0x2 + }; + + /** + * \internal + * Internal struct used to store information about arguments and return type of the + * functions added by the type system. This information is later used to create + * AbstractMetaType and AbstractMetaArgument for the AbstractMetaFunctions. + */ + struct TypeInfo { + TypeInfo() : isConstant(false), indirections(0), isReference(false) {} + static TypeInfo fromSignature(const QString& signature); + + QString name; + bool isConstant; + int indirections; + bool isReference; + QString defaultValue; + }; + + /// Creates a new AddedFunction with a signature and a return type. + AddedFunction(QString signature, QString returnType, double vr); + AddedFunction() : m_access(Protected), m_isConst(false), m_isStatic(false), m_version(0) {} + + /// 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. + QVector arguments() const + { + return m_arguments; + } + + /// Returns true if this is a constant method. + bool isConstant() const + { + return m_isConst; + } + + /// Set this method static. + void setStatic(bool value) + { + m_isStatic = value; + } + + /// Returns true if this is a static method. + bool isStatic() const + { + return m_isStatic; + } + + double version() const + { + return m_version; + } +private: + QString m_name; + Access m_access; + QVector m_arguments; + TypeInfo m_returnType; + bool m_isConst; + bool m_isStatic; + double m_version; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const AddedFunction::TypeInfo &ti); +QDebug operator<<(QDebug d, const AddedFunction &af); +#endif + +struct ExpensePolicy +{ + ExpensePolicy() : limit(-1) {} + int limit; + QString cost; + bool isValid() const + { + return limit >= 0; + } +}; + +class InterfaceTypeEntry; +class ObjectTypeEntry; + +class DocModification +{ +public: + DocModification() : format(TypeSystem::NativeCode), m_mode(TypeSystem::DocModificationXPathReplace), m_version(0) {} + DocModification(const QString& xpath, const QString& signature, double vr) + : format(TypeSystem::NativeCode), m_mode(TypeSystem::DocModificationXPathReplace), + m_xpath(xpath), m_signature(signature), m_version(vr) {} + DocModification(TypeSystem::DocModificationMode mode, const QString& signature, double vr) + : m_mode(mode), m_signature(signature), m_version(vr) {} + + void setCode(const QString& code) { m_code = code; } + void setCode(const QStringRef& code) { m_code = code.toString(); } + + QString code() const + { + return m_code; + } + QString xpath() const + { + return m_xpath; + } + QString signature() const + { + return m_signature; + } + TypeSystem::DocModificationMode mode() const + { + return m_mode; + } + double version() const + { + return m_version; + } + + TypeSystem::Language format; + +private: + TypeSystem::DocModificationMode m_mode; + QString m_code; + QString m_xpath; + QString m_signature; + double m_version; +}; + +class CustomConversion; + +class TypeEntry +{ + Q_GADGET +public: + enum Type { + PrimitiveType, + VoidType, + VarargsType, + FlagsType, + EnumType, + EnumValue, + TemplateArgumentType, + ThreadType, + BasicValueType, + StringType, + ContainerType, + InterfaceType, + ObjectType, + NamespaceType, + VariantType, + JObjectWrapperType, + CharType, + ArrayType, + TypeSystemType, + CustomType, + TargetLangType, + FunctionType, + SmartPointerType + }; + Q_ENUM(Type) + + enum CodeGeneration { + GenerateTargetLang = 0x0001, + GenerateCpp = 0x0002, + GenerateForSubclass = 0x0004, + + GenerateNothing = 0, + GenerateAll = 0xffff, + GenerateCode = GenerateTargetLang | GenerateCpp + }; + Q_ENUM(CodeGeneration) + + TypeEntry(const QString &name, Type t, double vr) + : m_name(name), + m_type(t), + m_codeGeneration(GenerateAll), + m_preferredConversion(true), + m_stream(false), + m_version(vr) + { + }; + + virtual ~TypeEntry(); + + Type type() const + { + return m_type; + } + bool isPrimitive() const + { + return m_type == PrimitiveType; + } + bool isEnum() const + { + return m_type == EnumType; + } + bool isFlags() const + { + return m_type == FlagsType; + } + bool isInterface() const + { + return m_type == InterfaceType; + } + bool isObject() const + { + return m_type == ObjectType; + } + bool isString() const + { + return m_type == StringType; + } + bool isChar() const + { + return m_type == CharType; + } + bool isNamespace() const + { + return m_type == NamespaceType; + } + bool isContainer() const + { + return m_type == ContainerType; + } + bool isSmartPointer() const + { + return m_type == SmartPointerType; + } + bool isVariant() const + { + return m_type == VariantType; + } + bool isJObjectWrapper() const + { + return m_type == JObjectWrapperType; + } + bool isArray() const + { + return m_type == ArrayType; + } + bool isTemplateArgument() const + { + return m_type == TemplateArgumentType; + } + bool isVoid() const + { + return m_type == VoidType; + } + bool isVarargs() const + { + return m_type == VarargsType; + } + bool isThread() const + { + return m_type == ThreadType; + } + bool isCustom() const + { + return m_type == CustomType; + } + bool isBasicValue() const + { + return m_type == BasicValueType; + } + bool isTypeSystem() const + { + return m_type == TypeSystemType; + } + bool isFunction() const + { + return m_type == FunctionType; + } + bool isEnumValue() const + { + return m_type == EnumValue; + } + + virtual bool preferredConversion() const + { + return m_preferredConversion; + } + virtual void setPreferredConversion(bool b) + { + m_preferredConversion = b; + } + + bool stream() const + { + return m_stream; + } + + void setStream(bool b) + { + m_stream = b; + } + + // The type's name in C++, fully qualified + QString name() const + { + return m_name; + } + + uint codeGeneration() const + { + return m_codeGeneration; + } + void setCodeGeneration(uint cg) + { + m_codeGeneration = cg; + } + + // Returns true if code must be generated for this entry, + // it will return false in case of types coming from typesystems + // included for reference only. + // NOTE: 'GenerateForSubclass' means 'generate="no"' + // on 'load-typesystem' tag + inline bool generateCode() const + { + return m_codeGeneration != TypeEntry::GenerateForSubclass + && m_codeGeneration != TypeEntry::GenerateNothing; + } + + virtual QString qualifiedCppName() const + { + return m_name; + } + + /** + * Its type's name in target language API + * The target language API name represents how this type is + * referred on low level code for the target language. + * Examples: for Java this would be a JNI name, for Python + * it should represent the CPython type name. + * /return string representing the target language API name + * for this type entry + */ + virtual QString targetLangApiName() const + { + return m_name; + } + + // The type's name in TargetLang + virtual QString targetLangName() const + { + return m_name; + } + + // The type to lookup when converting to TargetLang + virtual QString lookupName() const + { + return targetLangName(); + } + + // The package + virtual QString targetLangPackage() const + { + return QString(); + } + + virtual QString qualifiedTargetLangName() const + { + QString pkg = targetLangPackage(); + if (pkg.isEmpty()) + return targetLangName(); + return pkg + QLatin1Char('.') + targetLangName(); + } + + virtual InterfaceTypeEntry *designatedInterface() const + { + return 0; + } + + void setCustomConstructor(const CustomFunction &func) + { + m_customConstructor = func; + } + CustomFunction customConstructor() const + { + return m_customConstructor; + } + + void setCustomDestructor(const CustomFunction &func) + { + m_customDestructor = func; + } + CustomFunction customDestructor() const + { + return m_customDestructor; + } + + virtual bool isValue() const + { + return false; + } + virtual bool isComplex() const + { + return false; + } + + virtual bool isNativeIdBased() const + { + return false; + } + + CodeSnipList codeSnips() const; + void setCodeSnips(const CodeSnipList &codeSnips) + { + m_codeSnips = codeSnips; + } + void addCodeSnip(const CodeSnip &codeSnip) + { + m_codeSnips << codeSnip; + } + + void setDocModification(const DocModificationList& docMods) + { + m_docModifications << docMods; + } + DocModificationList docModifications() const + { + return m_docModifications; + } + + IncludeList extraIncludes() const + { + return m_extraIncludes; + } + void setExtraIncludes(const IncludeList &includes) + { + m_extraIncludes = includes; + } + void addExtraInclude(const Include &include) + { + if (!m_includesUsed.value(include.name(), false)) { + m_extraIncludes << include; + m_includesUsed[include.name()] = true; + } + } + + Include include() const + { + return m_include; + } + void setInclude(const Include &inc) + { + // This is a workaround for preventing double inclusion of the QSharedPointer implementation + // header, which does not use header guards. In the previous parser this was not a problem + // because the Q_QDOC define was set, and the implementation header was never included. + if (inc.name() == QLatin1String("qsharedpointer_impl.h")) + m_include = Include(inc.type(), QLatin1String("qsharedpointer.h")); + else + m_include = inc; + } + + // Replace conversionRule arg to CodeSnip in future version + /// Set the type convertion rule + void setConversionRule(const QString& conversionRule) + { + m_conversionRule = conversionRule; + } + + /// Returns the type convertion rule + QString conversionRule() const + { + //skip conversions flag + return m_conversionRule.mid(1); + } + + /// Returns true if there are any conversiton rule for this type, false otherwise. + bool hasConversionRule() const + { + return !m_conversionRule.isEmpty(); + } + + double version() const + { + return m_version; + } + + /// TODO-CONVERTER: mark as deprecated + bool hasNativeConversionRule() const + { + return m_conversionRule.startsWith(QLatin1String(NATIVE_CONVERSION_RULE_FLAG)); + } + + /// TODO-CONVERTER: mark as deprecated + bool hasTargetConversionRule() const + { + return m_conversionRule.startsWith(QLatin1String(TARGET_CONVERSION_RULE_FLAG)); + } + + bool isCppPrimitive() const; + + bool hasCustomConversion() const; + void setCustomConversion(CustomConversion* customConversion); + CustomConversion* customConversion() const; +private: + QString m_name; + Type m_type; + uint m_codeGeneration; + CustomFunction m_customConstructor; + CustomFunction m_customDestructor; + bool m_preferredConversion; + CodeSnipList m_codeSnips; + DocModificationList m_docModifications; + IncludeList m_extraIncludes; + Include m_include; + QHash m_includesUsed; + QString m_conversionRule; + bool m_stream; + double m_version; +}; + +class TypeSystemTypeEntry : public TypeEntry +{ +public: + TypeSystemTypeEntry(const QString &name, double vr) + : TypeEntry(name, TypeSystemType, vr) + { + }; +}; + +class VoidTypeEntry : public TypeEntry +{ +public: + VoidTypeEntry() : TypeEntry(QLatin1String("void"), VoidType, 0) { } +}; + +class VarargsTypeEntry : public TypeEntry +{ +public: + VarargsTypeEntry() : TypeEntry(QLatin1String("..."), VarargsType, 0) { } +}; + +class TemplateArgumentEntry : public TypeEntry +{ +public: + TemplateArgumentEntry(const QString &name, double vr) + : TypeEntry(name, TemplateArgumentType, vr), m_ordinal(0) + { + } + + int ordinal() const + { + return m_ordinal; + } + void setOrdinal(int o) + { + m_ordinal = o; + } + +private: + int m_ordinal; +}; + +class ArrayTypeEntry : public TypeEntry +{ +public: + ArrayTypeEntry(const TypeEntry *nested_type, double vr) + : TypeEntry(QLatin1String("Array"), ArrayType, vr), m_nestedType(nested_type) + { + Q_ASSERT(m_nestedType); + } + + void setNestedTypeEntry(TypeEntry *nested) + { + m_nestedType = nested; + } + const TypeEntry *nestedTypeEntry() const + { + return m_nestedType; + } + + QString targetLangName() const override + { + return m_nestedType->targetLangName() + QLatin1String("[]"); + } + QString targetLangApiName() const override + { + if (m_nestedType->isPrimitive()) + return m_nestedType->targetLangApiName() + QLatin1String("Array"); + else + return QLatin1String("jobjectArray"); + } + +private: + const TypeEntry *m_nestedType; +}; + + +class PrimitiveTypeEntry : public TypeEntry +{ +public: + PrimitiveTypeEntry(const QString &name, double vr) + : TypeEntry(name, PrimitiveType, vr), + m_preferredConversion(true), + m_preferredTargetLangType(true), + m_referencedTypeEntry(0) + { + } + + QString targetLangName() const override + { + return m_targetLangName; + } + void setTargetLangName(const QString &targetLangName) + { + m_targetLangName = targetLangName; + } + + QString targetLangApiName() const override + { + return m_targetLangApiName; + } + void setTargetLangApiName(const QString &targetLangApiName) + { + m_targetLangApiName = targetLangApiName; + } + + QString defaultConstructor() const + { + return m_defaultConstructor; + } + void setDefaultConstructor(const QString& defaultConstructor) + { + m_defaultConstructor = defaultConstructor; + } + bool hasDefaultConstructor() const + { + return !m_defaultConstructor.isEmpty(); + } + + /** + * The PrimitiveTypeEntry pointed by this type entry if it + * represents a typedef). + * /return the type referenced by the typedef, or a null pointer + * if the current object is not an typedef + */ + PrimitiveTypeEntry* referencedTypeEntry() const { return m_referencedTypeEntry; } + + /** + * Defines type referenced by this entry. + * /param referencedTypeEntry type referenced by this entry + */ + void setReferencedTypeEntry(PrimitiveTypeEntry* referencedTypeEntry) + { + m_referencedTypeEntry = 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 + */ + PrimitiveTypeEntry* basicReferencedTypeEntry() const; + + bool preferredConversion() const override + { + return m_preferredConversion; + } + void setPreferredConversion(bool b) override + { + m_preferredConversion = b; + } + + bool preferredTargetLangType() const + { + return m_preferredTargetLangType; + } + void setPreferredTargetLangType(bool b) + { + m_preferredTargetLangType = b; + } + + void setTargetLangPackage(const QString& package); + QString targetLangPackage() const override; +private: + QString m_targetLangName; + QString m_targetLangApiName; + QString m_defaultConstructor; + uint m_preferredConversion : 1; + uint m_preferredTargetLangType : 1; + PrimitiveTypeEntry* m_referencedTypeEntry; +}; + +struct EnumValueRedirection +{ + EnumValueRedirection() {} + EnumValueRedirection(const QString &rej, const QString &us) + : rejected(rej), + used(us) + { + } + QString rejected; + QString used; +}; + +class EnumTypeEntry : public TypeEntry +{ +public: + EnumTypeEntry(const QString &nspace, const QString &enumName, double vr) + : TypeEntry(nspace.isEmpty() ? enumName : nspace + QLatin1String("::") + enumName, + EnumType, vr), + m_qualifier(nspace), + m_targetLangName(enumName), + m_flags(0), + m_extensible(false), + m_forceInteger(false), + m_anonymous(false) + { + } + + QString targetLangPackage() const + { + return m_packageName; + } + void setTargetLangPackage(const QString &package) + { + m_packageName = package; + } + + QString targetLangName() const + { + return m_targetLangName; + } + QString targetLangQualifier() const; + QString qualifiedTargetLangName() const override + { + QString qualifiedName; + QString pkg = targetLangPackage(); + QString qualifier = targetLangQualifier(); + + if (!pkg.isEmpty()) + qualifiedName += pkg + QLatin1Char('.'); + if (!qualifier.isEmpty()) + qualifiedName += qualifier + QLatin1Char('.'); + qualifiedName += targetLangName(); + + return qualifiedName; + } + + QString targetLangApiName() const override; + + QString qualifier() const + { + return m_qualifier; + } + void setQualifier(const QString &q) + { + m_qualifier = q; + } + + bool preferredConversion() const override + { + return false; + } + + bool isBoundsChecked() const + { + return m_lowerBound.isEmpty() && m_upperBound.isEmpty(); + } + + QString upperBound() const + { + return m_upperBound; + } + void setUpperBound(const QString &bound) + { + m_upperBound = bound; + } + + QString lowerBound() const + { + return m_lowerBound; + } + void setLowerBound(const QString &bound) + { + m_lowerBound = bound; + } + + void setFlags(FlagsTypeEntry *flags) + { + m_flags = flags; + } + FlagsTypeEntry *flags() const + { + return m_flags; + } + + bool isExtensible() const + { + return m_extensible; + } + void setExtensible(bool is) + { + m_extensible = is; + } + + bool isEnumValueRejected(const QString &name) + { + return m_rejectedEnums.contains(name); + } + void addEnumValueRejection(const QString &name) + { + m_rejectedEnums << name; + } + QStringList enumValueRejections() const + { + return m_rejectedEnums; + } + + void addEnumValueRedirection(const QString &rejected, const QString &usedValue); + QString enumValueRedirection(const QString &value) const; + + bool forceInteger() const + { + return m_forceInteger; + } + void setForceInteger(bool force) + { + m_forceInteger = force; + } + + bool isAnonymous() const + { + return m_anonymous; + } + void setAnonymous(bool anonymous) + { + m_anonymous = anonymous; + } + +private: + QString m_packageName; + QString m_qualifier; + QString m_targetLangName; + + QString m_lowerBound; + QString m_upperBound; + + QStringList m_rejectedEnums; + QVector m_enumRedirections; + + FlagsTypeEntry *m_flags; + + bool m_extensible; + bool m_forceInteger; + bool m_anonymous; +}; + +class EnumValueTypeEntry : public TypeEntry +{ +public: + EnumValueTypeEntry(const QString& name, const QString& value, const EnumTypeEntry* enclosingEnum, double vr) + : TypeEntry(name, TypeEntry::EnumValue, vr), m_value(value), m_enclosingEnum(enclosingEnum) + { + } + + QString value() const { return m_value; } + const EnumTypeEntry* enclosingEnum() const { return m_enclosingEnum; } +private: + QString m_value; + const EnumTypeEntry* m_enclosingEnum; +}; + +class FlagsTypeEntry : public TypeEntry +{ +public: + FlagsTypeEntry(const QString &name, double vr) : TypeEntry(name, FlagsType, vr), m_enum(0) + { + } + + QString qualifiedTargetLangName() const override; + QString targetLangName() const override + { + return m_targetLangName; + } + QString targetLangApiName() const override; + bool preferredConversion() const override + { + return false; + } + + QString originalName() const + { + return m_originalName; + } + void setOriginalName(const QString &s) + { + m_originalName = s; + } + + QString flagsName() const + { + return m_targetLangName; + } + void setFlagsName(const QString &name) + { + m_targetLangName = name; + } + + bool forceInteger() const + { + return m_enum->forceInteger(); + } + + EnumTypeEntry *originator() const + { + return m_enum; + } + void setOriginator(EnumTypeEntry *e) + { + m_enum = e; + } + + QString targetLangPackage() const override + { + return m_enum->targetLangPackage(); + } + +private: + QString m_originalName; + QString m_targetLangName; + EnumTypeEntry *m_enum; +}; + + +class ComplexTypeEntry : public TypeEntry +{ +public: + enum TypeFlag { + ForceAbstract = 0x1, + DeleteInMainThread = 0x2, + Deprecated = 0x4 + }; + typedef QFlags TypeFlags; + + enum CopyableFlag { + CopyableSet, + NonCopyableSet, + Unknown + }; + + ComplexTypeEntry(const QString &name, Type t, double vr) + : TypeEntry(QString(name).replace(QLatin1String(".*::"), QString()), t, vr), + m_qualifiedCppName(name), + m_qobject(false), + m_polymorphicBase(false), + m_genericClass(false), + m_typeFlags(0), + m_copyableFlag(Unknown), + m_baseContainerType(0) + { + } + + bool isComplex() const + { + return true; + } + + ComplexTypeEntry *copy() const + { + ComplexTypeEntry *centry = new ComplexTypeEntry(name(), type(), version()); + centry->setInclude(include()); + centry->setExtraIncludes(extraIncludes()); + centry->setAddedFunctions(addedFunctions()); + centry->setFunctionModifications(functionModifications()); + centry->setFieldModifications(fieldModifications()); + centry->setQObject(isQObject()); + centry->setDefaultSuperclass(defaultSuperclass()); + centry->setCodeSnips(codeSnips()); + centry->setTargetLangPackage(targetLangPackage()); + centry->setBaseContainerType(baseContainerType()); + centry->setDefaultConstructor(defaultConstructor()); + + return centry; + } + + void setLookupName(const QString &name) + { + m_lookupName = name; + } + + QString lookupName() const override + { + return m_lookupName.isEmpty() ? targetLangName() : m_lookupName; + } + + QString targetLangApiName() const override; + + void setTypeFlags(TypeFlags flags) + { + m_typeFlags = flags; + } + + TypeFlags typeFlags() const + { + return m_typeFlags; + } + + FunctionModificationList functionModifications() const + { + return m_functionMods; + } + void setFunctionModifications(const FunctionModificationList &functionModifications) + { + m_functionMods = functionModifications; + } + void addFunctionModification(const FunctionModification &functionModification) + { + m_functionMods << functionModification; + } + FunctionModificationList functionModifications(const QString &signature) const; + + AddedFunctionList addedFunctions() const + { + return m_addedFunctions; + } + void setAddedFunctions(const AddedFunctionList &addedFunctions) + { + m_addedFunctions = addedFunctions; + } + void addNewFunction(const AddedFunction &addedFunction) + { + m_addedFunctions << addedFunction; + } + + FieldModification fieldModification(const QString &name) const; + void setFieldModifications(const FieldModificationList &mods) + { + m_fieldMods = mods; + } + FieldModificationList fieldModifications() const + { + return m_fieldMods; + } + + QString targetLangPackage() const + { + return m_package; + } + void setTargetLangPackage(const QString &package) + { + m_package = package; + } + + bool isQObject() const + { + return m_qobject; + } + void setQObject(bool qobject) + { + m_qobject = qobject; + } + + QString defaultSuperclass() const + { + return m_defaultSuperclass; + } + void setDefaultSuperclass(const QString &sc) + { + m_defaultSuperclass = sc; + } + + QString qualifiedCppName() const override + { + return m_qualifiedCppName; + } + + + void setIsPolymorphicBase(bool on) + { + m_polymorphicBase = on; + } + bool isPolymorphicBase() const + { + return m_polymorphicBase; + } + + void setPolymorphicIdValue(const QString &value) + { + m_polymorphicIdValue = value; + } + QString polymorphicIdValue() const + { + return m_polymorphicIdValue; + } + + void setHeldType(const QString &value) + { + m_heldTypeValue = value; + } + QString heldTypeValue() const + { + return m_heldTypeValue; + } + + + void setExpensePolicy(const ExpensePolicy &policy) + { + m_expensePolicy = policy; + } + const ExpensePolicy &expensePolicy() const + { + return m_expensePolicy; + } + + QString targetType() const + { + return m_targetType; + } + void setTargetType(const QString &code) + { + m_targetType = code; + } + + QString targetLangName() const override + { + return m_targetLangName.isEmpty() + ? TypeEntry::targetLangName() + : m_targetLangName; + } + void setTargetLangName(const QString &name) + { + m_targetLangName = name; + } + + bool isGenericClass() const + { + return m_genericClass; + } + void setGenericClass(bool isGeneric) + { + m_genericClass = isGeneric; + } + + CopyableFlag copyable() const + { + return m_copyableFlag; + } + void setCopyable(CopyableFlag flag) + { + m_copyableFlag = flag; + } + + QString hashFunction() const + { + return m_hashFunction; + } + void setHashFunction(QString hashFunction) + { + m_hashFunction = hashFunction; + } + + void setBaseContainerType(const ComplexTypeEntry *baseContainer) + { + m_baseContainerType = baseContainer; + } + + const ComplexTypeEntry* baseContainerType() const + { + return m_baseContainerType; + } + + QString defaultConstructor() const; + void setDefaultConstructor(const QString& defaultConstructor); + bool hasDefaultConstructor() const; + +private: + AddedFunctionList m_addedFunctions; + FunctionModificationList m_functionMods; + FieldModificationList m_fieldMods; + QString m_package; + QString m_defaultSuperclass; + QString m_qualifiedCppName; + QString m_targetLangName; + + uint m_qobject : 1; + uint m_polymorphicBase : 1; + uint m_genericClass : 1; + + QString m_polymorphicIdValue; + QString m_heldTypeValue; + QString m_lookupName; + QString m_targetType; + ExpensePolicy m_expensePolicy; + TypeFlags m_typeFlags; + CopyableFlag m_copyableFlag; + QString m_hashFunction; + + const ComplexTypeEntry* m_baseContainerType; +}; + +class ContainerTypeEntry : public ComplexTypeEntry +{ + Q_GADGET +public: + enum Type { + NoContainer, + ListContainer, + StringListContainer, + LinkedListContainer, + VectorContainer, + StackContainer, + QueueContainer, + SetContainer, + MapContainer, + MultiMapContainer, + HashContainer, + MultiHashContainer, + PairContainer, + }; + Q_ENUM(Type) + + ContainerTypeEntry(const QString &name, Type type, double vr) + : ComplexTypeEntry(name, ContainerType, vr), m_type(type) + { + setCodeGeneration(GenerateForSubclass); + } + + Type type() const + { + return m_type; + } + + QString typeName() const; + QString targetLangName() const; + QString targetLangPackage() const; + QString qualifiedCppName() const; + + static Type containerTypeFromString(QString typeName) + { + static QHash m_stringToContainerType; + if (m_stringToContainerType.isEmpty()) { + m_stringToContainerType.insert(QLatin1String("list"), ListContainer); + m_stringToContainerType.insert(QLatin1String("string-list"), StringListContainer); + m_stringToContainerType.insert(QLatin1String("linked-list"), LinkedListContainer); + m_stringToContainerType.insert(QLatin1String("vector"), VectorContainer); + m_stringToContainerType.insert(QLatin1String("stack"), StackContainer); + m_stringToContainerType.insert(QLatin1String("queue"), QueueContainer); + m_stringToContainerType.insert(QLatin1String("set"), SetContainer); + m_stringToContainerType.insert(QLatin1String("map"), MapContainer); + m_stringToContainerType.insert(QLatin1String("multi-map"), MultiMapContainer); + m_stringToContainerType.insert(QLatin1String("hash"), HashContainer); + m_stringToContainerType.insert(QLatin1String("multi-hash"), MultiHashContainer); + m_stringToContainerType.insert(QLatin1String("pair"), PairContainer); + } + return m_stringToContainerType.value(typeName, NoContainer); + } + +private: + Type m_type; +}; + +class SmartPointerTypeEntry : public ComplexTypeEntry +{ +public: + SmartPointerTypeEntry(const QString &name, + const QString &getterName, + const QString &smartPointerType, + const QString &refCountMethodName, + double vr) + : ComplexTypeEntry(name, SmartPointerType, vr), + m_getterName(getterName), + m_smartPointerType(smartPointerType), + m_refCountMethodName(refCountMethodName) + { + } + + QString getter() const + { + return m_getterName; + } + + QString refCountMethodName() const + { + return m_refCountMethodName; + } + +private: + QString m_getterName; + QString m_smartPointerType; + QString m_refCountMethodName; +}; + +class NamespaceTypeEntry : public ComplexTypeEntry +{ +public: + NamespaceTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, NamespaceType, vr) { } +}; + + +class ValueTypeEntry : public ComplexTypeEntry +{ +public: + ValueTypeEntry(const QString &name, double vr) : ComplexTypeEntry(name, BasicValueType, vr) { } + + bool isValue() const override + { + return true; + } + + bool isNativeIdBased() const override + { + return true; + } + +protected: + ValueTypeEntry(const QString &name, Type t, double vr) : ComplexTypeEntry(name, t, vr) { } +}; + + +class StringTypeEntry : public ValueTypeEntry +{ +public: + StringTypeEntry(const QString &name, double vr) + : ValueTypeEntry(name, StringType, vr) + { + setCodeGeneration(GenerateNothing); + } + + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override; + + bool isNativeIdBased() const override + { + return false; + } +}; + +class CharTypeEntry : public ValueTypeEntry +{ +public: + CharTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, CharType, vr) + { + setCodeGeneration(GenerateNothing); + } + + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override + { + return QString(); + } + + bool isNativeIdBased() const override + { + return false; + } +}; + +class VariantTypeEntry: public ValueTypeEntry +{ +public: + VariantTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, VariantType, vr) { } + + QString targetLangApiName() const override; + QString targetLangName() const override; + QString targetLangPackage() const override; + + bool isNativeIdBased() const override + { + return false; + } +}; + + +class InterfaceTypeEntry : public ComplexTypeEntry +{ +public: + InterfaceTypeEntry(const QString &name, double vr) + : ComplexTypeEntry(name, InterfaceType, vr) {} + + static QString interfaceName(const QString &name) + { + return name + QLatin1String("Interface"); + } + + ObjectTypeEntry *origin() const + { + return m_origin; + } + void setOrigin(ObjectTypeEntry *origin) + { + m_origin = origin; + } + + bool isNativeIdBased() const override + { + return true; + } + QString qualifiedCppName() const override + { + const int len = ComplexTypeEntry::qualifiedCppName().length() - interfaceName(QString()).length(); + return ComplexTypeEntry::qualifiedCppName().left(len); + } + +private: + ObjectTypeEntry *m_origin; +}; + + +class FunctionTypeEntry : public TypeEntry +{ +public: + FunctionTypeEntry(const QString& name, const QString& signature, double vr) + : TypeEntry(name, FunctionType, vr) + { + addSignature(signature); + } + void addSignature(const QString& signature) + { + m_signatures << signature; + } + + QStringList signatures() const + { + return m_signatures; + } + + bool hasSignature(const QString& signature) const + { + return m_signatures.contains(signature); + } +private: + QStringList m_signatures; +}; + +class ObjectTypeEntry : public ComplexTypeEntry +{ +public: + ObjectTypeEntry(const QString &name, double vr) + : ComplexTypeEntry(name, ObjectType, vr), m_interface(0) {} + + InterfaceTypeEntry *designatedInterface() const + { + return m_interface; + } + void setDesignatedInterface(InterfaceTypeEntry *entry) + { + m_interface = entry; + } + + bool isNativeIdBased() const override + { + return true; + } + +private: + InterfaceTypeEntry *m_interface; +}; + +struct TypeRejection +{ + enum MatchType + { + ExcludeClass, // Match className only + Function, // Match className and function name + Field, // Match className and field name + Enum, // Match className and enum name + ArgumentType, // Match className and argument type + ReturnType // Match className and return type + }; + + QRegularExpression className; + QRegularExpression pattern; + MatchType matchType; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const TypeRejection &r); +#endif + +QString fixCppTypeName(const QString &name); + +class CustomConversion +{ +public: + CustomConversion(TypeEntry* ownerType); + ~CustomConversion(); + + const TypeEntry* 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. + */ + bool replaceOriginalTargetToNativeConversions() const; + void setReplaceOriginalTargetToNativeConversions(bool replaceOriginalTargetToNativeConversions); + + typedef QVector TargetToNativeConversions; + bool hasTargetToNativeConversions() const; + TargetToNativeConversions& targetToNativeConversions(); + const TargetToNativeConversions& targetToNativeConversions() const; + void addTargetToNativeConversion(const QString& sourceTypeName, + const QString& sourceTypeCheck, + const QString& conversion = QString()); +private: + struct CustomConversionPrivate; + CustomConversionPrivate* m_d; +}; + +#endif // TYPESYSTEM_H diff --git a/sources/shiboken2/ApiExtractor/typesystem_enums.h b/sources/shiboken2/ApiExtractor/typesystem_enums.h new file mode 100644 index 000000000..2d67d7cc5 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typesystem_enums.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPESYSTEM_ENUMS_H +#define TYPESYSTEM_ENUMS_H + +namespace TypeSystem +{ +enum Language { + NoLanguage = 0x0000, + TargetLangCode = 0x0001, + NativeCode = 0x0002, + ShellCode = 0x0004, + ShellDeclaration = 0x0008, + PackageInitializer = 0x0010, + DestructorFunction = 0x0020, + Constructors = 0x0040, + Interface = 0x0080, + + // masks + All = TargetLangCode + | NativeCode + | ShellCode + | ShellDeclaration + | PackageInitializer + | Constructors + | Interface + | DestructorFunction, + + TargetLangAndNativeCode = TargetLangCode | NativeCode +}; + +enum Ownership { + InvalidOwnership, + DefaultOwnership, + TargetLangOwnership, + CppOwnership +}; + +enum CodeSnipPosition { + CodeSnipPositionBeginning, + CodeSnipPositionEnd, + CodeSnipPositionAfterThis, + // QtScript + CodeSnipPositionDeclaration, + CodeSnipPositionPrototypeInitialization, + CodeSnipPositionConstructorInitialization, + CodeSnipPositionConstructor, + CodeSnipPositionAny +}; + +enum DocModificationMode { + DocModificationAppend, + DocModificationPrepend, + DocModificationReplace, + DocModificationXPathReplace +}; + +} // namespace TypeSystem + +#endif // TYPESYSTEM_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/typesystem_p.h b/sources/shiboken2/ApiExtractor/typesystem_p.h new file mode 100644 index 000000000..f2105a631 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typesystem_p.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef TYPESYSTEM_P_H +#define TYPESYSTEM_P_H + +#include +#include "typesystem.h" + +QT_FORWARD_DECLARE_CLASS(QXmlStreamAttributes) +QT_FORWARD_DECLARE_CLASS(QXmlStreamReader) + +class TypeDatabase; +class StackElement +{ + public: + enum ElementType { + None = 0x0, + + // Type tags (0x1, ... , 0xff) + ObjectTypeEntry = 0x1, + ValueTypeEntry = 0x2, + InterfaceTypeEntry = 0x3, + NamespaceTypeEntry = 0x4, + ComplexTypeEntryMask = 0x7, + + // Non-complex type tags (0x8, 0x9, ... , 0xf) + PrimitiveTypeEntry = 0x8, + EnumTypeEntry = 0x9, + ContainerTypeEntry = 0xa, + FunctionTypeEntry = 0xb, + CustomTypeEntry = 0xc, + SmartPointerTypeEntry = 0xd, + TypeEntryMask = 0xf, + + // Documentation tags + InjectDocumentation = 0x10, + ModifyDocumentation = 0x20, + DocumentationMask = 0xf0, + + // Simple tags (0x100, 0x200, ... , 0xf00) + ExtraIncludes = 0x0100, + Include = 0x0200, + ModifyFunction = 0x0300, + ModifyField = 0x0400, + Root = 0x0500, + CustomMetaConstructor = 0x0600, + CustomMetaDestructor = 0x0700, + ArgumentMap = 0x0800, + SuppressedWarning = 0x0900, + Rejection = 0x0a00, + LoadTypesystem = 0x0b00, + RejectEnumValue = 0x0c00, + Template = 0x0d00, + TemplateInstanceEnum = 0x0e00, + Replace = 0x0f00, + AddFunction = 0x1000, + NativeToTarget = 0x1100, + TargetToNative = 0x1200, + AddConversion = 0x1300, + SimpleMask = 0x3f00, + + // Code snip tags (0x1000, 0x2000, ... , 0xf000) + InjectCode = 0x4000, + InjectCodeInFunction = 0x8000, + CodeSnipMask = 0xc000, + + // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) + Access = 0x010000, + Removal = 0x020000, + Rename = 0x040000, + ModifyArgument = 0x080000, + Thread = 0x100000, + FunctionModifiers = 0xff0000, + + // Argument modifier tags (0x01000000 ... 0xf0000000) + ConversionRule = 0x01000000, + ReplaceType = 0x02000000, + ReplaceDefaultExpression = 0x04000000, + RemoveArgument = 0x08000000, + DefineOwnership = 0x10000000, + RemoveDefaultExpression = 0x20000000, + NoNullPointers = 0x40000000, + ReferenceCount = 0x80000000, + ParentOwner = 0x90000000, + ArgumentModifiers = 0xff000000 + }; + + StackElement(StackElement *p) : entry(0), type(None), parent(p) { } + + TypeEntry* entry; + ElementType type; + StackElement *parent; + + union { + TemplateInstance* templateInstance; + TemplateEntry* templateEntry; + CustomFunction* customFunction; + } value; +}; + +struct StackElementContext +{ + CodeSnipList codeSnips; + AddedFunctionList addedFunctions; + FunctionModificationList functionMods; + FieldModificationList fieldMods; + DocModificationList docModifications; +}; + +class Handler +{ +public: + Handler(TypeDatabase* database, bool generate); + + bool parse(QXmlStreamReader &reader); + +private: + bool startElement(const QStringRef& localName, const QXmlStreamAttributes& atts); + bool handleSmartPointerEntry(StackElement *element, + QHash &attributes, + const QString &name, + double since); + bool endElement(const QStringRef& localName); + template // QString/QStringRef + bool characters(const String &ch); + void fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts, + QHash *acceptedAttributes); + + bool importFileElement(const QXmlStreamAttributes &atts); + bool convertBoolean(const QString &, const QString &, bool); + void addFlags(const QString &name, QString flagName, + const QHash &attributes, double since); + + TypeDatabase* m_database; + StackElement* m_current; + StackElement* m_currentDroppedEntry; + int m_currentDroppedEntryDepth; + int m_ignoreDepth; + QString m_defaultPackage; + QString m_defaultSuperclass; + QString m_error; + TypeEntry::CodeGeneration m_generate; + + EnumTypeEntry* m_currentEnum; + QStack m_contextStack; + + QHash tagNames; + QString m_currentSignature; +}; + +#endif diff --git a/sources/shiboken2/ApiExtractor/typesystem_typedefs.h b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h new file mode 100644 index 000000000..4f29deced --- /dev/null +++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPESYSTEM_TYPEDEFS_H +#define TYPESYSTEM_TYPEDEFS_H + +#include +#include +#include + +class CodeSnip; +class DocModification; + +struct AddedFunction; +struct FieldModification; +struct FunctionModification; + +typedef QVector AddedFunctionList; +typedef QVector CodeSnipList; +typedef QVector DocModificationList; +typedef QVector FieldModificationList; +typedef QVector FunctionModificationList; + +#endif // TYPESYSTEM_TYPEDEFS_H diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt new file mode 100644 index 000000000..ddba62df8 --- /dev/null +++ b/sources/shiboken2/CMakeLists.txt @@ -0,0 +1,285 @@ +Include(icecc.cmake) +project(shiboken2) + +cmake_minimum_required(VERSION 3.0) +cmake_policy(VERSION 3.0) + +set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ + ${CMAKE_MODULE_PATH}) + +find_package(Qt5 REQUIRED COMPONENTS Core Xml XmlPatterns) + +add_definitions(${Qt5Core_DEFINITIONS}) + +set(shiboken_MAJOR_VERSION "2") +set(shiboken_MINOR_VERSION "0") +set(shiboken_MICRO_VERSION "0") +set(shiboken2_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") + +option(BUILD_TESTS "Build tests." TRUE) +option(USE_PYTHON_VERSION "Use specific python version to build shiboken2." "") + +if (USE_PYTHON_VERSION) + find_package(PythonInterp ${USE_PYTHON_VERSION} REQUIRED) + find_package(PythonLibs ${USE_PYTHON_VERSION} REQUIRED) +else() + find_package(PythonInterp 2.6) + find_package(PythonLibs 2.6) +endif() + +set(CLANG_DIR "") +set(CLANG_DIR_SOURCE "") + +if (DEFINED ENV{LLVM_INSTALL_DIR}) + set(CLANG_DIR $ENV{LLVM_INSTALL_DIR}) + set(CLANG_DIR_SOURCE "LLVM_INSTALL_DIR") +elseif (DEFINED ENV{CLANG_INSTALL_DIR}) + set(CLANG_DIR $ENV{CLANG_INSTALL_DIR}) + set(CLANG_DIR_SOURCE "CLANG_INSTALL_DIR") +else () + EXEC_PROGRAM("llvm-config" ARGS "--prefix" OUTPUT_VARIABLE CLANG_DIR) + set(CLANG_DIR_SOURCE "llvm-config") + if (NOT "${CLANG_DIR}" STREQUAL "") + EXEC_PROGRAM("llvm-config" ARGS "--version" OUTPUT_VARIABLE CLANG_VERSION) + if (CLANG_VERSION VERSION_LESS 3.9) + message(FATAL_ERROR "LLVM version 3.9 is required (llvm-config detected ${CLANG_VERSION} at ${CLANG_DIR}).") + endif() + endif() +endif() + +if ("${CLANG_DIR}" STREQUAL "") + message(FATAL_ERROR "Unable to detect CLANG location by checking LLVM_INSTALL_DIR, CLANG_INSTALL_DIR or running llvm-config.") +elseif (NOT IS_DIRECTORY ${CLANG_DIR}) + message(FATAL_ERROR "${CLANG_DIR} detected by ${CLANG_DIR_SOURCE} does not exist.") +endif() + +set(CLANG_LIB_NAME "clang") +if(MSVC) + set(CLANG_LIB_NAME "libclang") +endif() + +find_library(CLANG_LIBRARY ${CLANG_LIB_NAME} HINTS ${CLANG_DIR}/lib) +if (NOT EXISTS ${CLANG_LIBRARY}) + message(FATAL_ERROR "Unable to find Clang library ${CLANG_LIB_NAME} in ${CLANG_DIR}.") +endif() + +message(STATUS "CLANG: ${CLANG_DIR}, ${CLANG_LIBRARY} detected by ${CLANG_DIR_SOURCE}") + +set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include) +set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY}) + +## For debugging the PYTHON* variables +message("PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) +message("PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) +message("PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) +message("PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) +message("PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) +message("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) +message("PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}) + +# Queries the python sysconfig for the abi flags which need to be inserted into extension suffixes. +# Only present starting with Python 3.2. +# Corresponding configure switches to single letter flags: +# --with-pymalloc -> m +# --with-pydebug -> d +# --with-unicode -> u (rare) +macro(get_python3_abi_flags) + if (NOT PYTHON_ABI_FLAGS) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sysconfig + print(sysconfig.get_config_var('abiflags')) + " + OUTPUT_VARIABLE PYTHON_ABI_FLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + message("PYTHON_ABI_FLAGS: " ${PYTHON_ABI_FLAGS}) +endmacro() + +macro(get_python_multi_arch_suffix) + # TODO: This part needs testing to check if it is available on Windows. + # It is present on macOS, but is not used yet. + # Result is something like 'x86_64-linux-gnu'. + if (NOT PYTHON_MULTIARCH_SUFFIX) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sysconfig + print(sysconfig.get_config_var('MULTIARCH')) + " + OUTPUT_VARIABLE PYTHON_MULTIARCH_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + message("PYTHON_MULTIARCH_SUFFIX: " ${PYTHON_MULTIARCH_SUFFIX}) +endmacro() + +macro(get_python2_release_suffix) + # Result of imp.get_suffixes() is something like: + # [('_d.so', 'rb', 3), ('module_d.so', 'rb', 3), ('.x86_64-linux-gnu_d.so', 'rb', 3)] + # or alternatively the same but withut the '_d' part. + # The list comprehension is used to choose which suffix to include in library names. + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import imp + print('_d' if any([tup[0].endswith('_d.so') for tup in imp.get_suffixes()]) else '') + " + OUTPUT_VARIABLE PYTHON_MODULE_RELEASE_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("PYTHON_MODULE_RELEASE_SUFFIX: " ${PYTHON_MODULE_RELEASE_SUFFIX}) +endmacro() + +# Note the quirk that UNIX includes Apple! +if (UNIX AND NOT APPLE) + if (NOT PYTHON_EXTENSION_SUFFIX) + get_python_multi_arch_suffix() + # The suffix added to .so libraries should be differenet between Python 2 and 3. + # The position of the multiarch suffix is different, and the way the debug flag is set + # computed differently. + # In Python 2 there is no standard way to query if the python interpeter was built in debug or + # release build (sysconfig.get_config_var('Py_Debug') can have a different value than you would + # expect if you do a custom Python build). The solution is to query for the import + # suffixes and check if _d is present there. It is present on Linux distribution + # packages of Python, but not in custom built Python builds, because the distros apply their + # custom patches too append the '_d's. + # In Python 3 (starting with 3.2) there is a standard way to check if '_d' needs to be added, + # as well as any other letters, by querying the abiflags sysconfig variable. + if (PYTHON_VERSION_MAJOR EQUAL 2) + get_python2_release_suffix() + if(PYTHON_MULTIARCH_SUFFIX) + set(PYTHON_EXTENSION_SUFFIX ".${PYTHON_MULTIARCH_SUFFIX}") + endif() + set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}${PYTHON_MODULE_RELEASE_SUFFIX}") + elseif (PYTHON_VERSION_MAJOR EQUAL 3) + get_python3_abi_flags() + set(PYTHON_EXTENSION_SUFFIX ".cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}${PYTHON_ABI_FLAGS}") + if(PYTHON_MULTIARCH_SUFFIX) + set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}-${PYTHON_MULTIARCH_SUFFIX}") + endif() + else() + message(FATAL_ERROR "Unsupported PYTHON_VERSION=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}!") + endif() + endif() + message(STATUS "PYTHON_EXTENSION_SUFFIX: ${PYTHON_EXTENSION_SUFFIX}") +endif () + +if (NOT PYTHON_SITE_PACKAGES) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + from distutils import sysconfig + from os.path import sep + print(sysconfig.get_python_lib(1, 0, prefix='${CMAKE_INSTALL_PREFIX}').replace(sep, '/')) + " + OUTPUT_VARIABLE PYTHON_SITE_PACKAGES + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (NOT PYTHON_SITE_PACKAGES) + message(FATAL_ERROR "Could not detect Python module installation directory.") + elseif (APPLE) + message(STATUS "!!! The generated bindings will be installed on ${PYTHON_SITE_PACKAGES}, is it right!?") + endif() +endif() + +if(MSVC) + # Qt5: this flag has changed from /Zc:wchar_t- in Qt4.X + set(CMAKE_CXX_FLAGS "/Zc:wchar_t /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") +else() + if(CMAKE_HOST_UNIX AND NOT CYGWIN) + add_definitions(-fPIC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") + endif() + set(CMAKE_CXX_FLAGS_DEBUG "-g") + option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library size and performance. Only available on Release Mode" 0) + if(ENABLE_GCC_OPTIMIZATION) + set(CMAKE_BUILD_TYPE Release) + set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG -Os -Wl,-O1") + if(NOT CMAKE_HOST_APPLE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--hash-style=gnu") + endif() + endif() +endif() + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_TO_ASCII") + +set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) + +if (WIN32) + set(PATH_SEP "\;") +else() + set(PATH_SEP ":") +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.") + if(OSX_USE_LIBCPP) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() +endif() + +add_subdirectory(ApiExtractor) + +set(generator_plugin_DIR ${LIB_INSTALL_DIR}/generatorrunner${generator_SUFFIX}) + +# uninstall target +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) +add_custom_target(uninstall "${CMAKE_COMMAND}" + -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") + +set(SHIBOKEN_BUILD_TYPE "Release") +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(NOT PYTHON_DEBUG_LIBRARIES) + message(WARNING "Python debug shared library not found; assuming python was built with shared library support disabled.") + endif() + if(NOT PYTHON_WITH_DEBUG) + message(WARNING "Compiling shiboken2 with debug enabled, but the python executable was not compiled with debug support.") + else() + add_definitions("-DPy_DEBUG") + set(SBK_ADD_PY_DEBUG_DEFINITION "add_definitions(\"-DPy_DEBUG\")") + set(SBK_PKG_CONFIG_PY_DEBUG_DEFINITION " -DPy_DEBUG") + endif() + set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) + set(SHIBOKEN_BUILD_TYPE "Debug") +else() + set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) + add_definitions("-DNDEBUG") +endif() +if(APPLE) + set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") +endif() + +if(CMAKE_VERSION VERSION_LESS 2.8) + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_PATH}) +else() + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS}) +endif() + +add_subdirectory(libshiboken) +add_subdirectory(doc) + +# deps found, compile the generator. +if (Qt5Core_FOUND AND PYTHONINTERP_FOUND) + add_subdirectory(generator) + add_subdirectory(shibokenmodule) + + if (BUILD_TESTS) + enable_testing() + add_subdirectory(tests) + endif() +else() + message(WARNING "Some dependencies were not found, shiboken2 generator compilation disabled!") +endif() + +add_subdirectory(data) + +# dist target +set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${shiboken2_VERSION}) +add_custom_target(dist + COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" && + git log > "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}/ChangeLog" && + git archive --prefix=${ARCHIVE_NAME}/ HEAD --format=tar --output="${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && + tar -C "${CMAKE_BINARY_DIR}" --owner=root --group=root -r "${ARCHIVE_NAME}/ChangeLog" -f "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && + bzip2 -f9 "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && + echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2." + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + + diff --git a/sources/shiboken2/COPYING b/sources/shiboken2/COPYING new file mode 100644 index 000000000..4ccd71466 --- /dev/null +++ b/sources/shiboken2/COPYING @@ -0,0 +1,342 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + +------------------------------------------------------------------------- diff --git a/sources/shiboken2/COPYING.libsample b/sources/shiboken2/COPYING.libsample new file mode 100644 index 000000000..9315102f7 --- /dev/null +++ b/sources/shiboken2/COPYING.libsample @@ -0,0 +1,501 @@ +GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + diff --git a/sources/shiboken2/COPYING.libshiboken b/sources/shiboken2/COPYING.libshiboken new file mode 100644 index 000000000..9315102f7 --- /dev/null +++ b/sources/shiboken2/COPYING.libshiboken @@ -0,0 +1,501 @@ +GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + diff --git a/sources/shiboken2/Doxyfile b/sources/shiboken2/Doxyfile new file mode 100644 index 000000000..9be56a0e4 --- /dev/null +++ b/sources/shiboken2/Doxyfile @@ -0,0 +1,311 @@ +# Doxyfile 1.5.7.1 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "Generator Runner" +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /tmp/src/generatorrunner/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +TYPEDEF_HIDES_STRUCT = NO +SYMBOL_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = NO +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /tmp/src/generatorrunner +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.d \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.py \ + *.f90 \ + *.f \ + *.vhd \ + *.vhdl \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.PY \ + *.F90 \ + *.F \ + *.VHD \ + *.VHDL +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 3 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +HTML_DYNAMIC_SECTIONS = NO +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHG_LOCATION = +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NONE +TREEVIEW_WIDTH = 250 +FORMULA_FONTSIZE = 10 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = ../libgenrunner/libgenrunner.tag=../libgenrunner +GENERATE_TAGFILE = generatorrunner.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = YES +DOT_FONTNAME = FreeSans +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = NO +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = NO +INCLUDED_BY_GRAPH = NO +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/sources/shiboken2/LICENSE.GPLv3 b/sources/shiboken2/LICENSE.GPLv3 new file mode 100644 index 000000000..71c4ad49c --- /dev/null +++ b/sources/shiboken2/LICENSE.GPLv3 @@ -0,0 +1,686 @@ + GNU GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2015 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3. That license references + the General Public License version 3, that is displayed below. Other + portions of the Qt Toolkit may be licensed directly under this license. + +------------------------------------------------------------------------- + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/sources/shiboken2/LICENSE.LGPLv21 b/sources/shiboken2/LICENSE.LGPLv21 new file mode 100644 index 000000000..15a208b48 --- /dev/null +++ b/sources/shiboken2/LICENSE.LGPLv21 @@ -0,0 +1,514 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 2.1, which is displayed below. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/sources/shiboken2/LICENSE.LGPLv3 b/sources/shiboken2/LICENSE.LGPLv3 new file mode 100644 index 000000000..849103ad9 --- /dev/null +++ b/sources/shiboken2/LICENSE.LGPLv3 @@ -0,0 +1,175 @@ + GNU LESSER GENERAL PUBLIC LICENSE + + The Qt Toolkit is Copyright (C) 2016 The Qt Company Ltd. + Contact: http://www.qt.io/licensing/ + + You may use, distribute and copy the Qt Toolkit under the terms of + GNU Lesser General Public License version 3, which is displayed below. + This license makes reference to the version 3 of the GNU General + Public License, which you can find in the LICENSE.GPLv3 file. + +------------------------------------------------------------------------- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright © 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies of this +licensedocument, but changing it is not allowed. + +This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + +0. Additional Definitions. + + As used herein, “this License” refers to version 3 of the GNU Lesser +General Public License, and the “GNU GPL” refers to version 3 of the +GNU General Public License. + + “The Library” refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An “Application” is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A “Combined Work” is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the “Linked +Version”. + + The “Minimal Corresponding Source” for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The “Corresponding Application Code” for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + +1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + +2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort + to ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + +3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this + license document. + +4. Combined Works. + + You may convey a Combined Work under terms of your choice that, taken +together, effectively do not restrict modification of the portions of +the Library contained in the Combined Work and reverse engineering for +debugging such modifications, if you also do each of the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this + license document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of + this License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with + the Library. A suitable mechanism is one that (a) uses at run + time a copy of the Library already present on the user's + computer system, and (b) will operate properly with a modified + version of the Library that is interface-compatible with the + Linked Version. + + e) Provide Installation Information, but only if you would + otherwise be required to provide such information under section 6 + of the GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the Application + with a modified version of the Linked Version. (If you use option + 4d0, the Installation Information must accompany the Minimal + Corresponding Source and Corresponding Application Code. If you + use option 4d1, you must provide the Installation Information in + the manner specified by section 6 of the GNU GPL for conveying + Corresponding Source.) + +5. Combined Libraries. + + You may place library facilities that are a work based on the Library +side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities, conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of + it is a work based on the Library, and explaining where to find + the accompanying uncombined form of the same work. + +6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +as you received it specifies that a certain numbered version of the +GNU Lesser General Public License “or any later version” applies to +it, you have the option of following the terms and conditions either +of that published version or of any later version published by the +Free Software Foundation. If the Library as you received it does not +specify a version number of the GNU Lesser General Public License, +you may choose any version of the GNU Lesser General Public License +ever published by the Free Software Foundation. + +If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the Library. + diff --git a/sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL b/sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL new file mode 100644 index 000000000..0f96e738c --- /dev/null +++ b/sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL @@ -0,0 +1,630 @@ +TECHNOLOGY PREVIEW LICENSE AGREEMENT + +For individuals and/or legal entities resident in the Americas (North +America, Central America and South America), the applicable licensing +terms are specified under the heading "Technology Preview License +Agreement: The Americas". + +For individuals and/or legal entities not resident in The Americas, the +applicable licensing terms are specified under the heading "Technology +Preview License Agreement: Rest of the World". + + +TECHNOLOGY PREVIEW LICENSE AGREEMENT: The Americas +Agreement version 2.4 + +This Technology Preview License Agreement ("Agreement")is a legal agreement +between The Qt Company USA, Inc. ("The Qt Company"), with its registered +office at 2350 Mission College Blvd., Suite 1020, Santa Clara, California +95054, U.S.A. and you (either an individual or a legal entity) ("Licensee") +for the Licensed Software (as defined below). + +1. DEFINITIONS + +"Affiliate" of a Party shall mean an entity (i) which is directly or +indirectly controlling such Party; (ii) which is under the same direct +or indirect ownership or control as such Party; or (iii) which is +directly or indirectly owned or controlled by such Party. For these +purposes, an entity shall be treated as being controlled by another if +that other entity has fifty percent (50 %) or more of the votes in such +entity, is able to direct its affairs and/or to control the composition +of its board of directors or equivalent body. + +"Applications" shall mean Licensee's software products created using the +Licensed Software which may include portions of the Licensed Software. + +"Term" shall mean the period of time six (6) months from the later of +(a) the Effective Date; or (b) the date the Licensed Software was +initially delivered to Licensee by The Qt Company. If no specific Effective +Date is set forth in the Agreement, the Effective Date shall be deemed to be +the date the Licensed Software was initially delivered to Licensee. + +"Licensed Software" shall mean the computer software, "online" or +electronic documentation, associated media and printed materials, +including the source code, example programs and the documentation +delivered by The Qt Company to Licensee in conjunction with this Agreement. + +"Party" or "Parties" shall mean Licensee and/or The Qt Company. + + +2. OWNERSHIP + +The Licensed Software is protected by copyright laws and international +copyright treaties, as well as other intellectual property laws and +treaties. The Licensed Software is licensed, not sold. + +If Licensee provides any findings, proposals, suggestions or other +feedback ("Feedback") to The Qt Company regarding the Licensed Software, +The Qt Company shall own all right, title and interest including the +intellectual property rights in and to such Feedback, excluding however any +existing patent rights of Licensee. To the extent Licensee owns or controls +any patents for such Feedback Licensee hereby grants to The Qt Company and its +Affiliates, a worldwide, perpetual, non-transferable, sublicensable, +royalty-free license to (i) use, copy and modify Feedback and to create +derivative works thereof, (ii) to make (and have made), use, import, +sell, offer for sale, lease, dispose, offer for disposal or otherwise +exploit any products or services of The Qt Company containing Feedback, and +(iii) sublicense all the foregoing rights to third party licensees and +customers of The Qt Company and/or its Affiliates. + + +3. VALIDITY OF THE AGREEMENT + +By installing, copying, or otherwise using the Licensed Software, +Licensee agrees to be bound by the terms of this Agreement. If Licensee +does not agree to the terms of this Agreement, Licensee may not install, +copy, or otherwise use the Licensed Software. Upon Licensee's acceptance +of the terms and conditions of this Agreement, The Qt Company grants Licensee +the right to use the Licensed Software in the manner provided below. + + +4. LICENSES + +4.1. Using and Copying + +The Qt Company grants to Licensee a non-exclusive, non-transferable, +time-limited license to use and copy the Licensed Software for sole purpose +of designing, developing and testing Applications, and evaluating and the +Licensed Software during the Term. + +Licensee may install copies of the Licensed Software on an unlimited +number of computers provided that (a) if an individual, only such +individual; or (b) if a legal entity only its employees; use the +Licensed Software for the authorized purposes. + +4.2 No Distribution or Modifications + +Licensee may not disclose, modify, sell, market, commercialise, +distribute, loan, rent, lease, or license the Licensed Software or any +copy of it or use the Licensed Software for any purpose that is not +expressly granted in this Section 4. Licensee may not alter or remove +any details of ownership, copyright, trademark or other property right +connected with the Licensed Software. Licensee may not distribute any +software statically or dynamically linked with the Licensed Software. + +4.3 No Technical Support + +The Qt Company has no obligation to furnish Licensee with any technical +support whatsoever. Any such support is subject to separate agreement between +the Parties. + + +5. PRE-RELEASE CODE +The Licensed Software contains pre-release code that is not at the level +of performance and compatibility of a final, generally available, +product offering. The Licensed Software may not operate correctly and +may be substantially modified prior to the first commercial product +release, if any. The Qt Company is not obligated to make this or any later +version of the Licensed Software commercially available. The License +Software is "Not for Commercial Use" and may only be used for the +purposes described in Section 4. The Licensed Software may not be used +in a live operating environment where it may be relied upon to perform +in the same manner as a commercially released product or with data that +has not been sufficiently backed up. + +6. THIRD PARTY SOFTWARE + +The Licensed Software may provide links to third party libraries or code +(collectively "Third Party Software") to implement various functions. +Third Party Software does not comprise part of the Licensed Software. In +some cases, access to Third Party Software may be included along with +the Licensed Software delivery as a convenience for development and +testing only. Such source code and libraries may be listed in the +".../src/3rdparty" source tree delivered with the Licensed Software or +documented in the Licensed Software where the Third Party Software is +used, as may be amended from time to time, do not comprise the Licensed +Software. Licensee acknowledges (1) that some part of Third Party +Software may require additional licensing of copyright and patents from +the owners of such, and (2) that distribution of any of the Licensed +Software referencing any portion of a Third Party Software may require +appropriate licensing from such third parties. + + +7. LIMITED WARRANTY AND WARRANTY DISCLAIMER + +The Licensed Software is licensed to Licensee "as is". To the maximum +extent permitted by applicable law, The Qt Company on behalf of itself and +its suppliers, disclaims all warranties and conditions, either express or +implied, including, but not limited to, implied warranties of +merchantability, fitness for a particular purpose, title and +non-infringement with regard to the Licensed Software. + + +8. LIMITATION OF LIABILITY + +If, The Qt Company's warranty disclaimer notwithstanding, The Qt Company is +held liable to Licensee, whether in contract, tort or any other legal theory, +based on the Licensed Software, The Qt Company's entire liability to Licensee +and Licensee's exclusive remedy shall be, at The Qt Company's option, either +(A) return of the price Licensee paid for the Licensed Software, or (B) +repair or replacement of the Licensed Software, provided Licensee +returns to The Qt Company all copies of the Licensed Software as originally +delivered to Licensee. The Qt Company shall not under any circumstances be +liable to Licensee based on failure of the Licensed Software if the failure +resulted from accident, abuse or misapplication, nor shall The Qt Company +under any circumstances be liable for special damages, punitive or exemplary +damages, damages for loss of profits or interruption of business or for +loss or corruption of data. Any award of damages from The Qt Company to +Licensee shall not exceed the total amount Licensee has paid to The Qt +Company in connection with this Agreement. + + +9. CONFIDENTIALITY + +Each party acknowledges that during the Term of this Agreement it shall +have access to information about the other party's business, business +methods, business plans, customers, business relations, technology, and +other information, including the terms of this Agreement, that is +confidential and of great value to the other party, and the value of +which would be significantly reduced if disclosed to third parties (the +"Confidential Information"). Accordingly, when a party (the "Receiving +Party") receives Confidential Information from another party (the +"Disclosing Party"), the Receiving Party shall, and shall obligate its +employees and agents and employees and agents of its Affiliates to: (i) +maintain the Confidential Information in strict confidence; (ii) not +disclose the Confidential Information to a third party without the +Disclosing Party's prior written approval; and (iii) not, directly or +indirectly, use the Confidential Information for any purpose other than +for exercising its rights and fulfilling its responsibilities pursuant +to this Agreement. Each party shall take reasonable measures to protect +the Confidential Information of the other party, which measures shall +not be less than the measures taken by such party to protect its own +confidential and proprietary information. + +"Confidential Information" shall not include information that (a) is or +becomes generally known to the public through no act or omission of the +Receiving Party; (b) was in the Receiving Party's lawful possession +prior to the disclosure hereunder and was not subject to limitations on +disclosure or use; (c) is developed by the Receiving Party without +access to the Confidential Information of the Disclosing Party or by +persons who have not had access to the Confidential Information of the +Disclosing Party as proven by the written records of the Receiving +Party; (d) is lawfully disclosed to the Receiving Party without +restrictions, by a third party not under an obligation of +confidentiality; or (e) the Receiving Party is legally compelled to +disclose the information, in which case the Receiving Party shall assert +the privileged and confidential nature of the information and cooperate +fully with the Disclosing Party to protect against and prevent +disclosure of any Confidential Information and to limit the scope of +disclosure and the dissemination of disclosed Confidential Information +by all legally available means. + +The obligations of the Receiving Party under this Section shall continue +during the Initial Term and for a period of five (5) years after +expiration or termination of this Agreement. To the extent that the +terms of the Non-Disclosure Agreement between The Qt Company and Licensee +conflict with the terms of this Section 9, this Section 9 shall be +controlling over the terms of the Non-Disclosure Agreement. + + +10. GENERAL PROVISIONS + +10.1 No Assignment + +Licensee shall not be entitled to assign or transfer all or any of its +rights, benefits and obligations under this Agreement without the prior +written consent of The Qt Company, which shall not be unreasonably withheld. + +10.2 Termination + +The Qt Company may terminate the Agreement at any time immediately upon +written notice by The Qt Company to Licensee if Licensee breaches this +Agreement. + +Upon termination of this Agreement, Licensee shall return to The Qt Company +all copies of Licensed Software that were supplied by The Qt Company. All +other copies of Licensed Software in the possession or control of Licensee +must be erased or destroyed. An officer of Licensee must promptly +deliver to The Qt Company a written confirmation that this has occurred. + +10.3 Surviving Sections + +Any terms and conditions that by their nature or otherwise reasonably +should survive a cancellation or termination of this Agreement shall +also be deemed to survive. Such terms and conditions include, but are +not limited to the following Sections: 2, 5, 6, 7, 8, 9, 10.2, 10.3, 10.4, +10.5, 10.6, 10.7, and 10.8 of this Agreement. + +10.4 Entire Agreement + +This Agreement constitutes the complete agreement between the parties +and supersedes all prior or contemporaneous discussions, +representations, and proposals, written or oral, with respect to the +subject matters discussed herein, with the exception of the +non-disclosure agreement executed by the parties in connection with this +Agreement ("Non-Disclosure Agreement"), if any, shall be subject to +Section 9. No modification of this Agreement shall be effective unless +contained in a writing executed by an authorized representative of each +party. No term or condition contained in Licensee's purchase order shall +apply unless expressly accepted by The Qt Company in writing. If any +provision of the Agreement is found void or unenforceable, the remainder +shall remain valid and enforceable according to its terms. If any remedy +provided is determined to have failed for its essential purpose, all +limitations of liability and exclusions of damages set forth in this +Agreement shall remain in effect. + +10.5 Export Control + +Licensee acknowledges that the Licensed Software may be subject to +export control restrictions of various countries. Licensee shall fully +comply with all applicable export license restrictions and requirements +as well as with all laws and regulations relating to the importation of +the Licensed Software and shall procure all necessary governmental +authorizations, including without limitation, all necessary licenses, +approvals, permissions or consents, where necessary for the +re-exportation of the Licensed Software., + +10.6 Governing Law and Legal Venue + +This Agreement shall be governed by and construed in accordance with the +federal laws of the United States of America and the internal laws of +the State of New York without given effect to any choice of law rule +that would result in the application of the laws of any other +jurisdiction. The United Nations Convention on Contracts for the +International Sale of Goods (CISG) shall not apply. Each Party (a) +hereby irrevocably submits itself to and consents to the jurisdiction of +the United States District Court for the Southern District of New York +(or if such court lacks jurisdiction, the state courts of the State of +New York) for the purposes of any action, claim, suit or proceeding +between the Parties in connection with any controversy, claim, or +dispute arising out of or relating to this Agreement; and (b) hereby +waives, and agrees not to assert by way of motion, as a defense or +otherwise, in any such action, claim, suit or proceeding, any claim that +is not personally subject to the jurisdiction of such court(s), that the +action, claim, suit or proceeding is brought in an inconvenient forum or +that the venue of the action, claim, suit or proceeding is improper. +Notwithstanding the foregoing, nothing in this Section 9.6 is intended +to, or shall be deemed to, constitute a submission or consent to, or +selection of, jurisdiction, forum or venue for any action for patent +infringement, whether or not such action relates to this Agreement. + +10.7 No Implied License + +There are no implied licenses or other implied rights granted under this +Agreement, and all rights, save for those expressly granted hereunder, +shall remain with The Qt Company and its licensors. In addition, no licenses +or immunities are granted to the combination of the Licensed Software with +any other software or hardware not delivered by The Qt Company under this +Agreement. + +10.8 Government End Users + +A "U.S. Government End User" shall mean any agency or entity of the +government of the United States. The following shall apply if Licensee +is a U.S. Government End User. The Licensed Software is a "commercial +item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), +consisting of "commercial computer software" and "commercial computer +software documentation," as such terms are used in 48 C.F.R. 12.212 +(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 +through 227.7202-4 (June 1995), all U.S. Government End Users acquire +the Licensed Software with only those rights set forth herein. The +Licensed Software (including related documentation) is provided to U.S. +Government End Users: (a) only as a commercial end item; and (b) only +pursuant to this Agreement. + + + + + +TECHNOLOGY PREVIEW LICENSE AGREEMENT: Rest of the World +Agreement version 2.4 + +This Technology Preview License Agreement ("Agreement") is a legal +agreement between The Qt Company Ltd ("The Qt Company"), with its registered +office at Valimotie 21,FI-00380 Helsinki, Finland and you (either an +individual or a legal entity) ("Licensee") for the Licensed Software. + +1. DEFINITIONS + +"Affiliate" of a Party shall mean an entity (i) which is directly or +indirectly controlling such Party; (ii) which is under the same direct +or indirect ownership or control as such Party; or (iii) which is +directly or indirectly owned or controlled by such Party. For these +purposes, an entity shall be treated as being controlled by another if +that other entity has fifty percent (50 %) or more of the votes in such +entity, is able to direct its affairs and/or to control the composition +of its board of directors or equivalent body. + +"Applications" shall mean Licensee's software products created using the +Licensed Software which may include portions of the Licensed Software. + +"Term" shall mean the period of time six (6) months from the later of +(a) the Effective Date; or (b) the date the Licensed Software was +initially delivered to Licensee by The Qt Company. If no specific Effective +Date is set forth in the Agreement, the Effective Date shall be deemed to be +the date the Licensed Software was initially delivered to Licensee. + +"Licensed Software" shall mean the computer software, "online" or +electronic documentation, associated media and printed materials, +including the source code, example programs and the documentation +delivered by The Qt Company to Licensee in conjunction with this Agreement. + +"Party" or "Parties" shall mean Licensee and/or The Qt Company. + + +2. OWNERSHIP + +The Licensed Software is protected by copyright laws and international +copyright treaties, as well as other intellectual property laws and +treaties. The Licensed Software is licensed, not sold. + +If Licensee provides any findings, proposals, suggestions or other +feedback ("Feedback") to The Qt Company regarding the Licensed Software, +The Qt Companyshall own all right, title and interest including the +intellectual property rights in and to such Feedback, excluding however any +existing patent rights of Licensee. To the extent Licensee owns or controls +any patents for such Feedback Licensee hereby grants to The Qt Company and +its Affiliates, a worldwide, perpetual, non-transferable, sublicensable, +royalty-free license to (i) use, copy and modify Feedback and to create +derivative works thereof, (ii) to make (and have made), use, import, +sell, offer for sale, lease, dispose, offer for disposal or otherwise +exploit any products or services of The Qt Company containing Feedback, and +(iii) sublicense all the foregoing rights to third party licensees and +customers of The Qt Company and/or its Affiliates. + +3. VALIDITY OF THE AGREEMENT + +By installing, copying, or otherwise using the Licensed Software, +Licensee agrees to be bound by the terms of this Agreement. If Licensee +does not agree to the terms of this Agreement, Licensee may not install, +copy, or otherwise use the Licensed Software. Upon Licensee's acceptance +of the terms and conditions of this Agreement, The Qt Company grants Licensee +the right to use the Licensed Software in the manner provided below. + + +4. LICENSES + +4.1. Using and Copying + +The Qt Company grants to Licensee a non-exclusive, non-transferable, +time-limited license to use and copy the Licensed Software for sole purpose +of designing, developing and testing Applications, and evaluating and the +Licensed Software during the Term. + +Licensee may install copies of the Licensed Software on an unlimited +number of computers provided that (a) if an individual, only such +individual; or (b) if a legal entity only its employees; use the +Licensed Software for the authorized purposes. + +4.2 No Distribution or Modifications + +Licensee may not disclose, modify, sell, market, commercialise, +distribute, loan, rent, lease, or license the Licensed Software or any +copy of it or use the Licensed Software for any purpose that is not +expressly granted in this Section 4. Licensee may not alter or remove +any details of ownership, copyright, trademark or other property right +connected with the Licensed Software. Licensee may not distribute any +software statically or dynamically linked with the Licensed Software. + +4.3 No Technical Support + +The Qt Company has no obligation to furnish Licensee with any technical +support whatsoever. Any such support is subject to separate agreement +between the Parties. + + +5. PRE-RELEASE CODE + +The Licensed Software contains pre-release code that is not at the level +of performance and compatibility of a final, generally available, +product offering. The Licensed Software may not operate correctly and +may be substantially modified prior to the first commercial product +release, if any. The Qt Company is not obligated to make this or any later +version of the Licensed Software commercially available. The License +Software is "Not for Commercial Use" and may only be used for the +purposes described in Section 4. The Licensed Software may not be used +in a live operating environment where it may be relied upon to perform +in the same manner as a commercially released product or with data that +has not been sufficiently backed up. + +6. THIRD PARTY SOFTWARE + +The Licensed Software may provide links to third party libraries or code +(collectively "Third Party Software") to implement various functions. +Third Party Software does not comprise part of the Licensed Software. In +some cases, access to Third Party Software may be included along with +the Licensed Software delivery as a convenience for development and +testing only. Such source code and libraries may be listed in the +".../src/3rdparty" source tree delivered with the Licensed Software or +documented in the Licensed Software where the Third Party Software is +used, as may be amended from time to time, do not comprise the Licensed +Software. Licensee acknowledges (1) that some part of Third Party +Software may require additional licensing of copyright and patents from +the owners of such, and (2) that distribution of any of the Licensed +Software referencing any portion of a Third Party Software may require +appropriate licensing from such third parties. + + +7. LIMITED WARRANTY AND WARRANTY DISCLAIMER + +The Licensed Software is licensed to Licensee "as is". To the maximum +extent permitted by applicable law, The Qt Company on behalf of itself and +its suppliers, disclaims all warranties and conditions, either express or +implied, including, but not limited to, implied warranties of +merchantability, fitness for a particular purpose, title and +non-infringement with regard to the Licensed Software. + + +8. LIMITATION OF LIABILITY + +If, The Qt Company's warranty disclaimer notwithstanding, The Qt Company is +held liable to Licensee, whether in contract, tort or any other legal theory, +based on the Licensed Software, The Qt Company's entire liability to Licensee +and Licensee's exclusive remedy shall be, at The Qt Company's option, either +(A) return of the price Licensee paid for the Licensed Software, or (B) +repair or replacement of the Licensed Software, provided Licensee +returns to The Qt Company all copies of the Licensed Software as originally +delivered to Licensee. The Qt Company shall not under any circumstances be +liable to Licensee based on failure of the Licensed Software if the failure +resulted from accident, abuse or misapplication, nor shall The Qt Company +under any circumstances be liable for special damages, punitive or exemplary +damages, damages for loss of profits or interruption of business or for +loss or corruption of data. Any award of damages from The Qt Company to +Licensee shall not exceed the total amount Licensee has paid to +The Qt Company in connection with this Agreement. + + +9. CONFIDENTIALITY + +Each party acknowledges that during the Term of this Agreement it shall +have access to information about the other party's business, business +methods, business plans, customers, business relations, technology, and +other information, including the terms of this Agreement, that is +confidential and of great value to the other party, and the value of +which would be significantly reduced if disclosed to third parties (the +"Confidential Information"). Accordingly, when a party (the "Receiving +Party") receives Confidential Information from another party (the +"Disclosing Party"), the Receiving Party shall, and shall obligate its +employees and agents and employees and agents of its Affiliates to: (i) +maintain the Confidential Information in strict confidence; (ii) not +disclose the Confidential Information to a third party without the +Disclosing Party's prior written approval; and (iii) not, directly or +indirectly, use the Confidential Information for any purpose other than +for exercising its rights and fulfilling its responsibilities pursuant +to this Agreement. Each party shall take reasonable measures to protect +the Confidential Information of the other party, which measures shall +not be less than the measures taken by such party to protect its own +confidential and proprietary information. + +"Confidential Information" shall not include information that (a) is or +becomes generally known to the public through no act or omission of the +Receiving Party; (b) was in the Receiving Party's lawful possession +prior to the disclosure hereunder and was not subject to limitations on +disclosure or use; (c) is developed by the Receiving Party without +access to the Confidential Information of the Disclosing Party or by +persons who have not had access to the Confidential Information of the +Disclosing Party as proven by the written records of the Receiving +Party; (d) is lawfully disclosed to the Receiving Party without +restrictions, by a third party not under an obligation of +confidentiality; or (e) the Receiving Party is legally compelled to +disclose the information, in which case the Receiving Party shall assert +the privileged and confidential nature of the information and cooperate +fully with the Disclosing Party to protect against and prevent +disclosure of any Confidential Information and to limit the scope of +disclosure and the dissemination of disclosed Confidential Information +by all legally available means. + +The obligations of the Receiving Party under this Section shall continue +during the Initial Term and for a period of five (5) years after +expiration or termination of this Agreement. To the extent that the +terms of the Non-Disclosure Agreement between The Qt Company and Licensee +conflict with the terms of this Section 9, this Section 9 shall be +controlling over the terms of the Non-Disclosure Agreement. + + +10. GENERAL PROVISIONS + +10.1 No Assignment + +Licensee shall not be entitled to assign or transfer all or any of its +rights, benefits and obligations under this Agreement without the prior +written consent of The Qt Company, which shall not be unreasonably withheld. + +10.2 Termination + +The Qt Company may terminate the Agreement at any time immediately upon +written notice by The Qt Company to Licensee if Licensee breaches this +Agreement. + +Upon termination of this Agreement, Licensee shall return to The Qt Company +all copies of Licensed Software that were supplied by The Qt Company. All +other copies of Licensed Software in the possession or control of Licensee +must be erased or destroyed. An officer of Licensee must promptly +deliver to The Qt Company a written confirmation that this has occurred. + +10.3 Surviving Sections + +Any terms and conditions that by their nature or otherwise reasonably +should survive a cancellation or termination of this Agreement shall +also be deemed to survive. Such terms and conditions include, but are +not limited to the following Sections: 2, 5, 6, 7, 8, 9, 10.2, 10.3, 10.4, +10.5, 10.6, 10.7, and 10.8 of this Agreement. + +10.4 Entire Agreement + +This Agreement constitutes the complete agreement between the parties +and supersedes all prior or contemporaneous discussions, +representations, and proposals, written or oral, with respect to the +subject matters discussed herein, with the exception of the +non-disclosure agreement executed by the parties in connection with this +Agreement ("Non-Disclosure Agreement"), if any, shall be subject to +Section 9. No modification of this Agreement shall be effective unless +contained in a writing executed by an authorized representative of each +party. No term or condition contained in Licensee's purchase order shall +apply unless expressly accepted by The Qt Company in writing. If any provision +of the Agreement is found void or unenforceable, the remainder shall remain +valid and enforceable according to its terms. If any remedy provided is +determined to have failed for its essential purpose, all limitations of +liability and exclusions of damages set forth in this Agreement shall +remain in effect. + +10.5 Export Control + +Licensee acknowledges that the Licensed Software may be subject to +export control restrictions of various countries. Licensee shall fully +comply with all applicable export license restrictions and requirements +as well as with all laws and regulations relating to the importation of +the Licensed Software and shall procure all necessary governmental +authorizations, including without limitation, all necessary licenses, +approvals, permissions or consents, where necessary for the +re-exportation of the Licensed Software., + +10.6 Governing Law and Legal Venue + +This Agreement shall be construed and interpreted in accordance with the +laws of Finland, excluding its choice of law provisions. Any disputes +arising out of or relating to this Agreement shall be resolved in +arbitration under the Rules of Arbitration of the Chamber of Commerce of +Helsinki, Finland. The arbitration tribunal shall consist of one (1), or +if either Party so requires, of three (3), arbitrators. The award shall +be final and binding and enforceable in any court of competent +jurisdiction. The arbitration shall be held in Helsinki, Finland and the +process shall be conducted in the English language. + +10.7 No Implied License + +There are no implied licenses or other implied rights granted under this +Agreement, and all rights, save for those expressly granted hereunder, +shall remain with The Qt Company and its licensors. In addition, no licenses +or immunities are granted to the combination of the Licensed Software with +any other software or hardware not delivered by The Qt Company under this +Agreement. + +10.8 Government End Users + +A "U.S. Government End User" shall mean any agency or entity of the +government of the United States. The following shall apply if Licensee +is a U.S. Government End User. The Licensed Software is a "commercial +item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), +consisting of "commercial computer software" and "commercial computer +software documentation," as such terms are used in 48 C.F.R. 12.212 +(Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 +through 227.7202-4 (June 1995), all U.S. Government End Users acquire +the Licensed Software with only those rights set forth herein. The +Licensed Software (including related documentation) is provided to U.S. +Government End Users: (a) only as a commercial end item; and (b) only +pursuant to this Agreement. + + + + diff --git a/sources/shiboken2/README.md b/sources/shiboken2/README.md new file mode 100644 index 000000000..b64f97d36 --- /dev/null +++ b/sources/shiboken2/README.md @@ -0,0 +1,19 @@ +# shiboken2 + +This is shiboken2, the code generator for PySide2. It is part of pyside2-setup, which you +should download for building and getting further information. + +Resources: + +* [PySide2-setup](https://github.com/PySide/pyside2-setup) + The container-project with the setup.py script. It contains the following sub-projects: + * [PySide2 Wiki](https://github.com/PySide/pyside2/wiki) + Developer information + * [PySide2](https://github.com/PySide/pyside2) + The PySide2 project + * [Shiboken2](https://github.com/PySide/shiboken2) + The Shiboken2 project + * [PySide2-tools](https://github.com/PySide/pyside2-examples) + The PySide2-tools project + * [PySide2-examples](https://github.com/PySide/pyside2-examples) + The PySide2 example scripts diff --git a/sources/shiboken2/cmake_uninstall.cmake b/sources/shiboken2/cmake_uninstall.cmake new file mode 100644 index 000000000..df95fb9d8 --- /dev/null +++ b/sources/shiboken2/cmake_uninstall.cmake @@ -0,0 +1,21 @@ +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") + +FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +STRING(REGEX REPLACE "\n" ";" files "${files}") +FOREACH(file ${files}) + MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + IF(EXISTS "$ENV{DESTDIR}${file}") + EXEC_PROGRAM( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + IF(NOT "${rm_retval}" STREQUAL 0) + MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") + ENDIF(NOT "${rm_retval}" STREQUAL 0) + ELSE(EXISTS "$ENV{DESTDIR}${file}") + MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + ENDIF(EXISTS "$ENV{DESTDIR}${file}") +ENDFOREACH(file) diff --git a/sources/shiboken2/data/CMakeLists.txt b/sources/shiboken2/data/CMakeLists.txt new file mode 100644 index 000000000..c36cb148d --- /dev/null +++ b/sources/shiboken2/data/CMakeLists.txt @@ -0,0 +1,28 @@ +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) +else() + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_RELEASE_POSTFIX}) +endif() + +add_custom_target(data) +add_dependencies(data shiboken2) +get_target_property(SHIBOKEN_GENERATOR shiboken2 OUTPUT_NAME) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2Config.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config.cmake" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2Config-spec.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/Shiboken2ConfigVersion.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2ConfigVersion.cmake" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken2.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/shiboken2${shiboken2_SUFFIX}.pc" @ONLY) + +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config.cmake" + DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake" + DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Shiboken2ConfigVersion.cmake" + DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken2-${shiboken2_VERSION}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shiboken2${shiboken2_SUFFIX}.pc" + DESTINATION "${LIB_INSTALL_DIR}/pkgconfig") + diff --git a/sources/shiboken2/data/GeneratorRunnerConfig.cmake.in b/sources/shiboken2/data/GeneratorRunnerConfig.cmake.in new file mode 100644 index 000000000..cf973e2a6 --- /dev/null +++ b/sources/shiboken2/data/GeneratorRunnerConfig.cmake.in @@ -0,0 +1,17 @@ +# GENERATORRUNNER_INCLUDE_DIR - Directories to include to use GENERATORRUNNER +# GENERATORRUNNER_LIBRARIES - Files to link against to use GENERATORRUNNER +# GENERATORRUNNER_PLUGIN_DIR - Where to find/put plugins for generator runner +# GENERATORRUNNER_BINARY - Executable name + +SET(GENERATORRUNNER_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/generatorrunner@generator_SUFFIX@") +if(MSVC) + SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@.lib") +elseif(CYGWIN) + SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_IMPORT_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") +elseif(WIN32) + SET(GENERATORRUNNER_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +else() + SET(GENERATORRUNNER_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@genrunner@generator_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +endif() +SET(GENERATORRUNNER_PLUGIN_DIR "@generator_plugin_DIR@") +SET(GENERATORRUNNER_BINARY "@CMAKE_INSTALL_PREFIX@/bin/generatorrunner@generator_SUFFIX@") diff --git a/sources/shiboken2/data/GeneratorRunnerConfigVersion.cmake.in b/sources/shiboken2/data/GeneratorRunnerConfigVersion.cmake.in new file mode 100644 index 000000000..8eb5ba479 --- /dev/null +++ b/sources/shiboken2/data/GeneratorRunnerConfigVersion.cmake.in @@ -0,0 +1,10 @@ +set(PACKAGE_VERSION @generator_VERSION@) + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") +endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/sources/shiboken2/data/Shiboken2Config-spec.cmake.in b/sources/shiboken2/data/Shiboken2Config-spec.cmake.in new file mode 100644 index 000000000..1aac9caa0 --- /dev/null +++ b/sources/shiboken2/data/Shiboken2Config-spec.cmake.in @@ -0,0 +1,29 @@ +# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN +# SHIBOKEN_LIBRARY - Files to link against to use SHIBOKEN +# SHIBOKEN_BINARY - Executable name +# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. +# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. +# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. + +SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken2@shiboken2_SUFFIX@") +if(MSVC) + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@.lib") +elseif(CYGWIN) + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_IMPORT_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@") +elseif(WIN32) + SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +else() + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +endif() +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") +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_LIBRARIES "@SBK_PYTHON_LIBRARIES@") +SET(SHIBOKEN_PYTHON_EXTENSION_SUFFIX "@PYTHON_EXTENSION_SUFFIX@") +message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") +@SBK_ADD_PY_DEBUG_DEFINITION@ + +set(SHIBOKEN_BINARY "@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@") diff --git a/sources/shiboken2/data/Shiboken2Config.cmake.in b/sources/shiboken2/data/Shiboken2Config.cmake.in new file mode 100644 index 000000000..5f7ecaec1 --- /dev/null +++ b/sources/shiboken2/data/Shiboken2Config.cmake.in @@ -0,0 +1,5 @@ +if (NOT PYTHON_EXTENSION_SUFFIX) + message(STATUS "Shiboken2Config: Using default python: @PYTHON_EXTENSION_SUFFIX@") + SET(PYTHON_EXTENSION_SUFFIX @PYTHON_EXTENSION_SUFFIX@) +endif() +include(@LIB_INSTALL_DIR@/cmake/Shiboken2-@shiboken2_VERSION@/Shiboken2Config${PYTHON_EXTENSION_SUFFIX}.cmake) diff --git a/sources/shiboken2/data/Shiboken2ConfigVersion.cmake.in b/sources/shiboken2/data/Shiboken2ConfigVersion.cmake.in new file mode 100644 index 000000000..9460099b2 --- /dev/null +++ b/sources/shiboken2/data/Shiboken2ConfigVersion.cmake.in @@ -0,0 +1,10 @@ +set(PACKAGE_VERSION @shiboken2_VERSION@) + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") +endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/sources/shiboken2/data/docgenerator.1 b/sources/shiboken2/data/docgenerator.1 new file mode 120000 index 000000000..c65282f98 --- /dev/null +++ b/sources/shiboken2/data/docgenerator.1 @@ -0,0 +1 @@ +generatorrunner.1 \ No newline at end of file diff --git a/sources/shiboken2/data/generatorrunner.1 b/sources/shiboken2/data/generatorrunner.1 new file mode 100644 index 000000000..045b55ad4 --- /dev/null +++ b/sources/shiboken2/data/generatorrunner.1 @@ -0,0 +1,76 @@ +.TH GENERATORRUNNER 1 "SEPTEMBER 2009" Linux "User Manuals" +.SH NAME +generatorrunner - plugin-based binding source code generator +.SH SYNOPSIS +.B generatorrunner \-\-generator-set= [options] header-file typesystem-file +.SH DESCRIPTION +.B generatorrunner +is a utility that uses the information taken from APIExtractor +related to the provided C++ headers and typesystem files and execute +generators using this information. Generators are plugins and you need +to specify one using the \-\-generator-set parameter. At the moment there +are two generators available: + +.B qtdoc +\- Generates Sphinx-based documentation for C++ libraries documented using +.B qdoc3 +documentation syntax, using the XML files created by the documentation tool +.B (qdoc3). +Can be called supplying +.B \-\-generator-set=qtdoc +to +.B generatorrunner +or by calling the convenience executable +.B docgenerator. + +Other plugins can be used with +.B generatorrunner, +provided that they follow the generator front-end specifications, +and can be written to generate code or documentation for any target +languague you desire. For more information about the generator front-end +architecture and current limitations, refer to http://www.pyside.org/home-binding. + +.SH OPTIONS +.SS "General options" +.IP \-\-api-version= +Specify the supported api version used to generate the bindings. +.IP \-\-debug-level=[sparse|medium|full] +The amount of messages displayed. +.IP \-\-documentation-only +Only generates the documentation. +.IP \-\-drop-type-entries="[;TypeEntry1;...]" +Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation. +.IP \-\-help \fR,\fP \-h \fR,\fP -? +Prints the usage message. +.IP \-\-project-file= +Text file containing a description of the binding project. Replaces and overrides command line arguments. +.IP \-\-include\-paths=\fI[:path:..]\fR +The directories where the generator will search for the +headers. Works like gcc's \-I flag. +.IP \-\-license\-file=\fI[licensefile]\fR +Template for copyright headers of generated files. +.IP \-\-no\-supress\-warnings +Show all warnings. +.IP \-\-output\-directory=\fI[dir]\fR +The directory where the generated files will be written. +.IP \-\-silent +Avoid printing any messages. +.IP \-\-typesytem\-paths=\fI[:path:..]\fR +The directories where the generator will search for the +external typesystems referred by the main one. +.IP \-\-version +Displays the current version. +Drops support for named args. +.SS "Specific to qtdoc plugin" +.IP \-\-documentation\-code\-snippets\-dir +Directory used to search code snippets used by the documentation +.IP \-\-documentation\-data\-dir +Directory with XML files generated by documentation tool (qdoc3 or Doxygen) +.IP \-\-documentation\-out\-dir +The directory where the generated documentation files will be written +.IP \-\-library\-source\-dir +Directory where library source code is located + +.SH AUTHORS +Lauro Moura , Bruno Araujo , Hugo Lima + diff --git a/sources/shiboken2/data/generatorrunner.pc.in b/sources/shiboken2/data/generatorrunner.pc.in new file mode 100644 index 000000000..a566f4356 --- /dev/null +++ b/sources/shiboken2/data/generatorrunner.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/include + + +Name: generatorrunner@generator_SUFFIX@ +Description: Generator Runner loads and calls binding generator front-ends. +Requires: apiextractor +Version: @generatorrunner_VERSION@ +Libs: -L${libdir} -lgenrunner@generator_SUFFIX@ +Cflags: -I${includedir}@generator_SUFFIX@ + diff --git a/sources/shiboken2/data/shiboken2.pc.in b/sources/shiboken2/data/shiboken2.pc.in new file mode 100644 index 000000000..aec210c5c --- /dev/null +++ b/sources/shiboken2/data/shiboken2.pc.in @@ -0,0 +1,13 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken2 +generator_location=@CMAKE_INSTALL_PREFIX@/bin/@SHIBOKEN_GENERATOR@ +python_interpreter=@PYTHON_EXECUTABLE@ +python_include_dir=@SBK_PYTHON_INCLUDE_DIR@ + +Name: shiboken2 +Description: Support library for Python bindings created with the Shiboken2 generator. +Version: @shiboken2_VERSION@ +Libs: @SBK_PYTHON_LIBRARIES@ -L${libdir} -lshiboken2@shiboken2_SUFFIX@@PYTHON_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ +Cflags: -I@SBK_PYTHON_INCLUDE_DIR@ -I${includedir}/@shiboken2_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@ diff --git a/sources/shiboken2/doc/CMakeLists.txt b/sources/shiboken2/doc/CMakeLists.txt new file mode 100644 index 000000000..7bd0161ad --- /dev/null +++ b/sources/shiboken2/doc/CMakeLists.txt @@ -0,0 +1,24 @@ + +find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") + +if (SPHINX) + message("-- sphinx-build - found") + configure_file(conf.py.in conf.py @ONLY) + add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) +else() + message("-- sphinx-build - not found! doc target disabled") + if (WIN32) + # if jom is used and we have no sphinx, then jom will crash. + # so for windows, we always create a doc target (until jom gets fixed...) + add_custom_target(doc echo. + COMMAND echo +++ This is a fake build, to make 'jom' happy. + COMMAND echo +++ The documentation was _not_ built! + COMMAND echo. + ) + endif() +endif() + +if (NOT WIN32) + file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") + install(FILES ${manpages} DESTINATION share/man/man1) +endif() diff --git a/sources/shiboken2/doc/_templates/index.html b/sources/shiboken2/doc/_templates/index.html new file mode 100644 index 000000000..00ac64271 --- /dev/null +++ b/sources/shiboken2/doc/_templates/index.html @@ -0,0 +1,35 @@ +{% extends "layout.html" %} +{% set title = 'Overview' %} +{% block body %} +
+

{{ project }} {{ version }}

+ +

{{ project }} is a plugin (front-end) for Generator Runner. It generates bindings for C++ libraries using CPython source code.

+ +

Documentation

+ + + +
+ + + + + + + + + + +
+
+{% endblock %} diff --git a/sources/shiboken2/doc/_templates/layout.html b/sources/shiboken2/doc/_templates/layout.html new file mode 100644 index 000000000..94ff3534e --- /dev/null +++ b/sources/shiboken2/doc/_templates/layout.html @@ -0,0 +1,29 @@ +{% extends "!layout.html" %} + +# Invert sidebars +{%- block sidebar1 %}{{ sidebar() }}{%- endblock %} +{%- block sidebar2 %}{%- endblock %} + +{%- block header %} +
+
+
+ + {{ relbar() }} +
+
+{%- endblock -%} + +{%- block footer %} + +
+{%- endblock %} + +# No top relbar. +{%- block relbar1 %}{%- endblock %} + +# No bottom relbar. +{%- block relbar2 %}{%- endblock %} diff --git a/sources/shiboken2/doc/_themes/pysidedocs/searchbox.html b/sources/shiboken2/doc/_themes/pysidedocs/searchbox.html new file mode 100644 index 000000000..55a972156 --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs/searchbox.html @@ -0,0 +1,12 @@ +{%- if pagename != "search" %} + + +{%- endif %} diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.png b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.png new file mode 100644 index 000000000..843e7e2c5 Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.png differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpg b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpg new file mode 100644 index 000000000..4229ae8db Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpg differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.png b/sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.png new file mode 100644 index 000000000..b45830e00 Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.png differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpg b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpg new file mode 100644 index 000000000..cd474efba Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpg differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.png b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.png new file mode 100644 index 000000000..39a4a26f3 Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.png differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/pysidedocs.css b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidedocs.css new file mode 100644 index 000000000..708ddf77c --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidedocs.css @@ -0,0 +1,475 @@ +* { + font: 100% Verdana, Arial, Helvetica, sans-serif; + font-size:12px; +} + +html { + height: 100%; +} + +body { + margin: 0; + padding: 0; + background-color: #EBEBEB; + height: 100%; + color: #333; +} + +strong { + font-weight:bold; +} + +.document { + padding-bottom: 90px; +} + +#container { + position: relative; + min-height: 100%; + background-image: url(fakebar.png); + background-repeat: repeat-y; + background-color: white; +} + +.footer { + position: absolute; + bottom: 0px; + margin-top: 50px; + text-align:center; + background-color: white; + border-top: 2px solid #e0e0e0; + white-space: nowrap; + height: 90px; + width: 100%; +} + +.footer img { + margin-left: 8px; + margin-right: 8px; +} + +.sphinxsidebar { + float: left; + width: 250px; + padding: 0px 10px 0px 10px; + text-align: left; +} + +.sphinxsidebar ul { + padding: 0px; + margin: 0px; + list-style-position: inside; +} + +.sphinxsidebar > ul { + padding: 0px; + margin: 0px; +} + +.sphinxsidebar ul li { + margin-left: 10px; + padding: 0px; +} + +.sphinxsidebar h3, .sphinxsidebar h3 a { + font-weight: bold; + color: #333; +} + +.documentwrapper { + margin-left: 270px; + text-align: left; + background-color: #ffffff; + border-left: 1px solid #989898; + font-size:18px; + padding: 10px 50px 15px 50px; + height: 100%; +} + +h1 { + font-size:18px; + padding-left: 50px; + padding-bottom: 15px; + padding-top: 15px; + border-bottom: 1px solid #c2c2c2; + margin-right: -100px; + position: relative; + left: -50px; + top: -10px; +} + +h2 { + font-size:12px; + font-weight:bold; + border-left-width: 1px; + border-right-width: 1px; + border-top-width: 1px; + border-bottom-width: 2px; + border-style: solid; + border-left-color: #b1b1b1; + border-right-color: #b1b1b1; + border-top-color: #b1b1b1; + border-bottom-color: #009491; + background-color: #e0e0e0; + padding:5px; + margin-top: 20px; + -moz-border-radius:5px; + -webkit-border-radius:5px; + -khtml-border-radius:5px; +} + +h3, h4 { + font-weight: bolder; +} + +pre { + border-top: 1px solid #e0e0e0; + border-bottom: 1px solid #e0e0e0; + background-color: #fafafa; + padding: 5px; + font: 100% monospace; + overflow: auto; +} + +pre * { + font: 100% monospace; +} + +.pre { + font: 100% monospace; +} + +.headerlink { + font-size: 100%; + color: inherit; + float: right; + visibility: Hidden +} + +h1 .headerlink { + padding-right: 50px; +} + +h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink { + visibility: Visible; +} + +a, a:visited { + color: #009491; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +div.seealso { + background-color: #ffffcc; + border: 1px solid #ffff66; +} + +div.note { + border: 1px solid #e3e3e3; +} + +table.docutils { + margin-left: auto; + margin-right: auto; + margin-bottom: 10px; + border: none; +} + +table.docutils td { + border: none; +} + +table.docutils th { + border: none; + font-weight: bold; + vertical-align: top; +} + +h2 em { + float: right; + font-size: 10px; + position: relative; + top: -20px; +} + +/* Table of pymaemo components */ + +#development table.docutils td { + border-bottom: 1px solid #EBEBEB; +} + +#development th { + background-color: #EBEBEB; + color: #FC7E00; + padding: 5px; +} + +#development th:first-child { + -moz-border-radius: 20px 0px 0px 0px; + -webkit-border-radius: 20px 0px 0px 0px; + -khtml-border-radius: 20px 0px 0px 0px; + padding-left: 10px; +} +#development th:last-child { + -moz-border-radius: 0px 20px 0px 0px; + -webkit-border-radius: 0px 20px 0px 0px; + -khtml-border-radius: 0px 20px 0px 0px; + padding-right: 10px; + width: 100px; +} + +hr { + border: none; + border-bottom: 1px dashed #EBEBEB; + width: 70% +} + +.oldnews { + text-align: right; +} + +/******************* TOPO *****************************/ +.header { + background-image: url(bg_topo.jpg); + background-repeat: repeat-x; + height: 147px; +} + +.header_container { + background-image: url(bg_header.png); + background-repeat: no-repeat; + background-position: 100px 0px; +} + +.logo { + text-align: left; + margin-bottom: 10px; +} + +#searchbox { + border-top: 1px solid #989898; + padding-top: 10px; + margin-left: -10px; + margin-right: -10px; + padding-left: 10px; + padding-right: 10px; +} + +#search_button { + border: 1px solid #3A393A; + background-color: #3A393A; + color: white; + cursor: pointer; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + +} + +form { + margin: 0px; + padding: 0px; +} + +/* search field */ +form #q { + width: 136px; +/* height: 22px; */ + border: none; + margin: 0px; + -moz-border-radius: 5px; + -webkit-border-radius: 5px; + -khtml-border-radius: 5px; + margin-top: 2px; + padding: 4px; + line-height: 22px +} + +#search-results h2 { + display: none; +} + +#search-results h2 { + display: none; +} + +#search-results ul.search { + margin: 0px; + padding: 0px; +} + +ul.search div.context { + padding-left: 40px; +} + +#installation td { + text-align: center; + font-weight: bold; +} + +em { + color: inherit; + font-style:italic; +} + +/******** REL bar *********/ + +.related { + display: inline; +} + +.related ul { + padding: 0px 0px 0px 10px; + margin: 0px; + text-align: left; + background-image: url(relbar_bg.png); +} + +.related li { + display: inline; + color: white; + font-weight: bold; +} + +.related li a { + color: inherit; + line-height: 35px; + font-weight: bold; + vertical-align: middle; +} + +.related li.right { + float: right; + margin-right: 5px; +} + +.related h3 { + display: none; +} + +.align-center { + text-align: center; +} + +.contentstable { + width: 100%; +} + +.contentstable td { + padding-left: 30px; + vertical-align: top; +} + +p.biglink a { + font-size: 20px; +} + +dt:target, .highlight { + background-color: #fbe54e; +} + +img { + border: 0px; +} + +.figure .caption { + font-style:italic; +} + +table.footnote { + margin: 0px; +} + +#synopsis table, table.field-list { + margin: 0px; +} + +tt.descname { + font-size: 120%; + font-weight: bold; +} + +#functions ul, #virtual-functions ul, #slots ul, #signals ul, #static-functions ul { + list-style: none; + margin: 0px; + padding: 10px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:10px; + -webkit-border-radius:10px; + -khtml-border-radius:10px; +} + +#synopsis span.pre { + color: #009491; + font-weight: bolder; +} + +#detailed-description .class dt, #detailed-description .method dt, #detailed-description .attribute dt, #detailed-description .function dt { + margin: 0px; + padding: 10px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:10px; + -webkit-border-radius:10px; + -khtml-border-radius:10px; +} + +.pysidetoc ul { + list-style: none; + padding: 0px; + margin: 0px; +} + +.pysidetoc em { + font-style: normal; +} + +.pysidetoc strong { + display: block; + padding: 5px; + border: 1px solid #ddd; + background-color: #f4f4f4; + -moz-border-radius:6px; + -webkit-border-radius:6px; + -khtml-border-radius:6px; +} + +.hide { + display: none; +} diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png new file mode 100644 index 000000000..076c1057c Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.png b/sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.png new file mode 100644 index 000000000..4036733a7 Binary files /dev/null and b/sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.png differ diff --git a/sources/shiboken2/doc/_themes/pysidedocs/theme.conf b/sources/shiboken2/doc/_themes/pysidedocs/theme.conf new file mode 100644 index 000000000..e0a652a5d --- /dev/null +++ b/sources/shiboken2/doc/_themes/pysidedocs/theme.conf @@ -0,0 +1,7 @@ +[theme] +inherit = default +stylesheet = pysidedocs.css +pygments_style = none + +[options] +nosidebar = false diff --git a/sources/shiboken2/doc/codeinjectionsemantics.rst b/sources/shiboken2/doc/codeinjectionsemantics.rst new file mode 100644 index 000000000..d748a3aae --- /dev/null +++ b/sources/shiboken2/doc/codeinjectionsemantics.rst @@ -0,0 +1,397 @@ +************************ +Code Injection Semantics +************************ + +API Extractor provides the `inject-code +`_ tag +allowing the user to put custom written code to on specific locations of the generated code. +Yet this is only part of what is needed to generate proper binding code, where the custom code +should be written to depends upon the technology used on the generated binding code. + +This is the ``inject-code`` tag options that matters to |project|. + + .. code-block:: xml + + + // custom code + + +Conventions +=========== + +**C++ Wrapper** + This term refers to a generated C++ class that extends a class from the + wrapped library. It is used only when a wrapped C++ class is polymorphic, + i.e. it has or inherits any virtual methods. + +**Python Wrapper** + The code that exports the C++ wrapped class to Python. **Python wrapper** + refers to all the code needed to export a C++ class to Python, and + **Python method/function wrapper** means the specific function that calls + the C++ method/function on behalf of Python. + +**Native** + This is a possible value for the ``class`` attribute of the ``inject-code`` + tag, it means things more akin to the C++ side. + +**Target** + Another ``class`` attribute value, it indicates things more close to the + Python side. + +inject-code tag +=============== + +The following table describes the semantics of ``inject-code`` tag as used on +|project|. + + +---------------+------+---------+--------------------------------------------------------------+ + |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 |beginning|Used only for virtual functions. The code is injected when the| + | | | |function does not has a pyhton 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. | + +---------------+------+---------+--------------------------------------------------------------+ + + +Anatomy of Code Injection +========================= + +To make things clear let's use a simplified example of generated wrapper code +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++ + + 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 +generated wrapper code with the injection spots marked with comments. + +Noteworthy Cases +---------------- + +The type system description system gives the binding developer a lot of +flexibility, which is power, which comes with responsibility. Some modifications +to the wrapped API will not be complete without some code injection. + + +Removing arguments and setting a default values for them +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A simple case is when a function have one argument removed, as when the C++ +method ``METHOD(ARG)`` is modified to be used from Python as ``METHOD()``; +of course the binding developer must provide some guidelines to the generator +on what to do to call it. The most common solution is to remove the argument and +set a default value for it at the same time, so the original C++ method could be +called without problems. + +Removing arguments and calling the method with your own hands +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the argument is removed and no default value is provided, the generator will +not write any call to the method and expect the ``modify-function - target/beginning`` +code injection to call the original C++ method on its own terms. If even this +custom code is not provided the generator will put an ``#error`` clause to +prevent compilation of erroneus binding code. + +Calling the method with your own hands always! +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If your custom code to be injected contains a call to the wrapped C++ method, +it surely means that you don't want the generator to write another call to the +same method. As expected |project| will detect the user written call on the code +injection and will not write its own call, but for this to work properly the +binding developer must use the template variable ``%FUNCTION_NAME`` instead +of writing the actual name of the wrapped method/function. + +In other words, use + + .. code-block:: xml + + + %CPPSELF.originalMethodName(); + + + +instead of + + + .. code-block:: xml + + + %CPPSELF.%FUNCTION_NAME(); + + + +Code Injection for Functions/Methods +==================================== + + +.. _codeinjecting_method_native: + +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++ + + 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 ...) + + // INJECT-CODE: + // Uses: pre method call custom code, modify the argument before the + // Python call. + + (... Python method call goes in here ...) + + // INJECT-CODE: + // Uses: post method call custom code, modify the result before delivering + // it to C++ caller. + + (... Python method and argument tuple are dereferenced here ...) + + return Shiboken::Converter::toCpp(method_result); + } + + +On The Target Side +------------------ + +All the overloads of a method from C++ are gathered together on a single Python +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++ + + static PyObject* + PyInjectCode_overloadedMethod(PyObject* self, PyObject* arg) + { + PyObject* py_result = 0; + if (PyFloat_Check(arg)) { + double cpp_arg0 = Shiboken::Converter::toCpp(arg); + + // INJECT-CODE: + // Uses: pre method call custom code. + + py_result = Shiboken::Converter::toPython( + PyInjectCode_cptr(self)->InjectCode::overloadedMethod(cpp_arg0) + ); + + // INJECT-CODE: + // Uses: post method call custom code. + + } else if (PyNumber_Check(arg)) { + (... other overload calling code ...) + } else goto PyInjectCode_overloadedMethod_TypeError; + + if (PyErr_Occurred() || !py_result) + return 0; + + return py_result; + + PyInjectCode_overloadedMethod_TypeError: + PyErr_SetString(PyExc_TypeError, "'overloadedMethod()' called with wrong parameters."); + return 0; + } + + +.. _codeinjecting_classes: + +Code Injection for Wrapped Classes +================================== + +.. _codeinjecting_classes_native: + +On The Native Side +------------------ + +Those injections go in the body of the ``CLASSNAME_wrapper.cpp`` file for the +wrapped class. + + .. code-block:: c++ + + // Start of ``CLASSNAME_wrapper.cpp`` + #define protected public + // default includes + #include + (...) + #include "injectcode_wrapper.h" + using namespace Shiboken; + + // INJECT-CODE: + // Uses: prototype declarations + + (... C++ wrapper virtual methods, if any ...) + + (... Python wrapper code ...) + + PyAPI_FUNC(void) + init_injectcode(PyObject *module) + { + (...) + } + + (...) + + // INJECT-CODE: + // Uses: definition of functions prototyped at ``native/beginning``. + + // End of ``CLASSNAME_wrapper.cpp`` + + +.. _codeinjecting_classes_target: + +On The Target Side +------------------ + +Code injections to the class Python initialization function. + + .. code-block:: c++ + + // Start of ``CLASSNAME_wrapper.cpp`` + + (...) + + PyAPI_FUNC(void) + init_injectcode(PyObject *module) + { + // INJECT-CODE: + // Uses: Alter something in the PyInjectCode_Type (tp_flags value for example) + // before registering it. + + if (PyType_Ready(&PyInjectCode_Type) < 0) + return; + + Py_INCREF(&PyInjectCode_Type); + PyModule_AddObject(module, "InjectCode", + ((PyObject*)&PyInjectCode_Type)); + + // INJECT-CODE: + // 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`` + +Code Injection for Modules +========================== + +The C++ libraries are wapped as Python modules, a collection of classes, +functions, enums and namespaces. |project| creates wrapper files for all of +them and also one extra ``MODULENAME_module_wrapper.cpp`` to register the whole +module. Code injection xml tags who have the ``typesystem`` tag as parent will +be put on this file. + +On The Native Side +------------------ + +This works exactly as the class wrapper code injections :ref:`codeinjecting_classes_native`. + +On The Target Side +------------------ + +This is very similar to class wrapper code injections :ref:`codeinjecting_classes_target`. +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++ + + // Start of ``MODULENAME_module_wrapper.cpp`` + + (...) + initMODULENAME() + { + // INJECT-CODE: + // Uses: do something before the module is created. + + PyObject* module = Py_InitModule("MODULENAME", MODULENAME_methods); + + (... initialization of wrapped classes, namespaces, functions and enums ...) + + // INJECT-CODE: + // Uses: do something after the module is registered and initialized. + + if (PyErr_Occurred()) + Py_FatalError("can't initialize module sample"); + } + + (...) + + // Start of ``MODULENAME_module_wrapper.cpp`` + diff --git a/sources/shiboken2/doc/commandlineoptions.rst b/sources/shiboken2/doc/commandlineoptions.rst new file mode 100644 index 000000000..d373561cd --- /dev/null +++ b/sources/shiboken2/doc/commandlineoptions.rst @@ -0,0 +1,105 @@ +.. _command-line: + +Command line options +******************** + +Usage +----- + +:: + + shiboken [options] header-file typesystem-file + + +Options +------- + +``--disable-verbose-error-messages`` + Disable verbose error messages. Turn the CPython code hard to debug but saves a few kilobytes + in the generated binding. + +.. _parent-heuristic: + +``--enable-parent-ctor-heuristic`` + This flag enable an useful heuristic which can save a lot of work related to object ownership when + writing the typesystem. + For more info, check :ref:`ownership-parent-heuristics`. + +.. _pyside-extensions: + +``--enable-pyside-extensions`` + Enable pyside extensions like support for signal/slots. Use this if you are creating a binding based + on PySide. + +.. _return-heuristic: + +``--enable-return-value-heuristic`` + Enable heuristics to detect parent relationship on return values. + For more info, check :ref:`return-value-heuristics`. + +.. _api-version: + +``--api-version=`` + Specify the supported api version used to generate the bindings. + +.. _debug-level: + +``--debug-level=[sparse|medium|full]`` + Set the debug level. + +.. _documentation-only: + +``--documentation-only`` + Do not generate any code, just the documentation. + +.. _drop-type-entries: + +``--drop-type-entries="[;TypeEntry1;...]"`` + Semicolon separated list of type system entries (classes, namespaces, + global functions and enums) to be dropped from generation. + +.. _generation-set: + +``--generation-set`` + Generator set to be used (e.g. qtdoc). + +.. _help: + +``--help`` + Display this help and exit. + +.. _include-paths: + +``--include-paths=[::...]`` + Include paths used by the C++ parser. + +.. _license-file=[license-file]: + +``--license-file=[license-file]`` + File used for copyright headers of generated files. + +.. _no-suppress-warnings: + +``--no-suppress-warnings`` + Show all warnings. + +.. _output-directory: + +``--output-directory=[dir]`` + The directory where the generated files will be written. + +.. _silent: + +``--silent`` + Avoid printing any message. + +.. _typesystem-paths: + +``--typesystem-paths=[::...]`` + Paths used when searching for type system files. + +.. _version: + +``--version`` + Output version information and exit. + diff --git a/sources/shiboken2/doc/conf.py.in b/sources/shiboken2/doc/conf.py.in new file mode 100644 index 000000000..ed61d2695 --- /dev/null +++ b/sources/shiboken2/doc/conf.py.in @@ -0,0 +1,166 @@ +# -*- coding: utf-8 -*- +# +# PyQtB 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. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, 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('.')) + +# -- 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'] + +rst_epilog = """ +.. |project| replace:: Shiboken +""" + +# 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' + +# The encoding of source files. +source_encoding = 'utf-8' + +# The master toctree document. +#master_doc = 'contents' + +# General information about the project. +project = u'Shiboken' +copyright = u'Copyright (C) 2016 The Qt Company Ltd.' + +# 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@' +# The full version, including alpha/beta/rc tags. +release = '@shiboken_VERSION@' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'pysidedocs' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = { +#} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# 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 = None + +# 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 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = { '' : ''} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +html_additional_pages = { 'index' : 'index.html'} + +# If false, no module index is generated. +html_use_modindex = False + +# If false, no index is generated. +html_use_index = False + +# If true, the index is split into individual pages for each letter. +html_split_index = False + +# If true, links to the reST sources are added to the pages. +html_show_sourcelink = False + +html_add_permalinks = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + diff --git a/sources/shiboken2/doc/contents.rst b/sources/shiboken2/doc/contents.rst new file mode 100644 index 000000000..24adb1c68 --- /dev/null +++ b/sources/shiboken2/doc/contents.rst @@ -0,0 +1,17 @@ +Table of contents +***************** +.. toctree:: + :numbered: + :maxdepth: 3 + + faq.rst + overview.rst + commandlineoptions.rst + projectfile.rst + typesystemvariables.rst + typeconverters.rst + codeinjectionsemantics.rst + sequenceprotocol.rst + ownership.rst + wordsofadvice.rst + shibokenmodule.rst diff --git a/sources/shiboken2/doc/dependency-pyqtb.svg b/sources/shiboken2/doc/dependency-pyqtb.svg new file mode 100644 index 000000000..a458bf6fb --- /dev/null +++ b/sources/shiboken2/doc/dependency-pyqtb.svg @@ -0,0 +1,600 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + API Extractor + 0.2 + Headers and libraries - compile-time + LGPL version 2.1 + + + + + + Shiboken (generator) + 0.1 + Binary executable - compile-time + GPL version 2 + + + + + + boost::graph + 1.38.0 + headers and libraries - compile-time + Boost Software License 1.0 + + + + + + + + + Boost + + + + Qt Software + + + + INdT/Nokia + + + + Python Foundation + + + + + + + + libshiboken + 0.1 + Headers and libraries - compile-time + LGPL version 2.1 + + + + + + Qt 4.5 + 4.5 + headers and libraries - compile-time and run-time + GNU General Public License v3 /GNU Lesser General Public Licence v2.1 + + + + + + Python + 2.6 + Headers and libraries - compile-time and run-time + Python license + + + + + + diff --git a/sources/shiboken2/doc/dependency-pyside.svg b/sources/shiboken2/doc/dependency-pyside.svg new file mode 100644 index 000000000..786bdb8a6 --- /dev/null +++ b/sources/shiboken2/doc/dependency-pyside.svg @@ -0,0 +1,527 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + boost::python + 1.38.0 + headers and libraries - compile-time and run-time + Boost Software License 1.0 + + + + Qt 4.5 + 4.5 + headers and libraries - compile-time and run-time + GNU General Public License v3 /GNU Lesser General Public Licence v2.1 + + + + libapiextractor + 0.1 + headers and libraries - compile-time and run-time + LGPL version 2.1 + + + + BoostPythonGenerator + 0.1 + Binary executable - compile-time + LGPL version 2.1 + + + + Qt Python bindings + 0.1 + Target + LGPL version 2.1 + + + + boost::graph + 1.38.0 + headers and libraries - compile-time and run-time + Boost Software License 1.0 + + + + + + + + + Boost + Qt Software + INdT/Nokia + + + + + diff --git a/sources/shiboken2/doc/faq.rst b/sources/shiboken2/doc/faq.rst new file mode 100644 index 000000000..77e0fbdfc --- /dev/null +++ b/sources/shiboken2/doc/faq.rst @@ -0,0 +1,67 @@ +************************** +Frequently Asked Questions +************************** + +This is a list of Frequently Asked Questions about |project|. Feel free to +suggest new entries! + +General +======= + +What is Shiboken? +----------------- + +Shiboken is a `GeneratorRunner `_ +plugin that outputs C++ code for CPython extensions. The first version of PySide +had source code based on Boost templates. It was easier to produce code but a +paradigm change was needed, as the next question explains. + +Why did you switch from Boost.Python to Shiboken? +------------------------------------------------- + +The main reason was the size reduction. Boost.Python makes excessive use of templates +resulting in a significant increase of the binaries size. On the other hand, as Shiboken +generates CPython code, the resulting binaries are smaller. + +Creating bindings +================= + +Can I wrap non-Qt libraries? +---------------------------- + +Yes. Check Shiboken source code for an example (libsample). + + +Is there any runtime dependency on the generated binding? +--------------------------------------------------------- + +Yes. Only libshiboken, and the obvious Python interpreter +and the C++ library that is being wrapped. + +What do I have to do to create my bindings? +------------------------------------------- + +.. todo: put link to typesystem documentation + +Most of the work is already done by the API Extractor. The developer creates +a `typesystem `_ file +with any customization wanted in the generated code, like removing classes or +changing method signatures. The generator will output the .h and .cpp files +with the CPython code that will wrap the target library for python. + +Is there any recommended build system? +-------------------------------------- + +Both API Extractor and generator uses and recommends the CMake build system. + +Can I write closed-source bindings with the generator? +------------------------------------------------------ + +Yes, as long as you use a LGPL version of Qt, due to runtime requirements. + +What is 'inject code'? +---------------------- + +That's how we call customized code that will be *injected* into the +generated at specific locations. They are specified inside the typesytem. + diff --git a/sources/shiboken2/doc/images/.directory b/sources/shiboken2/doc/images/.directory new file mode 100644 index 000000000..e65475f65 --- /dev/null +++ b/sources/shiboken2/doc/images/.directory @@ -0,0 +1,3 @@ +[Dolphin] +ShowPreview=true +Timestamp=2009,5,5,17,43,26 diff --git a/sources/shiboken2/doc/images/bindinggen-development.png b/sources/shiboken2/doc/images/bindinggen-development.png new file mode 100644 index 000000000..2dd64ba1d Binary files /dev/null and b/sources/shiboken2/doc/images/bindinggen-development.png differ diff --git a/sources/shiboken2/doc/images/bindinggen-development.svg b/sources/shiboken2/doc/images/bindinggen-development.svg new file mode 100644 index 000000000..3b6b3a26e --- /dev/null +++ b/sources/shiboken2/doc/images/bindinggen-development.svg @@ -0,0 +1,543 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + Qt bindings(generated code) + + + + generatorfront-end + + + + + + + + + + + + + API Extractor + + + + 1 + + + + 2 + + + + + + + + + + + typesystem(handwritten) + + + + + + + + + + + injected code(handwritten) + + + + 3 + + + + 4 + + + + diff --git a/sources/shiboken2/doc/images/boostgen.png b/sources/shiboken2/doc/images/boostgen.png new file mode 100644 index 000000000..ae9d9fc3d Binary files /dev/null and b/sources/shiboken2/doc/images/boostgen.png differ diff --git a/sources/shiboken2/doc/images/boostqtarch.png b/sources/shiboken2/doc/images/boostqtarch.png new file mode 100644 index 000000000..f1b145e9c Binary files /dev/null and b/sources/shiboken2/doc/images/boostqtarch.png differ diff --git a/sources/shiboken2/doc/images/boostqtarch.svg b/sources/shiboken2/doc/images/boostqtarch.svg new file mode 100644 index 000000000..9fbb38271 --- /dev/null +++ b/sources/shiboken2/doc/images/boostqtarch.svg @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + Boost::Pythonhelper library to interface with CPython APIand expose C++ entities to Python + + + + Qt-Python BindingsQt classes and functionsexported to Python + + + + + CPythonAPI + + + + Qt4Libraries + + + + + diff --git a/sources/shiboken2/doc/images/converter.dot b/sources/shiboken2/doc/images/converter.dot new file mode 100644 index 000000000..412341df9 --- /dev/null +++ b/sources/shiboken2/doc/images/converter.dot @@ -0,0 +1,14 @@ +digraph Conversions { + rankdir=LR + CppType1 [ label="C++\nType" ] + Converter1 [ label="Converter\nPython -> C++", shape=hexagon ] + PythonType1 -> Converter1 + PythonType2 -> Converter1 + PythonType3 -> Converter1 + Converter1 -> CppType1 + + CppType2 [ label="C++\nType" ] + PythonType4 [ label="PythonType" ] + Converter2 [ label="Converter\nPython -> C++", shape=hexagon ] + CppType2 -> Converter2 -> PythonType4 +} \ No newline at end of file diff --git a/sources/shiboken2/doc/images/converter.png b/sources/shiboken2/doc/images/converter.png new file mode 100644 index 000000000..51cd2af71 Binary files /dev/null and b/sources/shiboken2/doc/images/converter.png differ diff --git a/sources/shiboken2/doc/images/genrunnerarch.png b/sources/shiboken2/doc/images/genrunnerarch.png new file mode 100644 index 000000000..db1077cd0 Binary files /dev/null and b/sources/shiboken2/doc/images/genrunnerarch.png differ diff --git a/sources/shiboken2/doc/images/genrunnerarch.svg b/sources/shiboken2/doc/images/genrunnerarch.svg new file mode 100644 index 000000000..ea7eb73e7 --- /dev/null +++ b/sources/shiboken2/doc/images/genrunnerarch.svg @@ -0,0 +1,654 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + API Extractor + + + ApiExtractorcommands the parsing andbuilding of the data modeland calls the user generators + + + front-end + + Generator Runner + + + Generatorbase class for front-endoutput classes + + + + SpecificGeneratorgenerators written for anydesired output, e.g.: HppGenerator,CppGenerator,ConverterGenerator + + + + + + Generator App* loads generators* setup API Extractor* executes each generator + + + + + + + AbstractMetaBuilderbuilds the data model with informationfrom headers and binding directives + + + + TypeDatabaseparses typesystemand stores information + + + + Parserparses thelib headers + + + + + diff --git a/sources/shiboken2/doc/overview.rst b/sources/shiboken2/doc/overview.rst new file mode 100644 index 000000000..5f50610ff --- /dev/null +++ b/sources/shiboken2/doc/overview.rst @@ -0,0 +1,46 @@ +.. _gen-overview: + +****************** +Generator Overview +****************** + +In a few words, the Generator is a utility that parses a collection of header and +typesystem files, generating other files (code, documentation, etc.) as result. + +Creating new bindings +===================== + +.. figure:: images/bindinggen-development.png + :scale: 80 + :align: center + + Creating new bindings + +Each module of the generator system has an specific role. + +1. Provide enough data about the classes and functions. +2. Generate valid code, with modifications from typesystems and injected codes. +3. Modify the API to expose the objects in a way that fits you target language best. +4. Insert customizations where handwritten code is needed. + +.. figure:: images/boostqtarch.png + :scale: 80 + :align: center + + Runtime architecture + +The newly created binding will run on top of Boost.Python library which takes +care of interfacing Python and the underlying C++ library. + +Handwritten inputs +================== + +Creating new bindings involves creating two pieces of "code": the typesystem and +the inject code. + +:typesystem: XML files that provides the developer with a tool to customize the + way that the generators will see the classes and functions. For + example, functions can be renamed, have its signature changed and + many other actions. +:inject code: allows the developer to insert handwritten code where the generated + code is not suitable or needs some customization. diff --git a/sources/shiboken2/doc/ownership.rst b/sources/shiboken2/doc/ownership.rst new file mode 100644 index 000000000..69791f855 --- /dev/null +++ b/sources/shiboken2/doc/ownership.rst @@ -0,0 +1,153 @@ +**************** +Object ownership +**************** + +One of the main things a binding developer should have in mind is +how the C++ instances lives will cope with Python's reference count. +The last thing you want is to crash a program due to a segfault +when your C++ instance was deleted and the +wrapper object tries to access the invalid memory there. + +In this section we'll show how |project| deals with object ownership +and parentship, taking advantage of the information provided by the +APIExtractor. + +Ownership basics +================ + +As any python binding, |project|-based bindings uses reference counting +to handle the life of the wrapper object (the Python object that contains the +C++ object, do not confuse with the *wrapped* C++ object). +When a reference count reaches zero, the wrapper is deleted by Python garbage +collector and tries to delete the wrapped instance, but sometimes the wrapped +C++ object is already deleted, or maybe the C++ object should not be freed after +the Python wrapper go out of scope and die, because C++ is already taking care of +the wrapped instance. + +In order to handle this, you should tell the +generator whether the instance's ownership belongs to the binding or +to the C++ Library. When belonging to the binding, we are sure that the C++ object +won't be deleted by C++ code and we can call the C++ destructor when the refcount +reaches 0. Otherwise, instances owned by C++ code can be destroyed arbitrarily, +without notifying the Python wrapper of its destruction. + +Invalidating objects +==================== + +To prevent segfaults and double frees, the wrapper objects are invalidated. +An invalidated can't be passed as argument or have an attributte or method accessed. +Trying to do this will raise RuntimeError. + +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 ` or the transfer is due to the special case + of :ref:`parent ownership `. + + Besides being passed as argument, the callee 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. + +.. _ownership-virt-method: + +Objects with virtual methods +---------------------------- + + A little bit of implementation details: + 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 overriden destructor is called. + + One exception to this rule is when the object is created in C++, like in a + factory method. This way 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: + +Parent-child relationship +========================= + +One special type of ownership is the parent-child relationship. +Being a child of an object means that when the object's parent dies, +the C++ instance also dies, so the Python references will be invalidated. +Qt's QObject system, for example, implements this behavior, but this is valid +for any C++ library with similar behavior. + +.. _ownership-parent-heuristics: + +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. + + 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. + + 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. + + To activate this heuristic, use the :ref:`--enable-parent-ctor-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. + + To activate this heuristic, use the :ref:`--enable-return-value-heuristic ` + +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 indifinitely, 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. + + .. code-block:: python + + renderer.setModel(Source()) + renderer.render() + + To solve this, you should hold a reference to the source object, like in + + .. code-block:: python + + source = Source() + renderer.setSource(source) + renderer.render() + + diff --git a/sources/shiboken2/doc/projectfile.rst b/sources/shiboken2/doc/projectfile.rst new file mode 100644 index 000000000..6c9808da4 --- /dev/null +++ b/sources/shiboken2/doc/projectfile.rst @@ -0,0 +1,65 @@ +.. _project-file: + +******************** +Binding Project File +******************** + +Instead of directing the Generator behaviour via command line, the binding developer +can write a text project file describing the same information, and avoid the hassle +of a long stream of command line arguments. + +.. _project-file-structure: + +The project file structure +========================== + +Here follows a comprehensive example of a generator project file. + + .. 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 + + +Project file tags +================= + +The generator project file tags are in direct relation to the +:ref:`command line arguments `. All of the current command line +options provided by |project| were already seen on the :ref:`project-file-structure`, +for new command line options provided by additional generator modules (e.g.: qtdoc, +Shiboken) could also be used in the generator project file following simple conversion rules. + +For tags without options, just write as an empty tag without any attributes. Example: + + .. code-block:: bash + + --BOOLEAN-ARGUMENT + +becomes + + .. code-block:: ini + + BOOLEAN-ARGUMENT + +and + + .. code-block:: bash + + --VALUE-ARGUMENT=VALUE + +becomes + + .. code-block:: ini + + VALUE-ARGUMENT = VALUE + + diff --git a/sources/shiboken2/doc/sequenceprotocol.rst b/sources/shiboken2/doc/sequenceprotocol.rst new file mode 100644 index 000000000..587c0f95b --- /dev/null +++ b/sources/shiboken2/doc/sequenceprotocol.rst @@ -0,0 +1,23 @@ +Sequence Protocol +----------------- + +Support for the sequence protocol is achieved adding functions with special names, this is done using the 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 + ============= =============================================== ==================== =================== + +You just need to inform the function name to the add-function tag, without any parameter or return type information, when you do it, |project| will create a C function with parameters and return type definied by the table above. + +The function needs to follow the same semantics of the *CPython equivalent* function, the only way to do it is using the :doc:`inject-code ` tag. + +A concrete exemple how to add sequence protocol support to a class can be found on shiboken tests, more precisely in the definition of the Str class in ``tests/samplebinding/typesystem_sample.xml``. + diff --git a/sources/shiboken2/doc/shiboken2.1 b/sources/shiboken2/doc/shiboken2.1 new file mode 100644 index 000000000..e017bd9a9 --- /dev/null +++ b/sources/shiboken2/doc/shiboken2.1 @@ -0,0 +1,73 @@ +.TH SHIBOKEN "1" "March 2010" "shiboken v0.2.0" "User Commands" +.SH NAME +shiboken \- CPython bindings generator for C++ libraries +.SH DESCRIPTION +.SS "Usage:" +.IP +shiboken [options] header\-file typesystem\-file +.SS "General options:" +.TP +\fB\-\-debug\-level\fR=\fI[sparse\fR|medium|full] +Set the debug level +.TP +\fB\-\-documentation\-only\fR +Do not generates any code, just the documentation +.TP +\fB\-\-generatorSet\fR +generatorSet to be used. e.g. qtdoc +.TP +\fB\-\-help\fR +Display this help and exit +.TP +\fB\-\-include\-paths=\fR[::...] +Include paths used by the C++ parser +.TP +\fB\-\-license\-file\fR=\fI[licensefile]\fR +File used for copyright headers of generated files +.TP +\fB\-\-no\-suppress\-warnings\fR +Show all warnings +.TP +\fB\-\-output\-directory\fR=\fI[dir]\fR +The directory where the generated files will be written +.TP +\fB\-\-silent\fR +Avoid printing any message +.TP +\fB\-\-typesystem\-paths=\fR[::...] +Paths used when searching for typesystems +.TP +\fB\-\-version\fR +Output version information and exit +.SS "Shiboken options:" +.TP +\fB\-\-disable\-verbose\-error\-messages\fR +Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. +.TP +\fB\-\-enable\-parent\-ctor\-heuristic\fR +Enable heuristics to detect parent relationship on constructors. +.TP +\fB\-\-enable\-pyside\-extensions\fR +Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. +.TP +\fB\-\-enable\-return\-value\-heuristic\fR +Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) +.SS "Shiboken options:" +.TP +\fB\-\-disable\-verbose\-error\-messages\fR +Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. +.TP +\fB\-\-enable\-parent\-ctor\-heuristic\fR +Enable heuristics to detect parent relationship on constructors. +.TP +\fB\-\-enable\-pyside\-extensions\fR +Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. +.TP +\fB\-\-enable\-return\-value\-heuristic\fR +Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) +.SH COPYRIGHT +Copyright \(co 2016 The Qt Company Ltd. +.SH AUTHOR +.PP +This manpage was written for Debian, starting with a help2man output, by +Didier Raboud , on the 26. March 2010. diff --git a/sources/shiboken2/doc/shibokenmodule.rst b/sources/shiboken2/doc/shibokenmodule.rst new file mode 100644 index 000000000..150998ccd --- /dev/null +++ b/sources/shiboken2/doc/shibokenmodule.rst @@ -0,0 +1,79 @@ +.. module:: shiboken + +.. |maya| unicode:: Maya U+2122 + +Shiboken module +*************** + +Functions +^^^^^^^^^ + +.. container:: function_list + + * def :meth:`isValid` (obj) + * def :meth:`wrapInstance` (address, type) + * def :meth:`getCppPointer` (obj) + * def :meth:`delete` (obj) + * def :meth:`isOwnedByPython` (obj) + * def :meth:`wasCreatedByPython` (obj) + * def :meth:`dump` (obj) + +Detailed description +^^^^^^^^^^^^^^^^^^^^ + +This Python module can be used to access internal information related to our +binding technology. Access to this internal information is required to e.g.: +integrate PySide with Qt based programs that offer Python scripting like |maya| +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. + + +.. function:: isValid(obj) + + Given a Python object, returns True if the object methods can be called + without an exception being thrown. A Python wrapper becomes invalid when + the underlying C++ object is destroyed or unreachable. + +.. function:: wrapInstance(address, type) + + Creates a Python wrapper for a C++ object instantiated at a given memory + address - the returned object type will be the same given by the user. + + The type must be a Shiboken type, the C++ object will not be + destroyed when the returned Python object reach zero references. + + If the address is invalid or doesn't point to a C++ object of given type + the behavior is undefined. + +.. function:: getCppPointer(obj) + + Returns a tuple of longs that contain the memory addresses of the + C++ instances wrapped by the given object. + +.. function:: delete(obj) + + Deletes the C++ object wrapped by the given Python object. + +.. function:: isOwnedByPython(obj) + + Given a Python object, returns True if Python is responsible for deleting + the underlying C++ object, False otherwise. + + If the object was not a Shiboken based object, a TypeError is + thrown. + +.. function:: wasCreatedByPython(obj) + + Returns true if the given Python object was created by Python. + +.. function:: dump(obj) + + Returns a string with implementation-defined information about the + object. + This method should be used **only** for debug purposes by developers + 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. diff --git a/sources/shiboken2/doc/typeconverters.rst b/sources/shiboken2/doc/typeconverters.rst new file mode 100644 index 000000000..3779b26d7 --- /dev/null +++ b/sources/shiboken2/doc/typeconverters.rst @@ -0,0 +1,288 @@ +**************************** +User Defined Type Conversion +**************************** + +In the process of creating Python bindings of a C++ library, most of the C++ classes will have wrappers representing them in Python land. But there may be other classes that are very simple and/or have a Python type as a direct counter part. (Example: a "Complex" class, that represents complex 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++ + + // 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 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 "" tag must be used. + + .. code-block:: xml + + + + + + + + return PyComplex_FromDoubles(%in.real(), %in.imag()); + + + + + + double real = PyComplex_RealAsDouble(%in); + double imag = PyComplex_ImagAsDouble(%in); + %out = %OUTTYPE(real, imag); + + + + + + + + +The details will be given later, but the gist of it are the tags +` `_, +which has only one conversion from C++ to Python, and +` `_, +that may define the conversion of multiple Python types to C++'s "Complex" type. + +.. image:: images/converter.png + :height: 240px + :align: center + +|project| expects the code for ` `_, +to directly return the Python result of the conversion, and the added conversions inside the +` `_ +must attribute the Python to C++ conversion result to the :ref:`%out ` variable. + + +Expanding on the last example, if the binding developer want a Python 2-tuple of numbers to be accepted +by wrapped C++ functions with "Complex" arguments, an +` `_ +tag and a custom check must be added. Here's how to do it: + + .. code-block:: xml + + + + static bool Check2TupleOfNumbers(PyObject* pyIn) { + if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) + return false; + Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); + if (!SbkNumber_Check(pyReal)) + return false; + Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); + if (!SbkNumber_Check(pyImag)) + return false; + return true; + } + + + + + + + + + return PyComplex_FromDoubles(%in.real(), %in.imag()); + + + + + + double real = PyComplex_RealAsDouble(%in); + double imag = PyComplex_ImagAsDouble(%in); + %out = %OUTTYPE(real, imag); + + + + 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); + + + + + + + + + + +.. _container_conversions: + +Container Conversions +===================== + +Converters for +` `_ +are pretty much the same as for other type, except that they make use of the type system variables +:ref:`%INTYPE_# ` and :ref:`%OUTTYPE_# `. |project| combines the conversion code for +containers with the conversion defined (or automatically generated) for the containees. + + + .. code-block:: xml + + + + + + + + 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; + + + + + + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while (PyDict_Next(%in, &pos, &key, &value)) { + %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); + %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); + %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); + } + + + + + + + +.. _variables_and_functions: + +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. + + +.. _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. + + +.. _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. + + +.. _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 + + + + + + + +And implemented in a separate C++ file, like this: + + + .. code-block:: c++ + + namespace Shiboken { + template<> struct Converter + { + 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(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 +` `_ +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/shiboken2/doc/typesystemvariables.rst b/sources/shiboken2/doc/typesystemvariables.rst new file mode 100644 index 000000000..205430550 --- /dev/null +++ b/sources/shiboken2/doc/typesystemvariables.rst @@ -0,0 +1,336 @@ +********************* +Type System Variables +********************* + +User written code can be placed in arbitrary places using the +:doc:`inject-code ` tag. To ease the binding developer +work, the injected code can make use of special variables that will be replaced +by the correct values. This also shields the developer from some |project| +implementation specifics. + + +.. _variables: + +Variables +========= + + +.. _cpp_return_argument: + +**%0** + + Replaced by the C++ return variable of the Python method/function wrapper. + + +.. _arg_number: + +**%#** + + Replaced by the name of a C++ argument in the position indicated by ``#``. + 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++ + + void argRemoval(int a0, int a1 = 123); + + + .. code-block:: xml + + + + + + + + The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the + value ``123``. + + +.. _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 + system), this value will be inserted in the argument list. If you want to remove + the argument so completely that it doesn't appear in any form on the + ``%ARGUMENT_NAMES`` replacement, don't forget to remove also its default value + with the ` + `_ + type system tag. + + Take the following method and related type system description as an example: + + .. code-block:: c++ + + void argRemoval(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 56); + + + .. code-block:: xml + + + + + + + + + + + + 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++ + + %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 + return type, as this is already done by the + :ref:`%RETURN_TYPE ` variable. + Example: + + .. code-block:: c++ + + void argRemoval(int a0, int a1 = 123); + + + .. code-block:: xml + + + + + + + + The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the + value ``123``. + + +.. _converttocpp: + +**%CONVERTTOCPP[CPPTYPE]** + + Replaced by a |project| conversion call that converts a Python variable + to a C++ variable of the type indicated by ``CPPTYPE``. + + +.. _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. + + +.. _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``. + + +.. _checktype: + +**%CHECKTYPE[CPPTYPE]** + + Replaced by a |project| "checkType" call that verifies if a Python + if of the type indicated by ``CPPTYPE``. + + +.. _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 + the :ref:`%TYPE ` variable, for this latter may be translated to the original + C++ class name or to the C++ wrapper class name. + + Namespaces will are treated as classes, so ``CPPTYPE`` will work for them and their + enclosed functions as well. + +.. _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_#** + + Similar to ``%#``, but is replaced by the Python arguments (PyObjects) + received by the Python wrapper method. + + If used in the context of a native code injection, i.e. in a virtual method + override, ``%PYARG_#`` will be translated to one item of the Python tuple + holding the arguments that should be passed to the Python override for this + virtual method. + + The example + + .. code-block:: c++ + + long a = PyInt_AS_LONG(%PYARG_1); + + + is equivalent of + + .. code-block:: c++ + + long a = PyInt_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); + + + The generator tries to be smart with attributions, but it will work for the + only simplest cases. + + This example + + .. code-block:: c++ + + Py_DECREF(%PYARG_1); + %PYARG_1 = PyInt_FromLong(10); + + + is equivalent of + + .. code-block:: c++ + + Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); + PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyInt_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. + + +.. _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 + C++ parent's one. + + +.. _python_method_override: + +**%PYTHON_METHOD_OVERRIDE** + + This variable is used only on :ref:`native method code injections + `, i.e. on the binding overrides for C++ virtual + methods. It is replaced by a pointer to the Python method override. + + +.. _pythontypeobject: + +**%PYTHONTYPEOBJECT** + + Replaced by the Python type object for the context in which it is inserted: + method or class modification. + + +.. _beginallowthreads: + +**%BEGIN_ALLOW_THREADS** + + Replaced by a thread state saving procedure. + Must match with a :ref:`%END_ALLOW_THREADS ` variable. + + +.. _endallowthreads: + +**%END_ALLOW_THREADS** + + Replaced by a thread state restoring procedure. + Must match with a :ref:`%BEGIN_ALLOW_THREADS ` variable. + + +.. _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. + + +.. _example: + +Example +======= + +Just to illustrate the usage of the variables described in the previous +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 + + + + + + + + + + int argc; + char** argv; + if (!PySequence_to_argc_argv(%PYARG_1, &argc, &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 < argc; ++i) + delete[] argv[i]; + delete[] argv; + + + diff --git a/sources/shiboken2/doc/wordsofadvice.rst b/sources/shiboken2/doc/wordsofadvice.rst new file mode 100644 index 000000000..b66799338 --- /dev/null +++ b/sources/shiboken2/doc/wordsofadvice.rst @@ -0,0 +1,109 @@ +.. _words-of-advice: + +*************** +Words of Advice +*************** + +When writing or using Python bindings there is some things you must keep in mind. + + +.. _duck-punching-and-virtual-methods: + +Duck punching and virtual methods +================================= + +The combination of duck punching, the practice of altering class characteristics +of already instantiated objects, and virtual methods of wrapped C++ classes, can +be tricky. That was an optimistic statement. + +Let's see duck punching in action for educational purposes. + + .. code-block:: python + + import types + import Binding + + obj = Binding.CppClass() + + # 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) + + +If some C++ code happens to call `CppClass::virtualMethod(...)` on the C++ object +held by "obj" Python object, the new duck punched "virtualMethod" method will be +properly called. That happens because the underlying C++ object is in fact an instance +of a generated C++ class that inherits from `CppClass`, let's call it `CppClassWrapper`, +responsible for receiving the C++ virtual method calls and finding out the proper Python +override to which handle such a call. + +Now that you know this, consider the case when C++ has a factory method that gives you +new C++ objects originated somewhere in C++-land, in opposition to the ones generated in +Python-land by the usage of class constructors, like in the example above. + +Brief interruption to show what I was saying: + + .. code-block:: python + + import types + import Binding + + obj = Binding.createCppClass() + def myVirtualMethod(self_obj, arg): + pass + + # Punching a dead duck... + obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass) + + +The `Binding.createCppClass()` factory method is just an example, C++ created objects +can pop out for a number of other reasons. Objects created this way have a Python wrapper +holding them as usual, but the object held is not a `CppClassWrapper`, but a regular +`CppClass`. All virtual method calls originated in C++ will stay in C++ and never reach +a Python virtual method overridden via duck punching. + +Although duck punching is an interesting Python feature, it don't mix well with wrapped +C++ virtual methods, specially when you can't tell the origin of every single wrapped +C++ object. In summary: don't do it! + + +.. _pyside-old-style-class: + +Python old style classes and PySide +=================================== + +Because of some architectural decisions and deprecated Python types. Since PySide 1.1 old style classes are not supported with multiple inheritance. + +Below you can check the examples: + +Example with old style class: + + .. code-block:: python + + from PySide2 import QtCore + + class 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 + + from PySide2 import QtCore + + class MyOldStyleObject(object): + pass + + class MyObject(QtCore, MyOldStyleObject): + pass + + +All classes used for multiple inheritance with other PySide types need to have 'object' as base class. diff --git a/sources/shiboken2/generator/CMakeLists.txt b/sources/shiboken2/generator/CMakeLists.txt new file mode 100644 index 000000000..032118666 --- /dev/null +++ b/sources/shiboken2/generator/CMakeLists.txt @@ -0,0 +1,40 @@ +project(shibokengenerator) + +find_package(Qt5Xml) +find_package(Qt5XmlPatterns) + +set(shiboken2_SRC +generator.cpp +shiboken2/cppgenerator.cpp +shiboken2/headergenerator.cpp +shiboken2/overloaddata.cpp +shiboken2/shibokengenerator.cpp +main.cpp +) + +if (NOT DISABLE_DOCSTRINGS) + set(shiboken2_SRC ${shiboken2_SRC} qtdoc/qtdocgenerator.cpp) + add_definitions(-DDOCSTRINGS_ENABLED) +endif() + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shiboken2 + ${CMAKE_CURRENT_SOURCE_DIR}/qtdoc + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${apiextractor_SOURCE_DIR} + ${Qt5Core_INCLUDE_DIRS} + ${Qt5XmlPatterns_INCLUDE_DIRS} + ) + +add_executable(shiboken2 ${shiboken2_SRC}) +add_dependencies(shiboken2 apiextractor) +set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken2_SUFFIX}) +target_link_libraries(shiboken2 + apiextractor + ${Qt5Core_LIBRARIES} + ${Qt5XmlPatterns_LIBRARIES} + ) + +configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) + +install(TARGETS shiboken2 DESTINATION bin) diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp new file mode 100644 index 000000000..76d104c12 --- /dev/null +++ b/sources/shiboken2/generator/generator.cpp @@ -0,0 +1,864 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "generator.h" +#include "abstractmetalang.h" +#include "reporthandler.h" +#include "fileout.h" +#include "apiextractor.h" +#include "typesystem.h" + +#include +#include +#include +#include +#include +#include + +struct Generator::GeneratorPrivate { + const ApiExtractor* apiextractor; + QString outDir; + // License comment + QString licenseComment; + QString packageName; + int numGenerated; + QStringList instantiatedContainersNames; + QStringList instantiatedSmartPointerNames; + QVector instantiatedContainers; + QVector instantiatedSmartPointers; + +}; + +Generator::Generator() : m_d(new GeneratorPrivate) +{ + m_d->numGenerated = 0; +} + +Generator::~Generator() +{ + delete m_d; +} + +bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QString > args) +{ + m_d->apiextractor = &extractor; + TypeEntryHash allEntries = TypeDatabase::instance()->allEntries(); + TypeEntry* entryFound = 0; + for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) { + for (TypeEntry *entry : it.value()) { + if (entry->type() == TypeEntry::TypeSystemType && entry->generateCode()) { + entryFound = entry; + break; + } + } + if (entryFound) + break; + } + if (entryFound) + m_d->packageName = entryFound->name(); + else + qCWarning(lcShiboken) << "Couldn't find the package name!!"; + + collectInstantiatedContainersAndSmartPointers(); + + return doSetup(args); +} + +QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type) +{ + const QString signature = type->cppSignature(); + if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer()) + return signature; + QString typeName = signature; + if (type->isConstant()) + typeName.remove(0, sizeof("const ") / sizeof(char) - 1); + switch (type->referenceType()) { + case NoReference: + break; + case LValueReference: + typeName.chop(1); + break; + case RValueReference: + typeName.chop(2); + break; + } + while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' '))) + typeName.chop(1); + return typeName; +} + +void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, + const QString &context) +{ + if (!type) + return; + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType* t : instantiations) + addInstantiatedContainersAndSmartPointers(t, context); + if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer()) + return; + bool isContainer = type->typeEntry()->isContainer(); + if (type->hasTemplateChildren()) { + QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer"); + QString warning = + QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template" + " arguments.").arg(piece).arg(type->originalTypeDescription()); + if (!context.isEmpty()) + warning.append(QStringLiteral(" Calling context: %1").arg(context)); + + qCWarning(lcShiboken).noquote().nospace() << warning; + return; + + } + QString typeName = getSimplifiedContainerTypeName(type); + if (isContainer) { + if (!m_d->instantiatedContainersNames.contains(typeName)) { + m_d->instantiatedContainersNames.append(typeName); + m_d->instantiatedContainers.append(type); + } + } else { + // Is smart pointer. + if (!m_d->instantiatedSmartPointerNames.contains(typeName)) { + m_d->instantiatedSmartPointerNames.append(typeName); + m_d->instantiatedSmartPointers.append(type); + } + } + +} + +void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction *func) +{ + addInstantiatedContainersAndSmartPointers(func->type(), func->signature()); + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) + addInstantiatedContainersAndSmartPointers(arg->type(), func->signature()); +} + +void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass) +{ + if (!metaClass->typeEntry()->generateCode()) + return; + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (const AbstractMetaFunction *func : funcs) + collectInstantiatedContainersAndSmartPointers(func); + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *field : fields) + addInstantiatedContainersAndSmartPointers(field->type(), field->name()); + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) + collectInstantiatedContainersAndSmartPointers(innerClass); +} + +void Generator::collectInstantiatedContainersAndSmartPointers() +{ + const AbstractMetaFunctionList &funcs = globalFunctions(); + for (const AbstractMetaFunction *func : funcs) + collectInstantiatedContainersAndSmartPointers(func); + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) + collectInstantiatedContainersAndSmartPointers(metaClass); +} + +QVector Generator::instantiatedContainers() const +{ + return m_d->instantiatedContainers; +} + +QVector Generator::instantiatedSmartPointers() const +{ + return m_d->instantiatedSmartPointers; +} + +QMap< QString, QString > Generator::options() const +{ + return QMap(); +} + +AbstractMetaClassList Generator::classes() const +{ + return m_d->apiextractor->classes(); +} + +AbstractMetaClassList Generator::classesTopologicalSorted(const Dependencies &additionalDependencies) const +{ + return m_d->apiextractor->classesTopologicalSorted(additionalDependencies); +} + +AbstractMetaFunctionList Generator::globalFunctions() const +{ + return m_d->apiextractor->globalFunctions(); +} + +AbstractMetaEnumList Generator::globalEnums() const +{ + return m_d->apiextractor->globalEnums(); +} + +PrimitiveTypeEntryList Generator::primitiveTypes() const +{ + return m_d->apiextractor->primitiveTypes(); +} + +ContainerTypeEntryList Generator::containerTypes() const +{ + return m_d->apiextractor->containerTypes(); +} + +const AbstractMetaEnum* Generator::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const +{ + return m_d->apiextractor->findAbstractMetaEnum(typeEntry); +} + +const AbstractMetaEnum* Generator::findAbstractMetaEnum(const TypeEntry* typeEntry) const +{ + return m_d->apiextractor->findAbstractMetaEnum(typeEntry); +} + +const AbstractMetaEnum* Generator::findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const +{ + return m_d->apiextractor->findAbstractMetaEnum(typeEntry); +} + +const AbstractMetaEnum* Generator::findAbstractMetaEnum(const AbstractMetaType* metaType) const +{ + return m_d->apiextractor->findAbstractMetaEnum(metaType); +} + +QSet< QString > Generator::qtMetaTypeDeclaredTypeNames() const +{ + return m_d->apiextractor->qtMetaTypeDeclaredTypeNames(); +} + +QString Generator::licenseComment() const +{ + return m_d->licenseComment; +} + +void Generator::setLicenseComment(const QString& licenseComment) +{ + m_d->licenseComment = licenseComment; +} + +QString Generator::packageName() const +{ + return m_d->packageName; +} + +QString Generator::moduleName() const +{ + QString& pkgName = m_d->packageName; + return QString(pkgName).remove(0, pkgName.lastIndexOf(QLatin1Char('.')) + 1); +} + +QString Generator::outputDirectory() const +{ + return m_d->outDir; +} + +void Generator::setOutputDirectory(const QString &outDir) +{ + m_d->outDir = outDir; +} + +int Generator::numGenerated() const +{ + return m_d->numGenerated; +} + +inline void touchFile(const QString &filePath) +{ + QFile toucher(filePath); + qint64 size = toucher.size(); + if (!toucher.open(QIODevice::ReadWrite)) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Failed to touch file '%1'") + .arg(QDir::toNativeSeparators(filePath)); + return; + } + toucher.resize(size+1); + toucher.resize(size); + toucher.close(); +} + +bool Generator::generateFileForContext(GeneratorContext &context) +{ + AbstractMetaClass *cls = context.metaClass(); + + if (!shouldGenerate(cls)) + return true; + + const QString fileName = fileNameForContext(context); + if (fileName.isEmpty()) + return true; + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCDebug(lcShiboken) << "generating: " << fileName; + + QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls) + + QLatin1Char('/') + fileName; + FileOut fileOut(filePath); + + generateClass(fileOut.stream, context); + + FileOut::State state = fileOut.done(); + switch (state) { + case FileOut::Failure: + return false; + case FileOut::Unchanged: + // Even if contents is unchanged, the last file modification time should be updated, + // so that the build system can rely on the fact the generated file is up-to-date. + touchFile(filePath); + break; + case FileOut::Success: + break; + } + + ++m_d->numGenerated; + return true; +} + +QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType, + const AbstractMetaClass *smartPointerClass) const +{ + const AbstractMetaType *innerType = smartPointerType->getSmartPointerInnerType(); + QString fileName = smartPointerClass->qualifiedCppName().toLower(); + fileName.replace(QLatin1String("::"), QLatin1String("_")); + fileName.append(QLatin1String("_")); + fileName.append(innerType->name().toLower()); + + return fileName; +} + +bool Generator::generate() +{ + const AbstractMetaClassList &classList = m_d->apiextractor->classes(); + for (AbstractMetaClass *cls : classList) { + GeneratorContext context(cls); + if (!generateFileForContext(context)) + return false; + } + + for (const AbstractMetaType *type : qAsConst(m_d->instantiatedSmartPointers)) { + AbstractMetaClass *smartPointerClass = + AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->name()); + GeneratorContext context(smartPointerClass, type, true); + if (!generateFileForContext(context)) + return false; + } + return finishGeneration(); +} + +bool Generator::shouldGenerateTypeEntry(const TypeEntry* type) const +{ + return type->codeGeneration() & TypeEntry::GenerateTargetLang; +} + +bool Generator::shouldGenerate(const AbstractMetaClass* metaClass) const +{ + return shouldGenerateTypeEntry(metaClass->typeEntry()); +} + +void verifyDirectoryFor(const QFile &file) +{ + QDir dir = QFileInfo(file).dir(); + if (!dir.exists()) { + if (!dir.mkpath(dir.absolutePath())) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("unable to create directory '%1'").arg(dir.absolutePath()); + } + } +} + +void Generator::replaceTemplateVariables(QString &code, const AbstractMetaFunction *func) +{ + const AbstractMetaClass *cpp_class = func->ownerClass(); + if (cpp_class) + code.replace(QLatin1String("%TYPE"), cpp_class->name()); + + const AbstractMetaArgumentList &argument = func->arguments(); + for (AbstractMetaArgument *arg : argument) + code.replace(QLatin1Char('%') + QString::number(arg->argumentIndex() + 1), arg->name()); + + //template values + code.replace(QLatin1String("%RETURN_TYPE"), translateType(func->type(), cpp_class)); + code.replace(QLatin1String("%FUNCTION_NAME"), func->originalName()); + + if (code.contains(QLatin1String("%ARGUMENT_NAMES"))) { + QString str; + QTextStream aux_stream(&str); + writeArgumentNames(aux_stream, func, Generator::SkipRemovedArguments); + code.replace(QLatin1String("%ARGUMENT_NAMES"), str); + } + + if (code.contains(QLatin1String("%ARGUMENTS"))) { + QString str; + QTextStream aux_stream(&str); + writeFunctionArguments(aux_stream, func, Options(SkipDefaultValues) | SkipRemovedArguments); + code.replace(QLatin1String("%ARGUMENTS"), str); + } +} + +QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor) +{ + // detect number of spaces before the first character + const QStringList lst(code.split(QLatin1Char('\n'))); + static const QRegularExpression nonSpaceRegex(QStringLiteral("[^\\s]")); + Q_ASSERT(nonSpaceRegex.isValid()); + int spacesToRemove = 0; + for (const QString &line : lst) { + if (!line.trimmed().isEmpty()) { + spacesToRemove = line.indexOf(nonSpaceRegex); + if (spacesToRemove == -1) + spacesToRemove = 0; + break; + } + } + + static const QRegularExpression emptyLine(QStringLiteral("^\\s*[\\r]?[\\n]?\\s*$")); + Q_ASSERT(emptyLine.isValid()); + + for (QString line : lst) { + if (!line.isEmpty() && !emptyLine.match(line).hasMatch()) { + while (line.end()->isSpace()) + line.chop(1); + int limit = 0; + for(int i = 0; i < spacesToRemove; ++i) { + if (!line[i].isSpace()) + break; + limit++; + } + + s << indentor << line.remove(0, limit); + } + s << endl; + } + return s; +} + +AbstractMetaFunctionList Generator::implicitConversions(const TypeEntry* type) const +{ + if (type->isValue()) { + if (const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), type)) + return metaClass->implicitConversions(); + } + return AbstractMetaFunctionList(); +} + +AbstractMetaFunctionList Generator::implicitConversions(const AbstractMetaType* metaType) const +{ + return implicitConversions(metaType->typeEntry()); +} + +bool Generator::isObjectType(const TypeEntry* type) +{ + if (type->isComplex()) + return Generator::isObjectType((const ComplexTypeEntry*)type); + return type->isObject(); +} +bool Generator::isObjectType(const ComplexTypeEntry* type) +{ + return type->isObject() || type->isQObject(); +} +bool Generator::isObjectType(const AbstractMetaClass* metaClass) +{ + return Generator::isObjectType(metaClass->typeEntry()); +} +bool Generator::isObjectType(const AbstractMetaType* metaType) +{ + return isObjectType(metaType->typeEntry()); +} + +bool Generator::isPointer(const AbstractMetaType* type) +{ + return type->indirections() > 0 + || type->isNativePointer() + || type->isValuePointer(); +} + +bool Generator::isCString(const AbstractMetaType* type) +{ + return type->isNativePointer() + && type->indirections() == 1 + && type->name() == QLatin1String("char"); +} + +bool Generator::isVoidPointer(const AbstractMetaType* type) +{ + return type->isNativePointer() + && type->indirections() == 1 + && type->name() == QLatin1String("void"); +} + +QString Generator::getFullTypeName(const TypeEntry* type) const +{ + return type->isCppPrimitive() + ? type->qualifiedCppName() + : (QLatin1String("::") + type->qualifiedCppName()); +} + +QString Generator::getFullTypeName(const AbstractMetaType* type) const +{ + if (isCString(type)) + return QLatin1String("const char*"); + if (isVoidPointer(type)) + return QLatin1String("void*"); + if (type->typeEntry()->isContainer()) + return QLatin1String("::") + type->cppSignature(); + QString typeName; + if (type->typeEntry()->isComplex() && type->hasInstantiations()) + typeName = getFullTypeNameWithoutModifiers(type); + else + typeName = getFullTypeName(type->typeEntry()); + return typeName + QString::fromLatin1("*").repeated(type->indirections()); +} + +QString Generator::getFullTypeName(const AbstractMetaClass* metaClass) const +{ + return QLatin1String("::") + metaClass->qualifiedCppName(); +} + +QString Generator::getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const +{ + if (isCString(type)) + return QLatin1String("const char*"); + if (isVoidPointer(type)) + return QLatin1String("void*"); + if (!type->hasInstantiations()) + return getFullTypeName(type->typeEntry()); + QString typeName = type->cppSignature(); + if (type->isConstant()) + typeName.remove(0, sizeof("const ") / sizeof(char) - 1); + switch (type->referenceType()) { + case NoReference: + break; + case LValueReference: + typeName.chop(1); + break; + case RValueReference: + typeName.chop(2); + break; + } + while (typeName.endsWith(QLatin1Char('*')) || typeName.endsWith(QLatin1Char(' '))) + typeName.chop(1); + return QLatin1String("::") + typeName; +} + +QString Generator::minimalConstructor(const AbstractMetaType* type) const +{ + if (!type || (type->referenceType() == LValueReference && Generator::isObjectType(type))) + return QString(); + + if (type->isContainer()) { + QString ctor = type->cppSignature(); + if (ctor.endsWith(QLatin1Char('*'))) + return QLatin1String("0"); + if (ctor.startsWith(QLatin1String("const "))) + ctor.remove(0, sizeof("const ") / sizeof(char) - 1); + if (ctor.endsWith(QLatin1Char('&'))) { + ctor.chop(1); + ctor = ctor.trimmed(); + } + return QLatin1String("::") + ctor + QLatin1String("()"); + } + + if (type->isNativePointer()) + return QLatin1String("static_cast<") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)"); + if (Generator::isPointer(type)) + return QLatin1String("static_cast< ::") + type->typeEntry()->qualifiedCppName() + QLatin1String(" *>(0)"); + + if (type->typeEntry()->isComplex()) { + const ComplexTypeEntry* cType = reinterpret_cast(type->typeEntry()); + QString ctor = cType->defaultConstructor(); + if (!ctor.isEmpty()) + return ctor; + ctor = minimalConstructor(AbstractMetaClass::findClass(classes(), cType)); + if (type->hasInstantiations()) + ctor = ctor.replace(getFullTypeName(cType), getFullTypeNameWithoutModifiers(type)); + return ctor; + } + + return minimalConstructor(type->typeEntry()); +} + +QString Generator::minimalConstructor(const TypeEntry* type) const +{ + if (!type) + return QString(); + + if (type->isCppPrimitive()) { + const QString &name = type->qualifiedCppName(); + return name == QLatin1String("bool") + ? QLatin1String("false") : name + QLatin1String("(0)"); + } + + if (type->isEnum()) + return QLatin1String("static_cast< ::") + type->qualifiedCppName() + QLatin1String(">(0)"); + + if (type->isFlags()) + return type->qualifiedCppName() + QLatin1String("(0)"); + + if (type->isPrimitive()) { + QString ctor = reinterpret_cast(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 + // bindings will tell. + return ctor.isEmpty() + ? (QLatin1String("::") + type->qualifiedCppName() + QLatin1String("()")) + : ctor; + } + + if (type->isComplex()) + return minimalConstructor(AbstractMetaClass::findClass(classes(), type)); + + return QString(); +} + +QString Generator::minimalConstructor(const AbstractMetaClass* metaClass) const +{ + if (!metaClass) + return QString(); + + const ComplexTypeEntry* cType = reinterpret_cast(metaClass->typeEntry()); + if (cType->hasDefaultConstructor()) + return cType->defaultConstructor(); + + const AbstractMetaFunctionList &constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors); + int maxArgs = 0; + for (const AbstractMetaFunction *ctor : constructors) { + if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) + continue; + + int numArgs = ctor->arguments().size(); + if (numArgs == 0) { + maxArgs = 0; + break; + } + if (numArgs > maxArgs) + maxArgs = numArgs; + } + + QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName(); + QStringList templateTypes; + const QVector &templateArguments = metaClass->templateArguments(); + for (TypeEntry *templateType : templateArguments) + templateTypes << templateType->qualifiedCppName(); + + // Empty constructor. + if (maxArgs == 0) + return QLatin1String("::") + qualifiedCppName + QLatin1String("()"); + + QVector candidates; + + // Constructors with C++ primitive types, enums or pointers only. + // Start with the ones with fewer arguments. + for (int i = 1; i <= maxArgs; ++i) { + for (const AbstractMetaFunction *ctor : constructors) { + if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction) + continue; + + const AbstractMetaArgumentList &arguments = ctor->arguments(); + if (arguments.size() != i) + continue; + + QStringList args; + for (const AbstractMetaArgument *arg : arguments) { + const TypeEntry* type = arg->type()->typeEntry(); + if (type == metaClass->typeEntry()) { + args.clear(); + break; + } + + if (!arg->originalDefaultValueExpression().isEmpty()) { + if (!arg->defaultValueExpression().isEmpty() + && arg->defaultValueExpression() != arg->originalDefaultValueExpression()) { + args << arg->defaultValueExpression(); + } + break; + } + + if (type->isCppPrimitive() || type->isEnum() || isPointer(arg->type())) { + QString argValue = minimalConstructor(arg->type()); + if (argValue.isEmpty()) { + args.clear(); + break; + } + args << argValue; + } else { + args.clear(); + break; + } + } + + if (!args.isEmpty()) + return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", "))); + + candidates << ctor; + } + } + + // Constructors with C++ primitive types, enums, pointers, value types, + // and user defined primitive types. + // Builds the minimal constructor recursively. + for (const AbstractMetaFunction *ctor : qAsConst(candidates)) { + QStringList args; + const AbstractMetaArgumentList &arguments = ctor->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (arg->type()->typeEntry() == metaClass->typeEntry()) { + args.clear(); + break; + } + QString argValue = minimalConstructor(arg->type()); + if (argValue.isEmpty()) { + args.clear(); + break; + } + args << argValue; + } + if (!args.isEmpty()) { + return QString::fromLatin1("::%1(%2)").arg(qualifiedCppName, args.join(QLatin1String(", "))); + } + } + + return QString(); +} + +QString Generator::translateType(const AbstractMetaType *cType, + const AbstractMetaClass *context, + Options options) const +{ + QString s; + static int constLen = strlen("const"); + + if (context && cType && + context->typeEntry()->isGenericClass() && + cType->originalTemplateType()) { + cType = cType->originalTemplateType(); + } + + if (!cType) { + s = QLatin1String("void"); + } else if (cType->isArray()) { + s = translateType(cType->arrayElementType(), context, options) + QLatin1String("[]"); + } else if (options & Generator::EnumAsInts && (cType->isEnum() || cType->isFlags())) { + s = QLatin1String("int"); + } else { + if (options & Generator::OriginalName) { + s = cType->originalTypeDescription().trimmed(); + if ((options & Generator::ExcludeReference) && s.endsWith(QLatin1Char('&'))) + s.chop(1); + + // remove only the last const (avoid remove template const) + if (options & Generator::ExcludeConst) { + int index = s.lastIndexOf(QLatin1String("const")); + + if (index >= (s.size() - (constLen + 1))) // (VarType const) or (VarType const[*|&]) + s = s.remove(index, constLen); + } + } else if (options & Generator::ExcludeConst || options & Generator::ExcludeReference) { + AbstractMetaType* copyType = cType->copy(); + + 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(QLatin1String("::")); + delete copyType; + } else { + s = cType->cppSignature(); + } + } + + return s; +} + + +QString Generator::subDirectoryForClass(const AbstractMetaClass* clazz) const +{ + return subDirectoryForPackage(clazz->package()); +} + +QString Generator::subDirectoryForPackage(QString packageName) const +{ + if (packageName.isEmpty()) + packageName = m_d->packageName; + return QString(packageName).replace(QLatin1Char('.'), QDir::separator()); +} + +template +static QString getClassTargetFullName_(const T* t, bool includePackageName) +{ + QString name = t->name(); + const AbstractMetaClass* context = t->enclosingClass(); + while (context) { + name.prepend(QLatin1Char('.')); + name.prepend(context->name()); + context = context->enclosingClass(); + } + if (includePackageName) { + name.prepend(QLatin1Char('.')); + name.prepend(t->package()); + } + return name; +} + +QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName) +{ + return getClassTargetFullName_(metaClass, includePackageName); +} + +QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName) +{ + return getClassTargetFullName_(metaEnum, includePackageName); +} + +QString getClassTargetFullName(const AbstractMetaType *metaType, bool includePackageName) +{ + QString name = metaType->cppSignature(); + name.replace(QLatin1String("::"), QLatin1String("_")); + name.replace(QLatin1Char('<'), QLatin1Char('_')); + name.remove(QLatin1Char('>')); + name.remove(QLatin1Char(' ')); + if (includePackageName) { + name.prepend(QLatin1Char('.')); + name.prepend(metaType->package()); + } + return name; +} + +QString getFilteredCppSignatureString(QString signature) +{ + signature.replace(QLatin1String("::"), QLatin1String("_")); + signature.replace(QLatin1Char('<'), QLatin1Char('_')); + signature.replace(QLatin1Char('>'), QLatin1Char('_')); + signature.replace(QLatin1Char(' '), QLatin1Char('_')); + return signature; +} diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h new file mode 100644 index 000000000..5ff5d6ae5 --- /dev/null +++ b/sources/shiboken2/generator/generator.h @@ -0,0 +1,448 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GENERATOR_H +#define GENERATOR_H + +#include +#include +#include +#include +#include +#include +#include + +class ApiExtractor; +class AbstractMetaBuilder; +class AbstractMetaFunction; +class AbstractMetaClass; +class AbstractMetaEnum; +class TypeEntry; +class ComplexTypeEntry; +class AbstractMetaType; +class EnumTypeEntry; +class FlagsTypeEntry; + +QT_BEGIN_NAMESPACE +class QFile; +QT_END_NAMESPACE + +class PrimitiveTypeEntry; +class ContainerTypeEntry; +class Indentor; + +QTextStream& formatCode(QTextStream &s, const QString& code, Indentor &indentor); +void verifyDirectoryFor(const QFile &file); + +QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true); +QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true); +QString getClassTargetFullName(const AbstractMetaType *metaType, 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 + +/** + * 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. 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 { +public: + GeneratorContext() : m_metaClass(0), m_preciseClassType(0), m_forSmartPointer(false) {} + GeneratorContext(AbstractMetaClass *metaClass, + const AbstractMetaType *preciseType = 0, + bool forSmartPointer = false) + : m_metaClass(metaClass), + m_preciseClassType(preciseType), + m_forSmartPointer(forSmartPointer) {} + + + AbstractMetaClass *metaClass() const { return m_metaClass; } + bool forSmartPointer() const { return m_forSmartPointer; } + const AbstractMetaType *preciseType() const { return m_preciseClassType; } + +private: + AbstractMetaClass *m_metaClass; + const AbstractMetaType *m_preciseClassType; + bool m_forSmartPointer; +}; + +/** + * Base class for all generators. The default implementations does nothing, + * you must subclass this to create your own generators. + */ +class Generator +{ +public: + /// Optiosn used around the generator code + enum Option { + NoOption = 0x00000000, + BoxedPrimitive = 0x00000001, + ExcludeConst = 0x00000002, + ExcludeReference = 0x00000004, + UseNativeIds = 0x00000008, + + EnumAsInts = 0x00000010, + SkipName = 0x00000020, + NoCasts = 0x00000040, + SkipReturnType = 0x00000080, + OriginalName = 0x00000100, + ShowStatic = 0x00000200, + UnderscoreSpaces = 0x00000400, + ForceEnumCast = 0x00000800, + ArrayAsPointer = 0x00001000, + VirtualCall = 0x00002000, + SkipTemplateParameters = 0x00004000, + SkipAttributes = 0x00008000, + OriginalTypeDescription = 0x00010000, + SkipRemovedArguments = 0x00020000, + IncludeDefaultExpression = 0x00040000, + NoReturnStatement = 0x00080000, + NoBlockedSlot = 0x00100000, + + SuperCall = 0x00200000, + + GlobalRefJObject = 0x00100000, + + SkipDefaultValues = 0x00400000, + + WriteSelf = 0x00800000, + ExcludeMethodConst = 0x01000000, + + ForceValueType = ExcludeReference | ExcludeConst + }; + Q_DECLARE_FLAGS(Options, Option) + + Generator(); + virtual ~Generator(); + + bool setup(const ApiExtractor& extractor, const QMap args); + + virtual QMap options() const; + + /// Returns the classes used to generate the binding code. + AbstractMetaClassList classes() const; + + /// Returns the classes, topologically ordered, used to generate the binding code. + /// + /// The classes are ordered such that derived classes appear later in the list than + /// their parent classes. + AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const; + + /// Returns all global functions found by APIExtractor + AbstractMetaFunctionList globalFunctions() const; + + /// Returns all global enums found by APIExtractor + AbstractMetaEnumList globalEnums() const; + + /// Returns all primitive types found by APIExtractor + PrimitiveTypeEntryList primitiveTypes() const; + + /// Returns all container types found by APIExtractor + ContainerTypeEntryList containerTypes() const; + + /// Returns an AbstractMetaEnum for a given EnumTypeEntry, or NULL if not found. + const AbstractMetaEnum* findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const; + + /// Returns an AbstractMetaEnum for a given TypeEntry that is an EnumTypeEntry, or NULL if not found. + const AbstractMetaEnum* findAbstractMetaEnum(const TypeEntry* typeEntry) const; + + /// Returns an AbstractMetaEnum for the enum related to a given FlagsTypeEntry, or NULL if not found. + const AbstractMetaEnum* findAbstractMetaEnum(const FlagsTypeEntry* typeEntry) const; + + /// Returns an AbstractMetaEnum for a given AbstractMetaType that holds an EnumTypeEntry, or NULL if not found. + const AbstractMetaEnum* findAbstractMetaEnum(const AbstractMetaType* metaType) const; + + /// Returns the output directory + QString outputDirectory() const; + + /// Set the output directory + void setOutputDirectory(const QString &outDir); + + /** + * Start the code generation, be sure to call setClasses before callign this method. + * For each class it creates a QTextStream, call the write method with the current + * class and the associated text stream, then write the text stream contents if needed. + * \see #write + */ + bool generate(); + + + /// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case). + bool generateFileForContext(GeneratorContext &context); + + /// Returns the file base name for a smart pointer. + QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType, + const AbstractMetaClass *smartPointerClass) const; + + /// Returns the number of generated items + int numGenerated() const; + + /// Returns the generator's name. Used for cosmetic purposes. + virtual const char* name() const = 0; + + /// Returns true if the generator should generate any code for the TypeEntry. + bool shouldGenerateTypeEntry(const TypeEntry*) const; + + /// Returns true if the generator should generate any code for the AbstractMetaClass. + virtual bool shouldGenerate(const AbstractMetaClass *) const; + + /// Returns the subdirectory used to write the binding code of an AbstractMetaClass. + virtual QString subDirectoryForClass(const AbstractMetaClass* clazz) const; + + /** + * Translate metatypes to binding source format. + * \param metatype a pointer to metatype + * \param context the current meta class + * \param option some extra options + * \return the metatype translated to binding source format + */ + QString translateType(const AbstractMetaType *metatype, + const AbstractMetaClass *context, + Options options = NoOption) const; + + /** + * Function used to write the fucntion arguments on the class buffer. + * \param s the class output buffer + * \param metafunction the pointer to metafunction information + * \param count the number of function arguments + * \param options some extra options used during the parser + */ + virtual void writeFunctionArguments(QTextStream &s, + const AbstractMetaFunction *metafunction, + Options options = NoOption) const = 0; + + virtual void writeArgumentNames(QTextStream &s, + const AbstractMetaFunction *metafunction, + Options options = NoOption) const = 0; + + void replaceTemplateVariables(QString &code, const AbstractMetaFunction *func); + + // QtScript + QSet qtMetaTypeDeclaredTypeNames() const; + + /** + * Returns the license comment to be prepended to each source file generated. + */ + QString licenseComment() const; + + /** + * Sets the license comment to be prepended to each source file generated. + */ + void setLicenseComment(const QString &licenseComment); + + /** + * Returns the package name. + */ + QString packageName() const; + + /** + * Retrieves the name of the currently processed module. + * While package name is a complete package idetification, e.g. 'PySide.QtCore', + * a module name represents the last part of the package, e.g. 'QtCore'. + * If the target language separates the modules with characters other than + * dots ('.') the generator subclass must overload this method. + * \return a string representing the last part of a package name + */ + virtual QString moduleName() 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 + */ + AbstractMetaFunctionList implicitConversions(const TypeEntry* type) const; + + /// Convenience function for implicitConversions(const TypeEntry* type). + AbstractMetaFunctionList implicitConversions(const AbstractMetaType* metaType) const; + + /// Check if type is a pointer. + static bool isPointer(const AbstractMetaType* type); + + /// Tells if the type or class is an Object (or QObject) Type. + static bool isObjectType(const TypeEntry* type); + static bool isObjectType(const ComplexTypeEntry* type); + static bool isObjectType(const AbstractMetaType* metaType); + static bool isObjectType(const AbstractMetaClass* metaClass); + + /// Returns true if the type is a C string (const char*). + static bool isCString(const AbstractMetaType* type); + /// Returns true if the type is a void pointer. + static bool isVoidPointer(const AbstractMetaType* type); + + // Returns the full name of the type. + QString getFullTypeName(const TypeEntry* type) const; + QString getFullTypeName(const AbstractMetaType* type) const; + QString getFullTypeName(const AbstractMetaClass* metaClass) const; + + /** + * Returns the full qualified C++ name for an AbstractMetaType, but removing modifiers + * as 'const', '&', and '*' (except if the class is not derived from a template). + * This is useful for instantiated templates. + */ + QString getFullTypeNameWithoutModifiers(const AbstractMetaType* type) const; + + /** + * Tries to build a minimal constructor for the type. + * It will check first for a user defined default constructor. + * Returns a null string if it fails. + */ + QString minimalConstructor(const TypeEntry* type) const; + QString minimalConstructor(const AbstractMetaType* type) const; + QString minimalConstructor(const AbstractMetaClass* metaClass) const; + +protected: + /** + * Returns the file name used to write the binding code of an AbstractMetaClass/Type. + * \param context the GeneratorContext which contains an AbstractMetaClass or AbstractMetaType + * for which the file name must be returned + * \return the file name used to write the binding code for the class + */ + virtual QString fileNamePrefix() const = 0; + virtual QString fileNameForContext(GeneratorContext &context) const = 0; + + + virtual bool doSetup(const QMap& args) = 0; + + /** + * Write the bindding code for an AbstractMetaClass. + * This is called by generate method. + * \param s text stream to write the generated output + * \param metaClass the class that should be generated + */ + virtual void generateClass(QTextStream& s, GeneratorContext &classContext) = 0; + virtual bool finishGeneration() = 0; + + /** + * Returns the subdirectory path for a given package + * (aka module, aka library) name. + * If the target language separates the package modules with characters other + * than dots ('.') the generator subclass must overload this method. + * /param packageName complete package name for which to return the subdirectory path + * or nothing the use the name of the currently processed package + * /return a string representing the subdirectory path for the given package + */ + virtual QString subDirectoryForPackage(QString packageName = QString()) const; + + QVector instantiatedContainers() const; + QVector instantiatedSmartPointers() const; + + static QString getSimplifiedContainerTypeName(const AbstractMetaType *type); + void addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type, + const QString &context); + +private: + struct GeneratorPrivate; + GeneratorPrivate* m_d; + void collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction* func); + void collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass); + void collectInstantiatedContainersAndSmartPointers(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options) +typedef QSharedPointer GeneratorPtr; +typedef QVector Generators; + +/** +* Utility class to store the identation level, use it in a QTextStream. +*/ +class Indentor +{ +public: + Indentor() : indent(0) {} + int indent; +}; + +/** +* Class that use the RAII idiom to set and unset the identation level. +*/ +class Indentation +{ +public: + Indentation(Indentor &indentor) : indentor(indentor) + { + indentor.indent++; + } + ~Indentation() + { + indentor.indent--; + } + +private: + Indentor &indentor; +}; + +inline QTextStream &operator <<(QTextStream &s, const Indentor &indentor) +{ + for (int i = 0; i < indentor.indent; ++i) + s << " "; + return s; +} + +#endif // GENERATOR_H + diff --git a/sources/shiboken2/generator/main.cpp b/sources/shiboken2/generator/main.cpp new file mode 100644 index 000000000..25b50b04e --- /dev/null +++ b/sources/shiboken2/generator/main.cpp @@ -0,0 +1,552 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "generator.h" +#include "shibokenconfig.h" +#include "cppgenerator.h" +#include "headergenerator.h" +#include "qtdocgenerator.h" + +#ifdef _WINDOWS + #define PATH_SPLITTER ";" +#else + #define PATH_SPLITTER ":" +#endif + +namespace { + +class ArgsHandler +{ +public: + explicit ArgsHandler(const QMap& other); + virtual ~ArgsHandler(); + + inline QMap& args() const + { + return *m_args; + } + + inline bool argExists(const QString& s) const + { + return m_args->contains(s); + } + + QString removeArg(const QString& s); + bool argExistsRemove(const QString& s); + + inline QString argValue(const QString& s) const + { + return m_args->value(s); + } + + inline bool noArgs() const + { + return m_args->isEmpty(); + } + + QString errorMessage() const; + +private: + QMap* m_args; +}; + +ArgsHandler::ArgsHandler(const QMap& other) + : m_args(new QMap(other)) +{ +} + +ArgsHandler::~ArgsHandler() +{ + delete m_args; +} + +QString ArgsHandler::removeArg(const QString& s) +{ + QString retval; + + if (argExists(s)) { + retval = argValue(s); + m_args->remove(s); + } + + return retval; +} + +bool ArgsHandler::argExistsRemove(const QString& s) +{ + bool retval = false; + + if (argExists(s)) { + retval = true; + m_args->remove(s); + } + + return retval; +} + +QString ArgsHandler::errorMessage() const +{ + typedef QMap::ConstIterator StringMapConstIt; + + QString message; + QTextStream str(&message); + str << "shiboken: Called with wrong arguments:"; + for (StringMapConstIt it = m_args->cbegin(), end = m_args->cend(); it != end; ++it) { + str << ' ' << it.key(); + if (!it.value().isEmpty()) + str << ' ' << it.value(); + } + str << "\nCommand line: " << QCoreApplication::arguments().join(QLatin1Char(' ')); + return message; +} +} + +static void printOptions(QTextStream& s, const QMap& options) +{ + QMap::const_iterator it = options.constBegin(); + s.setFieldAlignment(QTextStream::AlignLeft); + for (; it != options.constEnd(); ++it) { + s << " --"; + s.setFieldWidth(38); + s << it.key() << it.value(); + s.setFieldWidth(0); + s << endl; + } +} + +typedef void (*getGeneratorsFunc)(QLinkedList*); + +static bool processProjectFile(QFile& projectFile, QMap& args) +{ + QByteArray line = projectFile.readLine().trimmed(); + if (line.isEmpty() || line != "[generator-project]") + return false; + + QStringList includePaths; + QStringList frameworkIncludePaths; + QStringList typesystemPaths; + QStringList apiVersions; + + 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 - 1).trimmed(); + value = QString::fromUtf8(line.mid(split + 1).trimmed()); + } else { + key = line; + } + + if (key == "include-path") + includePaths << QDir::toNativeSeparators(value); + else if (key == "framework-include-path") + frameworkIncludePaths << QDir::toNativeSeparators(value); + else if (key == "typesystem-path") + typesystemPaths << QDir::toNativeSeparators(value); + else if (key == "api-version") + apiVersions << value; + else if (key == "header-file") + args.insert(QLatin1String("arg-1"), value); + else if (key == "typesystem-file") + args.insert(QLatin1String("arg-2"), value); + else + args.insert(QString::fromUtf8(key), value); + } + + if (!includePaths.isEmpty()) + args.insert(QLatin1String("include-paths"), includePaths.join(QLatin1String(PATH_SPLITTER))); + + if (!frameworkIncludePaths.isEmpty()) + args.insert(QLatin1String("framework-include-paths"), + frameworkIncludePaths.join(QLatin1String(PATH_SPLITTER))); + + if (!typesystemPaths.isEmpty()) + args.insert(QLatin1String("typesystem-paths"), typesystemPaths.join(QLatin1String(PATH_SPLITTER))); + if (!apiVersions.isEmpty()) + args.insert(QLatin1String("api-version"), apiVersions.join(QLatin1Char('|'))); + return true; +} + +static QMap getInitializedArguments() +{ + QMap args; + QStringList arguments = QCoreApplication::arguments(); + QString appName = arguments.first(); + arguments.removeFirst(); + + QString projectFileName; + for (const QString &arg : qAsConst(arguments)) { + if (arg.startsWith(QLatin1String("--project-file"))) { + int split = arg.indexOf(QLatin1Char('=')); + if (split > 0) + projectFileName = arg.mid(split + 1).trimmed(); + break; + } + } + + if (projectFileName.isNull()) + return args; + + if (!QFile::exists(projectFileName)) { + std::cerr << qPrintable(appName) << ": Project file \""; + std::cerr << qPrintable(projectFileName) << "\" not found."; + std::cerr << std::endl; + return args; + } + + QFile projectFile(projectFileName); + if (!projectFile.open(QIODevice::ReadOnly)) + return args; + + if (!processProjectFile(projectFile, args)) { + std::cerr << qPrintable(appName) << ": first line of project file \""; + std::cerr << qPrintable(projectFileName) << "\" must be the string \"[generator-project]\""; + std::cerr << std::endl; + return args; + } + + return args; +} + +static QMap getCommandLineArgs() +{ + QMap args = getInitializedArguments(); + QStringList arguments = QCoreApplication::arguments(); + arguments.removeFirst(); + + int argNum = 0; + for (const QString &carg : qAsConst(arguments)) { + const QString &arg = carg.trimmed(); + if (arg.startsWith(QLatin1String("--"))) { + int split = arg.indexOf(QLatin1Char('=')); + if (split > 0) + args[arg.mid(2).left(split-2)] = arg.mid(split + 1).trimmed(); + else + args[arg.mid(2)] = QString(); + } else if (arg.startsWith(QLatin1Char('-'))) { + args[arg.mid(1)] = QString(); + } else { + argNum++; + args[QString::fromLatin1("arg-%1").arg(argNum)] = arg; + } + } + return args; +} + +static inline Generators docGenerators() +{ + Generators result; +#ifdef DOCSTRINGS_ENABLED + result.append(GeneratorPtr(new QtDocGenerator)); +#endif + return result; +} + +static inline Generators shibokenGenerators() +{ + Generators result; + result << GeneratorPtr(new CppGenerator) << GeneratorPtr(new HeaderGenerator); + return result; +} + +void printUsage() +{ + QTextStream s(stdout); + s << "Usage:\n " + << "shiboken [options] header-file typesystem-file\n\n" + << "General options:\n"; + QMap generalOptions; + generalOptions.insert(QLatin1String("project-file="), + QLatin1String("text file containing a description of the binding project. Replaces and overrides command line arguments")); + generalOptions.insert(QLatin1String("debug-level=[sparse|medium|full]"), + QLatin1String("Set the debug level")); + generalOptions.insert(QLatin1String("silent"), + QLatin1String("Avoid printing any message")); + generalOptions.insert(QLatin1String("help"), + QLatin1String("Display this help and exit")); + generalOptions.insert(QLatin1String("no-suppress-warnings"), + QLatin1String("Show all warnings")); + generalOptions.insert(QLatin1String("output-directory="), + QLatin1String("The directory where the generated files will be written")); + generalOptions.insert(QLatin1String("include-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), + QLatin1String("Include paths used by the C++ parser")); + generalOptions.insert(QLatin1String("framework-include-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), + QLatin1String("Framework include paths used by the C++ parser")); + generalOptions.insert(QLatin1String("typesystem-paths=[" PATH_SPLITTER "" PATH_SPLITTER "...]"), + QLatin1String("Paths used when searching for typesystems")); + generalOptions.insert(QLatin1String("documentation-only"), + QLatin1String("Do not generates any code, just the documentation")); + generalOptions.insert(QLatin1String("license-file="), + QLatin1String("File used for copyright headers of generated files")); + generalOptions.insert(QLatin1String("version"), + QLatin1String("Output version information and exit")); + generalOptions.insert(QLatin1String("generator-set=<\"generator module\">"), + QLatin1String("generator-set to be used. e.g. qtdoc")); + generalOptions.insert(QLatin1String("api-version=<\"package mask\">,<\"version\">"), + QLatin1String("Specify the supported api version used to generate the bindings")); + generalOptions.insert(QLatin1String("drop-type-entries=\"[;TypeEntry1;...]\""), + QLatin1String("Semicolon separated list of type system entries (classes, namespaces, global functions and enums) to be dropped from generation.")); + printOptions(s, generalOptions); + + const Generators generators = shibokenGenerators() + docGenerators(); + for (const GeneratorPtr &generator : generators) { + QMap options = generator->options(); + if (!options.isEmpty()) { + s << endl << generator->name() << " options:\n"; + printOptions(s, generator->options()); + } + } +} + +static inline void printVerAndBanner() +{ + std::cout << "shiboken v" SHIBOKEN_VERSION << std::endl; + std::cout << "Copyright (C) 2016 The Qt Company Ltd." << std::endl; +} + +static inline void errorPrint(const QString& s) +{ + QStringList arguments = QCoreApplication::arguments(); + arguments.pop_front(); + std::cerr << "shiboken: " << qPrintable(s) + << "\nCommand line: " << qPrintable(arguments.join(QLatin1Char(' '))) << '\n'; +} + +static QString msgInvalidVersion(const QString &package, const QString &version) +{ + return QLatin1String("Invalid version \"") + version + + QLatin1String("\" specified for package ") + package + QLatin1Char('.'); +} + +int main(int argc, char *argv[]) +{ + QElapsedTimer timer; + timer.start(); + // needed by qxmlpatterns + QCoreApplication app(argc, argv); + ReportHandler::install(); + qCDebug(lcShiboken()).noquote().nospace() << QCoreApplication::arguments().join(QLatin1Char(' ')); + + // Store command arguments in a map + QMap args = getCommandLineArgs(); + ArgsHandler argsHandler(args); + Generators generators; + + if (argsHandler.argExistsRemove(QLatin1String("version"))) { + printVerAndBanner(); + return EXIT_SUCCESS; + } + + QString generatorSet = argsHandler.removeArg(QLatin1String("generator-set")); + // Also check QLatin1String("generatorSet") command line argument for backward compatibility. + if (generatorSet.isEmpty()) + generatorSet = argsHandler.removeArg(QLatin1String("generatorSet")); + + // Pre-defined generator sets. + if (generatorSet == QLatin1String("qtdoc")) { + generators = docGenerators(); + if (generators.isEmpty()) { + errorPrint(QLatin1String("Doc strings extractions was not enabled in this shiboken build.")); + return EXIT_FAILURE; + } + } else if (generatorSet.isEmpty() || generatorSet == QLatin1String("shiboken")) { + generators = shibokenGenerators(); + } else { + errorPrint(QLatin1String("Unknown generator set, try \"shiboken\" or \"qtdoc\".")); + return EXIT_FAILURE; + } + + if (argsHandler.argExistsRemove(QLatin1String("help"))) { + printUsage(); + return EXIT_SUCCESS; + } + + QString licenseComment; + QString licenseFileName = argsHandler.removeArg(QLatin1String("license-file")); + if (!licenseFileName.isEmpty()) { + if (QFile::exists(licenseFileName)) { + QFile licenseFile(licenseFileName); + if (licenseFile.open(QIODevice::ReadOnly)) + licenseComment = QString::fromUtf8(licenseFile.readAll()); + } else { + errorPrint(QStringLiteral("Couldn't find the file containing the license heading: %1"). + arg(licenseFileName)); + return EXIT_FAILURE; + } + } + + QString outputDirectory = argsHandler.removeArg(QLatin1String("output-directory")); + if (outputDirectory.isEmpty()) + outputDirectory = QLatin1String("out"); + + if (!QDir(outputDirectory).exists()) { + if (!QDir().mkpath(outputDirectory)) { + qCWarning(lcShiboken).noquote().nospace() + << "Can't create output directory: " << QDir::toNativeSeparators(outputDirectory); + return EXIT_FAILURE; + } + } + + // Create and set-up API Extractor + ApiExtractor extractor; + extractor.setLogDirectory(outputDirectory); + + if (argsHandler.argExistsRemove(QLatin1String("silent"))) { + extractor.setSilent(true); + } else { + QString level = argsHandler.removeArg(QLatin1String("debug-level")); + if (!level.isEmpty()) { + if (level == QLatin1String("sparse")) + extractor.setDebugLevel(ReportHandler::SparseDebug); + else if (level == QLatin1String("medium")) + extractor.setDebugLevel(ReportHandler::MediumDebug); + else if (level == QLatin1String("full")) + extractor.setDebugLevel(ReportHandler::FullDebug); + } + } + if (argsHandler.argExistsRemove(QLatin1String("no-suppress-warnings"))) + extractor.setSuppressWarnings(false); + + if (argsHandler.argExists(QLatin1String("api-version"))) { + const QStringList &versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|')); + for (const QString &fullVersion : versions) { + QStringList parts = fullVersion.split(QLatin1Char(',')); + QString package; + QString version; + // avoid constFirst to stay Qt 5.5 compatible + package = parts.count() == 1 ? QLatin1String("*") : parts.first(); + version = parts.last(); + if (!extractor.setApiVersion(package, version)) { + errorPrint(msgInvalidVersion(package, version)); + return EXIT_FAILURE; + } + } + } + + if (argsHandler.argExists(QLatin1String("drop-type-entries"))) + extractor.setDropTypeEntries(argsHandler.removeArg(QLatin1String("drop-type-entries"))); + + QString path = argsHandler.removeArg(QLatin1String("typesystem-paths")); + if (!path.isEmpty()) + extractor.addTypesystemSearchPath(path.split(QLatin1String(PATH_SPLITTER))); + + path = argsHandler.removeArg(QLatin1String("include-paths")); + if (!path.isEmpty()) { + const QStringList includePathListList = path.split(QLatin1String(PATH_SPLITTER)); + for (const QString &s : qAsConst(includePathListList)) { + const bool isFramework = false; + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } + + path = argsHandler.removeArg(QLatin1String("framework-include-paths")); + if (!path.isEmpty()) { + const QStringList frameworkPathList = path.split(QLatin1String(PATH_SPLITTER)); + const bool isFramework = true; + for (const QString &s : qAsConst(frameworkPathList)) { + extractor.addIncludePath(HeaderPath(s, isFramework)); + } + } + + QString cppFileName = argsHandler.removeArg(QLatin1String("arg-1")); + QString typeSystemFileName = argsHandler.removeArg(QLatin1String("arg-2")); + + /* 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. + */ + argsHandler.removeArg(QLatin1String("project-file")); + QMap projectFileArgs = getInitializedArguments(); + if (!projectFileArgs.isEmpty()) { + QMap::const_iterator it = + projectFileArgs.constBegin(); + for ( ; it != projectFileArgs.constEnd(); ++it) + argsHandler.removeArg(it.key()); + } + for (const GeneratorPtr &generator : qAsConst(generators)) { + QMap options = generator->options(); + if (!options.isEmpty()) { + QMap::const_iterator it = options.constBegin(); + for ( ; it != options.constEnd(); ++it) + argsHandler.removeArg(it.key()); + } + } + + if (!argsHandler.noArgs()) { + errorPrint(argsHandler.errorMessage()); + std::cout << "Note: use --help option for more information." << std::endl; + return EXIT_FAILURE; + } + + extractor.setCppFileName(cppFileName); + extractor.setTypeSystem(typeSystemFileName); + if (!extractor.run()) { + errorPrint(QLatin1String("Error running ApiExtractor.")); + return EXIT_FAILURE; + } + + if (!extractor.classCount()) + qCWarning(lcShiboken) << "No C++ classes found!"; + + qCDebug(lcShiboken) << extractor; + + for (const GeneratorPtr &g : qAsConst(generators)) { + g->setOutputDirectory(outputDirectory); + g->setLicenseComment(licenseComment); + if (g->setup(extractor, args)) { + if (!g->generate()) { + errorPrint(QLatin1String("Error running generator: ") + + QLatin1String(g->name()) + QLatin1Char('.')); + return EXIT_FAILURE; + } + } + } + + QByteArray doneMessage = "Done, " + QByteArray::number(timer.elapsed()) + "ms"; + if (const int w = ReportHandler::warningCount()) + doneMessage += ", " + QByteArray::number(w) + " warnings"; + if (const int sw = ReportHandler::suppressedCount()) + doneMessage += " (" + QByteArray::number(sw) + " known issues)"; + qCDebug(lcShiboken()).noquote().nospace() << doneMessage; + std::cout << doneMessage.constData() << std::endl; + + return EXIT_SUCCESS; +} diff --git a/sources/shiboken2/generator/qtdoc/CMakeLists.txt b/sources/shiboken2/generator/qtdoc/CMakeLists.txt new file mode 100644 index 000000000..1361ba8f1 --- /dev/null +++ b/sources/shiboken2/generator/qtdoc/CMakeLists.txt @@ -0,0 +1,21 @@ +project(qtdoc_generator) + +set(qtdoc_generator_SRC +qtdocgenerator.cpp +) + +include_directories(${generators_SOURCE_DIR} + ${Qt5Core_INCLUDE_DIRS} + ${APIEXTRACTOR_INCLUDE_DIR}) +add_executable(docgenerator main.cpp) +set_target_properties(docgenerator PROPERTIES OUTPUT_NAME docgenerator${generator_SUFFIX}) + +target_link_libraries(docgenerator ${Qt5Core_LIBRARES}) + +add_library(qtdoc_generator SHARED ${qtdoc_generator_SRC}) +target_link_libraries(qtdoc_generator ${APIEXTRACTOR_LIBRARY} ${Qt5Core_LIBRARES} genrunner) +set_property(TARGET qtdoc_generator PROPERTY PREFIX "") + +install(TARGETS qtdoc_generator DESTINATION ${generator_plugin_DIR}) +install(TARGETS docgenerator DESTINATION bin) + diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp new file mode 100644 index 000000000..02fd40354 --- /dev/null +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp @@ -0,0 +1,1715 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtdocgenerator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static Indentor INDENT; + +static bool shouldSkip(const AbstractMetaFunction* func) +{ + bool skipable = func->isConstructor() + || func->isModifiedRemoved() + || func->declaringClass() != func->ownerClass() + || func->isCastOperator() + || func->name() == QLatin1String("operator="); + + // Search a const clone + if (!skipable && !func->isConstant()) { + const AbstractMetaArgumentList funcArgs = func->arguments(); + const AbstractMetaFunctionList &ownerFunctions = func->ownerClass()->functions(); + for (AbstractMetaFunction *f : ownerFunctions) { + if (f != func + && f->isConstant() + && f->name() == func->name() + && f->arguments().count() == funcArgs.count()) { + // Compare each argument + bool cloneFound = true; + + const AbstractMetaArgumentList fargs = f->arguments(); + for (int i = 0, max = funcArgs.count(); i < max; ++i) { + if (funcArgs.at(i)->type()->typeEntry() != fargs.at(i)->type()->typeEntry()) { + cloneFound = false; + break; + } + } + if (cloneFound) + return true; + } + } + } + return skipable; +} + +static bool functionSort(const AbstractMetaFunction* func1, const AbstractMetaFunction* func2) +{ + return func1->name() < func2->name(); +} + +static QString createRepeatedChar(int i, char c) +{ + QString out; + for (int j = 0; j < i; ++j) + out += QLatin1Char(c); + + return out; +} + +static QString escape(QString str) +{ + str.replace(QLatin1Char('*'), QLatin1String("\\*")); + str.replace(QLatin1Char('_'), QLatin1String("\\_")); + return str; +} + +static QString escape(const QStringRef& strref) +{ + QString str = strref.toString(); + return escape(str); +} + + +QtXmlToSphinx::QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context) + : m_context(context), m_generator(generator), m_insideBold(false), m_insideItalic(false) +{ + m_handlerMap.insert(QLatin1String("heading"), &QtXmlToSphinx::handleHeadingTag); + m_handlerMap.insert(QLatin1String("brief"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("para"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("italic"), &QtXmlToSphinx::handleItalicTag); + m_handlerMap.insert(QLatin1String("bold"), &QtXmlToSphinx::handleBoldTag); + m_handlerMap.insert(QLatin1String("see-also"), &QtXmlToSphinx::handleSeeAlsoTag); + m_handlerMap.insert(QLatin1String("snippet"), &QtXmlToSphinx::handleSnippetTag); + m_handlerMap.insert(QLatin1String("dots"), &QtXmlToSphinx::handleDotsTag); + m_handlerMap.insert(QLatin1String("codeline"), &QtXmlToSphinx::handleDotsTag); + m_handlerMap.insert(QLatin1String("table"), &QtXmlToSphinx::handleTableTag); + m_handlerMap.insert(QLatin1String("header"), &QtXmlToSphinx::handleRowTag); + m_handlerMap.insert(QLatin1String("row"), &QtXmlToSphinx::handleRowTag); + m_handlerMap.insert(QLatin1String("item"), &QtXmlToSphinx::handleItemTag); + m_handlerMap.insert(QLatin1String("argument"), &QtXmlToSphinx::handleArgumentTag); + m_handlerMap.insert(QLatin1String("teletype"), &QtXmlToSphinx::handleArgumentTag); + m_handlerMap.insert(QLatin1String("link"), &QtXmlToSphinx::handleLinkTag); + m_handlerMap.insert(QLatin1String("inlineimage"), &QtXmlToSphinx::handleImageTag); + m_handlerMap.insert(QLatin1String("image"), &QtXmlToSphinx::handleImageTag); + m_handlerMap.insert(QLatin1String("list"), &QtXmlToSphinx::handleListTag); + m_handlerMap.insert(QLatin1String("term"), &QtXmlToSphinx::handleTermTag); + m_handlerMap.insert(QLatin1String("raw"), &QtXmlToSphinx::handleRawTag); + m_handlerMap.insert(QLatin1String("underline"), &QtXmlToSphinx::handleItalicTag); + m_handlerMap.insert(QLatin1String("superscript"), &QtXmlToSphinx::handleSuperScriptTag); + m_handlerMap.insert(QLatin1String("code"), &QtXmlToSphinx::handleCodeTag); + m_handlerMap.insert(QLatin1String("badcode"), &QtXmlToSphinx::handleCodeTag); + m_handlerMap.insert(QLatin1String("legalese"), &QtXmlToSphinx::handleCodeTag); + m_handlerMap.insert(QLatin1String("section"), &QtXmlToSphinx::handleAnchorTag); + m_handlerMap.insert(QLatin1String("quotefile"), &QtXmlToSphinx::handleQuoteFileTag); + + // ignored tags + m_handlerMap.insert(QLatin1String("generatedlist"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("tableofcontents"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("quotefromfile"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("skipto"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("target"), &QtXmlToSphinx::handleIgnoredTag); + + // useless tags + m_handlerMap.insert(QLatin1String("description"), &QtXmlToSphinx::handleUselessTag); + m_handlerMap.insert(QLatin1String("definition"), &QtXmlToSphinx::handleUselessTag); + m_handlerMap.insert(QLatin1String("printuntil"), &QtXmlToSphinx::handleUselessTag); + m_handlerMap.insert(QLatin1String("relation"), &QtXmlToSphinx::handleUselessTag); + + // Doxygen tags + m_handlerMap.insert(QLatin1String("title"), &QtXmlToSphinx::handleHeadingTag); + m_handlerMap.insert(QLatin1String("ref"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("computeroutput"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("detaileddescription"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("name"), &QtXmlToSphinx::handleParaTag); + m_handlerMap.insert(QLatin1String("listitem"), &QtXmlToSphinx::handleItemTag); + m_handlerMap.insert(QLatin1String("parametername"), &QtXmlToSphinx::handleItemTag); + m_handlerMap.insert(QLatin1String("parameteritem"), &QtXmlToSphinx::handleItemTag); + m_handlerMap.insert(QLatin1String("ulink"), &QtXmlToSphinx::handleLinkTag); + m_handlerMap.insert(QLatin1String("itemizedlist"), &QtXmlToSphinx::handleListTag); + m_handlerMap.insert(QLatin1String("parameternamelist"), &QtXmlToSphinx::handleListTag); + m_handlerMap.insert(QLatin1String("parameterlist"), &QtXmlToSphinx::handleListTag); + + // Doxygen ignored tags + m_handlerMap.insert(QLatin1String("highlight"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("linebreak"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("programlisting"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("xreftitle"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("sp"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("entry"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("simplesect"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("verbatim"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("xrefsect"), &QtXmlToSphinx::handleIgnoredTag); + m_handlerMap.insert(QLatin1String("xrefdescription"), &QtXmlToSphinx::handleIgnoredTag); + + m_result = transform(doc); +} + +void QtXmlToSphinx::pushOutputBuffer() +{ + QString* buffer = new QString(); + m_buffers << buffer; + m_output.setString(buffer); +} + +QString QtXmlToSphinx::popOutputBuffer() +{ + Q_ASSERT(!m_buffers.isEmpty()); + QString* str = m_buffers.pop(); + QString strcpy(*str); + delete str; + m_output.setString(m_buffers.isEmpty() ? 0 : m_buffers.top()); + return strcpy; +} + +QString QtXmlToSphinx::expandFunction(const QString& function) +{ + QStringList functionSpec = function.split(QLatin1Char('.')); + QString className = functionSpec.first(); + const AbstractMetaClass* metaClass = 0; + const AbstractMetaClassList &classes = m_generator->classes(); + for (const AbstractMetaClass *cls : classes) { + if (cls->name() == className) { + metaClass = cls; + break; + } + } + + if (metaClass) { + functionSpec.removeFirst(); + return metaClass->typeEntry()->qualifiedTargetLangName() + + QLatin1Char('.') + functionSpec.join(QLatin1Char('.')); + } else { + return function; + } +} + +QString QtXmlToSphinx::resolveContextForMethod(const QString& methodName) +{ + // avoid constLast to stay Qt 5.5 compatible + QString currentClass = m_context.split(QLatin1Char('.')).last(); + + const AbstractMetaClass* metaClass = 0; + const AbstractMetaClassList &classes = m_generator->classes(); + for (const AbstractMetaClass *cls : classes) { + if (cls->name() == currentClass) { + metaClass = cls; + break; + } + } + + if (metaClass) { + QList funcList; + const AbstractMetaFunctionList &methods = metaClass->queryFunctionsByName(methodName); + for (const AbstractMetaFunction *func : methods) { + if (methodName == func->name()) + funcList.append(func); + } + + const AbstractMetaClass* implementingClass = 0; + for (const AbstractMetaFunction *func : qAsConst(funcList)) { + implementingClass = func->implementingClass(); + if (implementingClass->name() == currentClass) + break; + } + + if (implementingClass) + return implementingClass->typeEntry()->qualifiedTargetLangName(); + } + + return QLatin1Char('~') + m_context; +} + +QString QtXmlToSphinx::transform(const QString& doc) +{ + Q_ASSERT(m_buffers.isEmpty()); + Indentation indentation(INDENT); + if (doc.trimmed().isEmpty()) + return doc; + + pushOutputBuffer(); + + QXmlStreamReader reader(doc); + + while (!reader.atEnd()) { + QXmlStreamReader::TokenType token = reader.readNext(); + if (reader.hasError()) { + const QString message = QLatin1String("XML Error: ") + reader.errorString() + + QLatin1Char('\n') + doc; + m_output << INDENT << message; + qCWarning(lcShiboken).noquote().nospace() << message; + break; + } + + if (token == QXmlStreamReader::StartElement) { + QStringRef tagName = reader.name(); + TagHandler handler = m_handlerMap.value(tagName.toString(), &QtXmlToSphinx::handleUnknownTag); + if (!m_handlers.isEmpty() && ( (m_handlers.top() == &QtXmlToSphinx::handleIgnoredTag) || + (m_handlers.top() == &QtXmlToSphinx::handleRawTag)) ) + handler = &QtXmlToSphinx::handleIgnoredTag; + + m_handlers.push(handler); + } + if (!m_handlers.isEmpty()) + (this->*(m_handlers.top()))(reader); + + if (token == QXmlStreamReader::EndElement) { + m_handlers.pop(); + m_lastTagName = reader.name().toString(); + } + } + m_output.flush(); + QString retval = popOutputBuffer(); + Q_ASSERT(m_buffers.isEmpty()); + return retval; +} + +QString QtXmlToSphinx::readFromLocations(const QStringList& locations, const QString& path, const QString& identifier) +{ + QString result; + bool ok; + for (QString location : locations) { + location.append(QLatin1Char('/')); + location.append(path); + result = readFromLocation(location, identifier, &ok); + if (ok) + break; + } + if (!ok) { + qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: {" + << locations.join(QLatin1Char('|')) << '}' << path; + } + return result; + +} + +QString QtXmlToSphinx::readFromLocation(const QString& location, const QString& identifier, bool* ok) +{ + QFile inputFile; + inputFile.setFileName(location); + if (!inputFile.open(QIODevice::ReadOnly)) { + if (!ok) { + qCDebug(lcShiboken).noquote().nospace() << "Couldn't read code snippet file: " + << QDir::toNativeSeparators(inputFile.fileName()); + } else { + *ok = false; + } + return QString(); + } + + QRegExp searchString(QLatin1String("//!\\s*\\[") + identifier + QLatin1String("\\]")); + QRegExp codeSnippetCode(QLatin1String("//!\\s*\\[[\\w\\d\\s]+\\]")); + QString code; + + bool identifierIsEmpty = identifier.isEmpty(); + bool getCode = false; + + while (!inputFile.atEnd()) { + QString line = QString::fromUtf8(inputFile.readLine()); + if (identifierIsEmpty) { + code += line; + } else if (getCode && !line.contains(searchString)) { + line.remove(codeSnippetCode); + code += line; + } else if (line.contains(searchString)) { + if (getCode) + break; + else + getCode = true; + } + } + + if (!identifierIsEmpty && !getCode) { + qCDebug(lcShiboken).noquote().nospace() << "Code snippet file found (" + << location << "), but snippet " << identifier << " not found."; + } + + if (ok) + *ok = true; + return code; +} + +void QtXmlToSphinx::handleHeadingTag(QXmlStreamReader& reader) +{ + static QString heading; + static char type; + static char types[] = { '-', '^' }; + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + uint typeIdx = reader.attributes().value(QLatin1String("level")).toString().toInt(); + if (typeIdx >= sizeof(types)) + type = types[sizeof(types)-1]; + else + type = types[typeIdx]; + } else if (token == QXmlStreamReader::EndElement) { + m_output << createRepeatedChar(heading.length(), type) << endl << endl; + } else if (token == QXmlStreamReader::Characters) { + heading = escape(reader.text()).trimmed(); + m_output << endl << endl << heading << endl; + } +} + +void QtXmlToSphinx::handleParaTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + pushOutputBuffer(); + } else if (token == QXmlStreamReader::EndElement) { + QString result = popOutputBuffer().simplified(); + if (result.startsWith(QLatin1String("**Warning:**"))) + result.replace(0, 12, QLatin1String(".. warning:: ")); + else if (result.startsWith(QLatin1String("**Note:**"))) + result.replace(0, 9, QLatin1String(".. note:: ")); + + m_output << INDENT << result << endl << endl; + } else if (token == QXmlStreamReader::Characters) { + QString text = escape(reader.text()); + if (!m_output.string()->isEmpty()) { + QChar start = text[0]; + QChar end = m_output.string()->at(m_output.string()->length() - 1); + if ((end == QLatin1Char('*') || end == QLatin1Char('`')) && start != QLatin1Char(' ') && !start.isPunct()) + m_output << '\\'; + } + m_output << INDENT << text; + } +} + +void QtXmlToSphinx::handleItalicTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { + m_insideItalic = !m_insideItalic; + m_output << '*'; + } else if (token == QXmlStreamReader::Characters) { + m_output << escape(reader.text()).trimmed(); + } +} + +void QtXmlToSphinx::handleBoldTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) { + m_insideBold = !m_insideBold; + m_output << "**"; + } else if (token == QXmlStreamReader::Characters) { + m_output << escape(reader.text()).trimmed(); + } +} + +void QtXmlToSphinx::handleArgumentTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement || token == QXmlStreamReader::EndElement) + m_output << "``"; + else if (token == QXmlStreamReader::Characters) + m_output << reader.text().toString().trimmed(); +} + +void QtXmlToSphinx::handleSeeAlsoTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) + m_output << INDENT << ".. seealso:: "; + else if (token == QXmlStreamReader::EndElement) + m_output << endl; +} + +void QtXmlToSphinx::handleSnippetTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + const bool consecutiveSnippet = m_lastTagName == QLatin1String("snippet") + || m_lastTagName == QLatin1String("dots") || m_lastTagName == QLatin1String("codeline"); + if (consecutiveSnippet) { + m_output.flush(); + m_output.string()->chop(2); + } + QString location = reader.attributes().value(QLatin1String("location")).toString(); + QString identifier = reader.attributes().value(QLatin1String("identifier")).toString(); + QString code = readFromLocations(m_generator->codeSnippetDirs(), location, identifier); + if (!consecutiveSnippet) + m_output << INDENT << "::\n\n"; + + Indentation indentation(INDENT); + if (code.isEmpty()) { + m_output << INDENT << "" << endl; + } else { + const QStringList lines = code.split(QLatin1Char('\n')); + for (const QString &line : lines) { + if (!QString(line).trimmed().isEmpty()) + m_output << INDENT << line; + + m_output << endl; + } + } + m_output << endl; + } +} +void QtXmlToSphinx::handleDotsTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + const bool consecutiveSnippet = m_lastTagName == QLatin1String("snippet") + || m_lastTagName == QLatin1String("dots") || m_lastTagName == QLatin1String("codeline"); + if (consecutiveSnippet) { + m_output.flush(); + m_output.string()->chop(2); + } + Indentation indentation(INDENT); + pushOutputBuffer(); + m_output << INDENT; + int indent = reader.attributes().value(QLatin1String("indent")).toString().toInt(); + for (int i = 0; i < indent; ++i) + m_output << ' '; + } else if (token == QXmlStreamReader::Characters) { + m_output << reader.text().toString(); + } else if (token == QXmlStreamReader::EndElement) { + m_output << popOutputBuffer() << "\n\n\n"; + } +} + +void QtXmlToSphinx::handleTableTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + m_currentTable.clear(); + m_tableHasHeader = false; + } else if (token == QXmlStreamReader::EndElement) { + // write the table on m_output + m_currentTable.enableHeader(m_tableHasHeader); + m_currentTable.normalize(); + m_output << m_currentTable; + m_currentTable.clear(); + } +} + +void QtXmlToSphinx::handleTermTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + pushOutputBuffer(); + } else if (token == QXmlStreamReader::Characters) { + m_output << reader.text().toString().replace(QLatin1String("::"), QLatin1String(".")); + } else if (token == QXmlStreamReader::EndElement) { + TableCell cell; + cell.data = popOutputBuffer().trimmed(); + m_currentTable << (TableRow() << cell); + } +} + + +void QtXmlToSphinx::handleItemTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + if (m_currentTable.isEmpty()) + m_currentTable << TableRow(); + TableRow& row = m_currentTable.last(); + TableCell cell; + cell.colSpan = reader.attributes().value(QLatin1String("colspan")).toString().toShort(); + cell.rowSpan = reader.attributes().value(QLatin1String("rowspan")).toString().toShort(); + row << cell; + pushOutputBuffer(); + } else if (token == QXmlStreamReader::EndElement) { + QString data = popOutputBuffer().trimmed(); + if (!m_currentTable.isEmpty()) { + TableRow& row = m_currentTable.last(); + if (!row.isEmpty()) + row.last().data = data; + } + } +} + +void QtXmlToSphinx::handleRowTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + m_tableHasHeader = reader.name() == QLatin1String("header"); + m_currentTable << TableRow(); + } +} + +void QtXmlToSphinx::handleListTag(QXmlStreamReader& reader) +{ + // BUG We do not support a list inside a table cell + static QString listType; + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + listType = reader.attributes().value(QLatin1String("type")).toString(); + if (listType == QLatin1String("enum")) { + m_currentTable << (TableRow() << "Constant" << "Description"); + m_tableHasHeader = true; + } + INDENT.indent--; + } else if (token == QXmlStreamReader::EndElement) { + INDENT.indent++; + if (!m_currentTable.isEmpty()) { + if (listType == QLatin1String("bullet")) { + m_output << endl; + for (const TableCell &cell : m_currentTable.constFirst()) { + QStringList itemLines = cell.data.split(QLatin1Char('\n')); + m_output << INDENT << "* " << itemLines.first() << endl; + for (int i = 1, max = itemLines.count(); i < max; ++i) + m_output << INDENT << " " << itemLines[i] << endl; + } + m_output << endl; + } else if (listType == QLatin1String("enum")) { + m_currentTable.enableHeader(m_tableHasHeader); + m_currentTable.normalize(); + m_output << m_currentTable; + } + } + m_currentTable.clear(); + } +} + +void QtXmlToSphinx::handleLinkTag(QXmlStreamReader& reader) +{ + static QString l_linktag; + static QString l_linkref; + static QString l_linktext; + static QString l_linktagending; + static QString l_type; + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + l_linktagending = QLatin1String("` "); + if (m_insideBold) { + l_linktag.prepend(QLatin1String("**")); + l_linktagending.append(QLatin1String("**")); + } else if (m_insideItalic) { + l_linktag.prepend(QLatin1Char('*')); + l_linktagending.append(QLatin1Char('*')); + } + l_type = reader.attributes().value(QLatin1String("type")).toString(); + + // TODO: create a flag PROPERTY-AS-FUNCTION to ask if the properties + // are recognized as such or not in the binding + if (l_type == QLatin1String("property")) + l_type = QLatin1String("function"); + + if (l_type == QLatin1String("typedef")) + l_type = QLatin1String("class"); + + QString linkSource; + if (l_type == QLatin1String("function") || l_type == QLatin1String("class")) { + linkSource = QLatin1String("raw"); + } else if (l_type == QLatin1String("enum")) { + linkSource = QLatin1String("enum"); + } else if (l_type == QLatin1String("page")) { + linkSource = QLatin1String("page"); + } else { + linkSource = QLatin1String("href"); + } + + l_linkref = reader.attributes().value(linkSource).toString(); + l_linkref.replace(QLatin1String("::"), QLatin1String(".")); + l_linkref.remove(QLatin1String("()")); + + if (l_type == QLatin1String("function") && !m_context.isEmpty()) { + l_linktag = QLatin1String(" :meth:`"); + QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); + if (rawlinklist.size() == 1 || rawlinklist.first() == m_context) { + QString context = resolveContextForMethod(rawlinklist.last()); + if (!l_linkref.startsWith(context)) + l_linkref.prepend(context + QLatin1Char('.')); + } else { + l_linkref = expandFunction(l_linkref); + } + } else if (l_type == QLatin1String("function") && m_context.isEmpty()) { + l_linktag = QLatin1String(" :func:`"); + } else if (l_type == QLatin1String("class")) { + l_linktag = QLatin1String(" :class:`"); + TypeEntry* type = TypeDatabase::instance()->findType(l_linkref); + if (type) { + l_linkref = type->qualifiedTargetLangName(); + } else { // fall back to the old heuristic if the type wasn't found. + QStringList rawlinklist = l_linkref.split(QLatin1Char('.')); + QStringList splittedContext = m_context.split(QLatin1Char('.')); + if (rawlinklist.size() == 1 || rawlinklist.first() == splittedContext.last()) { + splittedContext.removeLast(); + l_linkref.prepend(QLatin1Char('~') + splittedContext.join(QLatin1Char('.')) + + QLatin1Char('.')); + } + } + } else if (l_type == QLatin1String("enum")) { + l_linktag = QLatin1String(" :attr:`"); + } else if (l_type == QLatin1String("page") && l_linkref == m_generator->moduleName()) { + l_linktag = QLatin1String(" :mod:`"); + } else { + l_linktag = QLatin1String(" :ref:`"); + } + + } else if (token == QXmlStreamReader::Characters) { + QString linktext = reader.text().toString(); + linktext.replace(QLatin1String("::"), QLatin1String(".")); + // avoid constLast to stay Qt 5.5 compatible + QString item = l_linkref.split(QLatin1Char('.')).last(); + if (l_linkref == linktext + || (l_linkref + QLatin1String("()")) == linktext + || item == linktext + || (item + QLatin1String("()")) == linktext) + l_linktext.clear(); + else + l_linktext = linktext + QLatin1Char('<'); + } else if (token == QXmlStreamReader::EndElement) { + if (!l_linktext.isEmpty()) + l_linktagending.prepend(QLatin1Char('>')); + m_output << l_linktag << l_linktext << escape(l_linkref) << l_linktagending; + } +} + +void QtXmlToSphinx::handleImageTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + QString href = reader.attributes().value(QLatin1String("href")).toString(); + QString packageName = m_generator->packageName(); + packageName.replace(QLatin1Char('.'), QLatin1Char('/')); + QDir dir(m_generator->outputDirectory() + QLatin1Char('/') + packageName); + QString imgPath = dir.relativeFilePath(m_generator->libSourceDir() + QLatin1String("/doc/src/")) + + QLatin1Char('/') + href; + + if (reader.name() == QLatin1String("image")) + m_output << INDENT << ".. image:: " << imgPath << endl << endl; + else + m_output << ".. image:: " << imgPath << ' '; + } +} + +void QtXmlToSphinx::handleRawTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + QString format = reader.attributes().value(QLatin1String("format")).toString(); + m_output << INDENT << ".. raw:: " << format.toLower() << endl << endl; + } else if (token == QXmlStreamReader::Characters) { + const QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); + for (const QString &row : lst) + m_output << INDENT << INDENT << row << endl; + } else if (token == QXmlStreamReader::EndElement) { + m_output << endl << endl; + } +} + +void QtXmlToSphinx::handleCodeTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + QString format = reader.attributes().value(QLatin1String("format")).toString(); + m_output << INDENT << "::" << endl << endl; + INDENT.indent++; + } else if (token == QXmlStreamReader::Characters) { + const QStringList lst(reader.text().toString().split(QLatin1Char('\n'))); + for (const QString row : lst) + m_output << INDENT << INDENT << row << endl; + } else if (token == QXmlStreamReader::EndElement) { + m_output << endl << endl; + INDENT.indent--; + } +} + +void QtXmlToSphinx::handleUnknownTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) + qCDebug(lcShiboken).noquote().nospace() << "Unknown QtDoc tag: \"" << reader.name().toString() << "\"."; +} + +void QtXmlToSphinx::handleSuperScriptTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + m_output << " :sup:`"; + pushOutputBuffer(); + } else if (token == QXmlStreamReader::Characters) { + m_output << reader.text().toString(); + } else if (token == QXmlStreamReader::EndElement) { + m_output << popOutputBuffer(); + m_output << '`'; + } +} + +void QtXmlToSphinx::handleIgnoredTag(QXmlStreamReader&) +{ +} + +void QtXmlToSphinx::handleUselessTag(QXmlStreamReader&) +{ + // Tag "description" just marks the init of "Detailed description" title. + // Tag "definition" just marks enums. We have a different way to process them. +} + +void QtXmlToSphinx::handleAnchorTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::StartElement) { + QString anchor; + if (reader.attributes().hasAttribute(QLatin1String("id"))) + anchor = reader.attributes().value(QLatin1String("id")).toString(); + else if (reader.attributes().hasAttribute(QLatin1String("name"))) + anchor = reader.attributes().value(QLatin1String("name")).toString(); + if (!anchor.isEmpty() && m_opened_anchor != anchor) { + m_opened_anchor = anchor; + m_output << INDENT << ".. _" << m_context << "_" << anchor.toLower() << ":" << endl << endl; + } + } else if (token == QXmlStreamReader::EndElement) { + m_opened_anchor.clear(); + } +} + +void QtXmlToSphinx::handleQuoteFileTag(QXmlStreamReader& reader) +{ + QXmlStreamReader::TokenType token = reader.tokenType(); + if (token == QXmlStreamReader::Characters) { + QString location = reader.text().toString(); + QString identifier; + location.prepend(m_generator->libSourceDir() + QLatin1Char('/')); + QString code = readFromLocation(location, identifier); + + m_output << INDENT << "::\n\n"; + Indentation indentation(INDENT); + if (code.isEmpty()) { + m_output << INDENT << "" << endl; + } else { + const QStringList lines = code.split(QLatin1Char('\n')); + for (const QString &line : lines) { + if (!QString(line).trimmed().isEmpty()) + m_output << INDENT << line; + + m_output << endl; + } + } + m_output << endl; + } +} + +void QtXmlToSphinx::Table::normalize() +{ + if (m_normalized || isEmpty()) + return; + + int row; + int col; + QtXmlToSphinx::Table& self = *this; + + //QDoc3 generates tables with wrong number of columns. We have to + //check and if necessary, merge the last columns. + int maxCols = self.at(0).count(); + // add col spans + for (row = 0; row < count(); ++row) { + for (col = 0; col < at(row).count(); ++col) { + QtXmlToSphinx::TableCell& cell = self[row][col]; + bool mergeCols = (col >= maxCols); + if (cell.colSpan > 0) { + QtXmlToSphinx::TableCell newCell; + newCell.colSpan = -1; + for (int i = 0, max = cell.colSpan-1; i < max; ++i) { + self[row].insert(col+1, newCell); + } + cell.colSpan = 0; + col++; + } else if (mergeCols) { + self[row][maxCols - 1].data += QLatin1Char(' ') + cell.data; + } + } + } + + // row spans + const int numCols = first().count(); + for (col = 0; col < numCols; ++col) { + for (row = 0; row < count(); ++row) { + if (col < self[row].count()) { + QtXmlToSphinx::TableCell& cell = self[row][col]; + if (cell.rowSpan > 0) { + QtXmlToSphinx::TableCell newCell; + newCell.rowSpan = -1; + int max = std::min(cell.rowSpan - 1, count()); + cell.rowSpan = 0; + for (int i = 0; i < max; ++i) { + self[row+i+1].insert(col, newCell); + } + row++; + } + } + } + } + m_normalized = true; +} + +QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table) +{ + if (table.isEmpty()) + return s; + + if (!table.isNormalized()) { + qCDebug(lcShiboken) << "Attempt to print an unnormalized table!"; + return s; + } + + // calc width and height of each column and row + QVector colWidths(table.first().count()); + QVector rowHeights(table.count()); + for (int i = 0, maxI = table.count(); i < maxI; ++i) { + const QtXmlToSphinx::TableRow& row = table[i]; + for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { + const QStringList rowLines = row[j].data.split(QLatin1Char('\n')); // cache this would be a good idea + for (const QString &str : rowLines) + colWidths[j] = std::max(colWidths[j], str.count()); + rowHeights[i] = std::max(rowHeights[i], row[j].data.count(QLatin1Char('\n')) + 1); + } + } + + if (!*std::max_element(colWidths.begin(), colWidths.end())) + return s; // empty table (table with empty cells) + + // create a horizontal line to be used later. + QString horizontalLine = QLatin1String("+"); + for (int i = 0, max = colWidths.count(); i < max; ++i) { + horizontalLine += createRepeatedChar(colWidths[i], '-'); + horizontalLine += QLatin1Char('+'); + } + + // write table rows + for (int i = 0, maxI = table.count(); i < maxI; ++i) { // for each row + const QtXmlToSphinx::TableRow& row = table[i]; + + // print line + s << INDENT << '+'; + for (int col = 0, max = colWidths.count(); col < max; ++col) { + char c; + if (col >= row.length() || row[col].rowSpan == -1) + c = ' '; + else if (i == 1 && table.hasHeader()) + c = '='; + else + c = '-'; + s << createRepeatedChar(colWidths[col], c) << '+'; + } + s << endl; + + + // Print the table cells + for (int rowLine = 0; rowLine < rowHeights[i]; ++rowLine) { // for each line in a row + for (int j = 0, maxJ = std::min(row.count(), colWidths.size()); j < maxJ; ++j) { // for each column + const QtXmlToSphinx::TableCell& cell = row[j]; + QStringList rowLines = cell.data.split(QLatin1Char('\n')); // FIXME: Cache this!!! + if (!j) // First column, so we need print the identation + s << INDENT; + + if (!j || !cell.colSpan) + s << '|'; + else + s << ' '; + s << qSetFieldWidth(colWidths[j]) << left; + s << (rowLine < rowLines.count() ? rowLines[rowLine] : QString()); + s << qSetFieldWidth(0); + } + s << '|' << endl; + } + } + s << INDENT << horizontalLine << endl; + s << endl; + return s; +} + +static QString getFuncName(const AbstractMetaFunction* cppFunc) { + static bool hashInitialized = false; + static QHash operatorsHash; + if (!hashInitialized) { + operatorsHash.insert(QLatin1String("operator+"), QLatin1String("__add__")); + operatorsHash.insert(QLatin1String("operator+="), QLatin1String("__iadd__")); + operatorsHash.insert(QLatin1String("operator-"), QLatin1String("__sub__")); + operatorsHash.insert(QLatin1String("operator-="), QLatin1String("__isub__")); + operatorsHash.insert(QLatin1String("operator*"), QLatin1String("__mul__")); + operatorsHash.insert(QLatin1String("operator*="), QLatin1String("__imul__")); + operatorsHash.insert(QLatin1String("operator/"), QLatin1String("__div__")); + operatorsHash.insert(QLatin1String("operator/="), QLatin1String("__idiv__")); + operatorsHash.insert(QLatin1String("operator%"), QLatin1String("__mod__")); + operatorsHash.insert(QLatin1String("operator%="), QLatin1String("__imod__")); + operatorsHash.insert(QLatin1String("operator<<"), QLatin1String("__lshift__")); + operatorsHash.insert(QLatin1String("operator<<="), QLatin1String("__ilshift__")); + operatorsHash.insert(QLatin1String("operator>>"), QLatin1String("__rshift__")); + operatorsHash.insert(QLatin1String("operator>>="), QLatin1String("__irshift__")); + operatorsHash.insert(QLatin1String("operator&"), QLatin1String("__and__")); + operatorsHash.insert(QLatin1String("operator&="), QLatin1String("__iand__")); + operatorsHash.insert(QLatin1String("operator|"), QLatin1String("__or__")); + operatorsHash.insert(QLatin1String("operator|="), QLatin1String("__ior__")); + operatorsHash.insert(QLatin1String("operator^"), QLatin1String("__xor__")); + operatorsHash.insert(QLatin1String("operator^="), QLatin1String("__ixor__")); + operatorsHash.insert(QLatin1String("operator=="), QLatin1String("__eq__")); + operatorsHash.insert(QLatin1String("operator!="), QLatin1String("__ne__")); + operatorsHash.insert(QLatin1String("operator<"), QLatin1String("__lt__")); + operatorsHash.insert(QLatin1String("operator<="), QLatin1String("__le__")); + operatorsHash.insert(QLatin1String("operator>"), QLatin1String("__gt__")); + operatorsHash.insert(QLatin1String("operator>="), QLatin1String("__ge__")); + hashInitialized = true; + } + + QHash::const_iterator it = operatorsHash.find(cppFunc->name()); + QString result = it != operatorsHash.end() ? it.value() : cppFunc->name(); + result.replace(QLatin1String("::"), QLatin1String(".")); + return result; +} + +QtDocGenerator::QtDocGenerator() : m_docParser(0) +{ +} + +QtDocGenerator::~QtDocGenerator() +{ + delete m_docParser; +} + +QString QtDocGenerator::fileNamePrefix() const +{ + return QLatin1String(".rst"); +} + +QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const +{ + const AbstractMetaClass *metaClass = context.metaClass(); + if (!context.forSmartPointer()) { + return getClassTargetFullName(metaClass, false) + fileNamePrefix(); + } else { + const AbstractMetaType *smartPointerType = context.preciseType(); + QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); + return fileNameBase + fileNamePrefix(); + } +} + +void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass) +{ + QString metaClassName; + + if (metaClass) + metaClassName = getClassTargetFullName(metaClass); + + if (doc.format() == Documentation::Native) { + QtXmlToSphinx x(this, doc.value(), metaClassName); + s << x; + } else { + const QStringList lines = doc.value().split(QLatin1Char('\n')); + QRegExp regex(QLatin1String("\\S")); // non-space character + int typesystemIndentation = std::numeric_limits().max(); + // check how many spaces must be removed from the begining of each line + for (const QString &line : lines) { + int idx = line.indexOf(regex); + if (idx >= 0) + typesystemIndentation = qMin(typesystemIndentation, idx); + } + for (QString line : lines) + s << INDENT << line.remove(0, typesystemIndentation) << endl; + } + + s << endl; +} + +static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaClass, const AbstractMetaClassList& allClasses) +{ + AbstractMetaClassList res; + for (AbstractMetaClass *c : allClasses) { + if (c != metaClass && c->inheritsFrom(metaClass)) + res << c; + } + + if (res.isEmpty()) + return; + + s << "**Inherited by:** "; + QStringList classes; + for (AbstractMetaClass *c : qAsConst(res)) + classes << QLatin1String(":ref:`") + getClassTargetFullName(c, false) + QLatin1Char('`'); + s << classes.join(QLatin1String(", ")) << endl << endl; +} + +void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +{ + AbstractMetaClass *metaClass = classContext.metaClass(); + qCDebug(lcShiboken).noquote().nospace() << "Generating Documentation for " << metaClass->fullName(); + + m_packages[metaClass->package()] << fileNameForContext(classContext); + + m_docParser->setPackageName(metaClass->package()); + m_docParser->fillDocumentation(const_cast(metaClass)); + + s << ".. module:: " << metaClass->package() << endl; + QString className = getClassTargetFullName(metaClass, false); + s << ".. _" << className << ":" << endl << endl; + + s << className << endl; + s << createRepeatedChar(className.count(), '*') << endl << endl; + + s << ".. inheritance-diagram:: " << className << endl + << " :parts: 2" << endl << endl; // TODO: This would be a parameter in the future... + + + writeInheritedByList(s, metaClass, classes()); + + if (metaClass->typeEntry() && (metaClass->typeEntry()->version() != 0)) + s << ".. note:: This class was introduced in Qt " << metaClass->typeEntry()->version() << endl; + + writeFunctionList(s, metaClass); + + //Function list + AbstractMetaFunctionList functionList = metaClass->functions(); + qSort(functionList.begin(), functionList.end(), functionSort); + + s << "Detailed Description\n" + "--------------------\n\n"; + + writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, metaClass, 0); + if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, metaClass, 0)) + writeFormatedText(s, metaClass->documentation(), metaClass); + + if (!metaClass->isNamespace()) + writeConstructors(s, metaClass); + writeEnums(s, metaClass); + if (!metaClass->isNamespace()) + writeFields(s, metaClass); + + + for (AbstractMetaFunction *func : qAsConst(functionList)) { + if (shouldSkip(func)) + continue; + + if (func->isStatic()) + s << ".. staticmethod:: "; + else + s << ".. method:: "; + + writeFunction(s, true, metaClass, func); + } + + writeInjectDocumentation(s, TypeSystem::DocModificationAppend, metaClass, 0); +} + +void QtDocGenerator::writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass) +{ + QStringList functionList; + QStringList virtualList; + QStringList signalList; + QStringList slotList; + QStringList staticFunctionList; + + const AbstractMetaFunctionList &classFunctions = cppClass->functions(); + for (AbstractMetaFunction *func : classFunctions) { + if (shouldSkip(func)) + continue; + + QString className; + if (!func->isConstructor()) + className = getClassTargetFullName(cppClass) + QLatin1Char('.'); + else if (func->implementingClass() && func->implementingClass()->enclosingClass()) + className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + QLatin1Char('.'); + QString funcName = getFuncName(func); + + QString str = QLatin1String("def :meth:`"); + + str += funcName; + str += QLatin1Char('<'); + if (!funcName.startsWith(className)) + str += className; + str += funcName; + str += QLatin1String(">` ("); + str += parseArgDocStyle(cppClass, func); + str += QLatin1Char(')'); + + 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 ((functionList.size() > 0) || (staticFunctionList.size() > 0)) { + QtXmlToSphinx::Table functionTable; + QtXmlToSphinx::TableRow row; + + s << "Synopsis" << endl + << "--------" << endl << endl; + + writeFunctionBlock(s, QLatin1String("Functions"), functionList); + writeFunctionBlock(s, QLatin1String("Virtual functions"), virtualList); + writeFunctionBlock(s, QLatin1String("Slots"), slotList); + writeFunctionBlock(s, QLatin1String("Signals"), signalList); + writeFunctionBlock(s, QLatin1String("Static functions"), staticFunctionList); + } +} + +void QtDocGenerator::writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions) +{ + if (functions.size() > 0) { + s << title << endl + << QString(title.size(), QLatin1Char('^')) << endl; + + qSort(functions); + + s << ".. container:: function_list" << endl << endl; + Indentation indentation(INDENT); + for (const QString &func : qAsConst(functions)) + s << '*' << INDENT << func << endl; + + s << endl << endl; + } +} + +void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass) +{ + static const QString section_title = QLatin1String(".. attribute:: "); + + const AbstractMetaEnumList &enums = cppClass->enums(); + for (AbstractMetaEnum *en : enums) { + s << section_title << getClassTargetFullName(cppClass) << '.' << en->name() << endl << endl; + writeFormatedText(s, en->documentation(), cppClass); + + if (en->typeEntry() && (en->typeEntry()->version() != 0)) + s << ".. note:: This enum was introduced or modified in Qt " << en->typeEntry()->version() << endl; + } + +} + +void QtDocGenerator::writeFields(QTextStream& s, const AbstractMetaClass* cppClass) +{ + static const QString section_title = QLatin1String(".. attribute:: "); + + const AbstractMetaFieldList &fields = cppClass->fields(); + for (AbstractMetaField *field : fields) { + s << section_title << getClassTargetFullName(cppClass) << "." << field->name() << endl << endl; + //TODO: request for member ‘documentation’ is ambiguous + writeFormatedText(s, field->AbstractMetaAttributes::documentation(), cppClass); + } +} + +void QtDocGenerator::writeConstructors(QTextStream& s, const AbstractMetaClass* cppClass) +{ + static const QString sectionTitle = QLatin1String(".. class:: "); + static const QString sectionTitleSpace = QString(sectionTitle.size(), QLatin1Char(' ')); + + const AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible); + + bool first = true; + QHash arg_map; + + for (AbstractMetaFunction *func : lst) { + if (func->isModifiedRemoved()) + continue; + + if (first) { + first = false; + s << sectionTitle; + } else { + s << sectionTitleSpace; + } + writeFunction(s, false, cppClass, func); + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + if (!arg_map.contains(arg->name())) { + arg_map.insert(arg->name(), arg); + } + } + } + + s << endl; + + for (QHash::const_iterator it = arg_map.cbegin(), end = arg_map.cend(); it != end; ++it) { + Indentation indentation(INDENT); + writeParamerteType(s, cppClass, it.value()); + } + + s << endl; + + for (AbstractMetaFunction *func : lst) + writeFormatedText(s, func->documentation(), cppClass); +} + +QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +{ + QString ret; + int optArgs = 0; + + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + + bool thisIsoptional = !arg->defaultValueExpression().isEmpty(); + if (optArgs || thisIsoptional) { + ret += QLatin1Char('['); + optArgs++; + } + + if (arg->argumentIndex() > 0) + ret += QLatin1String(", "); + + ret += arg->name(); + + if (thisIsoptional) { + QString defValue = arg->defaultValueExpression(); + if (defValue == QLatin1String("QString()")) { + defValue = QLatin1String("\"\""); + } else if (defValue == QLatin1String("QStringList()") + || defValue.startsWith(QLatin1String("QVector")) + || defValue.startsWith(QLatin1String("QList"))) { + defValue = QLatin1String("list()"); + } else if (defValue == QLatin1String("QVariant()")) { + defValue = QLatin1String("None"); + } else { + defValue.replace(QLatin1String("::"), QLatin1String(".")); + if (defValue == QLatin1String("0") && (arg->type()->isQObject() || arg->type()->isObject())) + defValue = QLatin1String("None"); + } + ret += QLatin1Char('=') + defValue; + } + } + + ret += QString(optArgs, QLatin1Char(']')); + return ret; +} + +void QtDocGenerator::writeDocSnips(QTextStream &s, + const CodeSnipList &codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language) +{ + Indentation indentation(INDENT); + QStringList invalidStrings; + const static QString startMarkup = QLatin1String("[sphinx-begin]"); + const static QString endMarkup = QLatin1String("[sphinx-end]"); + + invalidStrings << QLatin1String("*") << QLatin1String("//") << QLatin1String("/*") << QLatin1String("*/"); + + for (const CodeSnip &snip : codeSnips) { + if ((snip.position != position) || + !(snip.language & language)) + continue; + + QString code = snip.code(); + while (code.contains(startMarkup) && code.contains(endMarkup)) { + int startBlock = code.indexOf(startMarkup) + startMarkup.size(); + int endBlock = code.indexOf(endMarkup); + + if ((startBlock == -1) || (endBlock == -1)) + break; + + QString codeBlock = code.mid(startBlock, endBlock - startBlock); + const QStringList rows = codeBlock.split(QLatin1Char('\n')); + int currenRow = 0; + int offset = 0; + + for (QString row : rows) { + for (const QString &invalidString : qAsConst(invalidStrings)) + row.remove(invalidString); + + if (row.trimmed().size() == 0) { + if (currenRow == 0) + continue; + else + s << endl; + } + + if (currenRow == 0) { + //find offset + for (int i=0, i_max = row.size(); i < i_max; i++) { + if (row[i] == QLatin1Char(' ')) + offset++; + else if (row[i] == QLatin1Char('\n')) + offset = 0; + else + break; + } + } + row = row.mid(offset); + s << row << endl; + currenRow++; + } + + code = code.mid(endBlock+endMarkup.size()); + } + } +} + +bool QtDocGenerator::writeInjectDocumentation(QTextStream& s, + TypeSystem::DocModificationMode mode, + const AbstractMetaClass* cppClass, + const AbstractMetaFunction* func) +{ + Indentation indentation(INDENT); + 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 doc; + Documentation::Format fmt; + + if (mod.format == TypeSystem::NativeCode) + fmt = Documentation::Native; + else if (mod.format == TypeSystem::TargetLangCode) + fmt = Documentation::Target; + else + continue; + + doc.setValue(mod.code() , fmt); + writeFormatedText(s, doc, cppClass); + didSomething = true; + } + } + } + + s << endl; + + // TODO: 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); + return didSomething; +} + +void QtDocGenerator::writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +{ + QString className; + if (!func->isConstructor()) + className = getClassTargetFullName(cppClass) + QLatin1Char('.'); + else if (func->implementingClass() && func->implementingClass()->enclosingClass()) + className = getClassTargetFullName(func->implementingClass()->enclosingClass()) + QLatin1Char('.'); + + QString funcName = getFuncName(func); + if (!funcName.startsWith(className)) + funcName = className + funcName; + + s << funcName << "(" << parseArgDocStyle(cppClass, func) << ")"; +} + +QString QtDocGenerator::translateToPythonType(const AbstractMetaType* type, const AbstractMetaClass* cppClass) +{ + QString strType; + if (type->name() == QLatin1String("QString")) { + strType = QLatin1String("unicode"); + } else if (type->name() == QLatin1String("QVariant")) { + strType = QLatin1String("object"); + } else if (type->name() == QLatin1String("QStringList")) { + strType = QLatin1String("list of strings"); + } else if (type->isConstant() && type->name() == QLatin1String("char") && type->indirections() == 1) { + strType = QLatin1String("str"); + } else if (type->name().startsWith(QLatin1String("unsigned short"))) { + strType = QLatin1String("int"); + } else if (type->name().startsWith(QLatin1String("unsigned "))) { // uint and ulong + strType = QLatin1String("long"); + } else if (type->isContainer()) { + QString strType = translateType(type, cppClass, Options(ExcludeConst) | ExcludeReference); + strType.remove(QLatin1Char('*')); + strType.remove(QLatin1Char('>')); + strType.remove(QLatin1Char('<')); + strType.replace(QLatin1String("::"), QLatin1String(".")); + if (strType.contains(QLatin1String("QList")) || strType.contains(QLatin1String("QVector"))) { + strType.replace(QLatin1String("QList"), QLatin1String("list of ")); + strType.replace(QLatin1String("QVector"), QLatin1String("list of ")); + } else if (strType.contains(QLatin1String("QHash")) || strType.contains(QLatin1String("QMap"))) { + strType.remove(QLatin1String("QHash")); + strType.remove(QLatin1String("QMap")); + QStringList types = strType.split(QLatin1Char(',')); + strType = QString::fromLatin1("Dictionary with keys of type %1 and values of type %2.") + .arg(types[0], types[1]); + } + } else { + QString refTag; + if (type->isEnum()) + refTag = QLatin1String("attr"); + else + refTag = QLatin1String("class"); + strType = QLatin1Char(':') + refTag + QLatin1String(":`") + type->fullName() + QLatin1Char('`'); + } + return strType; +} + +void QtDocGenerator::writeParamerteType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaArgument* arg) +{ + s << INDENT << ":param " << arg->name() << ": " + << translateToPythonType(arg->type(), cppClass) << endl; +} + +void QtDocGenerator::writeFunctionParametersType(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +{ + Indentation indentation(INDENT); + + s << endl; + const AbstractMetaArgumentList &funcArgs = func->arguments(); + for (AbstractMetaArgument *arg : funcArgs) { + + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + + writeParamerteType(s, cppClass, arg); + } + + if (!func->isConstructor() && func->type()) { + + QString retType; + // check if the return type was modified + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.index == 0) { + retType = argMod.modified_type; + break; + } + } + } + + if (retType.isEmpty()) + retType = translateToPythonType(func->type(), cppClass); + s << INDENT << ":rtype: " << retType << endl; + } + s << endl; +} + +void QtDocGenerator::writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func) +{ + writeFunctionSignature(s, cppClass, func); + s << endl; + + if (func->typeEntry() && (func->typeEntry()->version() != 0)) + s << ".. note:: This method was introduced in Qt " << func->typeEntry()->version() << endl; + + if (writeDoc) { + s << endl; + writeFunctionParametersType(s, cppClass, func); + s << endl; + writeInjectDocumentation(s, TypeSystem::DocModificationPrepend, cppClass, func); + if (!writeInjectDocumentation(s, TypeSystem::DocModificationReplace, cppClass, func)) + writeFormatedText(s, func->documentation(), cppClass); + writeInjectDocumentation(s, TypeSystem::DocModificationAppend, cppClass, func); + } +} + +static void writeFancyToc(QTextStream& s, const QStringList& items, int cols = 4) +{ + typedef QMap TocMap; + TocMap tocMap; + QChar Q = QLatin1Char('Q'); + QChar idx; + for (QString item : items) { + if (item.isEmpty()) + continue; + if (item.startsWith(Q) && item.length() > 1) + idx = item[1]; + item.chop(4); // Remove the .rst extension + tocMap[idx] << item; + } + QtXmlToSphinx::Table table; + QtXmlToSphinx::TableRow row; + + int itemsPerCol = (items.size() + tocMap.size()*2) / cols; + QString currentColData; + int i = 0; + QTextStream ss(¤tColData); + QMutableMapIterator it(tocMap); + while (it.hasNext()) { + it.next(); + qSort(it.value()); + + if (i) + ss << endl; + + ss << "**" << it.key() << "**" << endl << endl; + i += 2; // a letter title is equivalent to two entries in space + for (const QString &item : qAsConst(it.value())) { + ss << "* :doc:`" << item << "`" << endl; + ++i; + + // end of column detected! + if (i > itemsPerCol) { + ss.flush(); + QtXmlToSphinx::TableCell cell(currentColData); + row << cell; + currentColData.clear(); + i = 0; + } + } + } + if (i) { + ss.flush(); + QtXmlToSphinx::TableCell cell(currentColData); + row << cell; + currentColData.clear(); + i = 0; + } + table << row; + table.normalize(); + s << ".. container:: pysidetoc" << endl << endl; + s << table; +} + +bool QtDocGenerator::finishGeneration() +{ + if (classes().isEmpty()) + return true; + + QMap::iterator it = m_packages.begin(); + for (; it != m_packages.end(); ++it) { + QString key = it.key(); + key.replace(QLatin1Char('.'), QLatin1Char('/')); + QString outputDir = outputDirectory() + QLatin1Char('/') + key; + FileOut output(outputDir + QLatin1String("/index.rst")); + QTextStream& s = output.stream; + + s << ".. module:: " << it.key() << endl << endl; + + QString title = it.key(); + s << title << endl; + s << createRepeatedChar(title.length(), '*') << endl << endl; + + /* Avoid showing "Detailed Description for *every* class in toc tree */ + Indentation indentation(INDENT); + + // Search for extra-sections + if (!m_extraSectionDir.isEmpty()) { + QDir extraSectionDir(m_extraSectionDir); + QStringList fileList = extraSectionDir.entryList(QStringList() << (it.key() + QLatin1String("?*.rst")), QDir::Files); + QStringList::iterator it2 = fileList.begin(); + for (; it2 != fileList.end(); ++it2) { + QString origFileName(*it2); + it2->remove(0, it.key().count() + 1); + QString newFilePath = outputDir + QLatin1Char('/') + *it2; + if (QFile::exists(newFilePath)) + QFile::remove(newFilePath); + if (!QFile::copy(m_extraSectionDir + QLatin1Char('/') + origFileName, newFilePath)) { + qCDebug(lcShiboken).noquote().nospace() << "Error copying extra doc " + << QDir::toNativeSeparators(m_extraSectionDir + QLatin1Char('/') + origFileName) + << " to " << QDir::toNativeSeparators(newFilePath); + } + } + it.value().append(fileList); + } + + writeFancyToc(s, it.value()); + + s << INDENT << ".. container:: hide" << endl << endl; + { + Indentation indentation(INDENT); + s << INDENT << ".. toctree::" << endl; + Indentation deeperIndentation(INDENT); + s << INDENT << ":maxdepth: 1" << endl << endl; + for (const QString &className : qAsConst(it.value())) + s << INDENT << className << endl; + s << endl << endl; + } + + s << "Detailed Description" << endl; + s << "--------------------" << endl << endl; + + // module doc is always wrong and C++istic, so go straight to the extra directory! + QFile moduleDoc(m_extraSectionDir + QLatin1Char('/') + it.key() + QLatin1String(".rst")); + if (moduleDoc.open(QIODevice::ReadOnly | QIODevice::Text)) { + s << moduleDoc.readAll(); + moduleDoc.close(); + } else { + // try the normal way + Documentation moduleDoc = m_docParser->retrieveModuleDocumentation(it.key()); + if (moduleDoc.format() == Documentation::Native) { + QString context = it.key(); + context.remove(0, context.lastIndexOf(QLatin1Char('.')) + 1); + QtXmlToSphinx x(this, moduleDoc.value(), context); + s << x; + } else { + s << moduleDoc.value(); + } + } + } + return true; +} + +bool QtDocGenerator::doSetup(const QMap& args) +{ + m_libSourceDir = args.value(QLatin1String("library-source-dir")); + m_docDataDir = args.value(QLatin1String("documentation-data-dir")); +#ifdef __WIN32__ +# define PATH_SEP ';' +#else +# define PATH_SEP ':' +#endif + m_codeSnippetDirs = args.value(QLatin1String("documentation-code-snippets-dir"), m_libSourceDir).split(QLatin1Char(PATH_SEP)); + m_extraSectionDir = args.value(QLatin1String("documentation-extra-sections-dir")); + + m_docParser = args.value(QLatin1String("doc-parser")) == QLatin1String("doxygen") + ? static_cast(new DoxygenParser) + : static_cast(new QtDocParser); + qCDebug(lcShiboken).noquote().nospace() << "doc-parser: " << args.value(QLatin1String("doc-parser")); + + if (m_libSourceDir.isEmpty() || m_docDataDir.isEmpty()) { + qCWarning(lcShiboken) << "Documentation data dir and/or Qt source dir not informed, " + "documentation will not be extracted from Qt sources."; + return false; + } else { + m_docParser->setDocumentationDataDirectory(m_docDataDir); + m_docParser->setLibrarySourceDirectory(m_libSourceDir); + } + return true; +} + + +QMap QtDocGenerator::options() const +{ + QMap options; + options.insert(QLatin1String("doc-parser"), + QLatin1String("The documentation parser used to interpret the documentation input files (qdoc3|doxygen)")); + options.insert(QLatin1String("library-source-dir"), + QLatin1String("Directory where library source code is located")); + options.insert(QLatin1String("documentation-data-dir"), + QLatin1String("Directory with XML files generated by documentation tool (qdoc3 or Doxygen)")); + options.insert(QLatin1String("documentation-code-snippets-dir"), + QLatin1String("Directory used to search code snippets used by the documentation")); + options.insert(QLatin1String("documentation-extra-sections-dir"), + QLatin1String("Directory used to search for extra documentation sections")); + return options; +} + diff --git a/sources/shiboken2/generator/qtdoc/qtdocgenerator.h b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h new file mode 100644 index 000000000..fa8524b21 --- /dev/null +++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.h @@ -0,0 +1,235 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef DOCGENERATOR_H +#define DOCGENERATOR_H + +#include +#include +#include +#include +#include "generator.h" +#include "docparser.h" +#include "typesystem_enums.h" +#include "typesystem_typedefs.h" + +class QtDocParser; +class AbstractMetaFunction; +class AbstractMetaClass; +QT_BEGIN_NAMESPACE +class QXmlStreamReader; +QT_END_NAMESPACE +class QtDocGenerator; + +class QtXmlToSphinx +{ +public: + struct TableCell + { + short rowSpan; + short colSpan; + QString data; + + TableCell(const QString& text = QString()) : rowSpan(0), colSpan(0), data(text) {} + TableCell(const char* text) : rowSpan(0), colSpan(0), data(QLatin1String(text)) {} + }; + + typedef QList TableRow; + class Table : public QList + { + public: + Table() : m_hasHeader(false), m_normalized(false) + { + } + + void enableHeader(bool enable) + { + m_hasHeader = enable; + } + + bool hasHeader() const + { + return m_hasHeader; + } + + void normalize(); + + bool isNormalized() const + { + return m_normalized; + } + + void clear() { + m_normalized = false; + QList::clear(); + } + + private: + bool m_hasHeader; + bool m_normalized; + }; + + QtXmlToSphinx(QtDocGenerator* generator, const QString& doc, const QString& context = QString()); + + QString result() const + { + return m_result; + } + +private: + QString resolveContextForMethod(const QString& methodName); + QString expandFunction(const QString& function); + QString transform(const QString& doc); + + void handleHeadingTag(QXmlStreamReader& reader); + void handleParaTag(QXmlStreamReader& reader); + void handleItalicTag(QXmlStreamReader& reader); + void handleBoldTag(QXmlStreamReader& reader); + void handleArgumentTag(QXmlStreamReader& reader); + void handleSeeAlsoTag(QXmlStreamReader& reader); + void handleSnippetTag(QXmlStreamReader& reader); + void handleDotsTag(QXmlStreamReader& reader); + void handleLinkTag(QXmlStreamReader& reader); + void handleImageTag(QXmlStreamReader& reader); + void handleListTag(QXmlStreamReader& reader); + void handleTermTag(QXmlStreamReader& reader); + void handleSuperScriptTag(QXmlStreamReader& reader); + void handleQuoteFileTag(QXmlStreamReader& reader); + + // table tagsvoid QtXmlToSphinx::handleValueTag(QXmlStreamReader& reader) + + void handleTableTag(QXmlStreamReader& reader); + void handleRowTag(QXmlStreamReader& reader); + void handleItemTag(QXmlStreamReader& reader); + void handleRawTag(QXmlStreamReader& reader); + void handleCodeTag(QXmlStreamReader& reader); + + void handleIgnoredTag(QXmlStreamReader& reader); + void handleUnknownTag(QXmlStreamReader& reader); + void handleUselessTag(QXmlStreamReader& reader); + void handleAnchorTag(QXmlStreamReader& reader); + + typedef void (QtXmlToSphinx::*TagHandler)(QXmlStreamReader&); + QHash m_handlerMap; + QStack m_handlers; + QTextStream m_output; + QString m_result; + + QStack m_buffers; + + + Table m_currentTable; + bool m_tableHasHeader; + QString m_context; + QtDocGenerator* m_generator; + bool m_insideBold; + bool m_insideItalic; + QString m_lastTagName; + QString m_opened_anchor; + + QString readFromLocations(const QStringList& locations, const QString& path, const QString& identifier); + QString readFromLocation(const QString& location, const QString& identifier, bool* ok = 0); + void pushOutputBuffer(); + QString popOutputBuffer(); + void writeTable(Table& table); +}; + +inline QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx& xmlToSphinx) +{ + return s << xmlToSphinx.result(); +} + +QTextStream& operator<<(QTextStream& s, const QtXmlToSphinx::Table &table); + +/** +* The DocGenerator generates documentation from library being binded. +*/ +class QtDocGenerator : public Generator +{ +public: + QtDocGenerator(); + ~QtDocGenerator(); + + QString libSourceDir() const + { + return m_libSourceDir; + } + + bool doSetup(const QMap& args); + + const char* name() const + { + return "QtDocGenerator"; + } + + QMap options() const; + + QStringList codeSnippetDirs() const + { + return m_codeSnippetDirs; + } + +protected: + QString fileNamePrefix() const; + QString fileNameForContext(GeneratorContext &context) const; + void generateClass(QTextStream &s, GeneratorContext &classContext); + bool finishGeneration(); + + void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {} + void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {} + +private: + void writeEnums(QTextStream& s, const AbstractMetaClass* cppClass); + + void writeFields(QTextStream &s, const AbstractMetaClass *cppClass); + void writeArguments(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); + void writeFunctionSignature(QTextStream& s, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + void writeFunction(QTextStream& s, bool writeDoc, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + void writeFunctionParametersType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaFunction* func); + void writeFunctionList(QTextStream& s, const AbstractMetaClass* cppClass); + void writeFunctionBlock(QTextStream& s, const QString& title, QStringList& functions); + void writeParamerteType(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaArgument *arg); + + void writeConstructors(QTextStream &s, const AbstractMetaClass *cppClass); + void writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaclass = 0); + bool writeInjectDocumentation(QTextStream& s, TypeSystem::DocModificationMode mode, const AbstractMetaClass* cppClass, const AbstractMetaFunction* func); + void writeDocSnips(QTextStream &s, const CodeSnipList &codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); + + + QString parseArgDocStyle(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func); + QString translateToPythonType(const AbstractMetaType *type, const AbstractMetaClass *cppClass); + + QString m_docDataDir; + QString m_libSourceDir; + QStringList m_codeSnippetDirs; + QString m_extraSectionDir; + QStringList m_functionList; + QMap m_packages; + DocParser* m_docParser; +}; + +#endif // DOCGENERATOR_H diff --git a/sources/shiboken2/generator/shiboken2/CMakeLists.txt b/sources/shiboken2/generator/shiboken2/CMakeLists.txt new file mode 100644 index 000000000..5c1b612dd --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/CMakeLists.txt @@ -0,0 +1,28 @@ +project(shibokengenerator) + +set(shiboken_SRC +../generator.cpp +cppgenerator.cpp +headergenerator.cpp +overloaddata.cpp +shibokengenerator.cpp +main.cpp +) + +include_directories(${generators_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${APIEXTRACTOR_INCLUDE_DIR} + ${Qt5Core_INCLUDE_DIRS} + ) + +add_executable(shiboken2 ${shiboken_SRC}) +set_target_properties(shiboken2 PROPERTIES OUTPUT_NAME shiboken2${shiboken_SUFFIX}) +target_link_libraries(shiboken2 + ${APIEXTRACTOR_LIBRARY} + ${Qt5Core_LIBRARIES} + ) + +configure_file(shibokenconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/shibokenconfig.h" @ONLY) + +install(TARGETS shiboken2 DESTINATION bin) diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp new file mode 100644 index 000000000..6aa2c83df --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -0,0 +1,5755 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "cppgenerator.h" +#include "overloaddata.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +QHash CppGenerator::m_nbFuncs = QHash(); +QHash CppGenerator::m_sqFuncs = QHash(); +QHash CppGenerator::m_mpFuncs = QHash(); +QString CppGenerator::m_currentErrorCode(QLatin1String("0")); + +// utility functions +inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg) +{ + if (arg && arg->typeEntry()->isContainer()) { + AbstractMetaTypeList lst = arg->instantiations(); + // only support containers with 1 type + if (lst.size() == 1) + return lst[0]; + } + return arg; +} + +CppGenerator::CppGenerator() +{ + // Number protocol structure members names + m_nbFuncs.insert(QLatin1String("__add__"), QLatin1String("nb_add")); + m_nbFuncs.insert(QLatin1String("__sub__"), QLatin1String("nb_subtract")); + m_nbFuncs.insert(QLatin1String("__mul__"), QLatin1String("nb_multiply")); + m_nbFuncs.insert(QLatin1String("__div__"), QLatin1String("nb_divide")); + m_nbFuncs.insert(QLatin1String("__mod__"), QLatin1String("nb_remainder")); + m_nbFuncs.insert(QLatin1String("__neg__"), QLatin1String("nb_negative")); + m_nbFuncs.insert(QLatin1String("__pos__"), QLatin1String("nb_positive")); + m_nbFuncs.insert(QLatin1String("__invert__"), QLatin1String("nb_invert")); + m_nbFuncs.insert(QLatin1String("__lshift__"), QLatin1String("nb_lshift")); + m_nbFuncs.insert(QLatin1String("__rshift__"), QLatin1String("nb_rshift")); + m_nbFuncs.insert(QLatin1String("__and__"), QLatin1String("nb_and")); + m_nbFuncs.insert(QLatin1String("__xor__"), QLatin1String("nb_xor")); + m_nbFuncs.insert(QLatin1String("__or__"), QLatin1String("nb_or")); + m_nbFuncs.insert(QLatin1String("__iadd__"), QLatin1String("nb_inplace_add")); + m_nbFuncs.insert(QLatin1String("__isub__"), QLatin1String("nb_inplace_subtract")); + m_nbFuncs.insert(QLatin1String("__imul__"), QLatin1String("nb_inplace_multiply")); + m_nbFuncs.insert(QLatin1String("__idiv__"), QLatin1String("nb_inplace_divide")); + m_nbFuncs.insert(QLatin1String("__imod__"), QLatin1String("nb_inplace_remainder")); + m_nbFuncs.insert(QLatin1String("__ilshift__"), QLatin1String("nb_inplace_lshift")); + m_nbFuncs.insert(QLatin1String("__irshift__"), QLatin1String("nb_inplace_rshift")); + m_nbFuncs.insert(QLatin1String("__iand__"), QLatin1String("nb_inplace_and")); + m_nbFuncs.insert(QLatin1String("__ixor__"), QLatin1String("nb_inplace_xor")); + m_nbFuncs.insert(QLatin1String("__ior__"), QLatin1String("nb_inplace_or")); + m_nbFuncs.insert(QLatin1String("bool"), QLatin1String("nb_nonzero")); + + // sequence protocol functions + typedef QPair StrPair; + m_sequenceProtocol.insert(QLatin1String("__len__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR), QLatin1String("Py_ssize_t"))); + m_sequenceProtocol.insert(QLatin1String("__getitem__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i"), + QLatin1String("PyObject*"))); + m_sequenceProtocol.insert(QLatin1String("__setitem__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* _value"), + QLatin1String("int"))); + m_sequenceProtocol.insert(QLatin1String("__getslice__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2"), + QLatin1String("PyObject*"))); + m_sequenceProtocol.insert(QLatin1String("__setslice__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i1, Py_ssize_t _i2, PyObject* _value"), + QLatin1String("int"))); + m_sequenceProtocol.insert(QLatin1String("__contains__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _value"), + QLatin1String("int"))); + m_sequenceProtocol.insert(QLatin1String("__concat__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _other"), + QLatin1String("PyObject*"))); + + // Sequence protocol structure members names + m_sqFuncs.insert(QLatin1String("__concat__"), QLatin1String("sq_concat")); + m_sqFuncs.insert(QLatin1String("__contains__"), QLatin1String("sq_contains")); + m_sqFuncs.insert(QLatin1String("__getitem__"), QLatin1String("sq_item")); + m_sqFuncs.insert(QLatin1String("__getslice__"), QLatin1String("sq_slice")); + m_sqFuncs.insert(QLatin1String("__len__"), QLatin1String("sq_length")); + m_sqFuncs.insert(QLatin1String("__setitem__"), QLatin1String("sq_ass_item")); + m_sqFuncs.insert(QLatin1String("__setslice__"), QLatin1String("sq_ass_slice")); + + // mapping protocol function + m_mappingProtocol.insert(QLatin1String("__mlen__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR), + QLatin1String("Py_ssize_t"))); + m_mappingProtocol.insert(QLatin1String("__mgetitem__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key"), + QLatin1String("PyObject*"))); + m_mappingProtocol.insert(QLatin1String("__msetitem__"), + StrPair(QLatin1String("PyObject* " PYTHON_SELF_VAR ", PyObject* _key, PyObject* _value"), + QLatin1String("int"))); + + // Sequence protocol structure members names + m_mpFuncs.insert(QLatin1String("__mlen__"), QLatin1String("mp_length")); + m_mpFuncs.insert(QLatin1String("__mgetitem__"), QLatin1String("mp_subscript")); + m_mpFuncs.insert(QLatin1String("__msetitem__"), QLatin1String("mp_ass_subscript")); +} + +QString CppGenerator::fileNamePrefix() const +{ + return QLatin1String("_wrapper.cpp"); +} + +QString CppGenerator::fileNameForContext(GeneratorContext &context) const +{ + const AbstractMetaClass *metaClass = context.metaClass(); + if (!context.forSmartPointer()) { + QString fileNameBase = metaClass->qualifiedCppName().toLower(); + fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); + return fileNameBase + fileNamePrefix(); + } else { + const AbstractMetaType *smartPointerType = context.preciseType(); + QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); + return fileNameBase + fileNamePrefix(); + } +} + +QVector CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, + uint queryIn) +{ + // ( func_name, num_args ) => func_list + typedef QMap, AbstractMetaFunctionList> ResultMap; + ResultMap results; + const AbstractMetaClass::OperatorQueryOptions query(queryIn); + const AbstractMetaFunctionList &funcs = metaClass->operatorOverloads(query); + for (AbstractMetaFunction *func : funcs) { + if (func->isModifiedRemoved() + || func->usesRValueReferences() + || func->name() == QLatin1String("operator[]") + || func->name() == QLatin1String("operator->") + || func->name() == QLatin1String("operator!")) { + continue; + } + int args; + if (func->isComparisonOperator()) { + args = -1; + } else { + args = func->arguments().size(); + } + QPair op(func->name(), args); + results[op].append(func); + } + QVector result; + result.reserve(results.size()); + for (ResultMap::const_iterator it = results.cbegin(), end = results.cend(); it != end; ++it) + result.append(it.value()); + return result; +} + +bool CppGenerator::hasBoolCast(const AbstractMetaClass* metaClass) const +{ + if (!useIsNullAsNbNonZero()) + return false; + // TODO: This could be configurable someday + const AbstractMetaFunction* func = metaClass->findFunction(QLatin1String("isNull")); + if (!func || !func->type() || !func->type()->typeEntry()->isPrimitive() || !func->isPublic()) + return false; + const PrimitiveTypeEntry* pte = static_cast(func->type()->typeEntry()); + while (pte->referencedTypeEntry()) + pte = pte->referencedTypeEntry(); + return func && func->isConstant() && pte->name() == QLatin1String("bool") && func->arguments().isEmpty(); +} + +typedef QMap FunctionGroupMap; +typedef FunctionGroupMap::const_iterator FunctionGroupMapIt; + +// Prevent ELF symbol qt_version_tag from being generated into the source +static const char includeQDebug[] = +"#ifndef QT_NO_VERSION_TAGGING\n" +"# define QT_NO_VERSION_TAGGING\n" +"#endif\n" +"#include \n"; + +static QString chopType(QString s) +{ + if (s.endsWith(QLatin1String("_Type"))) + s.chop(5); + return s; +} + +/*! + Function used to write the class generated binding code on the buffer + \param s the output buffer + \param metaClass the pointer to metaclass information +*/ +void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +{ + AbstractMetaClass *metaClass = classContext.metaClass(); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName(); + + // write license comment + s << licenseComment() << endl; + + if (!avoidProtectedHack() && !metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { + s << "//workaround to access protected functions" << endl; + s << "#define protected public" << endl << endl; + } + + // headers + s << "// default includes" << endl; + s << "#include " << endl; + if (usePySideExtensions()) { + s << includeQDebug; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + } + + s << "#include " << endl; + s << "#include " << endl; + if (usePySideExtensions() && metaClass->isQObject()) { + s << "#include " << endl; + s << "#include " << endl; + } + + // The multiple inheritance initialization function + // needs the 'set' class from C++ STL. + if (hasMultipleInheritanceInAncestry(metaClass)) + s << "#include " << endl; + + s << endl << "// module include" << endl << "#include \"" << getModuleHeaderFileName() << '"' << endl; + + QString headerfile = fileNameForContext(classContext); + headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); + s << endl << "// main header" << endl << "#include \"" << headerfile << '"' << endl; + + // PYSIDE-500: Use also includes for inherited wrapper classes, because + // without the protected hack, we sometimes need to cast inherited wrappers. + s << endl << "// inherited wrapper classes" << endl; + AbstractMetaClass *basis = metaClass->baseClass(); + for (; basis; basis = basis->baseClass()) { + GeneratorContext basisContext(basis); + QString headerfile = fileNameForContext(basisContext); + headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); + s << "#include \"" << headerfile << '"' << endl; + } + + s << endl << "// inner classes" << endl; + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) { + GeneratorContext innerClassContext(innerClass); + if (shouldGenerate(innerClass)) { + QString headerfile = fileNameForContext(innerClassContext); + headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h")); + s << "#include \"" << headerfile << '"' << endl; + } + } + + AbstractMetaEnumList classEnums = metaClass->enums(); + for (AbstractMetaClass *innerClass : innerClasses) + lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + + //Extra includes + s << endl << "// Extra includes" << endl; + QVector includes = metaClass->typeEntry()->extraIncludes(); + for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) + includes.append(cppEnum->typeEntry()->extraIncludes()); + qSort(includes.begin(), includes.end()); + for (const Include &inc : qAsConst(includes)) + s << inc.toString() << endl; + s << endl; + + if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) + s << "#Deprecated" << endl; + + // Use class base namespace + { + const AbstractMetaClass *context = metaClass->enclosingClass(); + while (context) { + if (context->isNamespace() && !context->enclosingClass()) { + s << "using namespace " << context->qualifiedCppName() << ";" << endl; + break; + } + context = context->enclosingClass(); + } + } + + s << endl; + + // Create string literal for smart pointer getter method. + if (classContext.forSmartPointer()) { + const SmartPointerTypeEntry *typeEntry = + static_cast(classContext.preciseType() + ->typeEntry()); + QString rawGetter = typeEntry->getter(); + s << "static const char * " SMART_POINTER_GETTER " = \"" << rawGetter << "\";"; + } + + // class inject-code native/beginning + if (!metaClass->typeEntry()->codeSnips().isEmpty()) { + writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass); + s << endl; + } + + // python conversion rules + if (metaClass->typeEntry()->hasTargetConversionRule()) { + s << "// Python Conversion" << endl; + s << metaClass->typeEntry()->conversionRule() << endl; + } + + if (shouldGenerateCppWrapper(metaClass)) { + s << "// Native ---------------------------------------------------------" << endl; + s << endl; + + if (avoidProtectedHack() && usePySideExtensions()) { + s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n"; + Indentation indent(INDENT); + writeInitQtMetaTypeFunctionBody(s, classContext); + s << "}\n\n"; + } + + const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); + for (const AbstractMetaFunction *func : funcs) { + if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) + || (func->isModifiedRemoved() && !func->isAbstract())) + continue; + if (func->functionType() == AbstractMetaFunction::ConstructorFunction && !func->isUserAdded()) + writeConstructorNative(s, func); + else if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) + && (func->isVirtual() || func->isAbstract())) + writeVirtualMethodNative(s, func); + } + + if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) { + if (usePySideExtensions() && metaClass->isQObject()) + writeMetaObjectMethod(s, metaClass); + writeDestructorNative(s, metaClass); + } + } + + Indentation indentation(INDENT); + + QString methodsDefinitions; + QTextStream md(&methodsDefinitions); + QString singleMethodDefinitions; + QTextStream smd(&singleMethodDefinitions); + + s << endl << "// Target ---------------------------------------------------------" << endl << endl; + s << "extern \"C\" {" << endl; + const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); + for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + AbstractMetaFunctionList overloads; + QSet seenSignatures; + for (AbstractMetaFunction *func : it.value()) { + if (!func->isAssignmentOperator() + && !func->usesRValueReferences() + && !func->isCastOperator() + && !func->isModifiedRemoved() + && (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction) + && func->ownerClass() == func->implementingClass() + && (func->name() != QLatin1String("qt_metacall"))) { + // PYSIDE-331: Inheritance works correctly when there are disjoint functions. + // But when a function is both in a class and inherited in a subclass, + // then we need to search through all subclasses and collect the new signatures. + overloads << getFunctionAndInheritedOverloads(func, &seenSignatures); + } + } + + if (overloads.isEmpty()) + continue; + + const AbstractMetaFunction* rfunc = overloads.first(); + if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name())) + continue; + + if (rfunc->isConstructor()) { + // @TODO: Implement constructor support for smart pointers, so that they can be + // instantiated in python code. + if (classContext.forSmartPointer()) + continue; + writeConstructorWrapper(s, overloads, classContext); + } + // call operators + else if (rfunc->name() == QLatin1String("operator()")) + writeMethodWrapper(s, overloads, classContext); + else if (!rfunc->isOperatorOverload()) { + + if (classContext.forSmartPointer()) { + const SmartPointerTypeEntry *smartPointerTypeEntry = + static_cast( + classContext.preciseType()->typeEntry()); + + if (smartPointerTypeEntry->getter() == rfunc->name()) { + // Replace the return type of the raw pointer getter method with the actual + // return type. + QString innerTypeName = + classContext.preciseType()->getSmartPointerInnerType()->name(); + QString pointerToInnerTypeName = innerTypeName + QLatin1Char('*'); + // @TODO: This possibly leaks, but there are a bunch of other places where this + // is done, so this will be fixed in bulk with all the other cases, because the + // ownership of the pointers is not clear at the moment. + AbstractMetaType *pointerToInnerType = + buildAbstractMetaTypeFromString(pointerToInnerTypeName); + + AbstractMetaFunction *mutableRfunc = overloads.first(); + mutableRfunc->replaceType(pointerToInnerType); + } else if (smartPointerTypeEntry->refCountMethodName().isEmpty() + || smartPointerTypeEntry->refCountMethodName() != rfunc->name()) { + // Skip all public methods of the smart pointer except for the raw getter and + // the ref count method. + continue; + } + } + + writeMethodWrapper(s, overloads, classContext); + if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { + QString methDefName = cpythonMethodDefinitionName(rfunc); + smd << "static PyMethodDef " << methDefName << " = {" << endl; + smd << INDENT; + writeMethodDefinitionEntry(smd, overloads); + smd << endl << "};" << endl << endl; + } + writeMethodDefinition(md, overloads); + } + } + + const QString className = chopType(cpythonTypeName(metaClass)); + + if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) + writeCopyFunction(s, classContext); + + // Write single method definitions + s << singleMethodDefinitions; + + // Write methods definition + s << "static PyMethodDef " << className << "_methods[] = {" << endl; + s << methodsDefinitions << endl; + if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) + s << INDENT << "{\"__copy__\", (PyCFunction)" << className << "___copy__" << ", METH_NOARGS}," << endl; + s << INDENT << "{0} // Sentinel" << endl; + s << "};" << endl << endl; + + // Write tp_getattro function + if ((usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))) { + writeGetattroFunction(s, classContext); + s << endl; + writeSetattroFunction(s, classContext); + s << endl; + } else { + if (classNeedsGetattroFunction(metaClass)) { + writeGetattroFunction(s, classContext); + s << endl; + } + if (classNeedsSetattroFunction(metaClass)) { + writeSetattroFunction(s, classContext); + s << endl; + } + } + + if (hasBoolCast(metaClass)) { + ErrorCode errorCode(-1); + s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, classContext); + s << INDENT << "int result;" << endl; + s << INDENT << BEGIN_ALLOW_THREADS << endl; + s << INDENT << "result = !" CPP_SELF_VAR "->isNull();" << endl; + s << INDENT << END_ALLOW_THREADS << endl; + s << INDENT << "return result;" << endl; + s << '}' << endl << endl; + } + + if (supportsNumberProtocol(metaClass) && !metaClass->typeEntry()->isSmartPointer()) { + const QVector opOverloads = filterGroupedOperatorFunctions( + metaClass, + AbstractMetaClass::ArithmeticOp + | AbstractMetaClass::LogicalOp + | AbstractMetaClass::BitwiseOp); + + for (const AbstractMetaFunctionList &allOverloads : opOverloads) { + AbstractMetaFunctionList overloads; + for (AbstractMetaFunction *func : allOverloads) { + if (!func->isModifiedRemoved() + && !func->isPrivate() + && (func->ownerClass() == func->implementingClass() || func->isAbstract())) + overloads.append(func); + } + + if (overloads.isEmpty()) + continue; + + writeMethodWrapper(s, overloads, classContext); + } + } + + if (supportsSequenceProtocol(metaClass)) { + writeSequenceMethods(s, metaClass, classContext); + } + + if (supportsMappingProtocol(metaClass)) { + writeMappingMethods(s, metaClass, classContext); + } + + if (metaClass->hasComparisonOperatorOverload()) { + s << "// Rich comparison" << endl; + writeRichCompareFunction(s, classContext); + } + + if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *metaField : fields) { + if (metaField->isStatic()) + continue; + writeGetterFunction(s, metaField, classContext); + if (!metaField->type()->isConstant()) + writeSetterFunction(s, metaField, classContext); + s << endl; + } + + s << "// Getters and Setters for " << metaClass->name() << endl; + s << "static PyGetSetDef " << cpythonGettersSettersDefinitionName(metaClass) << "[] = {" << endl; + for (const AbstractMetaField *metaField : fields) { + if (metaField->isStatic()) + continue; + + bool hasSetter = !metaField->type()->isConstant(); + s << INDENT << "{const_cast(\"" << metaField->name() << "\"), "; + s << cpythonGetterFunctionName(metaField); + s << ", " << (hasSetter ? cpythonSetterFunctionName(metaField) : QLatin1String("0")); + s << "}," << endl; + } + s << INDENT << "{0} // Sentinel" << endl; + s << "};" << endl << endl; + } + + s << "} // extern \"C\"" << endl << endl; + + if (!metaClass->typeEntry()->hashFunction().isEmpty()) + writeHashFunction(s, classContext); + + // Write tp_traverse and tp_clear functions. + writeTpTraverseFunction(s, metaClass); + writeTpClearFunction(s, metaClass); + + writeClassDefinition(s, metaClass, classContext); + s << endl; + + if (metaClass->isPolymorphic() && metaClass->baseClass()) + writeTypeDiscoveryFunction(s, metaClass); + + + for (AbstractMetaEnum *cppEnum : qAsConst(classEnums)) { + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) + continue; + + bool hasFlags = cppEnum->typeEntry()->flags(); + if (hasFlags) { + writeFlagsMethods(s, cppEnum); + writeFlagsNumberMethodsDefinition(s, cppEnum); + s << endl; + } + } + s << endl; + + writeConverterFunctions(s, metaClass, classContext); + writeClassRegister(s, metaClass, classContext); + + // class inject-code native/end + if (!metaClass->typeEntry()->codeSnips().isEmpty()) { + writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, metaClass); + s << endl; + } +} + +void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func) +{ + Indentation indentation(INDENT); + s << functionSignature(func, wrapperName(func->ownerClass()) + QLatin1String("::"), QString(), + OriginalTypeDescription | SkipDefaultValues); + s << " : "; + writeFunctionCall(s, func); + s << " {" << endl; + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); + s << INDENT << "// ... middle" << endl; + writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); + s << '}' << endl << endl; +} + +void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass *metaClass) +{ + Indentation indentation(INDENT); + s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; + // kill pyobject + s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "Shiboken::Object::destroy(wrapper, this);" << endl; + s << '}' << endl; +} + +static bool allArgumentsRemoved(const AbstractMetaFunction* func) +{ + if (func->arguments().isEmpty()) + return false; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (!func->argumentRemoved(arg->argumentIndex() + 1)) + return false; + } + return true; +} + +QString CppGenerator::getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func) +{ + if (!func->type()) + return QLatin1String("\"\""); + + if (!func->typeReplaced(0).isEmpty()) + return QLatin1Char('"') + func->typeReplaced(0) + QLatin1Char('"'); + + // SbkType would return null when the type is a container. + if (func->type()->typeEntry()->isContainer()) { + return QLatin1Char('"') + + reinterpret_cast(func->type()->typeEntry())->typeName() + + QLatin1Char('"'); + } + + if (avoidProtectedHack()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); + if (metaEnum && metaEnum->isProtected()) + return QLatin1Char('"') + protectedEnumSurrogateName(metaEnum) + QLatin1Char('"'); + } + + if (func->type()->isPrimitive()) + return QLatin1Char('"') + func->type()->name() + QLatin1Char('"'); + + return QString::fromLatin1("Shiboken::SbkType< %1 >()->tp_name").arg(func->type()->typeEntry()->qualifiedCppName()); +} + +void CppGenerator::writeVirtualMethodNative(QTextStream&s, const AbstractMetaFunction* func) +{ + //skip metaObject function, this will be written manually ahead + if (usePySideExtensions() && func->ownerClass() && func->ownerClass()->isQObject() && + ((func->name() == QLatin1String("metaObject")) || (func->name() == QLatin1String("qt_metacall")))) + return; + + const TypeEntry* retType = func->type() ? func->type()->typeEntry() : 0; + const QString funcName = func->isOperatorOverload() ? pythonOperatorFunctionName(func) : func->name(); + + QString prefix = wrapperName(func->ownerClass()) + QLatin1String("::"); + s << functionSignature(func, prefix, QString(), Generator::SkipDefaultValues|Generator::OriginalTypeDescription) + << endl << '{' << endl; + + Indentation indentation(INDENT); + + QString defaultReturnExpr; + if (retType) { + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { + for (const ArgumentModification &argMod : mod.argument_mods) { + if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { + static const QRegularExpression regex(QStringLiteral("%(\\d+)")); + Q_ASSERT(regex.isValid()); + defaultReturnExpr = argMod.replacedDefaultExpression; + for (int offset = 0; ; ) { + const QRegularExpressionMatch match = regex.match(defaultReturnExpr, offset); + if (!match.hasMatch()) + break; + const int argId = match.capturedRef(1).toInt() - 1; + if (argId < 0 || argId > func->arguments().count()) { + qCWarning(lcShiboken) << "The expression used in return value contains an invalid index."; + break; + } + defaultReturnExpr.replace(match.captured(0), func->arguments()[argId]->name()); + offset = match.capturedStart(1); + } + } + } + } + if (defaultReturnExpr.isEmpty()) + defaultReturnExpr = minimalConstructor(func->type()); + if (defaultReturnExpr.isEmpty()) { + QString errorMsg = QLatin1String(__FUNCTION__) + QLatin1String(": "); + if (const AbstractMetaClass *c = func->implementingClass()) + errorMsg += c->qualifiedCppName() + QLatin1String("::"); + errorMsg += func->signature(); + errorMsg = ShibokenGenerator::msgCouldNotFindMinimalConstructor(errorMsg, func->type()->cppSignature()); + qCWarning(lcShiboken).noquote().nospace() << errorMsg; + s << endl << INDENT << "#error " << errorMsg << endl; + } + } + + if (func->isAbstract() && func->isModifiedRemoved()) { + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("Pure virtual method '%1::%2' must be implement but was "\ + "completely removed on type system.") + .arg(func->ownerClass()->name(), func->minimalSignature()); + s << INDENT << "return " << defaultReturnExpr << ';' << endl; + s << '}' << endl << endl; + return; + } + + //Write declaration/native injected code + if (func->hasInjectedCode()) { + CodeSnipList snips = func->injectedCodeSnips(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode, func, lastArg); + s << endl; + } + + s << INDENT << "Shiboken::GilState gil;" << endl; + + // Get out of virtual method call if someone already threw an error. + s << INDENT << "if (PyErr_Occurred())" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << defaultReturnExpr << ';' << endl; + } + + s << INDENT << "Shiboken::AutoDecRef " PYTHON_OVERRIDE_VAR "(Shiboken::BindingManager::instance().getOverride(this, \""; + s << funcName << "\"));" << endl; + + s << INDENT << "if (" PYTHON_OVERRIDE_VAR ".isNull()) {" << endl; + { + Indentation indentation(INDENT); + CodeSnipList snips; + if (func->hasInjectedCode()) { + snips = func->injectedCodeSnips(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::ShellCode, func, lastArg); + s << endl; + } + + if (func->isAbstract()) { + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; + s << func->ownerClass()->name() << '.' << funcName; + s << "()' not implemented.\");" << endl; + s << INDENT << "return " << (retType ? defaultReturnExpr : QString()); + } else { + s << INDENT << "gil.release();" << endl; + s << INDENT; + if (retType) + s << "return "; + s << "this->::" << func->implementingClass()->qualifiedCppName() << "::"; + writeFunctionCall(s, func, Generator::VirtualCall); + if (!retType) + s << ";\n" << INDENT << "return"; + } + } + s << ';' << endl; + s << INDENT << '}' << endl << endl; + + writeConversionRule(s, func, TypeSystem::TargetLangCode); + + s << INDENT << "Shiboken::AutoDecRef " PYTHON_ARGS "("; + + if (func->arguments().isEmpty() || allArgumentsRemoved(func)) { + s << "PyTuple_New(0));" << endl; + } else { + QStringList argConversions; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + + QString argConv; + QTextStream ac(&argConv); + const PrimitiveTypeEntry* argType = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); + bool convert = argType->isObject() + || arg->type()->isQObject() + || argType->isValue() + || arg->type()->isValuePointer() + || arg->type()->isNativePointer() + || argType->isFlags() + || argType->isEnum() + || argType->isContainer() + || arg->type()->referenceType() == LValueReference; + + if (!convert && argType->isPrimitive()) { + if (argType->basicReferencedTypeEntry()) + argType = argType->basicReferencedTypeEntry(); + convert = !m_formatUnits.contains(argType->name()); + } + + Indentation indentation(INDENT); + ac << INDENT; + if (!func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty()) { + // Has conversion rule. + ac << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); + } else { + QString argName = arg->name(); + if (convert) + writeToPythonConversion(ac, arg->type(), func->ownerClass(), argName); + else + ac << argName; + } + + argConversions << argConv; + } + + s << "Py_BuildValue(\"(" << getFormatUnitString(func, false) << ")\"," << endl; + s << argConversions.join(QLatin1String(",\n")) << endl; + s << INDENT << "));" << endl; + } + + bool invalidateReturn = false; + QSet invalidateArgs; + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &funcMod : mods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { + if (argMod.resetAfterUse && !invalidateArgs.contains(argMod.index)) { + invalidateArgs.insert(argMod.index); + s << INDENT << "bool invalidateArg" << argMod.index; + s << " = PyTuple_GET_ITEM(" PYTHON_ARGS ", " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl; + } else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) { + invalidateReturn = true; + } + } + } + s << endl; + + CodeSnipList snips; + if (func->hasInjectedCode()) { + snips = func->injectedCodeSnips(); + + if (injectedCodeUsesPySelf(func)) + s << INDENT << "PyObject* pySelf = BindingManager::instance().retrieveWrapper(this);" << endl; + + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, func, lastArg); + s << endl; + } + + if (!injectedCodeCallsPythonOverride(func)) { + s << INDENT; + s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(" PYTHON_OVERRIDE_VAR ", " PYTHON_ARGS ", NULL));" << endl; + + s << INDENT << "// An error happened in python code!" << endl; + s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_Print();" << endl; + s << INDENT << "return " << defaultReturnExpr << ';' << endl; + } + s << INDENT << '}' << endl; + + if (retType) { + if (invalidateReturn) + s << INDENT << "bool invalidateArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl; + + if (func->typeReplaced(0) != QLatin1String("PyObject")) { + + s << INDENT << "// Check return type" << endl; + s << INDENT; + if (func->typeReplaced(0).isEmpty()) { + s << "PythonToCppFunc " PYTHON_TO_CPP_VAR " = " << cpythonIsConvertibleFunction(func->type()); + s << PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "if (!" PYTHON_TO_CPP_VAR ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\ + "\"Invalid return value in function %s, expected %s, got %s.\", \""; + s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); + s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; + s << INDENT << "return " << defaultReturnExpr << ';' << endl; + } + s << INDENT << '}' << endl; + + } else { + + s << INDENT << "// Check return type" << endl; + s << INDENT << "bool typeIsValid = "; + writeTypeCheck(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), + isNumber(func->type()->typeEntry()), func->typeReplaced(0)); + s << ';' << endl; + s << INDENT << "if (!typeIsValid"; + s << (isPointerToWrapperType(func->type()) ? " && " PYTHON_RETURN_VAR " != Py_None" : ""); + s << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Shiboken::warning(PyExc_RuntimeWarning, 2, "\ + "\"Invalid return value in function %s, expected %s, got %s.\", \""; + s << func->ownerClass()->name() << '.' << funcName << "\", " << getVirtualFunctionReturnTypeName(func); + s << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; + s << INDENT << "return " << defaultReturnExpr << ';' << endl; + } + s << INDENT << '}' << endl; + + } + } + + if (!func->conversionRule(TypeSystem::NativeCode, 0).isEmpty()) { + // Has conversion rule. + writeConversionRule(s, func, TypeSystem::NativeCode, QLatin1String(CPP_RETURN_VAR)); + } else if (!injectedCodeHasReturnValueAttribution(func, TypeSystem::NativeCode)) { + writePythonToCppTypeConversion(s, func->type(), QLatin1String(PYTHON_RETURN_VAR), + QLatin1String(CPP_RETURN_VAR), func->implementingClass()); + } + } + } + + if (invalidateReturn) { + s << INDENT << "if (invalidateArg0)" << endl; + Indentation indentation(INDENT); + s << INDENT << "Shiboken::Object::releaseOwnership(" << PYTHON_RETURN_VAR ".object());" << endl; + } + for (int argIndex : qAsConst(invalidateArgs)) { + s << INDENT << "if (invalidateArg" << argIndex << ')' << endl; + Indentation indentation(INDENT); + s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", "; + s << (argIndex - 1) << "));" << endl; + } + + + const FunctionModificationList &funcMods = func->modifications(); + for (const FunctionModification &funcMod : funcMods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { + if (argMod.ownerships.contains(TypeSystem::NativeCode) + && argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) { + s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl; + Indentation indent(INDENT); + s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl; + } + } + } + + if (func->hasInjectedCode()) { + s << endl; + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode, func, lastArg); + } + + if (retType) { + s << INDENT << "return "; + if (avoidProtectedHack() && retType->isEnum()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(retType); + bool isProtectedEnum = metaEnum && metaEnum->isProtected(); + if (isProtectedEnum) { + QString typeCast; + if (metaEnum->enclosingClass()) + typeCast += QLatin1String("::") + metaEnum->enclosingClass()->qualifiedCppName(); + typeCast += QLatin1String("::") + metaEnum->name(); + s << '(' << typeCast << ')'; + } + } + if (func->type()->referenceType() == LValueReference && !isPointer(func->type())) + s << '*'; + s << CPP_RETURN_VAR ";" << endl; + } + + s << '}' << endl << endl; +} + +void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass) +{ + Indentation indentation(INDENT); + QString wrapperClassName = wrapperName(metaClass); + s << "const QMetaObject* " << wrapperClassName << "::metaObject() const" << endl; + s << '{' << endl; + s << INDENT << "if (QObject::d_ptr->metaObject)" << endl + << INDENT << INDENT << "return QObject::d_ptr->dynamicMetaObject();" << endl; + s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "if (pySelf == NULL)" << endl; + s << INDENT << INDENT << "return " << metaClass->qualifiedCppName() << "::metaObject();" << endl; + s << INDENT << "return PySide::SignalManager::retriveMetaObject(reinterpret_cast(pySelf));" << endl; + s << '}' << endl << endl; + + // qt_metacall function + s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void** args)" << endl; + s << "{" << endl; + + AbstractMetaFunction *func = NULL; + AbstractMetaFunctionList list = metaClass->queryFunctionsByName(QLatin1String("qt_metacall")); + if (list.size() == 1) + func = list[0]; + + CodeSnipList snips; + if (func) { + snips = func->injectedCodeSnips(); + if (func->isUserAdded()) { + CodeSnipList snips = func->injectedCodeSnips(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode, func); + } + } + + s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);" << endl; + s << INDENT << "return result < 0 ? result : PySide::SignalManager::qt_metacall(this, call, id, args);" << endl; + s << "}" << endl << endl; + + // qt_metacast function + writeMetaCast(s, metaClass); +} + +void CppGenerator::writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass) +{ + Indentation indentation(INDENT); + QString wrapperClassName = wrapperName(metaClass); + s << "void* " << wrapperClassName << "::qt_metacast(const char* _clname)" << endl; + s << '{' << endl; + s << INDENT << "if (!_clname) return 0;" << endl; + s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "if (pySelf && PySide::inherits(Py_TYPE(pySelf), _clname))" << endl; + s << INDENT << INDENT << "return static_cast(const_cast< " << wrapperClassName << "* >(this));" << endl; + s << INDENT << "return " << metaClass->qualifiedCppName() << "::qt_metacast(_clname);" << endl; + s << "}" << endl << endl; +} + +void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum) +{ + if (metaEnum->isPrivate() || metaEnum->isAnonymous()) + return; + writeEnumConverterFunctions(s, metaEnum->typeEntry()); +} + +void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType) +{ + if (!enumType) + return; + QString enumFlagName = enumType->isFlags() ? QLatin1String("flag") : QLatin1String("enum"); + QString typeName = fixedCppTypeName(enumType); + QString enumPythonType = cpythonTypeNameExt(enumType); + QString cppTypeName = getFullTypeName(enumType).trimmed(); + if (avoidProtectedHack()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(enumType); + if (metaEnum && metaEnum->isProtected()) + cppTypeName = protectedEnumSurrogateName(metaEnum); + } + QString code; + QTextStream c(&code); + c << INDENT << "*((" << cppTypeName << "*)cppOut) = "; + if (enumType->isFlags()) + c << cppTypeName << "(QFlag((int)PySide::QFlags::getValue(reinterpret_cast(pyIn))))"; + else + c << "(" << cppTypeName << ") Shiboken::Enum::getValue(pyIn)"; + c << ';' << endl; + writePythonToCppFunction(s, code, typeName, typeName); + + QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, %1)").arg(enumPythonType); + writeIsPythonConvertibleToCppFunction(s, typeName, typeName, pyTypeCheck); + + code.clear(); + + c << INDENT << "int castCppIn = *((" << cppTypeName << "*)cppIn);" << endl; + c << INDENT; + c << "return "; + if (enumType->isFlags()) + c << "reinterpret_cast(PySide::QFlags::newObject(castCppIn, " << enumPythonType << "))"; + + else + c << "Shiboken::Enum::newItem(" << enumPythonType << ", castCppIn)"; + c << ';' << endl; + writeCppToPythonFunction(s, code, typeName, typeName); + s << endl; + + if (enumType->isFlags()) + return; + + const FlagsTypeEntry* flags = reinterpret_cast(enumType)->flags(); + if (!flags) + return; + + // QFlags part. + + writeEnumConverterFunctions(s, flags); + + code.clear(); + cppTypeName = getFullTypeName(flags).trimmed(); + c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName; + c << "(QFlag((int)Shiboken::Enum::getValue(pyIn)));" << endl; + + QString flagsTypeName = fixedCppTypeName(flags); + writePythonToCppFunction(s, code, typeName, flagsTypeName); + writeIsPythonConvertibleToCppFunction(s, typeName, flagsTypeName, pyTypeCheck); + + code.clear(); + c << INDENT << "Shiboken::AutoDecRef pyLong(PyNumber_Long(pyIn));" << endl; + c << INDENT << "*((" << cppTypeName << "*)cppOut) = " << cppTypeName; + c << "(QFlag((int)PyLong_AsLong(pyLong.object())));" << endl; + writePythonToCppFunction(s, code, QLatin1String("number"), flagsTypeName); + writeIsPythonConvertibleToCppFunction(s, QLatin1String("number"), flagsTypeName, + QLatin1String("PyNumber_Check(pyIn)")); +} + +void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, + GeneratorContext &classContext) +{ + s << "// Type conversion functions." << endl << endl; + + AbstractMetaEnumList classEnums = metaClass->enums(); + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) + lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + if (!classEnums.isEmpty()) + s << "// Python to C++ enum conversion." << endl; + for (const AbstractMetaEnum *metaEnum : qAsConst(classEnums)) + writeEnumConverterFunctions(s, metaEnum); + + if (metaClass->isNamespace()) + return; + + QString typeName; + if (!classContext.forSmartPointer()) + typeName = getFullTypeName(metaClass); + else + typeName = getFullTypeName(classContext.preciseType()); + + QString cpythonType = cpythonTypeName(metaClass); + + // Returns the C++ pointer of the Python wrapper. + s << "// Python to C++ pointer conversion - returns the C++ object of the Python wrapper (keeps object identity)." << endl; + + QString sourceTypeName = metaClass->name(); + QString targetTypeName = metaClass->name() + QLatin1String("_PTR"); + QString code; + QTextStream c(&code); + c << INDENT << "Shiboken::Conversions::pythonToCppPointer(&" << cpythonType << ", pyIn, cppOut);"; + writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); + + // "Is convertible" function for the Python object to C++ pointer conversion. + QString pyTypeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, (PyTypeObject*)&%1)").arg(cpythonType); + writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck, QString(), true); + s << endl; + + // 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)." << endl; + code.clear(); + if (usePySideExtensions() && metaClass->isQObject()) + { + c << INDENT << "return PySide::getWrapperForQObject((" << typeName << "*)cppIn, &" << cpythonType << ");" << endl; + } else { + c << INDENT << "PyObject* pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(cppIn);" << endl; + c << INDENT << "if (pyOut) {" << endl; + { + Indentation indent(INDENT); + c << INDENT << "Py_INCREF(pyOut);" << endl; + c << INDENT << "return pyOut;" << endl; + } + c << INDENT << '}' << endl; + c << INDENT << "const char* typeName = typeid(*((" << typeName << "*)cppIn)).name();" << endl; + c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType; + c << ", const_cast(cppIn), false, false, typeName);"; + } + std::swap(targetTypeName, sourceTypeName); + writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); + + // The conversions for an Object Type end here. + if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) { + s << endl; + return; + } + + // Always copies C++ value (not pointer, and not reference) to a new Python wrapper. + s << endl << "// C++ to Python copy conversion." << endl; + if (!classContext.forSmartPointer()) + targetTypeName = metaClass->name(); + else + targetTypeName = classContext.preciseType()->name(); + + sourceTypeName = targetTypeName + QLatin1String("_COPY"); + + code.clear(); + + QString computedWrapperName; + if (!classContext.forSmartPointer()) + computedWrapperName = wrapperName(metaClass); + else + computedWrapperName = wrapperName(classContext.preciseType()); + + c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << computedWrapperName; + c << "(*((" << typeName << "*)cppIn)), true, true);"; + writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName); + s << endl; + + // Python to C++ copy conversion. + s << "// Python to C++ copy conversion." << endl; + if (!classContext.forSmartPointer()) + sourceTypeName = metaClass->name(); + else + sourceTypeName = classContext.preciseType()->name(); + + targetTypeName = QStringLiteral("%1_COPY").arg(sourceTypeName); + code.clear(); + + QString pyInVariable = QLatin1String("pyIn"); + QString wrappedCPtrExpression; + if (!classContext.forSmartPointer()) + wrappedCPtrExpression = cpythonWrapperCPtr(metaClass->typeEntry(), pyInVariable); + else + wrappedCPtrExpression = cpythonWrapperCPtr(classContext.preciseType(), pyInVariable); + + c << INDENT << "*((" << typeName << "*)cppOut) = *" + << wrappedCPtrExpression << ';'; + writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); + + // "Is convertible" function for the Python object to C++ value copy conversion. + writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, pyTypeCheck); + s << endl; + + // User provided implicit conversions. + CustomConversion* customConversion = metaClass->typeEntry()->customConversion(); + + // Implicit conversions. + AbstractMetaFunctionList implicitConvs; + if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { + const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); + for (AbstractMetaFunction *func : allImplicitConvs) { + if (!func->isUserAdded()) + implicitConvs << func; + } + } + + if (!implicitConvs.isEmpty()) + s << "// Implicit conversions." << endl; + + AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); + for (const AbstractMetaFunction* conv : qAsConst(implicitConvs)) { + if (conv->isModifiedRemoved()) + continue; + + QString typeCheck; + QString toCppConv; + QString toCppPreConv; + if (conv->isConversionOperator()) { + const AbstractMetaClass* sourceClass = conv->ownerClass(); + typeCheck = QStringLiteral("PyObject_TypeCheck(pyIn, %1)").arg(cpythonTypeNameExt(sourceClass->typeEntry())); + toCppConv = QLatin1Char('*') + cpythonWrapperCPtr(sourceClass->typeEntry(), QLatin1String("pyIn")); + } else { + // Constructor that does implicit conversion. + if (!conv->typeReplaced(1).isEmpty()) + continue; + const AbstractMetaType* sourceType = conv->arguments().first()->type(); + typeCheck = cpythonCheckFunction(sourceType); + bool isUserPrimitiveWithoutTargetLangName = isUserPrimitive(sourceType) + && sourceType->typeEntry()->targetLangApiName() == sourceType->typeEntry()->name(); + if (!isWrapperType(sourceType) + && !isUserPrimitiveWithoutTargetLangName + && !sourceType->typeEntry()->isEnum() + && !sourceType->typeEntry()->isFlags() + && !sourceType->typeEntry()->isContainer()) { + typeCheck += QLatin1Char('('); + } + if (isWrapperType(sourceType)) { + typeCheck += QLatin1String("pyIn)"); + toCppConv = (sourceType->referenceType() == LValueReference || !isPointerToWrapperType(sourceType)) + ? QLatin1String("*") : QString(); + toCppConv += cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); + } else if (typeCheck.contains(QLatin1String("%in"))) { + typeCheck.replace(QLatin1String("%in"), QLatin1String("pyIn")); + typeCheck.append(QLatin1Char(')')); + } else { + typeCheck += QLatin1String("pyIn)"); + } + + if (isUserPrimitive(sourceType) + || isCppPrimitive(sourceType) + || sourceType->typeEntry()->isContainer() + || sourceType->typeEntry()->isEnum() + || sourceType->typeEntry()->isFlags()) { + QTextStream pc(&toCppPreConv); + pc << INDENT << getFullTypeNameWithoutModifiers(sourceType) << " cppIn"; + writeMinimalConstructorExpression(pc, sourceType); + pc << ';' << endl; + writeToCppConversion(pc, sourceType, 0, QLatin1String("pyIn"), QLatin1String("cppIn")); + pc << ';'; + toCppConv.append(QLatin1String("cppIn")); + } else if (!isWrapperType(sourceType)) { + QTextStream tcc(&toCppConv); + writeToCppConversion(tcc, sourceType, metaClass, QLatin1String("pyIn"), QLatin1String("/*BOZO-1061*/")); + } + + + } + const AbstractMetaType* sourceType = conv->isConversionOperator() + ? buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass()) + : conv->arguments().first()->type(); + writePythonToCppConversionFunctions(s, sourceType, targetType, typeCheck, toCppConv, toCppPreConv); + } + + writeCustomConverterFunctions(s, customConversion); +} + +void CppGenerator::writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion) +{ + if (!customConversion) + return; + const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); + if (toCppConversions.isEmpty()) + return; + s << "// Python to C++ conversions for type '" << customConversion->ownerType()->qualifiedCppName() << "'." << endl; + for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) + writePythonToCppConversionFunctions(s, toNative, customConversion->ownerType()); + s << endl; +} + +void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, + GeneratorContext &classContext) +{ + if (metaClass->isNamespace()) + return; + s << INDENT << "// Register Converter" << endl; + s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(&"; + s << cpythonTypeName(metaClass) << ',' << endl; + { + Indentation indent(INDENT); + QString sourceTypeName = metaClass->name(); + QString targetTypeName = sourceTypeName + QLatin1String("_PTR"); + s << INDENT << pythonToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; + s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl; + std::swap(targetTypeName, sourceTypeName); + s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); + if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) { + s << ',' << endl; + sourceTypeName = metaClass->name() + QLatin1String("_COPY"); + s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName); + } + } + s << ");" << endl; + + s << endl; + + QStringList cppSignature; + if (!classContext.forSmartPointer()) { + cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"), + QString::SkipEmptyParts); + } else { + cppSignature = classContext.preciseType()->cppSignature().split(QLatin1String("::"), + QString::SkipEmptyParts); + } + while (!cppSignature.isEmpty()) { + QString signature = cppSignature.join(QLatin1String("::")); + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");" << endl; + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "*\");" << endl; + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "&\");" << endl; + cppSignature.removeFirst(); + } + + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::"; + QString qualifiedCppNameInvocation; + if (!classContext.forSmartPointer()) + qualifiedCppNameInvocation = metaClass->qualifiedCppName(); + else + qualifiedCppNameInvocation = classContext.preciseType()->cppSignature(); + + s << qualifiedCppNameInvocation << ").name());" << endl; + + if (shouldGenerateCppWrapper(metaClass)) { + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::"; + s << wrapperName(metaClass) << ").name());" << endl; + } + + s << endl; + + if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) + return; + + // Python to C++ copy (value, not pointer neither reference) conversion. + s << INDENT << "// Add Python to C++ copy (value, not pointer neither reference) conversion to type converter." << endl; + QString sourceTypeName = metaClass->name(); + QString targetTypeName = sourceTypeName + QLatin1String("_COPY"); + QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName); + QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName); + writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); + + // User provided implicit conversions. + CustomConversion* customConversion = metaClass->typeEntry()->customConversion(); + + // Add implicit conversions. + AbstractMetaFunctionList implicitConvs; + if (!customConversion || !customConversion->replaceOriginalTargetToNativeConversions()) { + const AbstractMetaFunctionList &allImplicitConvs = implicitConversions(metaClass->typeEntry()); + for (AbstractMetaFunction *func : allImplicitConvs) { + if (!func->isUserAdded()) + implicitConvs << func; + } + } + + if (!implicitConvs.isEmpty()) + s << INDENT << "// Add implicit conversions to type converter." << endl; + + AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass); + for (const AbstractMetaFunction *conv : qAsConst(implicitConvs)) { + if (conv->isModifiedRemoved()) + continue; + const AbstractMetaType* sourceType; + if (conv->isConversionOperator()) { + sourceType = buildAbstractMetaTypeFromAbstractMetaClass(conv->ownerClass()); + } else { + // Constructor that does implicit conversion. + if (!conv->typeReplaced(1).isEmpty()) + continue; + sourceType = conv->arguments().first()->type(); + } + QString toCpp = pythonToCppFunctionName(sourceType, targetType); + QString isConv = convertibleToCppFunctionName(sourceType, targetType); + writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); + } + + writeCustomConverterRegister(s, customConversion, QLatin1String("converter")); +} + +void CppGenerator::writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar) +{ + if (!customConversion) + return; + const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); + if (toCppConversions.isEmpty()) + return; + s << INDENT << "// Add user defined implicit conversions to type converter." << endl; + for (CustomConversion::TargetToNativeConversion *toNative : toCppConversions) { + QString toCpp = pythonToCppFunctionName(toNative, customConversion->ownerType()); + QString isConv = convertibleToCppFunctionName(toNative, customConversion->ownerType()); + writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); + } +} + +void CppGenerator::writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar) +{ + s << INDENT << "// Add user defined container conversion to type converter." << endl; + QString typeName = fixedCppTypeName(container); + QString toCpp = pythonToCppFunctionName(typeName, typeName); + QString isConv = convertibleToCppFunctionName(typeName, typeName); + writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); +} + +void CppGenerator::writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType) +{ + writeCppToPythonFunction(s, containerType); + writePythonToCppConversionFunctions(s, containerType); +} + +void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, + GeneratorContext &context) +{ + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + const AbstractMetaClass* ownerClass = rfunc->ownerClass(); + int minArgs = overloadData.minArgs(); + int maxArgs = overloadData.maxArgs(); + bool initPythonArguments; + bool usesNamedArguments; + + // If method is a constructor... + if (rfunc->isConstructor()) { + // Check if the right constructor was called. + if (!ownerClass->hasPrivateDestructor()) { + s << INDENT; + s << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ") && !Shiboken::ObjectType::canCallConstructor(" PYTHON_SELF_VAR "->ob_type, Shiboken::SbkType< ::"; + QString qualifiedCppName; + if (!context.forSmartPointer()) + qualifiedCppName = ownerClass->qualifiedCppName(); + else + qualifiedCppName = context.preciseType()->cppSignature(); + + s << qualifiedCppName << " >()))" << endl; + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; + } + // Declare pointer for the underlying C++ object. + s << INDENT << "::"; + if (!context.forSmartPointer()) { + s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass) + : ownerClass->qualifiedCppName()); + } else { + s << context.preciseType()->cppSignature(); + } + s << "* cptr = 0;" << endl; + + initPythonArguments = maxArgs > 0; + usesNamedArguments = !ownerClass->isQObject() && overloadData.hasArgumentWithDefaultValue(); + + } else { + if (rfunc->implementingClass() && + (!rfunc->implementingClass()->isNamespace() && overloadData.hasInstanceFunction())) { + writeCppSelfDefinition(s, rfunc, context, overloadData.hasStaticFunction()); + } + if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType()) + s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; + + initPythonArguments = minArgs != maxArgs || maxArgs > 1; + usesNamedArguments = rfunc->isCallOperator() || overloadData.hasArgumentWithDefaultValue(); + } + + if (maxArgs > 0) { + s << INDENT << "int overloadId = -1;" << endl; + s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR; + if (pythonFunctionWrapperUsesListOfArguments(overloadData)) + s << "[] = { 0" << QString::fromLatin1(", 0").repeated(maxArgs-1) << " }"; + s << ';' << endl; + writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); + } + + if (usesNamedArguments && !rfunc->isCallOperator()) + s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; + + if (initPythonArguments) { + s << INDENT << "int numArgs = "; + if (minArgs == 0 && maxArgs == 1 && !rfunc->isConstructor() && !pythonFunctionWrapperUsesListOfArguments(overloadData)) + s << "(" PYTHON_ARG " == 0 ? 0 : 1);" << endl; + else + writeArgumentsInitializer(s, overloadData); + } +} + +void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, + GeneratorContext &classContext) +{ + ErrorCode errorCode(-1); + OverloadData overloadData(overloads, this); + + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + const AbstractMetaClass* metaClass = rfunc->ownerClass(); + + s << "static int" << endl; + s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* args, PyObject* kwds)" << endl; + s << '{' << endl; + + QSet argNamesSet; + if (usePySideExtensions() && metaClass->isQObject()) { + // Write argNames variable with all known argument names. + const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); + for (const AbstractMetaFunction *func : overloads) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + argNamesSet << arg->name(); + } + } + QStringList argNamesList = argNamesSet.toList(); + qSort(argNamesList.begin(), argNamesList.end()); + if (argNamesList.isEmpty()) { + s << INDENT << "const char** argNames = 0;" << endl; + } else { + s << INDENT << "const char* argNames[] = {\"" + << argNamesList.join(QLatin1String("\", \"")) << "\"};" << endl; + } + s << INDENT << "const QMetaObject* metaObject;" << endl; + } + + s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(" PYTHON_SELF_VAR ");" << endl; + + if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { + s << INDENT << "SbkObjectType* type = reinterpret_cast(" PYTHON_SELF_VAR "->ob_type);" << endl; + s << INDENT << "SbkObjectType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; + } + + if (metaClass->isAbstract()) { + s << INDENT << "if (type == myType) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl; + { + Indentation indentation(INDENT); + s << INDENT << "\"'" << metaClass->qualifiedCppName(); + } + s << "' represents a C++ abstract class and cannot be instantiated\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}' << endl << endl; + } + + if (metaClass->baseClassNames().size() > 1) { + if (!metaClass->isAbstract()) { + s << INDENT << "if (type != myType) {" << endl; + } + { + Indentation indentation(INDENT); + s << INDENT << "Shiboken::ObjectType::copyMultimpleheritance(type, myType);" << endl; + } + if (!metaClass->isAbstract()) + s << INDENT << '}' << endl << endl; + } + + writeMethodWrapperPreamble(s, overloadData, classContext); + + s << endl; + + if (overloadData.maxArgs() > 0) + writeOverloadedFunctionDecisor(s, overloadData); + + writeFunctionCalls(s, overloadData, classContext); + s << endl; + + s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "delete cptr;" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}' << endl; + if (overloadData.maxArgs() > 0) { + s << INDENT << "if (!cptr) goto " << cpythonFunctionName(rfunc) << "_TypeError;" << endl; + s << endl; + } + + s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);" << endl; + // If the created C++ object has a C++ wrapper the ownership is assigned to Python + // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper + // is marked as true (the second "1"). Otherwise the default values apply: + // Python owns it and C++ wrapper is false. + if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) + s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl; + // 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 << INDENT << "if (Shiboken::BindingManager::instance().hasWrapper(cptr)) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Shiboken::BindingManager::instance().releaseWrapper(Shiboken::BindingManager::instance().retrieveWrapper(cptr));" << endl; + } + s << INDENT << "}" << endl; + s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; + + // Create metaObject and register signal/slot + if (metaClass->isQObject() && usePySideExtensions()) { + s << endl << INDENT << "// QObject setup" << endl; + s << INDENT << "PySide::Signal::updateSourceObject(" PYTHON_SELF_VAR ");" << endl; + s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl; + s << INDENT << "if (kwds && !PySide::fillQtProperties(" PYTHON_SELF_VAR ", metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + } + + // Constructor code injections, position=end + bool hasCodeInjectionsAtEnd = false; + for (AbstractMetaFunction *func : overloads) { + const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); + for (const CodeSnip &cs : injectedCodeSnips) { + if (cs.position == TypeSystem::CodeSnipPositionEnd) { + hasCodeInjectionsAtEnd = true; + break; + } + } + } + if (hasCodeInjectionsAtEnd) { + // FIXME: C++ arguments are not available in code injection on constructor when position = end. + s << INDENT << "switch(overloadId) {" << endl; + for (AbstractMetaFunction *func : overloads) { + Indentation indent(INDENT); + const CodeSnipList &injectedCodeSnips = func->injectedCodeSnips(); + for (const CodeSnip &cs : injectedCodeSnips) { + if (cs.position == TypeSystem::CodeSnipPositionEnd) { + s << INDENT << "case " << metaClass->functions().indexOf(func) << ':' << endl; + s << INDENT << '{' << endl; + { + Indentation indent(INDENT); + writeCodeSnips(s, func->injectedCodeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func); + } + s << INDENT << '}' << endl; + break; + } + } + } + s << '}' << endl; + } + + s << endl; + s << endl << INDENT << "return 1;" << endl; + if (overloadData.maxArgs() > 0) + writeErrorSection(s, overloadData); + s << '}' << endl << endl; +} + +void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, + GeneratorContext &classContext) +{ + OverloadData overloadData(overloads, this); + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + + int maxArgs = overloadData.maxArgs(); + + s << "static PyObject* "; + s << cpythonFunctionName(rfunc) << "(PyObject* " PYTHON_SELF_VAR; + if (maxArgs > 0) { + s << ", PyObject* " << (pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : PYTHON_ARG); + if (overloadData.hasArgumentWithDefaultValue() || rfunc->isCallOperator()) + s << ", PyObject* kwds"; + } + s << ')' << endl << '{' << endl; + + writeMethodWrapperPreamble(s, overloadData, classContext); + + s << endl; + + /* + * 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(); + if (callExtendedReverseOperator) { + QString revOpName = ShibokenGenerator::pythonOperatorFunctionName(rfunc).insert(2, QLatin1Char('r')); + if (rfunc->isBinaryOperator()) { + s << INDENT << "if (!isReverse" << endl; + { + Indentation indent(INDENT); + s << INDENT << "&& Shiboken::Object::checkType(" PYTHON_ARG ")" << endl; + s << INDENT << "&& !PyObject_TypeCheck(" PYTHON_ARG ", " PYTHON_SELF_VAR "->ob_type)" << endl; + s << INDENT << "&& PyObject_HasAttrString(" PYTHON_ARG ", const_cast(\"" << revOpName << "\"))) {" << endl; + + // 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 << INDENT << "PyObject* revOpMethod = PyObject_GetAttrString(" PYTHON_ARG ", const_cast(\"" << revOpName << "\"));" << endl; + s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast(\"O\"), " PYTHON_SELF_VAR ");" << endl; + s << INDENT << "if (PyErr_Occurred() && (PyErr_ExceptionMatches(PyExc_NotImplementedError)"; + s << " || PyErr_ExceptionMatches(PyExc_AttributeError))) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_Clear();" << endl; + s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; + s << INDENT << PYTHON_RETURN_VAR " = 0;" << endl; + } + s << INDENT << '}' << endl; + } + s << INDENT << "}" << endl; + s << INDENT << "Py_XDECREF(revOpMethod);" << endl << endl; + } + s << INDENT << "}" << endl; + } + s << INDENT << "// Do not enter here if other object has implemented a reverse operator." << endl; + s << INDENT << "if (!" PYTHON_RETURN_VAR ") {" << endl << endl; + } + + if (maxArgs > 0) + writeOverloadedFunctionDecisor(s, overloadData); + + writeFunctionCalls(s, overloadData, classContext); + + if (callExtendedReverseOperator) + s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl; + + s << endl; + + writeFunctionReturnErrorCheckSection(s, hasReturnValue && !rfunc->isInplaceOperator()); + + if (hasReturnValue) { + if (rfunc->isInplaceOperator()) { + s << INDENT << "Py_INCREF(" PYTHON_SELF_VAR ");\n"; + s << INDENT << "return " PYTHON_SELF_VAR ";\n"; + } else { + s << INDENT << "return " PYTHON_RETURN_VAR ";\n"; + } + } else { + s << INDENT << "Py_RETURN_NONE;" << endl; + } + + if (maxArgs > 0) + writeErrorSection(s, overloadData); + + s << '}' << endl << endl; +} + +void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData) +{ + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + s << "PyTuple_GET_SIZE(args);" << endl; + + int minArgs = overloadData.minArgs(); + int maxArgs = overloadData.maxArgs(); + + s << INDENT << "PyObject* "; + s << PYTHON_ARGS "[] = {" + << QString(maxArgs, QLatin1Char('0')).split(QLatin1String(""), QString::SkipEmptyParts).join(QLatin1String(", ")) + << "};" << endl; + s << endl; + + if (overloadData.hasVarargs()) { + maxArgs--; + if (minArgs > maxArgs) + minArgs = maxArgs; + + s << INDENT << "PyObject* nonvarargs = PyTuple_GetSlice(args, 0, " << maxArgs << ");" << endl; + s << INDENT << "Shiboken::AutoDecRef auto_nonvarargs(nonvarargs);" << endl; + s << INDENT << PYTHON_ARGS "[" << maxArgs << "] = PyTuple_GetSlice(args, " << maxArgs << ", numArgs);" << endl; + s << INDENT << "Shiboken::AutoDecRef auto_varargs(" PYTHON_ARGS "[" << maxArgs << "]);" << endl; + s << endl; + } + + bool usesNamedArguments = overloadData.hasArgumentWithDefaultValue(); + + s << INDENT << "// invalid argument lengths" << endl; + bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); + if (usesNamedArguments) { + if (!ownerClassIsQObject) { + s << INDENT << "if (numArgs" << (overloadData.hasArgumentWithDefaultValue() ? " + numNamedArgs" : "") << " > " << maxArgs << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): too many arguments\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}'; + } + if (minArgs > 0) { + if (ownerClassIsQObject) + s << INDENT; + else + s << " else "; + s << "if (numArgs < " << minArgs << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_TypeError, \"" << fullPythonFunctionName(rfunc) << "(): not enough arguments\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}'; + } + } + const QVector invalidArgsLength = overloadData.invalidArgumentLengths(); + if (!invalidArgsLength.isEmpty()) { + QStringList invArgsLen; + for (int i : qAsConst(invalidArgsLength)) + invArgsLen << QStringLiteral("numArgs == %1").arg(i); + if (usesNamedArguments && (!ownerClassIsQObject || minArgs > 0)) + s << " else "; + else + s << INDENT; + s << "if (" << invArgsLen.join(QLatin1String(" || ")) << ")" << endl; + Indentation indent(INDENT); + s << INDENT << "goto " << cpythonFunctionName(rfunc) << "_TypeError;"; + } + s << endl << endl; + + QString funcName; + if (rfunc->isOperatorOverload()) + funcName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); + else + funcName = rfunc->name(); + + QString argsVar = overloadData.hasVarargs() ? QLatin1String("nonvarargs") : QLatin1String("args"); + s << INDENT << "if (!"; + if (usesNamedArguments) + s << "PyArg_ParseTuple(" << argsVar << ", \"|" << QByteArray(maxArgs, 'O') << ':' << funcName << '"'; + else + s << "PyArg_UnpackTuple(" << argsVar << ", \"" << funcName << "\", " << minArgs << ", " << maxArgs; + QStringList palist; + for (int i = 0; i < maxArgs; i++) + palist << QString::fromLatin1("&(" PYTHON_ARGS "[%1])").arg(i); + s << ", " << palist.join(QLatin1String(", ")) << "))" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << endl; +} + +void CppGenerator::writeCppSelfDefinition(QTextStream &s, + GeneratorContext &context, + bool hasStaticOverload, + bool cppSelfAsReference) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers(); + QString className; + if (!context.forSmartPointer()) { + className = useWrapperClass + ? wrapperName(metaClass) + : (QLatin1String("::") + metaClass->qualifiedCppName()); + } else { + className = context.preciseType()->cppSignature(); + } + + QString cppSelfAttribution; + QString pythonSelfVar = QLatin1String(PYTHON_SELF_VAR); + QString cpythonWrapperCPtrResult; + if (!context.forSmartPointer()) + cpythonWrapperCPtrResult = cpythonWrapperCPtr(metaClass, pythonSelfVar); + else + cpythonWrapperCPtrResult = cpythonWrapperCPtr(context.preciseType(), pythonSelfVar); + + if (cppSelfAsReference) { + QString cast = useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString(); + cppSelfAttribution = QString::fromLatin1("%1& %2 = *(%3%4)") + .arg(className, QLatin1String(CPP_SELF_VAR), cast, + cpythonWrapperCPtrResult); + } else { + s << INDENT << className << "* " CPP_SELF_VAR " = 0;" << endl; + writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); + cppSelfAttribution = QString::fromLatin1("%1 = %2%3") + .arg(QLatin1String(CPP_SELF_VAR), + (useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString()), + cpythonWrapperCPtrResult); + } + + // Checks if the underlying C++ object is valid. + if (hasStaticOverload && !cppSelfAsReference) { + s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl; + { + Indentation indent(INDENT); + writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); + s << INDENT << cppSelfAttribution << ';' << endl; + } + s << INDENT << '}' << endl; + return; + } + + writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); + s << INDENT << cppSelfAttribution << ';' << endl; +} + +void CppGenerator::writeCppSelfDefinition(QTextStream &s, + const AbstractMetaFunction *func, + GeneratorContext &context, + bool hasStaticOverload) +{ + if (!func->ownerClass() || func->isConstructor()) + return; + + if (func->isOperatorOverload() && func->isBinaryOperator()) { + QString checkFunc = cpythonCheckFunction(func->ownerClass()->typeEntry()); + s << INDENT << "bool isReverse = " << checkFunc << PYTHON_ARG ")" << endl; + { + Indentation indent1(INDENT); + Indentation indent2(INDENT); + Indentation indent3(INDENT); + Indentation indent4(INDENT); + s << INDENT << "&& !" << checkFunc << PYTHON_SELF_VAR ");" << endl; + } + s << INDENT << "if (isReverse)" << endl; + Indentation indent(INDENT); + s << INDENT << "std::swap(" PYTHON_SELF_VAR ", " PYTHON_ARG ");" << endl; + } + + writeCppSelfDefinition(s, context, hasStaticOverload); +} + +void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) +{ + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + s << endl << INDENT << cpythonFunctionName(rfunc) << "_TypeError:" << endl; + Indentation indentation(INDENT); + QString funcName = fullPythonFunctionName(rfunc); + + QString argsVar = pythonFunctionWrapperUsesListOfArguments(overloadData) + ? QLatin1String("args") : QLatin1String(PYTHON_ARG); + if (verboseErrorMessagesDisabled()) { + s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl; + } else { + QStringList overloadSignatures; + const OverloadData::MetaFunctionList &overloads = overloadData.overloads(); + for (const AbstractMetaFunction *f : overloads) { + QStringList args; + const AbstractMetaArgumentList &arguments = f->arguments(); + for (AbstractMetaArgument *arg : arguments) { + QString strArg; + AbstractMetaType* argType = arg->type(); + if (isCString(argType)) { + strArg = QLatin1String("\" SBK_STR_NAME \""); + } else if (argType->isPrimitive()) { + const PrimitiveTypeEntry* ptp = reinterpret_cast(argType->typeEntry()); + while (ptp->referencedTypeEntry()) + ptp = ptp->referencedTypeEntry(); + strArg = ptp->name(); + if (strArg == QLatin1String("QString")) { + strArg = QLatin1String("unicode"); + } else if (strArg == QLatin1String("QChar")) { + strArg = QLatin1String("1-unicode"); + } else { + strArg = ptp->name(); + static const QRegularExpression regex(QStringLiteral("^signed\\s+")); + Q_ASSERT(regex.isValid()); + strArg.remove(regex); + if (strArg == QLatin1String("double")) + strArg = QLatin1String("float"); + } + } else if (argType->typeEntry()->isContainer()) { + strArg = argType->fullName(); + if (strArg == QLatin1String("QList") || strArg == QLatin1String("QVector") + || strArg == QLatin1String("QLinkedList") || strArg == QLatin1String("QStack") + || strArg == QLatin1String("QQueue")) { + strArg = QLatin1String("list"); + } else if (strArg == QLatin1String("QMap") || strArg == QLatin1String("QHash") + || strArg == QLatin1String("QMultiMap") || strArg == QLatin1String("QMultiHash")) { + strArg = QLatin1String("dict"); + } else if (strArg == QLatin1String("QPair")) { + strArg = QLatin1String("2-tuple"); + } + } else { + strArg = argType->fullName(); + if (strArg == QLatin1String("PyUnicode")) + strArg = QLatin1String("unicode"); + else if (strArg == QLatin1String("PyString")) + strArg = QLatin1String("str"); + else if (strArg == QLatin1String("PyBytes")) + strArg = QLatin1String("\" SBK_STR_NAME \""); + else if (strArg == QLatin1String("PySequece")) + strArg = QLatin1String("list"); + else if (strArg == QLatin1String("PyTuple")) + strArg = QLatin1String("tuple"); + else if (strArg == QLatin1String("PyDict")) + strArg = QLatin1String("dict"); + else if (strArg == QLatin1String("PyObject")) + strArg = QLatin1String("object"); + else if (strArg == QLatin1String("PyCallable")) + strArg = QLatin1String("callable"); + else if (strArg == QLatin1String("uchar")) + strArg = QLatin1String("buffer"); // This depends on an inject code to be true, but if it's not true + // the function wont work at all, so it must be true. + } + if (!arg->defaultValueExpression().isEmpty()) { + strArg += QLatin1String(" = "); + if ((isCString(argType) || isPointerToWrapperType(argType)) + && arg->defaultValueExpression() == QLatin1String("0")) { + strArg += QLatin1String("None"); + } else { + QString e = arg->defaultValueExpression(); + e.replace(QLatin1String("::"), QLatin1String(".")); + e.replace(QLatin1String("\""), QLatin1String("\\\"")); + strArg += e; + } + } + args << strArg; + } + overloadSignatures << QLatin1Char('"') + args.join(QLatin1String(", ")) + QLatin1Char('"'); + } + s << INDENT << "const char* overloads[] = {" << overloadSignatures.join(QLatin1String(", ")) + << ", 0};" << endl; + s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", overloads);" << endl; + } + s << INDENT << "return " << m_currentErrorCode << ';' << endl; +} + +void CppGenerator::writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue) +{ + s << INDENT << "if (PyErr_Occurred()" << (hasReturnValue ? " || !" PYTHON_RETURN_VAR : "") << ") {" << endl; + { + Indentation indent(INDENT); + if (hasReturnValue) + s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}' << endl; +} + +void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj) +{ + s << INDENT << "if (!Shiboken::Object::isValid(" << pyObj << "))" << endl; + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; +} + +static QString pythonToCppConverterForArgumentName(const QString& argumentName) +{ + static const QRegularExpression pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])")); + Q_ASSERT(pyArgsRegex.isValid()); + const QRegularExpressionMatch match = pyArgsRegex.match(argumentName); + QString result = QLatin1String(PYTHON_TO_CPP_VAR); + if (match.hasMatch()) + result += match.captured(1); + return result; +} + +void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType, bool rejectNull) +{ + QString customCheck; + if (!customType.isEmpty()) { + AbstractMetaType* metaType; + customCheck = guessCPythonCheckFunction(customType, &metaType); + if (metaType) + argType = metaType; + } + + // TODO-CONVERTER: merge this with the code below. + QString typeCheck; + if (customCheck.isEmpty()) + typeCheck = cpythonIsConvertibleFunction(argType, argType->isEnum() ? false : isNumber); + else + typeCheck = customCheck; + typeCheck.append(QString::fromLatin1("(%1)").arg(argumentName)); + + // TODO-CONVERTER ----------------------------------------------------------------------- + if (customCheck.isEmpty() && !argType->typeEntry()->isCustom()) { + typeCheck = QString::fromLatin1("(%1 = %2))").arg(pythonToCppConverterForArgumentName(argumentName), typeCheck); + if (!isNumber && argType->typeEntry()->isCppPrimitive()) + typeCheck.prepend(QString::fromLatin1("%1(%2) && ").arg(cpythonCheckFunction(argType), argumentName)); + } + // TODO-CONVERTER ----------------------------------------------------------------------- + + if (rejectNull) + typeCheck = QString::fromLatin1("(%1 != Py_None && %2)").arg(argumentName, typeCheck); + + s << typeCheck; +} + +static void checkTypeViability(const AbstractMetaFunction* func, const AbstractMetaType* type, int argIdx) +{ + if (!type + || !type->typeEntry()->isPrimitive() + || type->indirections() == 0 + || ShibokenGenerator::isCString(type) + || func->argumentRemoved(argIdx) + || !func->typeReplaced(argIdx).isEmpty() + || !func->conversionRule(TypeSystem::All, argIdx).isEmpty() + || func->hasInjectedCode()) + return; + QString prefix; + if (func->ownerClass()) + prefix = func->ownerClass()->qualifiedCppName() + QLatin1String("::"); + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("There's no user provided way (conversion rule, argument removal, custom code, etc) " + "to handle the primitive %1 type '%2' in function '%3%4'.") + .arg(argIdx == 0 ? QStringLiteral("return") : QStringLiteral("argument"), + type->cppSignature(), prefix, func->signature()); +} + +static void checkTypeViability(const AbstractMetaFunction* func) +{ + if (func->isUserAdded()) + return; + const AbstractMetaType* type = func->type(); + checkTypeViability(func, type, 0); + for (int i = 0; i < func->arguments().count(); ++i) + checkTypeViability(func, func->arguments().at(i)->type(), i + 1); +} + +void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName) +{ + QSet numericTypes; + const OverloadDataList &overloads = overloadData->previousOverloadData()->nextOverloadData(); + for (OverloadData *od : overloads) { + const OverloadData::MetaFunctionList &odOverloads = od->overloads(); + for (const AbstractMetaFunction *func : odOverloads) { + checkTypeViability(func); + const AbstractMetaType* argType = od->argument(func)->type(); + if (!argType->isPrimitive()) + continue; + if (ShibokenGenerator::isNumber(argType->typeEntry())) + numericTypes << argType->typeEntry(); + } + } + + // This condition trusts that the OverloadData object will arrange for + // PyInt type to come after the more precise numeric types (e.g. float and bool) + const AbstractMetaType* argType = overloadData->argType(); + bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType); + QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : QString()); + bool rejectNull = shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos()); + writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull); +} + +void CppGenerator::writeArgumentConversion(QTextStream& s, + const AbstractMetaType* argType, + const QString& argName, const QString& pyArgName, + const AbstractMetaClass* context, + const QString& defaultValue, + bool castArgumentAsUnused) +{ + if (argType->typeEntry()->isCustom() || argType->typeEntry()->isVarargs()) + return; + if (isWrapperType(argType)) + writeInvalidPyObjectCheck(s, pyArgName); + writePythonToCppTypeConversion(s, argType, pyArgName, argName, context, defaultValue); + if (castArgumentAsUnused) + writeUnusedVariableCast(s, argName); +} + +const AbstractMetaType* CppGenerator::getArgumentType(const AbstractMetaFunction* func, int argPos) +{ + if (argPos < 0 || argPos > func->arguments().size()) { + qCWarning(lcShiboken).noquote().nospace() + << QStringLiteral("Argument index for function '%1' out of range.").arg(func->signature()); + return 0; + } + + const AbstractMetaType* argType = 0; + QString typeReplaced = func->typeReplaced(argPos); + if (typeReplaced.isEmpty()) + argType = (argPos == 0) ? func->type() : func->arguments().at(argPos-1)->type(); + else + argType = buildAbstractMetaTypeFromString(typeReplaced); + if (!argType && !m_knownPythonTypes.contains(typeReplaced)) { + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("Unknown type '%1' used as argument type replacement "\ + "in function '%2', the generated code may be broken.") + .arg(typeReplaced, func->signature()); + } + return argType; +} + +void CppGenerator::writePythonToCppTypeConversion(QTextStream& s, + const AbstractMetaType* type, + const QString& pyIn, + const QString& cppOut, + const AbstractMetaClass* /* context */, + const QString& defaultValue) +{ + const TypeEntry* typeEntry = type->typeEntry(); + if (typeEntry->isCustom() || typeEntry->isVarargs()) + return; + + QString cppOutAux = cppOut + QLatin1String("_local"); + + bool treatAsPointer = isValueTypeWithCopyConstructorOnly(type); + bool isPointerOrObjectType = (isObjectType(type) || isPointer(type)) && !isUserPrimitive(type) && !isCppPrimitive(type); + bool isNotContainerEnumOrFlags = !typeEntry->isContainer() && !typeEntry->isEnum() && !typeEntry->isFlags(); + bool mayHaveImplicitConversion = type->referenceType() == LValueReference + && !isUserPrimitive(type) + && !isCppPrimitive(type) + && isNotContainerEnumOrFlags + && !(treatAsPointer || isPointerOrObjectType); + QString typeName = getFullTypeNameWithoutModifiers(type); + + bool isProtectedEnum = false; + + if (mayHaveImplicitConversion) { + s << INDENT << typeName << ' ' << cppOutAux; + writeMinimalConstructorExpression(s, type, defaultValue); + s << ';' << endl; + } else if (avoidProtectedHack() && type->typeEntry()->isEnum()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type); + if (metaEnum && metaEnum->isProtected()) { + typeName = QLatin1String("long"); + isProtectedEnum = true; + } + } + + s << INDENT << typeName; + if (treatAsPointer || isPointerOrObjectType) { + s << "* " << cppOut; + if (!defaultValue.isEmpty()) + s << " = " << defaultValue; + } else if (type->referenceType() == LValueReference && !typeEntry->isPrimitive() && isNotContainerEnumOrFlags) { + s << "* " << cppOut << " = &" << cppOutAux; + } else { + s << ' ' << cppOut; + if (isProtectedEnum && avoidProtectedHack()) { + s << " = "; + if (defaultValue.isEmpty()) + s << "0"; + else + s << "(long)" << defaultValue; + } else if (isUserPrimitive(type) || typeEntry->isEnum() || typeEntry->isFlags()) { + writeMinimalConstructorExpression(s, typeEntry, defaultValue); + } else if (!type->isContainer() && !type->isSmartPointer()) { + writeMinimalConstructorExpression(s, type, defaultValue); + } + } + s << ';' << endl; + + QString pythonToCppFunc = pythonToCppConverterForArgumentName(pyIn); + + s << INDENT; + if (!defaultValue.isEmpty()) + s << "if (" << pythonToCppFunc << ") "; + + QString pythonToCppCall = QString::fromLatin1("%1(%2, &%3)").arg(pythonToCppFunc, pyIn, cppOut); + if (!mayHaveImplicitConversion) { + s << pythonToCppCall << ';' << endl; + return; + } + + if (!defaultValue.isEmpty()) + s << '{' << endl << INDENT; + + s << "if (Shiboken::Conversions::isImplicitConversion(reinterpret_cast(" + << cpythonTypeNameExt(type) << "), " << pythonToCppFunc << "))" << endl; + { + Indentation indent(INDENT); + s << INDENT << pythonToCppFunc << '(' << pyIn << ", &" << cppOutAux << ");" << endl; + } + s << INDENT << "else" << endl; + { + Indentation indent(INDENT); + s << INDENT << pythonToCppCall << ';' << endl; + } + + if (!defaultValue.isEmpty()) + s << INDENT << '}'; + s << endl; +} + +static void addConversionRuleCodeSnippet(CodeSnipList& snippetList, QString& rule, + TypeSystem::Language /* conversionLanguage */, + TypeSystem::Language snippetLanguage, + QString outputName = QString(), + QString inputName = QString()) +{ + if (rule.isEmpty()) + return; + if (snippetLanguage == TypeSystem::TargetLangCode) { + rule.replace(QLatin1String("%in"), inputName); + rule.replace(QLatin1String("%out"), outputName + QLatin1String("_out")); + } else { + rule.replace(QLatin1String("%out"), outputName); + } + CodeSnip snip(0, snippetLanguage); + snip.position = (snippetLanguage == TypeSystem::NativeCode) ? TypeSystem::CodeSnipPositionAny : TypeSystem::CodeSnipPositionBeginning; + snip.addCode(rule); + snippetList << snip; +} + +void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language) +{ + CodeSnipList snippets; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + QString rule = func->conversionRule(language, arg->argumentIndex() + 1); + addConversionRuleCodeSnippet(snippets, rule, language, TypeSystem::TargetLangCode, + arg->name(), arg->name()); + } + writeCodeSnips(s, snippets, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func); +} + +void CppGenerator::writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar) +{ + CodeSnipList snippets; + QString rule = func->conversionRule(language, 0); + addConversionRuleCodeSnippet(snippets, rule, language, language, outputVar); + writeCodeSnips(s, snippets, TypeSystem::CodeSnipPositionAny, language, func); +} + +void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue) +{ + if (thereIsReturnValue && (!func->type() || func->argumentRemoved(0)) && !injectedCodeHasReturnValueAttribution(func)) { + s << INDENT << PYTHON_RETURN_VAR " = Py_None;" << endl; + s << INDENT << "Py_INCREF(Py_None);" << endl; + } +} + +void CppGenerator::writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData) +{ + s << INDENT << "// Overloaded function decisor" << endl; + const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); + const OverloadData::MetaFunctionList &functionOverloads = overloadData.overloadsWithoutRepetition(); + for (int i = 0; i < functionOverloads.count(); i++) + s << INDENT << "// " << i << ": " << functionOverloads.at(i)->minimalSignature() << endl; + writeOverloadedFunctionDecisorEngine(s, &overloadData); + s << endl; + + // Ensure that the direct overload that called this reverse + // is called. + if (rfunc->isOperatorOverload() && !rfunc->isCallOperator()) { + s << INDENT << "if (isReverse && overloadId == -1) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"reverse operator not implemented.\");" << endl; + s << INDENT << "return 0;" << endl; + } + s << INDENT << "}" << endl << endl; + } + + s << INDENT << "// Function signature not found." << endl; + s << INDENT << "if (overloadId == -1) goto " << cpythonFunctionName(overloadData.referenceFunction()) << "_TypeError;" << endl; + s << endl; +} + +void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData) +{ + bool hasDefaultCall = parentOverloadData->nextArgumentHasDefaultValue(); + const AbstractMetaFunction* referenceFunction = parentOverloadData->referenceFunction(); + + // If the next argument has not an argument with a default value, it is still possible + // that one of the overloads for the current overload data has its final occurrence here. + // If found, the final occurrence of a method is attributed to the referenceFunction + // variable to be used further on this method on the conditional that identifies default + // method calls. + if (!hasDefaultCall) { + const OverloadData::MetaFunctionList &overloads = parentOverloadData->overloads(); + for (const AbstractMetaFunction *func : overloads) { + if (parentOverloadData->isFinalOccurrence(func)) { + referenceFunction = func; + hasDefaultCall = true; + break; + } + } + } + + int maxArgs = parentOverloadData->maxArgs(); + // Python constructors always receive multiple arguments. + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(*parentOverloadData); + + // Functions without arguments are identified right away. + if (maxArgs == 0) { + s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(referenceFunction); + s << "; // " << referenceFunction->minimalSignature() << endl; + return; + + // To decide if a method call is possible at this point the current overload + // data object cannot be the head, since it is just an entry point, or a root, + // for the tree of arguments and it does not represent a valid method call. + } else if (!parentOverloadData->isHeadOverloadData()) { + bool isLastArgument = parentOverloadData->nextOverloadData().isEmpty(); + bool signatureFound = parentOverloadData->overloads().size() == 1; + + // The current overload data describes the last argument of a signature, + // so the method can be identified right now. + if (isLastArgument || (signatureFound && !hasDefaultCall)) { + const AbstractMetaFunction* func = parentOverloadData->referenceFunction(); + s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); + s << "; // " << func->minimalSignature() << endl; + return; + } + } + + bool isFirst = true; + + // If the next argument has a default value the decisor can perform a method call; + // it just need to check if the number of arguments received from Python are equal + // to the number of parameters preceding the argument with the default value. + const OverloadDataList &overloads = parentOverloadData->nextOverloadData(); + if (hasDefaultCall) { + isFirst = false; + int numArgs = parentOverloadData->argPos() + 1; + s << INDENT << "if (numArgs == " << numArgs << ") {" << endl; + { + Indentation indent(INDENT); + const AbstractMetaFunction* func = referenceFunction; + for (OverloadData *overloadData : overloads) { + const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue(); + if (defValFunc) { + func = defValFunc; + break; + } + } + s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func); + s << "; // " << func->minimalSignature() << endl; + } + s << INDENT << '}'; + } + + for (OverloadData *overloadData : overloads) { + bool signatureFound = overloadData->overloads().size() == 1 + && !overloadData->getFunctionWithDefaultValue() + && !overloadData->findNextArgWithDefault(); + + const AbstractMetaFunction* refFunc = overloadData->referenceFunction(); + + QStringList typeChecks; + QString pyArgName = (usePyArgs && maxArgs > 1) + ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(overloadData->argPos()) + : QLatin1String(PYTHON_ARG); + OverloadData* od = overloadData; + int startArg = od->argPos(); + int sequenceArgCount = 0; + while (od && !od->argType()->isVarargs()) { + bool typeReplacedByPyObject = od->argumentTypeReplaced() == QLatin1String("PyObject"); + if (!typeReplacedByPyObject) { + if (usePyArgs) + pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(od->argPos()); + QString typeCheck; + QTextStream tck(&typeCheck); + const AbstractMetaFunction* func = od->referenceFunction(); + + if (func->isConstructor() && func->arguments().count() == 1) { + const AbstractMetaClass* ownerClass = func->ownerClass(); + const ComplexTypeEntry* baseContainerType = ownerClass->typeEntry()->baseContainerType(); + if (baseContainerType && baseContainerType == func->arguments().first()->type()->typeEntry() && isCopyable(ownerClass)) { + tck << '!' << cpythonCheckFunction(ownerClass->typeEntry()) << pyArgName << ')' << endl; + Indentation indent(INDENT); + tck << INDENT << "&& "; + } + } + writeTypeCheck(tck, od, pyArgName); + typeChecks << typeCheck; + } + + sequenceArgCount++; + + if (od->nextOverloadData().isEmpty() + || od->nextArgumentHasDefaultValue() + || od->nextOverloadData().size() != 1 + || od->overloads().size() != od->nextOverloadData().first()->overloads().size()) { + overloadData = od; + od = 0; + } else { + od = od->nextOverloadData().first(); + } + } + + if (usePyArgs && signatureFound) { + AbstractMetaArgumentList args = refFunc->arguments(); + int lastArgIsVarargs = (int) (args.size() > 1 && args.last()->type()->isVarargs()); + int numArgs = args.size() - OverloadData::numberOfRemovedArguments(refFunc) - lastArgIsVarargs; + typeChecks.prepend(QString::fromLatin1("numArgs %1 %2").arg(lastArgIsVarargs ? QLatin1String(">=") : QLatin1String("==")).arg(numArgs)); + } else if (sequenceArgCount > 1) { + typeChecks.prepend(QString::fromLatin1("numArgs >= %1").arg(startArg + sequenceArgCount)); + } else if (refFunc->isOperatorOverload() && !refFunc->isCallOperator()) { + typeChecks.prepend(QString::fromLatin1("%1isReverse").arg(refFunc->isReverseOperator() ? QString() : QLatin1String("!"))); + } + + if (isFirst) { + isFirst = false; + s << INDENT; + } else { + s << " else "; + } + s << "if ("; + if (typeChecks.isEmpty()) { + s << "true"; + } else { + Indentation indent(INDENT); + QString separator; + QTextStream sep(&separator); + sep << endl << INDENT << "&& "; + s << typeChecks.join(separator); + } + s << ") {" << endl; + { + Indentation indent(INDENT); + writeOverloadedFunctionDecisorEngine(s, overloadData); + } + s << INDENT << "}"; + } + s << endl; +} + +void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData, + GeneratorContext &context) +{ + const OverloadData::MetaFunctionList &overloads = overloadData.overloadsWithoutRepetition(); + s << INDENT << "// Call function/method" << endl; + s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl; + { + Indentation indent(INDENT); + if (overloads.count() == 1) { + writeSingleFunctionCall(s, overloadData, overloads.first(), context); + } else { + for (int i = 0; i < overloads.count(); i++) { + const AbstractMetaFunction* func = overloads.at(i); + s << INDENT << "case " << i << ": // " << func->signature() << endl; + s << INDENT << '{' << endl; + { + Indentation indent(INDENT); + writeSingleFunctionCall(s, overloadData, func, context); + s << INDENT << "break;" << endl; + } + s << INDENT << '}' << endl; + } + } + } + s << INDENT << '}' << endl; +} + +void CppGenerator::writeSingleFunctionCall(QTextStream &s, + const OverloadData &overloadData, + const AbstractMetaFunction *func, + GeneratorContext &context) +{ + if (func->isDeprecated()) { + s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '" + << func->signature().replace(QLatin1String("::"), QLatin1String(".")) + << "' is marked as deprecated, please check the documentation for more information.\");" << endl; + } + + if (func->functionType() == AbstractMetaFunction::EmptyFunction) { + s << INDENT << "PyErr_Format(PyExc_TypeError, \"%s is a private method.\", \"" + << func->signature().replace(QLatin1String("::"), QLatin1String(".")) + << "\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + return; + } + + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); + + // Handle named arguments. + writeNamedArgumentResolution(s, func, usePyArgs); + + bool injectCodeCallsFunc = injectedCodeCallsCppFunction(func); + bool mayHaveUnunsedArguments = !func->isUserAdded() && func->hasInjectedCode() && injectCodeCallsFunc; + int removedArgs = 0; + for (int argIdx = 0; argIdx < func->arguments().count(); ++argIdx) { + bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, argIdx + 1).isEmpty(); + const AbstractMetaArgument* arg = func->arguments().at(argIdx); + if (func->argumentRemoved(argIdx + 1)) { + if (!arg->defaultValueExpression().isEmpty()) { + QString cppArgRemoved = QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(argIdx); + s << INDENT << getFullTypeName(arg->type()) << ' ' << cppArgRemoved; + s << " = " << guessScopeForDefaultValue(func, arg) << ';' << endl; + writeUnusedVariableCast(s, 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. + qFatal(qPrintable(QString::fromLatin1("No way to call '%1::%2' with the modifications described in the type system.") + .arg(func->ownerClass()->name(), func->signature())), NULL); + } + removedArgs++; + continue; + } + if (hasConversionRule) + continue; + const AbstractMetaType* argType = getArgumentType(func, argIdx + 1); + if (!argType || (mayHaveUnunsedArguments && !injectedCodeUsesArgument(func, argIdx))) + continue; + int argPos = argIdx - removedArgs; + QString argName = QString::fromLatin1(CPP_ARG"%1").arg(argPos); + QString pyArgName = usePyArgs ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) : QLatin1String(PYTHON_ARG); + QString defaultValue = guessScopeForDefaultValue(func, arg); + writeArgumentConversion(s, argType, argName, pyArgName, func->implementingClass(), defaultValue, func->isUserAdded()); + } + + s << endl; + + int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); + + s << INDENT << "if (!PyErr_Occurred()) {" << endl; + { + Indentation indentation(INDENT); + writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs); + if (!func->isConstructor()) + writeNoneReturn(s, func, overloadData.hasNonVoidReturnType()); + } + s << INDENT << '}' << endl; +} + +QString CppGenerator::cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName) +{ + if (targetTypeName.isEmpty()) + targetTypeName = sourceTypeName; + return QString::fromLatin1("%1_CppToPython_%2").arg(sourceTypeName, targetTypeName); +} + +QString CppGenerator::pythonToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName) +{ + return QString::fromLatin1("%1_PythonToCpp_%2").arg(sourceTypeName, targetTypeName); +} +QString CppGenerator::pythonToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType) +{ + return pythonToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType)); +} +QString CppGenerator::pythonToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, + const TypeEntry* targetType) +{ + return pythonToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType)); +} + +QString CppGenerator::convertibleToCppFunctionName(const QString& sourceTypeName, const QString& targetTypeName) +{ + return QString::fromLatin1("is_%1_PythonToCpp_%2_Convertible").arg(sourceTypeName, targetTypeName); +} +QString CppGenerator::convertibleToCppFunctionName(const AbstractMetaType* sourceType, const AbstractMetaType* targetType) +{ + return convertibleToCppFunctionName(fixedCppTypeName(sourceType), fixedCppTypeName(targetType)); +} +QString CppGenerator::convertibleToCppFunctionName(const CustomConversion::TargetToNativeConversion* toNative, + const TypeEntry* targetType) +{ + return convertibleToCppFunctionName(fixedCppTypeName(toNative), fixedCppTypeName(targetType)); +} + +void CppGenerator::writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName) +{ + QString prettyCode; + QTextStream c(&prettyCode); + formatCode(c, code, INDENT); + processCodeSnip(prettyCode); + + s << "static PyObject* " << cppToPythonFunctionName(sourceTypeName, targetTypeName); + s << "(const void* cppIn) {" << endl; + s << prettyCode; + s << '}' << endl; +} + +static void replaceCppToPythonVariables(QString& code, const QString& typeName) +{ + code.prepend(QString::fromLatin1("%1& cppInRef = *((%1*)cppIn);\n").arg(typeName)); + code.replace(QLatin1String("%INTYPE"), typeName); + code.replace(QLatin1String("%OUTTYPE"), QLatin1String("PyObject*")); + code.replace(QLatin1String("%in"), QLatin1String("cppInRef")); + code.replace(QLatin1String("%out"), QLatin1String("pyOut")); +} +void CppGenerator::writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion) +{ + QString code = customConversion->nativeToTargetConversion(); + replaceCppToPythonVariables(code, getFullTypeName(customConversion->ownerType())); + writeCppToPythonFunction(s, code, fixedCppTypeName(customConversion->ownerType())); +} +void CppGenerator::writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType) +{ + const CustomConversion* customConversion = containerType->typeEntry()->customConversion(); + if (!customConversion) { + qFatal(qPrintable(QString::fromLatin1("Can't write the C++ to Python conversion function for container type '%1' - "\ + "no conversion rule was defined for it in the type system.") + .arg(containerType->typeEntry()->qualifiedCppName())), NULL); + } + if (!containerType->typeEntry()->isContainer()) { + writeCppToPythonFunction(s, customConversion); + return; + } + QString code = customConversion->nativeToTargetConversion(); + for (int i = 0; i < containerType->instantiations().count(); ++i) { + AbstractMetaType* type = containerType->instantiations().at(i); + QString typeName = getFullTypeName(type); + if (type->isConstant()) + typeName = QLatin1String("const ") + typeName; + code.replace(QString::fromLatin1("%INTYPE_%1").arg(i), typeName); + } + replaceCppToPythonVariables(code, getFullTypeNameWithoutModifiers(containerType)); + processCodeSnip(code); + writeCppToPythonFunction(s, code, fixedCppTypeName(containerType)); +} + +void CppGenerator::writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName) +{ + QString prettyCode; + QTextStream c(&prettyCode); + formatCode(c, code, INDENT); + processCodeSnip(prettyCode); + s << "static void " << pythonToCppFunctionName(sourceTypeName, targetTypeName); + s << "(PyObject* pyIn, void* cppOut) {" << endl; + s << prettyCode; + s << '}' << endl; +} + +void CppGenerator::writeIsPythonConvertibleToCppFunction(QTextStream& s, + const QString& sourceTypeName, + const QString& targetTypeName, + const QString& condition, + QString pythonToCppFuncName, + bool acceptNoneAsCppNull) +{ + if (pythonToCppFuncName.isEmpty()) + pythonToCppFuncName = pythonToCppFunctionName(sourceTypeName, targetTypeName); + + s << "static PythonToCppFunc " << convertibleToCppFunctionName(sourceTypeName, targetTypeName); + s << "(PyObject* pyIn) {" << endl; + if (acceptNoneAsCppNull) { + s << INDENT << "if (pyIn == Py_None)" << endl; + Indentation indent(INDENT); + s << INDENT << "return Shiboken::Conversions::nonePythonToCppNullPtr;" << endl; + } + s << INDENT << "if (" << condition << ')' << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " << pythonToCppFuncName << ';' << endl; + } + s << INDENT << "return 0;" << endl; + s << '}' << endl; +} + +void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, + const AbstractMetaType* sourceType, + const AbstractMetaType* targetType, + QString typeCheck, + QString conversion, + QString preConversion) +{ + QString sourcePyType = cpythonTypeNameExt(sourceType); + + // Python to C++ conversion function. + QString code; + QTextStream c(&code); + if (conversion.isEmpty()) + conversion = QLatin1Char('*') + cpythonWrapperCPtr(sourceType->typeEntry(), QLatin1String("pyIn")); + if (!preConversion.isEmpty()) + c << INDENT << preConversion << endl; + c << INDENT << QString::fromLatin1("*((%1*)cppOut) = %1(%2);") + .arg(getFullTypeName(targetType->typeEntry()), conversion); + QString sourceTypeName = fixedCppTypeName(sourceType); + QString targetTypeName = fixedCppTypeName(targetType); + writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); + + // Python to C++ convertible check function. + if (typeCheck.isEmpty()) + typeCheck = QString::fromLatin1("PyObject_TypeCheck(pyIn, %1)").arg(sourcePyType); + writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); + s << endl; +} + +void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, + const CustomConversion::TargetToNativeConversion* toNative, + const TypeEntry* targetType) +{ + // Python to C++ conversion function. + QString code = toNative->conversion(); + QString inType; + if (toNative->sourceType()) + inType = cpythonTypeNameExt(toNative->sourceType()); + else + inType = QString::fromLatin1("(&%1_Type)").arg(toNative->sourceTypeName()); + code.replace(QLatin1String("%INTYPE"), inType); + code.replace(QLatin1String("%OUTTYPE"), targetType->qualifiedCppName()); + code.replace(QLatin1String("%in"), QLatin1String("pyIn")); + code.replace(QLatin1String("%out"), QString::fromLatin1("*((%1*)cppOut)").arg(getFullTypeName(targetType))); + + QString sourceTypeName = fixedCppTypeName(toNative); + QString targetTypeName = fixedCppTypeName(targetType); + writePythonToCppFunction(s, code, sourceTypeName, targetTypeName); + + // Python to C++ convertible check function. + QString typeCheck = toNative->sourceTypeCheck(); + if (typeCheck.isEmpty()) { + QString pyTypeName = toNative->sourceTypeName(); + if (pyTypeName == QLatin1String("Py_None") || pyTypeName == QLatin1String("PyNone")) + typeCheck = QLatin1String("%in == Py_None"); + else if (pyTypeName == QLatin1String("SbkEnumType")) + typeCheck = QLatin1String("Shiboken::isShibokenEnum(%in)"); + else if (pyTypeName == QLatin1String("SbkObject")) + typeCheck = QLatin1String("Shiboken::Object::checkType(%in)"); + else if (pyTypeName == QLatin1String("PyTypeObject")) + typeCheck = QLatin1String("PyType_Check(%in)"); + else if (pyTypeName == QLatin1String("PyObject")) + typeCheck = QLatin1String("PyObject_TypeCheck(%in, &PyBaseObject_Type)"); + else if (pyTypeName.startsWith(QLatin1String("Py"))) + typeCheck = pyTypeName + QLatin1String("_Check(%in)"); + } + if (typeCheck.isEmpty()) { + if (!toNative->sourceType() || toNative->sourceType()->isPrimitive()) { + qFatal(qPrintable(QString::fromLatin1("User added implicit conversion for C++ type '%1' must provide either an input "\ + "type check function or a non primitive type entry.") + .arg(targetType->qualifiedCppName())), NULL); + + } + typeCheck = QString::fromLatin1("PyObject_TypeCheck(%in, %1)").arg(cpythonTypeNameExt(toNative->sourceType())); + } + typeCheck.replace(QLatin1String("%in"), QLatin1String("pyIn")); + processCodeSnip(typeCheck); + writeIsPythonConvertibleToCppFunction(s, sourceTypeName, targetTypeName, typeCheck); +} + +void CppGenerator::writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType) +{ + const CustomConversion* customConversion = containerType->typeEntry()->customConversion(); + if (!customConversion) { + //qFatal + return; + } + const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); + if (toCppConversions.isEmpty()) { + //qFatal + return; + } + // Python to C++ conversion function. + QString cppTypeName = getFullTypeNameWithoutModifiers(containerType); + QString code; + QTextStream c(&code); + c << INDENT << QString::fromLatin1("%1& cppOutRef = *((%1*)cppOut);").arg(cppTypeName) << endl; + code.append(toCppConversions.first()->conversion()); + for (int i = 0; i < containerType->instantiations().count(); ++i) { + const AbstractMetaType* type = containerType->instantiations().at(i); + QString typeName = getFullTypeName(type); + if (type->isValue() && isValueTypeWithCopyConstructorOnly(type)) { + static const QRegularExpression regex(QLatin1String(CONVERTTOCPP_REGEX)); + Q_ASSERT(regex.isValid()); + for (int pos = 0; ; ) { + const QRegularExpressionMatch match = regex.match(code, pos); + if (!match.hasMatch()) + break; + pos = match.capturedEnd(); + const QString varName = match.captured(1); + QString rightCode = code.mid(pos); + rightCode.replace(varName, QLatin1Char('*') + varName); + code.replace(pos, code.size() - pos, rightCode); + } + typeName.append(QLatin1Char('*')); + } + code.replace(QString::fromLatin1("%OUTTYPE_%1").arg(i), typeName); + } + code.replace(QLatin1String("%OUTTYPE"), cppTypeName); + code.replace(QLatin1String("%in"), QLatin1String("pyIn")); + code.replace(QLatin1String("%out"), QLatin1String("cppOutRef")); + QString typeName = fixedCppTypeName(containerType); + writePythonToCppFunction(s, code, typeName, typeName); + + // Python to C++ convertible check function. + QString typeCheck = cpythonCheckFunction(containerType); + if (typeCheck.isEmpty()) + typeCheck = QLatin1String("false"); + else + typeCheck = QString::fromLatin1("%1pyIn)").arg(typeCheck); + writeIsPythonConvertibleToCppFunction(s, typeName, typeName, typeCheck); + s << endl; +} + +void CppGenerator::writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc) +{ + s << INDENT << "Shiboken::Conversions::addPythonToCppValueConversion(" << converterVar << ',' << endl; + { + Indentation indent(INDENT); + s << INDENT << pythonToCppFunc << ',' << endl; + s << INDENT << isConvertibleFunc; + } + s << ");" << endl; +} + +void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs) +{ + const AbstractMetaArgumentList &args = OverloadData::getArgumentsWithDefaultValues(func); + if (args.isEmpty()) + return; + + QString pyErrString(QLatin1String("PyErr_SetString(PyExc_TypeError, \"") + fullPythonFunctionName(func) + + QLatin1String("(): got multiple values for keyword argument '%1'.\");")); + + s << INDENT << "if (kwds) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* "; + for (const AbstractMetaArgument *arg : args) { + int pyArgIndex = arg->argumentIndex() - OverloadData::numberOfRemovedArguments(func, arg->argumentIndex()); + QString pyArgName = usePyArgs + ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(pyArgIndex) + : QLatin1String(PYTHON_ARG); + s << "value = PyDict_GetItemString(kwds, \"" << arg->name() << "\");" << endl; + s << INDENT << "if (value && " << pyArgName << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << pyErrString.arg(arg->name()) << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << "} else if (value) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << pyArgName << " = value;" << endl; + s << INDENT << "if (!"; + writeTypeCheck(s, arg->type(), pyArgName, isNumber(arg->type()->typeEntry()), func->typeReplaced(arg->argumentIndex() + 1)); + s << ')' << endl; + { + Indentation indent(INDENT); + s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl; + } + } + s << INDENT << '}' << endl; + if (arg != args.last()) + s << INDENT; + } + } + s << INDENT << '}' << endl; +} + +QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass) +{ + *wrappedClass = 0; + QString pyArgName; + if (argIndex == -1) { + pyArgName = QLatin1String(PYTHON_SELF_VAR); + *wrappedClass = func->implementingClass(); + } else if (argIndex == 0) { + AbstractMetaType *funcType = func->type(); + AbstractMetaType *returnType = getTypeWithoutContainer(funcType); + if (returnType) { + pyArgName = QLatin1String(PYTHON_RETURN_VAR); + *wrappedClass = AbstractMetaClass::findClass(classes(), returnType->typeEntry()->name()); + } else { + QString message = QLatin1String("Invalid Argument index (0, return value) on function modification: ") + + (funcType ? funcType->name() : QLatin1String("void")) + QLatin1Char(' '); + if (const AbstractMetaClass *declaringClass = func->declaringClass()) + message += declaringClass->name() + QLatin1String("::"); + message += func->name() + QLatin1String("()"); + qCWarning(lcShiboken).noquote().nospace() << message; + } + } else { + int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); + AbstractMetaType* argType = getTypeWithoutContainer(func->arguments().at(realIndex)->type()); + + if (argType) { + *wrappedClass = AbstractMetaClass::findClass(classes(), argType->typeEntry()->name()); + if (argIndex == 1 + && !func->isConstructor() + && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) + pyArgName = QLatin1String(PYTHON_ARG); + else + pyArgName = QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argIndex - 1); + } + } + return pyArgName; +} + +void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, + GeneratorContext &context, int maxArgs) +{ + s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl; + if (func->isConstructor()) { + const CodeSnipList &snips = func->injectedCodeSnips(); + for (const CodeSnip &cs : snips) { + if (cs.position == TypeSystem::CodeSnipPositionEnd) { + s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast(func)) << ';' << endl; + break; + } + } + } + + if (func->isAbstract()) { + s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast(" PYTHON_SELF_VAR "))) {\n"; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; + s << func->ownerClass()->name() << '.' << func->name() << "()' not implemented.\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << "}\n"; + } + + // Used to provide contextual information to custom code writer function. + const AbstractMetaArgument* lastArg = 0; + + CodeSnipList snips; + if (func->hasInjectedCode()) { + snips = func->injectedCodeSnips(); + + // Find the last argument available in the method call to provide + // the injected code writer with information to avoid invalid replacements + // on the %# variable. + if (maxArgs > 0 && maxArgs < func->arguments().size() - OverloadData::numberOfRemovedArguments(func)) { + int removedArgs = 0; + for (int i = 0; i < maxArgs + removedArgs; i++) { + lastArg = func->arguments().at(i); + if (func->argumentRemoved(i + 1)) + removedArgs++; + } + } else if (maxArgs != 0 && !func->arguments().isEmpty()) { + lastArg = func->arguments().last(); + } + + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, func, lastArg); + s << endl; + } + + writeConversionRule(s, func, TypeSystem::NativeCode); + + if (!func->isUserAdded()) { + QStringList userArgs; + if (func->functionType() != AbstractMetaFunction::CopyConstructorFunction) { + int removedArgs = 0; + for (int i = 0; i < maxArgs + removedArgs; i++) { + const AbstractMetaArgument* arg = func->arguments().at(i); + bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); + if (func->argumentRemoved(i + 1)) { + // If some argument with default value is removed from a + // method signature, the said value must be explicitly + // added to the method call. + removedArgs++; + + // If have conversion rules I will use this for removed args + if (hasConversionRule) + userArgs << arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); + else if (!arg->defaultValueExpression().isEmpty()) + userArgs << QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i); + } else { + int idx = arg->argumentIndex() - removedArgs; + bool deRef = isValueTypeWithCopyConstructorOnly(arg->type()) + || isObjectTypeUsedAsValueType(arg->type()) + || (arg->type()->referenceType() == LValueReference && isWrapperType(arg->type()) && !isPointer(arg->type())); + QString argName = hasConversionRule + ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX) + : QString::fromLatin1("%1" CPP_ARG "%2").arg(deRef ? QLatin1String("*") : QString()).arg(idx); + userArgs << argName; + } + } + + // If any argument's default value was modified the method must be called + // with this new value whenever the user doesn't pass an explicit value to it. + // Also, any unmodified default value coming after the last user specified + // argument and before the modified argument must be explicitly stated. + QStringList otherArgs; + bool otherArgsModified = false; + bool argsClear = true; + for (int i = func->arguments().size() - 1; i >= maxArgs + removedArgs; i--) { + const AbstractMetaArgument* arg = func->arguments().at(i); + bool defValModified = arg->defaultValueExpression() != arg->originalDefaultValueExpression(); + bool hasConversionRule = !func->conversionRule(TypeSystem::NativeCode, arg->argumentIndex() + 1).isEmpty(); + if (argsClear && !defValModified && !hasConversionRule) + continue; + else + argsClear = false; + otherArgsModified |= defValModified || hasConversionRule || func->argumentRemoved(i + 1); + if (hasConversionRule) + otherArgs.prepend(arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX)); + else + otherArgs.prepend(QString::fromLatin1(CPP_ARG_REMOVED "%1").arg(i)); + } + if (otherArgsModified) + userArgs << otherArgs; + } + + bool isCtor = false; + QString methodCall; + QTextStream mc(&methodCall); + QString useVAddr; + QTextStream uva(&useVAddr); + if (func->isOperatorOverload() && !func->isCallOperator()) { + QString firstArg = QLatin1String("(*" CPP_SELF_VAR ")"); + if (func->isPointerOperator()) + firstArg.remove(1, 1); // remove the de-reference operator + + QString secondArg = QLatin1String(CPP_ARG0); + if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { + secondArg.prepend(QLatin1String("(*")); + secondArg.append(QLatin1Char(')')); + } + + if (func->isUnaryOperator()) + std::swap(firstArg, secondArg); + + QString op = func->originalName(); + op = op.right(op.size() - (sizeof("operator")/sizeof(char)-1)); + + if (func->isBinaryOperator()) { + if (func->isReverseOperator()) + std::swap(firstArg, secondArg); + + if (((op == QLatin1String("++")) || (op == QLatin1String("--"))) && !func->isReverseOperator()) { + s << endl << INDENT << "for(int i=0; i < " << secondArg << "; i++, " << firstArg << op << ");" << endl; + mc << firstArg; + } else { + mc << firstArg << ' ' << op << ' ' << secondArg; + } + } else { + mc << op << ' ' << secondArg; + } + } else if (!injectedCodeCallsCppFunction(func)) { + if (func->isConstructor()) { + isCtor = true; + QString className = wrapperName(func->ownerClass()); + + if (func->functionType() == AbstractMetaFunction::CopyConstructorFunction && maxArgs == 1) { + mc << "new ::" << className << "(*" << CPP_ARG0 << ')'; + } else { + QString ctorCall = className + QLatin1Char('(') + userArgs.join(QLatin1String(", ")) + QLatin1Char(')'); + if (usePySideExtensions() && func->ownerClass()->isQObject()) { + s << INDENT << "void* addr = PySide::nextQObjectMemoryAddr();" << endl; + uva << "if (addr) {" << endl; + { + Indentation indent(INDENT); + + uva << INDENT << "cptr = " << "new (addr) ::" + << ctorCall << ';' << endl + << INDENT + << "PySide::setNextQObjectMemoryAddr(0);" + << endl; + } + uva << INDENT << "} else {" << endl; + { + Indentation indent(INDENT); + + uva << INDENT << "cptr = " << "new ::" + << ctorCall << ';' << endl; + } + uva << INDENT << "}" << endl; + } else { + mc << "new ::" << ctorCall; + } + } + } else { + QString methodCallClassName; + if (context.forSmartPointer()) + methodCallClassName = context.preciseType()->cppSignature(); + else if (func->ownerClass()) + methodCallClassName = func->ownerClass()->qualifiedCppName(); + + if (func->ownerClass()) { + if (!avoidProtectedHack() || !func->isProtected()) { + if (func->isStatic()) { + mc << "::" << methodCallClassName << "::"; + } else { + const QString selfVarCast = func->ownerClass() == func->implementingClass() + ? QLatin1String(CPP_SELF_VAR) + : QLatin1String("reinterpret_cast<") + methodCallClassName + QLatin1String(" *>(" CPP_SELF_VAR ")"); + if (func->isConstant()) { + if (avoidProtectedHack()) { + mc << "const_castownerClass()->hasProtectedMembers()) { + // PYSIDE-500: Need a special wrapper cast when inherited + const QString selfWrapCast = func->ownerClass() == func->implementingClass() + ? QLatin1String(CPP_SELF_VAR) + : QLatin1String("reinterpret_cast<") + wrapperName(func->ownerClass()) + QLatin1String(" *>(" CPP_SELF_VAR ")"); + mc << wrapperName(func->ownerClass()); + mc << "*>(" << selfWrapCast << ")->"; + } + else { + mc << methodCallClassName; + mc << "*>(" << selfVarCast << ")->"; + } + } else { + mc << "const_cast(" << selfVarCast << ")->"; + } + } else { + mc << selfVarCast << "->"; + } + } + + if (!func->isAbstract() && func->isVirtual()) + mc << "::%CLASS_NAME::"; + + mc << func->originalName(); + } else { + if (!func->isStatic()) + mc << "((::" << wrapperName(func->ownerClass()) << "*) " << CPP_SELF_VAR << ")->"; + + if (!func->isAbstract()) + mc << (func->isProtected() ? wrapperName(func->ownerClass()) : + QLatin1String("::") + + methodCallClassName) << "::"; + mc << func->originalName() << "_protected"; + } + } else { + mc << func->originalName(); + } + mc << '(' << userArgs.join(QLatin1String(", ")) << ')'; + if (!func->isAbstract() && func->isVirtual()) { + mc.flush(); + if (!avoidProtectedHack() || !func->isProtected()) { + QString virtualCall(methodCall); + QString normalCall(methodCall); + virtualCall = virtualCall.replace(QLatin1String("%CLASS_NAME"), + methodCallClassName); + normalCall.remove(QLatin1String("::%CLASS_NAME::")); + methodCall.clear(); + mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast(" PYTHON_SELF_VAR ")) ? "; + mc << virtualCall << " : " << normalCall; + } + } + } + } + + if (!injectedCodeCallsCppFunction(func)) { + s << INDENT << BEGIN_ALLOW_THREADS << endl << INDENT; + if (isCtor) { + s << (useVAddr.isEmpty() ? + QString::fromLatin1("cptr = %1;").arg(methodCall) : useVAddr) << endl; + } else if (func->type() && !func->isInplaceOperator()) { + bool writeReturnType = true; + if (avoidProtectedHack()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); + if (metaEnum) { + QString enumName; + if (metaEnum->isProtected()) + enumName = protectedEnumSurrogateName(metaEnum); + else + enumName = func->type()->cppSignature(); + methodCall.prepend(enumName + QLatin1Char('(')); + methodCall.append(QLatin1Char(')')); + s << enumName; + writeReturnType = false; + } + } + if (writeReturnType) { + s << func->type()->cppSignature(); + if (isObjectTypeUsedAsValueType(func->type())) { + s << '*'; + methodCall.prepend(QString::fromLatin1("new %1(").arg(func->type()->typeEntry()->qualifiedCppName())); + methodCall.append(QLatin1Char(')')); + } + } + s << " " CPP_RETURN_VAR " = "; + s << methodCall << ';' << endl; + } else { + s << methodCall << ';' << endl; + } + s << INDENT << END_ALLOW_THREADS << endl; + + if (!func->conversionRule(TypeSystem::TargetLangCode, 0).isEmpty()) { + writeConversionRule(s, func, TypeSystem::TargetLangCode, QLatin1String(PYTHON_RETURN_VAR)); + } else if (!isCtor && !func->isInplaceOperator() && func->type() + && !injectedCodeHasReturnValueAttribution(func, TypeSystem::TargetLangCode)) { + s << INDENT << PYTHON_RETURN_VAR " = "; + if (isObjectTypeUsedAsValueType(func->type())) { + s << "Shiboken::Object::newObject(reinterpret_cast(" << cpythonTypeNameExt(func->type()->typeEntry()) + << "), " << CPP_RETURN_VAR << ", true, true)"; + } else { + writeToPythonConversion(s, func->type(), func->ownerClass(), QLatin1String(CPP_RETURN_VAR)); + } + s << ';' << endl; + } + } + } + + if (func->hasInjectedCode() && !func->isConstructor()) { + s << endl; + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, func, lastArg); + } + + bool hasReturnPolicy = false; + + // Ownership transference between C++ and Python. + QVector ownership_mods; + // Python object reference management. + QVector refcount_mods; + const FunctionModificationList &funcMods = func->modifications(); + for (const FunctionModification &func_mod : funcMods) { + for (const ArgumentModification &arg_mod : func_mod.argument_mods) { + if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode)) + ownership_mods.append(arg_mod); + else if (!arg_mod.referenceCounts.isEmpty()) + refcount_mods.append(arg_mod); + } + } + + // If there's already a setParent(return, me), don't use the return heuristic! + if (func->argumentOwner(func->ownerClass(), -1).index == 0) + hasReturnPolicy = true; + + if (!ownership_mods.isEmpty()) { + s << endl << INDENT << "// Ownership transferences." << endl; + for (const ArgumentModification &arg_mod : qAsConst(ownership_mods)) { + const AbstractMetaClass* wrappedClass = 0; + QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); + if (!wrappedClass) { + s << "#error Invalid ownership modification for argument " << arg_mod.index << '(' << pyArgName << ')' << endl << endl; + break; + } + + if (arg_mod.index == 0 || arg_mod.owner.index == 0) + hasReturnPolicy = true; + + // The default ownership does nothing. This is useful to avoid automatic heuristically + // based generation of code defining parenting. + if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership) + continue; + + s << INDENT << "Shiboken::Object::"; + if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { + s << "getOwnership(" << pyArgName << ");"; + } else if (wrappedClass->hasVirtualDestructor()) { + if (arg_mod.index == 0) + s << "releaseOwnership(" PYTHON_RETURN_VAR ");"; + else + s << "releaseOwnership(" << pyArgName << ");"; + } else { + s << "invalidate(" << pyArgName << ");"; + } + s << endl; + } + + } else if (!refcount_mods.isEmpty()) { + for (const ArgumentModification &arg_mod : qAsConst(refcount_mods)) { + ReferenceCount refCount = arg_mod.referenceCounts.first(); + if (refCount.action != ReferenceCount::Set + && refCount.action != ReferenceCount::Remove + && refCount.action != ReferenceCount::Add) { + qCWarning(lcShiboken) << "\"set\", \"add\" and \"remove\" are the only values supported by Shiboken for action attribute of reference-count tag."; + continue; + } + const AbstractMetaClass* wrappedClass = 0; + + QString pyArgName; + if (refCount.action == ReferenceCount::Remove) { + pyArgName = QLatin1String("Py_None"); + } else { + pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass); + if (pyArgName.isEmpty()) { + s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl; + break; + } + } + + if (refCount.action == ReferenceCount::Add || refCount.action == ReferenceCount::Set) + s << INDENT << "Shiboken::Object::keepReference("; + else + s << INDENT << "Shiboken::Object::removeReference("; + + s << "reinterpret_cast(" PYTHON_SELF_VAR "), \""; + QString varName = arg_mod.referenceCounts.first().varName; + if (varName.isEmpty()) + varName = func->minimalSignature() + QString().number(arg_mod.index); + + s << varName << "\", " << pyArgName + << (refCount.action == ReferenceCount::Add ? ", true" : "") + << ");" << endl; + + if (arg_mod.index == 0) + hasReturnPolicy = true; + } + } + writeParentChildManagement(s, func, !hasReturnPolicy); +} + +QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass) +{ + QStringList result; + const AbstractMetaClassList &baseClases = getBaseClasses(metaClass); + if (!baseClases.isEmpty()) { + for (const AbstractMetaClass *baseClass : baseClases) { + result.append(QString::fromLatin1("((size_t) static_cast(class_ptr)) - base") + .arg(baseClass->qualifiedCppName())); + result.append(QString::fromLatin1("((size_t) static_cast((%2*)((void*)class_ptr))) - base") + .arg(baseClass->qualifiedCppName(), metaClass->qualifiedCppName())); + } + for (const AbstractMetaClass *baseClass : baseClases) + result.append(getAncestorMultipleInheritance(baseClass)); + } + return result; +} + +void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* 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 };" << endl; + s << "int*" << endl; + s << multipleInheritanceInitializerFunctionName(metaClass) << "(const void* cptr)" << endl; + s << '{' << endl; + s << INDENT << "if (mi_offsets[0] == -1) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "std::set offsets;" << endl; + s << INDENT << "std::set::iterator it;" << endl; + s << INDENT << "const " << className << "* class_ptr = reinterpret_cast(cptr);" << endl; + s << INDENT << "size_t base = (size_t) class_ptr;" << endl; + + for (const QString &ancestor : ancestors) + s << INDENT << "offsets.insert(" << ancestor << ");" << endl; + + s << endl; + s << INDENT << "offsets.erase(0);" << endl; + s << endl; + + s << INDENT << "int i = 0;" << endl; + s << INDENT << "for (it = offsets.begin(); it != offsets.end(); it++) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "mi_offsets[i] = *it;" << endl; + s << INDENT << "i++;" << endl; + } + s << INDENT << '}' << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "return mi_offsets;" << endl; + s << '}' << endl; +} + +void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString className = metaClass->qualifiedCppName(); + s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n"; + s << "{\n"; + s << INDENT << className << "* me = reinterpret_cast< ::" << className << "*>(obj);\n"; + bool firstClass = true; + const AbstractMetaClassList &allAncestors = getAllAncestors(metaClass); + for (const AbstractMetaClass *baseClass : allAncestors) { + s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; + Indentation indent(INDENT); + s << INDENT << "return static_cast< ::" << baseClass->qualifiedCppName() << "*>(me);\n"; + firstClass = false; + } + s << INDENT << "return me;\n"; + s << "}\n\n"; +} + +void CppGenerator::writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion) +{ + const TypeEntry* type = customConversion->ownerType(); + QString converter = converterObject(type); + s << INDENT << "// Register converter for type '" << type->qualifiedTargetLangName() << "'." << endl; + s << INDENT << converter << " = Shiboken::Conversions::createConverter("; + if (type->targetLangApiName() == type->name()) + s << '0'; + else if (type->targetLangApiName() == QLatin1String("PyObject")) + s << "&PyBaseObject_Type"; + else + s << '&' << type->targetLangApiName() << "_Type"; + QString typeName = fixedCppTypeName(type); + s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl; + s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << type->qualifiedCppName() << "\");" << endl; + writeCustomConverterRegister(s, customConversion, converter); +} + +void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum) +{ + if (metaEnum->isPrivate() || metaEnum->isAnonymous()) + return; + writeEnumConverterInitialization(s, metaEnum->typeEntry()); +} + +void CppGenerator::writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType) +{ + if (!enumType) + return; + QString enumFlagName = enumType->isFlags() ? QLatin1String("flag") : QLatin1String("enum"); + QString enumPythonType = cpythonTypeNameExt(enumType); + + const FlagsTypeEntry* flags = 0; + if (enumType->isFlags()) + flags = reinterpret_cast(enumType); + + s << INDENT << "// Register converter for " << enumFlagName << " '" << enumType->qualifiedCppName() << "'." << endl; + s << INDENT << '{' << endl; + { + Indentation indent(INDENT); + QString typeName = fixedCppTypeName(enumType); + s << INDENT << "SbkConverter* converter = Shiboken::Conversions::createConverter(" << enumPythonType << ',' << endl; + { + Indentation indent(INDENT); + s << INDENT << cppToPythonFunctionName(typeName, typeName) << ");" << endl; + } + + if (flags) { + QString enumTypeName = fixedCppTypeName(flags->originator()); + QString toCpp = pythonToCppFunctionName(enumTypeName, typeName); + QString isConv = convertibleToCppFunctionName(enumTypeName, typeName); + writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); + } + + QString toCpp = pythonToCppFunctionName(typeName, typeName); + QString isConv = convertibleToCppFunctionName(typeName, typeName); + writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); + + if (flags) { + QString toCpp = pythonToCppFunctionName(QLatin1String("number"), typeName); + QString isConv = convertibleToCppFunctionName(QLatin1String("number"), typeName); + writeAddPythonToCppConversion(s, QLatin1String("converter"), toCpp, isConv); + } + + s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; + s << INDENT << "Shiboken::Enum::setTypeConverter(" << enumPythonType << ", converter);" << endl; + QStringList cppSignature = enumType->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + while (!cppSignature.isEmpty()) { + QString signature = cppSignature.join(QLatin1String("::")); + s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \""; + if (flags) + s << "QFlags<"; + s << signature << "\");" << endl; + cppSignature.removeFirst(); + } + } + s << INDENT << '}' << endl; + + if (!flags) + writeEnumConverterInitialization(s, reinterpret_cast(enumType)->flags()); +} + +void CppGenerator::writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type) +{ + QByteArray cppSignature = QMetaObject::normalizedSignature(type->cppSignature().toUtf8()); + s << INDENT << "// Register converter for type '" << cppSignature << "'." << endl; + QString converter = converterObject(type); + s << INDENT << converter << " = Shiboken::Conversions::createConverter("; + if (type->typeEntry()->targetLangApiName() == QLatin1String("PyObject")) { + s << "&PyBaseObject_Type"; + } else { + QString baseName = cpythonBaseName(type->typeEntry()); + if (baseName == QLatin1String("PySequence")) + baseName = QLatin1String("PyList"); + s << '&' << baseName << "_Type"; + } + QString typeName = fixedCppTypeName(type); + s << ", " << cppToPythonFunctionName(typeName, typeName) << ");" << endl; + QString toCpp = pythonToCppFunctionName(typeName, typeName); + QString isConv = convertibleToCppFunctionName(typeName, typeName); + s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl; + if (usePySideExtensions() && cppSignature.startsWith("const ") && cppSignature.endsWith("&")) { + cppSignature.chop(1); + cppSignature.remove(0, sizeof("const ") / sizeof(char) - 1); + s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << cppSignature << "\");" << endl; + } + writeAddPythonToCppConversion(s, converterObject(type), toCpp, isConv); +} + +void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, + const QVector& conversions) +{ + s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + for (const AbstractMetaClass *sourceClass : conversions) { + const QString converterVar = QLatin1String("reinterpret_cast(") + + cppApiVariableName(externalType->targetLangPackage()) + QLatin1Char('[') + + getTypeIndexVariableName(externalType) + QLatin1String("])"); + QString sourceTypeName = fixedCppTypeName(sourceClass->typeEntry()); + QString targetTypeName = fixedCppTypeName(externalType); + QString toCpp = pythonToCppFunctionName(sourceTypeName, targetTypeName); + QString isConv = convertibleToCppFunctionName(sourceTypeName, targetTypeName); + writeAddPythonToCppConversion(s, converterVar, toCpp, isConv); + } +} + +QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass) +{ + if (!hasMultipleInheritanceInAncestry(metaClass)) + return QString(); + return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("_mi_init"); +} + +typedef QHash >::const_iterator ProtocolIt; + +bool CppGenerator::supportsMappingProtocol(const AbstractMetaClass* metaClass) +{ + for (ProtocolIt it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { + if (metaClass->hasFunction(it.key())) + return true; + } + + return false; +} + +bool CppGenerator::supportsNumberProtocol(const AbstractMetaClass* metaClass) +{ + return metaClass->hasArithmeticOperatorOverload() + || metaClass->hasLogicalOperatorOverload() + || metaClass->hasBitwiseOperatorOverload() + || hasBoolCast(metaClass); +} + +bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) +{ + for (ProtocolIt it = m_sequenceProtocol.cbegin(), end = m_sequenceProtocol.cend(); it != end; ++it) { + if (metaClass->hasFunction(it.key())) + return true; + } + + const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType(); + if (baseType && baseType->isContainer()) + return true; + + return false; +} + +bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass) +{ + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *f : fields) { + if (!f->isStatic()) + return true; + } + return false; +} + +void CppGenerator::writeClassDefinition(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &classContext) +{ + QString tp_flags; + QString tp_init; + QString tp_new; + QString tp_dealloc; + QString tp_hash(QLatin1Char('0')); + QString tp_call = tp_hash; + QString cppClassName = metaClass->qualifiedCppName(); + const QString className = chopType(cpythonTypeName(metaClass)); + QString baseClassName(QLatin1Char('0')); + AbstractMetaFunctionList ctors; + const AbstractMetaFunctionList &allCtors = metaClass->queryFunctions(AbstractMetaClass::Constructors); + for (AbstractMetaFunction *f : allCtors) { + if (!f->isPrivate() && !f->isModifiedRemoved() && !classContext.forSmartPointer()) + ctors.append(f); + } + + if (!metaClass->baseClass()) + baseClassName = QLatin1String("reinterpret_cast(&SbkObject_Type)"); + + bool onlyPrivCtor = !metaClass->hasNonPrivateConstructor(); + + if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { + tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); + tp_dealloc = metaClass->hasPrivateDestructor() ? + QLatin1String("SbkDeallocWrapperWithPrivateDtor") : QLatin1String("0"); + tp_init = QLatin1String("0"); + } else { + if (onlyPrivCtor) + tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); + else + tp_flags = QLatin1String("Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES|Py_TPFLAGS_HAVE_GC"); + + QString deallocClassName; + if (shouldGenerateCppWrapper(metaClass)) + deallocClassName = wrapperName(metaClass); + else + deallocClassName = cppClassName; + tp_dealloc = QLatin1String("&SbkDeallocWrapper"); + // avoid constFirst to stay Qt 5.5 compatible + tp_init = (onlyPrivCtor || ctors.isEmpty()) ? QLatin1String("0") : cpythonFunctionName(ctors.first()); + } + + QString tp_getattro(QLatin1Char('0')); + QString tp_setattro = tp_getattro; + if (usePySideExtensions() && (metaClass->qualifiedCppName() == QLatin1String("QObject"))) { + tp_getattro = cpythonGetattroFunctionName(metaClass); + tp_setattro = cpythonSetattroFunctionName(metaClass); + } else { + if (classNeedsGetattroFunction(metaClass)) + tp_getattro = cpythonGetattroFunctionName(metaClass); + if (classNeedsSetattroFunction(metaClass)) + tp_setattro = cpythonSetattroFunctionName(metaClass); + } + + if (metaClass->hasPrivateDestructor() || onlyPrivCtor) + tp_new = QLatin1String("0"); + else + tp_new = QLatin1String("SbkObjectTpNew"); + + QString tp_richcompare = QString(QLatin1Char('0')); + if (metaClass->hasComparisonOperatorOverload()) + tp_richcompare = cpythonBaseName(metaClass) + QLatin1String("_richcompare"); + + QString tp_getset = QString(QLatin1Char('0')); + if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) + tp_getset = cpythonGettersSettersDefinitionName(metaClass); + + // search for special functions + ShibokenGenerator::clearTpFuncs(); + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { + if (m_tpFuncs.contains(func->name())) + m_tpFuncs[func->name()] = cpythonFunctionName(func); + } + if (m_tpFuncs[QLatin1String("__repr__")] == QLatin1String("0") + && !metaClass->isQObject() + && metaClass->hasToStringCapability()) { + m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, classContext); + } + + // class or some ancestor has multiple inheritance + const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); + if (miClass) { + if (metaClass == miClass) + writeMultipleInheritanceInitializerFunction(s, metaClass); + writeSpecialCastFunction(s, metaClass); + s << endl; + } + + if (!metaClass->typeEntry()->hashFunction().isEmpty()) + tp_hash = QLatin1Char('&') + cpythonBaseName(metaClass) + QLatin1String("_HashFunc"); + + const AbstractMetaFunction* callOp = metaClass->findFunction(QLatin1String("operator()")); + if (callOp && !callOp->isModifiedRemoved()) + tp_call = QLatin1Char('&') + cpythonFunctionName(callOp); + + s << "// Class Definition -----------------------------------------------" << endl; + s << "extern \"C\" {" << endl; + + if (supportsNumberProtocol(metaClass)) { + s << "static PyNumberMethods " << className + QLatin1String("_TypeAsNumber") << ";" << endl; + s << endl; + } + + if (supportsSequenceProtocol(metaClass)) { + s << "static PySequenceMethods " << className + QLatin1String("_TypeAsSequence") << ";" << endl; + s << endl; + } + + if (supportsMappingProtocol(metaClass)) { + s << "static PyMappingMethods " << className + QLatin1String("_TypeAsMapping") << ";" << endl; + s << endl; + } + + s << "static SbkObjectType " << className + QLatin1String("_Type") << " = { { {" << endl; + s << INDENT << "PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)" << endl; + QString computedClassTargetFullName; + if (!classContext.forSmartPointer()) + computedClassTargetFullName = getClassTargetFullName(metaClass); + else + computedClassTargetFullName = getClassTargetFullName(classContext.preciseType()); + + s << INDENT << "/*tp_name*/ \"" << computedClassTargetFullName << "\"," << endl; + s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; + s << INDENT << "/*tp_itemsize*/ 0," << endl; + s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl; + s << INDENT << "/*tp_print*/ 0," << endl; + s << INDENT << "/*tp_getattr*/ 0," << endl; + s << INDENT << "/*tp_setattr*/ 0," << endl; + s << INDENT << "/*tp_compare*/ 0," << endl; + s << INDENT << "/*tp_repr*/ " << m_tpFuncs[QLatin1String("__repr__")] << "," << endl; + s << INDENT << "/*tp_as_number*/ 0," << endl; + s << INDENT << "/*tp_as_sequence*/ 0," << endl; + s << INDENT << "/*tp_as_mapping*/ 0," << endl; + s << INDENT << "/*tp_hash*/ " << tp_hash << ',' << endl; + s << INDENT << "/*tp_call*/ " << tp_call << ',' << endl; + s << INDENT << "/*tp_str*/ " << m_tpFuncs[QLatin1String("__str__")] << ',' << endl; + s << INDENT << "/*tp_getattro*/ " << tp_getattro << ',' << endl; + s << INDENT << "/*tp_setattro*/ " << tp_setattro << ',' << endl; + s << INDENT << "/*tp_as_buffer*/ 0," << endl; + s << INDENT << "/*tp_flags*/ " << tp_flags << ',' << endl; + s << INDENT << "/*tp_doc*/ 0," << endl; + s << INDENT << "/*tp_traverse*/ " << className << "_traverse," << endl; + s << INDENT << "/*tp_clear*/ " << className << "_clear," << endl; + s << INDENT << "/*tp_richcompare*/ " << tp_richcompare << ',' << endl; + s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; + s << INDENT << "/*tp_iter*/ " << m_tpFuncs[QLatin1String("__iter__")] << ',' << endl; + s << INDENT << "/*tp_iternext*/ " << m_tpFuncs[QLatin1String("__next__")] << ',' << endl; + s << INDENT << "/*tp_methods*/ " << className << "_methods," << endl; + s << INDENT << "/*tp_members*/ 0," << endl; + s << INDENT << "/*tp_getset*/ " << tp_getset << ',' << endl; + s << INDENT << "/*tp_base*/ " << baseClassName << ',' << endl; + s << INDENT << "/*tp_dict*/ 0," << endl; + s << INDENT << "/*tp_descr_get*/ 0," << endl; + s << INDENT << "/*tp_descr_set*/ 0," << endl; + s << INDENT << "/*tp_dictoffset*/ 0," << endl; + s << INDENT << "/*tp_init*/ " << tp_init << ',' << endl; + s << INDENT << "/*tp_alloc*/ 0," << endl; + s << INDENT << "/*tp_new*/ " << tp_new << ',' << endl; + s << INDENT << "/*tp_free*/ 0," << endl; + s << INDENT << "/*tp_is_gc*/ 0," << endl; + s << INDENT << "/*tp_bases*/ 0," << endl; + s << INDENT << "/*tp_mro*/ 0," << endl; + s << INDENT << "/*tp_cache*/ 0," << endl; + s << INDENT << "/*tp_subclasses*/ 0," << endl; + s << INDENT << "/*tp_weaklist*/ 0" << endl; + s << "}, }," << endl; + s << INDENT << "/*priv_data*/ 0" << endl; + s << "};" << endl; + QString suffix; + if (isObjectType(metaClass)) + suffix = QLatin1String("*"); + s << "} //extern" << endl; +} + +void CppGenerator::writeMappingMethods(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &context) +{ + + QMap funcs; + + QHash< QString, QPair< QString, QString > >::const_iterator it = m_mappingProtocol.begin(); + for (; it != m_mappingProtocol.end(); ++it) { + const AbstractMetaFunction* func = metaClass->findFunction(it.key()); + if (!func) + continue; + QString funcName = cpythonFunctionName(func); + QString funcArgs = it.value().first; + QString funcRetVal = it.value().second; + + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); + s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; + writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); + + writeCppSelfDefinition(s, func, context); + + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); + s << '}' << endl << endl; + } +} + +void CppGenerator::writeSequenceMethods(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &context) +{ + + QMap funcs; + bool injectedCode = false; + + QHash< QString, QPair< QString, QString > >::const_iterator it = m_sequenceProtocol.begin(); + for (; it != m_sequenceProtocol.end(); ++it) { + const AbstractMetaFunction* func = metaClass->findFunction(it.key()); + if (!func) + continue; + injectedCode = true; + QString funcName = cpythonFunctionName(func); + QString funcArgs = it.value().first; + QString funcRetVal = it.value().second; + + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); + s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl; + writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR)); + + writeCppSelfDefinition(s, func, context); + + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg); + s << '}' << endl << endl; + } + + if (!injectedCode) + writeStdListWrapperMethods(s, context); +} + +void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass) +{ + bool hasFunctions = false; + QMap funcs; + for (ProtocolIt it = m_sequenceProtocol.cbegin(), end = m_sequenceProtocol.cend(); it != end; ++it) { + const QString &funcName = it.key(); + const AbstractMetaFunction* func = metaClass->findFunction(funcName); + funcs[funcName] = func ? cpythonFunctionName(func).prepend(QLatin1Char('&')) : QString(); + if (!hasFunctions && func) + hasFunctions = true; + } + + QString baseName = cpythonBaseName(metaClass); + + //use default implementation + if (!hasFunctions) { + funcs[QLatin1String("__len__")] = baseName + QLatin1String("__len__"); + funcs[QLatin1String("__getitem__")] = baseName + QLatin1String("__getitem__"); + funcs[QLatin1String("__setitem__")] = baseName + QLatin1String("__setitem__"); + } + + s << INDENT << "memset(&" << baseName << "_TypeAsSequence, 0, sizeof(PySequenceMethods));" << endl; + for (QHash::const_iterator it = m_sqFuncs.cbegin(), end = m_sqFuncs.cend(); it != end; ++it) { + const QString& sqName = it.key(); + if (funcs[sqName].isEmpty()) + continue; + if (it.value() == QLatin1String("sq_slice")) + s << "#ifndef IS_PY3K" << endl; + s << INDENT << baseName << "_TypeAsSequence." << it.value() << " = " << funcs[sqName] << ';' << endl; + if (it.value() == QLatin1String("sq_slice")) + s << "#endif" << endl; + } +} + +void CppGenerator::writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass) +{ + bool hasFunctions = false; + QMap funcs; + for (ProtocolIt it = m_mappingProtocol.cbegin(), end = m_mappingProtocol.cend(); it != end; ++it) { + const QString &funcName = it.key(); + const AbstractMetaFunction* func = metaClass->findFunction(funcName); + funcs[funcName] = func ? cpythonFunctionName(func).prepend(QLatin1Char('&')) : QLatin1String("0"); + if (!hasFunctions && func) + hasFunctions = true; + } + + //use default implementation + if (!hasFunctions) { + funcs.insert(QLatin1String("__mlen__"), QString()); + funcs.insert(QLatin1String("__mgetitem__"), QString()); + funcs.insert(QLatin1String("__msetitem__"), QString()); + } + + QString baseName = cpythonBaseName(metaClass); + s << INDENT << "memset(&" << baseName << "_TypeAsMapping, 0, sizeof(PyMappingMethods));" << endl; + for (QHash::const_iterator it = m_mpFuncs.cbegin(), end = m_mpFuncs.end(); it != end; ++it) { + const QString &mpName = it.key(); + if (funcs[mpName].isEmpty()) + continue; + s << INDENT << baseName << "_TypeAsMapping." << it.value() << " = " << funcs[mpName] << ';' << endl; + } +} + +void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QMap nb; + + nb.insert(QLatin1String("__add__"), QString()); + nb.insert(QLatin1String("__sub__"), QString()); + nb.insert(QLatin1String("__mul__"), QString()); + nb.insert(QLatin1String("__div__"), QString()); + nb.insert(QLatin1String("__mod__"), QString()); + nb.insert(QLatin1String("__neg__"), QString()); + nb.insert(QLatin1String("__pos__"), QString()); + nb.insert(QLatin1String("__invert__"), QString()); + nb.insert(QLatin1String("__lshift__"), QString()); + nb.insert(QLatin1String("__rshift__"), QString()); + nb.insert(QLatin1String("__and__"), QString()); + nb.insert(QLatin1String("__xor__"), QString()); + nb.insert(QLatin1String("__or__"), QString()); + nb.insert(QLatin1String("__iadd__"), QString()); + nb.insert(QLatin1String("__isub__"), QString()); + nb.insert(QLatin1String("__imul__"), QString()); + nb.insert(QLatin1String("__idiv__"), QString()); + nb.insert(QLatin1String("__imod__"), QString()); + nb.insert(QLatin1String("__ilshift__"), QString()); + nb.insert(QLatin1String("__irshift__"), QString()); + nb.insert(QLatin1String("__iand__"), QString()); + nb.insert(QLatin1String("__ixor__"), QString()); + nb.insert(QLatin1String("__ior__"), QString()); + + const QVector opOverloads = + filterGroupedOperatorFunctions(metaClass, + AbstractMetaClass::ArithmeticOp + | AbstractMetaClass::LogicalOp + | AbstractMetaClass::BitwiseOp); + + for (const AbstractMetaFunctionList &opOverload : opOverloads) { + const AbstractMetaFunction* rfunc = opOverload[0]; + QString opName = ShibokenGenerator::pythonOperatorFunctionName(rfunc); + nb[opName] = cpythonFunctionName(rfunc); + } + + QString baseName = cpythonBaseName(metaClass); + + nb[QLatin1String("bool")] = hasBoolCast(metaClass) ? baseName + QLatin1String("___nb_bool") : QString(); + + s << INDENT << "memset(&" << baseName << "_TypeAsNumber, 0, sizeof(PyNumberMethods));" << endl; + for (QHash::const_iterator it = m_nbFuncs.cbegin(), end = m_nbFuncs.cend(); it != end; ++it) { + const QString &nbName = it.key(); + if (nb[nbName].isEmpty()) + continue; + + // bool is special because the field name differs on Python 2 and 3 (nb_nonzero vs nb_bool) + // so a shiboken macro is used. + if (nbName == QLatin1String("bool")) { + s << INDENT << "SBK_NB_BOOL(" << baseName << "_TypeAsNumber) = " << nb[nbName] << ';' << endl; + } else { + bool excludeFromPy3K = nbName == QLatin1String("__div__") || nbName == QLatin1String("__idiv__"); + if (excludeFromPy3K) { + s << "#ifdef IS_PY3K" << endl; + s << INDENT << "SBK_UNUSED(&" << nb[nbName] << ");" << endl; + s << "#else" << endl; + } + s << INDENT << baseName << "_TypeAsNumber." << it.value() << " = " << nb[nbName] << ';' << endl; + if (excludeFromPy3K) + s << "#endif" << endl; + } + } + if (!nb[QLatin1String("__div__")].isEmpty()) + s << INDENT << baseName << "_TypeAsNumber.nb_true_divide = " << nb[QLatin1String("__div__")] << ';' << endl; +} + +void CppGenerator::writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString baseName = cpythonBaseName(metaClass); + s << "static int "; + s << baseName << "_traverse(PyObject* " PYTHON_SELF_VAR ", visitproc visit, void* arg)" << endl; + s << '{' << endl; + s << INDENT << "return reinterpret_cast(&SbkObject_Type)->tp_traverse(" PYTHON_SELF_VAR ", visit, arg);" << endl; + s << '}' << endl; +} + +void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString baseName = cpythonBaseName(metaClass); + s << "static int "; + s << baseName << "_clear(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << '{' << endl; + s << INDENT << "return reinterpret_cast(&SbkObject_Type)->tp_clear(" PYTHON_SELF_VAR ");" << endl; + s << '}' << endl; +} + +void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + const QString className = chopType(cpythonTypeName(metaClass)); + s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << "{" << endl; + writeCppSelfDefinition(s, context, false, true); + QString conversionCode; + if (!context.forSmartPointer()) + conversionCode = cpythonToPythonConversionFunction(metaClass); + else + conversionCode = cpythonToPythonConversionFunction(context.preciseType()); + + s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << conversionCode; + s << CPP_SELF_VAR ");" << endl; + writeFunctionReturnErrorCheckSection(s); + s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; + s << "}" << endl; + s << endl; +} + +void CppGenerator::writeGetterFunction(QTextStream &s, + const AbstractMetaField *metaField, + GeneratorContext &context) +{ + ErrorCode errorCode(0); + s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", void*)" << endl; + s << '{' << endl; + + writeCppSelfDefinition(s, context); + + AbstractMetaType* fieldType = metaField->type(); + // Force use of pointer to return internal variable memory + bool newWrapperSameObject = !fieldType->isConstant() && isWrapperType(fieldType) && !isPointer(fieldType); + + QString cppField; + if (avoidProtectedHack() && metaField->isProtected()) { + cppField = QString::fromLatin1("((%1*)%2)->%3()") + .arg(wrapperName(metaField->enclosingClass()), QLatin1String(CPP_SELF_VAR), + protectedFieldGetterName(metaField)); + } else { + cppField = QLatin1String(CPP_SELF_VAR) + QLatin1String("->") + metaField->name(); + if (newWrapperSameObject) { + cppField.prepend(QLatin1String("&(")); + cppField.append(QLatin1Char(')')); + } + } + if (isCppIntegralPrimitive(fieldType) || fieldType->isEnum()) { + s << INDENT << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl; + cppField = QLatin1String("cppOut_local"); + } else if (avoidProtectedHack() && metaField->isProtected()) { + s << INDENT << getFullTypeNameWithoutModifiers(fieldType); + if (fieldType->isContainer() || fieldType->isFlags() || fieldType->isSmartPointer()) { + s << '&'; + cppField.prepend(QLatin1Char('*')); + } else if ((!fieldType->isConstant() && !fieldType->isEnum() && !fieldType->isPrimitive()) || fieldType->indirections() == 1) { + s << '*'; + } + s << " fieldValue = " << cppField << ';' << endl; + cppField = QLatin1String("fieldValue"); + } + + s << INDENT << "PyObject* pyOut = 0;\n"; + if (newWrapperSameObject) { + // Special case colocated field with same address (first field in a struct) + s << INDENT << "if (reinterpret_cast(" + << cppField + << ") == reinterpret_cast(" + << CPP_SELF_VAR << ")) {\n"; + { + Indentation indent(INDENT); + s << INDENT << "pyOut = reinterpret_cast(Shiboken::Object::findColocatedChild(" + << "reinterpret_cast(self), reinterpret_cast(" + << cpythonTypeNameExt(fieldType) + << ")));\n"; + s << INDENT << "if (pyOut) {Py_IncRef(pyOut); return pyOut;}\n"; + } + s << INDENT << "}\n"; + // Check if field wrapper has already been created. + s << INDENT << "else if (Shiboken::BindingManager::instance().hasWrapper(" << cppField << ")) {" << "\n"; + { + Indentation indent(INDENT); + s << INDENT << "pyOut = (PyObject*)Shiboken::BindingManager::instance().retrieveWrapper(" << cppField << ");" << "\n"; + s << INDENT << "Py_IncRef(pyOut);" << "\n"; + s << INDENT << "return pyOut;" << "\n"; + } + s << INDENT << "}\n"; + // Create and register new wrapper + s << INDENT << "pyOut = "; + s << "Shiboken::Object::newObject(reinterpret_cast(" << cpythonTypeNameExt(fieldType) + << "), " << cppField << ", false, true);" << endl; + s << INDENT << "Shiboken::Object::setParent(" PYTHON_SELF_VAR ", pyOut)"; + } else { + s << INDENT << "pyOut = "; + writeToPythonConversion(s, fieldType, metaField->enclosingClass(), cppField); + } + s << ';' << endl; + + s << INDENT << "return pyOut;" << endl; + s << '}' << endl; +} + +void CppGenerator::writeSetterFunction(QTextStream &s, + const AbstractMetaField *metaField, + GeneratorContext &context) +{ + ErrorCode errorCode(0); + s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* pyIn, void*)" << endl; + s << '{' << endl; + + writeCppSelfDefinition(s, context); + + s << INDENT << "if (pyIn == 0) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_TypeError, \"'"; + s << metaField->name() << "' may not be deleted\");" << endl; + s << INDENT << "return -1;" << endl; + } + s << INDENT << '}' << endl; + + AbstractMetaType* fieldType = metaField->type(); + + s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl; + s << INDENT << "if (!"; + writeTypeCheck(s, fieldType, QLatin1String("pyIn"), isNumber(fieldType->typeEntry())); + s << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_TypeError, \"wrong type attributed to '"; + s << metaField->name() << "', '" << fieldType->name() << "' or convertible type expected\");" << endl; + s << INDENT << "return -1;" << endl; + } + s << INDENT << '}' << endl << endl; + + QString cppField = QString::fromLatin1("%1->%2").arg(QLatin1String(CPP_SELF_VAR), metaField->name()); + s << INDENT; + if (avoidProtectedHack() && metaField->isProtected()) { + s << getFullTypeNameWithoutModifiers(fieldType); + s << (fieldType->indirections() == 1 ? "*" : "") << " cppOut;" << endl; + s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut);" << endl; + s << INDENT << QString::fromLatin1("((%1*)%2)->%3(cppOut)") + .arg(wrapperName(metaField->enclosingClass()), + QLatin1String(CPP_SELF_VAR), protectedFieldSetterName(metaField)); + } else if (isCppIntegralPrimitive(fieldType) || fieldType->typeEntry()->isEnum() || fieldType->typeEntry()->isFlags()) { + s << getFullTypeNameWithoutModifiers(fieldType) << " cppOut_local = " << cppField << ';' << endl; + s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_local);" << endl; + s << INDENT << cppField << " = cppOut_local"; + } else { + s << getFullTypeNameWithoutModifiers(fieldType); + s << QString::fromLatin1("*").repeated(fieldType->indirections()) << "& cppOut_ptr = "; + s << cppField << ';' << endl; + s << INDENT << PYTHON_TO_CPP_VAR << "(pyIn, &cppOut_ptr)"; + } + s << ';' << endl << endl; + + if (isPointerToWrapperType(fieldType)) { + s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast(" PYTHON_SELF_VAR "), \""; + s << metaField->name() << "\", pyIn);" << endl; + } + + s << INDENT << "return 0;" << endl; + s << '}' << endl; +} + +void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + QString baseName = cpythonBaseName(metaClass); + s << "static PyObject* "; + s << baseName << "_richcompare(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ", int op)" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, context, false, true); + writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR)); + s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; + s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR << ';' << endl; + writeUnusedVariableCast(s, QLatin1String(PYTHON_TO_CPP_VAR)); + s << endl; + + s << INDENT << "switch (op) {" << endl; + { + Indentation indent(INDENT); + const QVector &groupedFuncs = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); + for (const AbstractMetaFunctionList &overloads : groupedFuncs) { + const AbstractMetaFunction* rfunc = overloads[0]; + + QString operatorId = ShibokenGenerator::pythonRichCompareOperatorId(rfunc); + s << INDENT << "case " << operatorId << ':' << endl; + + Indentation indent(INDENT); + + QString op = rfunc->originalName(); + op = op.right(op.size() - QLatin1String("operator").size()); + + int alternativeNumericTypes = 0; + for (const AbstractMetaFunction *func : overloads) { + if (!func->isStatic() && + ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry())) + alternativeNumericTypes++; + } + + bool first = true; + OverloadData overloadData(overloads, this); + const OverloadDataList &nextOverloads = overloadData.nextOverloadData(); + for (OverloadData *od : nextOverloads) { + const AbstractMetaFunction* func = od->referenceFunction(); + if (func->isStatic()) + continue; + const AbstractMetaType* argType = getArgumentType(func, 1); + if (!argType) + continue; + if (!first) { + s << " else "; + } else { + first = false; + s << INDENT; + } + s << "if ("; + writeTypeCheck(s, argType, QLatin1String(PYTHON_ARG), alternativeNumericTypes == 1 || isPyInt(argType)); + s << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "// " << func->signature() << endl; + writeArgumentConversion(s, argType, QLatin1String(CPP_ARG0), + QLatin1String(PYTHON_ARG), metaClass, + QString(), func->isUserAdded()); + + // If the function is user added, use the inject code + if (func->isUserAdded()) { + CodeSnipList snips = func->injectedCodeSnips(); + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, func->arguments().last()); + } else { + QString expression = QString::fromLatin1("%1%2 %3 (%4" CPP_ARG0 ")") + .arg(func->isPointerOperator() ? QLatin1String("&") : QString(), + QLatin1String(CPP_SELF_VAR), op, + shouldDereferenceAbstractMetaTypePointer(argType) ? QLatin1String("*") : QString()); + s << INDENT; + if (func->type()) + s << func->type()->cppSignature() << " " CPP_RETURN_VAR " = "; + s << expression << ';' << endl; + s << INDENT << PYTHON_RETURN_VAR " = "; + if (func->type()) + writeToPythonConversion(s, func->type(), metaClass, QLatin1String(CPP_RETURN_VAR)); + else + s << "Py_None;" << endl << INDENT << "Py_INCREF(Py_None)"; + s << ';' << endl; + } + } + s << INDENT << '}'; + } + + s << " else {" << endl; + if (operatorId == QLatin1String("Py_EQ") || operatorId == QLatin1String("Py_NE")) { + Indentation indent(INDENT); + s << INDENT << PYTHON_RETURN_VAR " = " + << (operatorId == QLatin1String("Py_EQ") ? "Py_False" : "Py_True") << ';' << endl; + s << INDENT << "Py_INCREF(" PYTHON_RETURN_VAR ");" << endl; + } else { + Indentation indent(INDENT); + s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl; + } + s << INDENT << '}' << endl << endl; + + s << INDENT << "break;" << endl; + } + s << INDENT << "default:" << endl; + { + Indentation indent(INDENT); + s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl; + } + } + s << INDENT << '}' << endl << endl; + + s << INDENT << "if (" PYTHON_RETURN_VAR " && !PyErr_Occurred())" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; + } + s << INDENT << baseName << "_RichComparison_TypeError:" << endl; + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; + s << '}' << endl << endl; +} + +void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads) +{ + Q_ASSERT(!overloads.isEmpty()); + OverloadData overloadData(overloads, this); + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); + const AbstractMetaFunction* func = overloadData.referenceFunction(); + int min = overloadData.minArgs(); + int max = overloadData.maxArgs(); + + s << '"' << func->name() << "\", (PyCFunction)" << cpythonFunctionName(func) << ", "; + if ((min == max) && (max < 2) && !usePyArgs) { + if (max == 0) + s << "METH_NOARGS"; + else + s << "METH_O"; + } else { + s << "METH_VARARGS"; + if (overloadData.hasArgumentWithDefaultValue()) + s << "|METH_KEYWORDS"; + } + if (func->ownerClass() && overloadData.hasStaticFunction()) + s << "|METH_STATIC"; +} + +void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads) +{ + Q_ASSERT(!overloads.isEmpty()); + const AbstractMetaFunction* func = overloads.first(); + if (m_tpFuncs.contains(func->name())) + return; + + s << INDENT; + if (OverloadData::hasStaticAndInstanceFunctions(overloads)) { + s << cpythonMethodDefinitionName(func); + } else { + s << '{'; + writeMethodDefinitionEntry(s, overloads); + s << '}'; + } + s << ',' << endl; +} + +void CppGenerator::writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums) +{ + if (enums.isEmpty()) + return; + s << INDENT << "// Initialization of enums." << endl << endl; + for (const AbstractMetaEnum *cppEnum : qAsConst(enums)) { + if (cppEnum->isPrivate()) + continue; + writeEnumInitialization(s, cppEnum); + } +} + +void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum); + const AbstractMetaClass* upper = enclosingClass ? enclosingClass->enclosingClass() : 0; + bool hasUpperEnclosingClass = upper && upper->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + QString enclosingObjectVariable; + if (enclosingClass) + enclosingObjectVariable = QLatin1Char('&') + cpythonTypeName(enclosingClass); + else if (hasUpperEnclosingClass) + enclosingObjectVariable = QLatin1String("enclosingClass"); + else + enclosingObjectVariable = QLatin1String("module"); + + s << INDENT << "// Initialization of "; + s << (cppEnum->isAnonymous() ? "anonymous enum identified by enum value" : "enum"); + s << " '" << cppEnum->name() << "'." << endl; + + if (!cppEnum->isAnonymous()) { + FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); + if (flags) { + s << INDENT << cpythonTypeNameExt(flags) << " = PySide::QFlags::create(\"" << flags->flagsName() << "\", &" + << cpythonEnumName(cppEnum) << "_as_number);" << endl; + } + + s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = Shiboken::Enum::"; + s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnum" : "createGlobalEnum"); + s << '(' << enclosingObjectVariable << ',' << endl; + { + Indentation indent(INDENT); + s << INDENT << '"' << cppEnum->name() << "\"," << endl; + s << INDENT << '"' << getClassTargetFullName(cppEnum) << "\"," << endl; + s << INDENT << '"' << (cppEnum->enclosingClass() ? (cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::")) : QString()); + s << cppEnum->name() << '"'; + if (flags) + s << ',' << endl << INDENT << cpythonTypeNameExt(flags); + s << ");" << endl; + } + s << INDENT << "if (!" << cpythonTypeNameExt(cppEnum->typeEntry()) << ')' << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; + } + } + + const AbstractMetaEnumValueList &enumValues = cppEnum->values(); + for (const AbstractMetaEnumValue *enumValue : enumValues) { + if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) + continue; + + QString enumValueText; + if (!avoidProtectedHack() || !cppEnum->isProtected()) { + enumValueText = QLatin1String("(long) "); + if (cppEnum->enclosingClass()) + enumValueText += cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::"); + enumValueText += enumValue->name(); + } else { + enumValueText += QString::number(enumValue->value()); + } + + if (cppEnum->isAnonymous()) { + if (enclosingClass || hasUpperEnclosingClass) { + s << INDENT << '{' << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl; + s << INDENT << "if (PyDict_SetItemString(reinterpret_cast(" << enclosingObjectVariable + << ")->super.ht_type.tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << "Py_DECREF(anonEnumItem);" << endl; + } + s << INDENT << '}' << endl; + } else { + s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", "; + s << enumValueText << ") < 0)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + } + } else { + s << INDENT << "if (!Shiboken::Enum::"; + s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); + s << '(' << cpythonTypeNameExt(cppEnum->typeEntry()) << ',' << endl; + Indentation indent(INDENT); + s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", "; + s << enumValueText << "))" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + } + + writeEnumConverterInitialization(s, cppEnum); + + s << INDENT << "// End of '" << cppEnum->name() << "' enum"; + if (cppEnum->typeEntry()->flags()) + s << "/flags"; + s << '.' << endl << endl; +} + +void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) +{ + // Try to check something and print some warnings + const AbstractMetaFunctionList &signalFuncs = metaClass->cppSignalFunctions(); + for (const AbstractMetaFunction *cppSignal : signalFuncs) { + if (cppSignal->declaringClass() != metaClass) + continue; + const AbstractMetaArgumentList &arguments = cppSignal->arguments(); + for (AbstractMetaArgument *arg : arguments) { + AbstractMetaType* metaType = arg->type(); + const QByteArray origType = + QMetaObject::normalizedType(qPrintable(metaType->originalTypeDescription())); + const QByteArray cppSig = + QMetaObject::normalizedType(qPrintable(metaType->cppSignature())); + if ((origType != cppSig) && (!metaType->isFlags())) { + qCWarning(lcShiboken).noquote().nospace() + << "Typedef used on signal " << metaClass->qualifiedCppName() << "::" + << cppSignal->signature(); + } + } + } + + s << INDENT << "PySide::Signal::registerSignals(&" << cpythonTypeName(metaClass) << ", &::" + << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl; +} + +void CppGenerator::writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); + if (!flagsEntry) + return; + s << "static PyObject* " << cpythonEnumName(cppEnum) << "_long(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << "{" << endl; + s << INDENT << "int val;" << endl; + AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); + s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl; + s << INDENT << "return Shiboken::Conversions::copyToPython(Shiboken::Conversions::PrimitiveTypeConverter(), &val);" << endl; + s << "}" << endl; +} + +void CppGenerator::writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); + if (!flagsEntry) + return; + s << "static int " << cpythonEnumName(cppEnum) << "__nonzero(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << "{" << endl; + + s << INDENT << "int val;" << endl; + AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); + s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &val);" << endl; + s << INDENT << "return val != 0;" << endl; + s << "}" << endl; +} + +void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + writeFlagsBinaryOperator(s, cppEnum, QLatin1String("and"), QLatin1String("&")); + writeFlagsBinaryOperator(s, cppEnum, QLatin1String("or"), QLatin1String("|")); + writeFlagsBinaryOperator(s, cppEnum, QLatin1String("xor"), QLatin1String("^")); + + writeFlagsUnaryOperator(s, cppEnum, QLatin1String("invert"), QLatin1String("~")); + writeFlagsToLong(s, cppEnum); + writeFlagsNonZero(s, cppEnum); + + s << endl; +} + +void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + QString cpythonName = cpythonEnumName(cppEnum); + + s << "static PyNumberMethods " << cpythonName << "_as_number = {" << endl; + s << INDENT << "/*nb_add*/ 0," << endl; + s << INDENT << "/*nb_subtract*/ 0," << endl; + s << INDENT << "/*nb_multiply*/ 0," << endl; + s << INDENT << "#ifndef IS_PY3K" << endl; + s << INDENT << "/* nb_divide */ 0," << endl; + s << INDENT << "#endif" << endl; + s << INDENT << "/*nb_remainder*/ 0," << endl; + s << INDENT << "/*nb_divmod*/ 0," << endl; + s << INDENT << "/*nb_power*/ 0," << endl; + s << INDENT << "/*nb_negative*/ 0," << endl; + s << INDENT << "/*nb_positive*/ 0," << endl; + s << INDENT << "/*nb_absolute*/ 0," << endl; + s << INDENT << "/*nb_nonzero*/ " << cpythonName << "__nonzero," << endl; + s << INDENT << "/*nb_invert*/ (unaryfunc)" << cpythonName << "___invert__," << endl; + s << INDENT << "/*nb_lshift*/ 0," << endl; + s << INDENT << "/*nb_rshift*/ 0," << endl; + s << INDENT << "/*nb_and*/ (binaryfunc)" << cpythonName << "___and__," << endl; + s << INDENT << "/*nb_xor*/ (binaryfunc)" << cpythonName << "___xor__," << endl; + s << INDENT << "/*nb_or*/ (binaryfunc)" << cpythonName << "___or__," << endl; + s << INDENT << "#ifndef IS_PY3K" << endl; + s << INDENT << "/* nb_coerce */ 0," << endl; + s << INDENT << "#endif" << endl; + s << INDENT << "/*nb_int*/ " << cpythonName << "_long," << endl; + s << INDENT << "#ifdef IS_PY3K" << endl; + s << INDENT << "/*nb_reserved*/ 0," << endl; + s << INDENT << "/*nb_float*/ 0," << endl; + s << INDENT << "#else" << endl; + s << INDENT << "/*nb_long*/ " << cpythonName << "_long," << endl; + s << INDENT << "/*nb_float*/ 0," << endl; + s << INDENT << "/*nb_oct*/ 0," << endl; + s << INDENT << "/*nb_hex*/ 0," << endl; + s << INDENT << "#endif" << endl; + s << INDENT << "/*nb_inplace_add*/ 0," << endl; + s << INDENT << "/*nb_inplace_subtract*/ 0," << endl; + s << INDENT << "/*nb_inplace_multiply*/ 0," << endl; + s << INDENT << "#ifndef IS_PY3K" << endl; + s << INDENT << "/*nb_inplace_divide*/ 0," << endl; + s << INDENT << "#endif" << endl; + s << INDENT << "/*nb_inplace_remainder*/ 0," << endl; + s << INDENT << "/*nb_inplace_power*/ 0," << endl; + s << INDENT << "/*nb_inplace_lshift*/ 0," << endl; + s << INDENT << "/*nb_inplace_rshift*/ 0," << endl; + s << INDENT << "/*nb_inplace_and*/ 0," << endl; + s << INDENT << "/*nb_inplace_xor*/ 0," << endl; + s << INDENT << "/*nb_inplace_or*/ 0," << endl; + s << INDENT << "/*nb_floor_divide*/ 0," << endl; + s << INDENT << "/*nb_true_divide*/ 0," << endl; + s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl; + s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl; + s << INDENT << "/*nb_index*/ 0" << endl; + s << "};" << endl << endl; +} + +void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, + QString pyOpName, QString cppOpName) +{ + FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); + Q_ASSERT(flagsEntry); + + s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl; + s << '{' << endl; + + AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); + s << INDENT << "::" << flagsEntry->originalName() << " cppResult, " CPP_SELF_VAR ", cppArg;" << endl; + s << "#ifdef IS_PY3K" << endl; + s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_SELF_VAR ");" << endl; + s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyLong_AsLong(" PYTHON_ARG ");" << endl; + s << "#else" << endl; + s << INDENT << CPP_SELF_VAR " = (::" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_SELF_VAR ");" << endl; + s << INDENT << "cppArg = (" << flagsEntry->originalName() << ")(int)PyInt_AsLong(" PYTHON_ARG ");" << endl; + s << "#endif" << endl << endl; + s << INDENT << "cppResult = " CPP_SELF_VAR " " << cppOpName << " cppArg;" << endl; + s << INDENT << "return "; + writeToPythonConversion(s, flagsType, 0, QLatin1String("cppResult")); + s << ';' << endl; + s << '}' << endl << endl; +} + +void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, + QString pyOpName, QString cppOpName, bool boolResult) +{ + FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags(); + Q_ASSERT(flagsEntry); + + s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ")" << endl; + s << '{' << endl; + + AbstractMetaType* flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); + s << INDENT << "::" << flagsEntry->originalName() << " " CPP_SELF_VAR ";" << endl; + s << INDENT << cpythonToCppConversionFunction(flagsType) << PYTHON_SELF_VAR << ", &" CPP_SELF_VAR ");" << endl; + s << INDENT; + if (boolResult) + s << "bool"; + else + s << "::" << flagsEntry->originalName(); + s << " cppResult = " << cppOpName << CPP_SELF_VAR ";" << endl; + s << INDENT << "return "; + if (boolResult) + s << "PyBool_FromLong(cppResult)"; + else + writeToPythonConversion(s, flagsType, 0, QLatin1String("cppResult")); + s << ';' << endl; + s << '}' << endl << endl; +} + +QString CppGenerator::getInitFunctionName(GeneratorContext &context) const +{ + QString initFunctionName; + if (!context.forSmartPointer()) { + initFunctionName = context.metaClass()->qualifiedCppName(); + initFunctionName.replace(QLatin1String("::"), QLatin1String("_")); + } else { + initFunctionName = getFilteredCppSignatureString(context.preciseType()->cppSignature()); + } + return initFunctionName; +} + +void CppGenerator::writeClassRegister(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &classContext) +{ + const ComplexTypeEntry* classTypeEntry = metaClass->typeEntry(); + + const AbstractMetaClass* enc = metaClass->enclosingClass(); + bool hasEnclosingClass = enc && enc->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass; + QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module"); + + QString pyTypeName = cpythonTypeName(metaClass); + QString initFunctionName = getInitFunctionName(classContext); + s << "void init_" << initFunctionName; + s << "(PyObject* " << enclosingObjectVariable << ")" << endl; + s << '{' << endl; + + if (supportsNumberProtocol(metaClass)) { + s << INDENT << "// type has number operators" << endl; + writeTypeAsNumberDefinition(s, metaClass); + s << INDENT << pyTypeName << ".super.ht_type.tp_as_number = &" << pyTypeName << "AsNumber;" << endl; + s << endl; + } + + if (supportsSequenceProtocol(metaClass)) { + s << INDENT << "// type supports sequence protocol" << endl; + writeTypeAsSequenceDefinition(s, metaClass); + s << INDENT << pyTypeName << ".super.ht_type.tp_as_sequence = &" << pyTypeName << "AsSequence;" << endl; + s << endl; + } + + if (supportsMappingProtocol(metaClass)) { + s << INDENT << "// type supports mapping protocol" << endl; + writeTypeAsMappingDefinition(s, metaClass); + s << INDENT << pyTypeName << ".super.ht_type.tp_as_mapping = &" << pyTypeName << "AsMapping;" << endl; + s << endl; + } + + if (!classContext.forSmartPointer()) + s << INDENT << cpythonTypeNameExt(classTypeEntry); + else + s << INDENT << cpythonTypeNameExt(classContext.preciseType()); + + s << " = reinterpret_cast(&" << pyTypeName << ");" << endl; + s << endl; + + // Multiple inheritance + QString pyTypeBasesVariable = pyTypeName + QLatin1String("_bases"); + const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); + if (metaClass->baseClassNames().size() > 1) { + s << INDENT << "PyObject* " << pyTypeBasesVariable << " = PyTuple_Pack(" << baseClasses.size() << ',' << endl; + QStringList bases; + for (const AbstractMetaClass *base : baseClasses) + bases << QLatin1String("(PyObject*)") + cpythonTypeNameExt(base->typeEntry()); + Indentation indent(INDENT); + QString separator; + QTextStream sep(&separator); + sep << "," << endl << INDENT; + s << INDENT << bases.join(separator) << ");" << endl << endl; + } + + // Create type and insert it in the module or enclosing class. + s << INDENT << "if (!Shiboken::ObjectType::introduceWrapperType(" << enclosingObjectVariable; + QString typeName; + if (!classContext.forSmartPointer()) + typeName = metaClass->name(); + else + typeName = classContext.preciseType()->cppSignature(); + + s << ", \"" << typeName << "\", \""; + + // Original name + if (!classContext.forSmartPointer()) + s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : ""); + else + s << classContext.preciseType()->cppSignature(); + + s << "\"," << endl; + { + Indentation indent(INDENT); + s << INDENT << "&" << pyTypeName; + + // Set destructor function + if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { + QString dtorClassName = metaClass->qualifiedCppName(); + if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue()) + dtorClassName = wrapperName(metaClass); + if (classContext.forSmartPointer()) + dtorClassName = wrapperName(classContext.preciseType()); + + s << ", &Shiboken::callCppDestructor< ::" << dtorClassName << " >"; + } else if (metaClass->baseClass() || hasEnclosingClass) { + s << ", 0"; + } + + // Base type + if (metaClass->baseClass()) { + s << ", reinterpret_cast(" << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ')'; + // The other base types + if (metaClass->baseClassNames().size() > 1) + s << ", " << pyTypeBasesVariable; + else if (hasEnclosingClass) + s << ", 0"; + } else if (hasEnclosingClass) { + s << ", 0, 0"; + } + if (hasEnclosingClass) + s << ", true"; + s << ")) {" << endl; + s << INDENT << "return;" << endl; + } + s << INDENT << '}' << endl << endl; + + // Register conversions for the type. + writeConverterRegister(s, metaClass, classContext); + s << endl; + + // class inject-code target/beginning + if (!classTypeEntry->codeSnips().isEmpty()) { + writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode, metaClass); + s << endl; + } + + // Fill multiple inheritance data, if needed. + const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); + if (miClass) { + s << INDENT << "MultipleInheritanceInitFunction func = "; + if (miClass == metaClass) { + s << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl; + } else { + s << "Shiboken::ObjectType::getMultipleIheritanceFunction(reinterpret_cast("; + s << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; + } + s << INDENT << "Shiboken::ObjectType::setMultipleIheritanceFunction(&"; + s << cpythonTypeName(metaClass) << ", func);" << endl; + s << INDENT << "Shiboken::ObjectType::setCastFunction(&" << cpythonTypeName(metaClass); + s << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; + } + + // Set typediscovery struct or fill the struct of another one + if (metaClass->isPolymorphic() && metaClass->baseClass()) { + s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunctionV2(&" << cpythonTypeName(metaClass); + s << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl << endl; + } + + AbstractMetaEnumList classEnums = metaClass->enums(); + const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); + for (AbstractMetaClass *innerClass : innerClasses) + lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + + ErrorCode errorCode(QString::null); + writeEnumsInitialization(s, classEnums); + + if (metaClass->hasSignals()) + writeSignalInitialization(s, metaClass); + + // Write static fields + const AbstractMetaFieldList &fields = metaClass->fields(); + for (const AbstractMetaField *field : fields) { + if (!field->isStatic()) + continue; + s << INDENT << QLatin1String("PyDict_SetItemString(") + cpythonTypeName(metaClass) + QLatin1String(".super.ht_type.tp_dict, \""); + s << field->name() << "\", "; + writeToPythonConversion(s, field->type(), metaClass, metaClass->qualifiedCppName() + QLatin1String("::") + field->name()); + s << ");" << endl; + } + s << endl; + + // class inject-code target/end + if (!classTypeEntry->codeSnips().isEmpty()) { + s << endl; + writeCodeSnips(s, classTypeEntry->codeSnips(), TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode, metaClass); + } + + if (usePySideExtensions()) { + if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass)) + s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n"; + else + writeInitQtMetaTypeFunctionBody(s, classContext); + } + + if (usePySideExtensions() && metaClass->isQObject()) { + s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(&" << pyTypeName << ", &PySide::initQObjectSubType);" << endl; + s << INDENT << "PySide::initDynamicMetaObject(&" << pyTypeName << ", &::" << metaClass->qualifiedCppName() + << "::staticMetaObject, sizeof(::" << metaClass->qualifiedCppName() << "));" << endl; + } + + s << '}' << endl; +} + +void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const +{ + const AbstractMetaClass* metaClass = context.metaClass(); + // Gets all class name variants used on different possible scopes + QStringList nameVariants; + if (!context.forSmartPointer()) + nameVariants << metaClass->name(); + else + nameVariants << context.preciseType()->cppSignature(); + + const AbstractMetaClass* enclosingClass = metaClass->enclosingClass(); + while (enclosingClass) { + if (enclosingClass->typeEntry()->generateCode()) + nameVariants << (enclosingClass->name() + QLatin1String("::") + nameVariants.last()); + enclosingClass = enclosingClass->enclosingClass(); + } + + QString className; + if (!context.forSmartPointer()) + className = metaClass->qualifiedCppName(); + else + className = context.preciseType()->cppSignature(); + + if (!metaClass->isNamespace() && !metaClass->isAbstract()) { + // Qt metatypes are registered only on their first use, so we do this now. + bool canBeValue = false; + if (!isObjectType(metaClass)) { + // check if there's a empty ctor + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { + if (func->isConstructor() && !func->arguments().count()) { + canBeValue = true; + break; + } + } + } + + if (canBeValue) { + for (const QString &name : qAsConst(nameVariants)) { + if (name == QLatin1String("iterator")) { + qCWarning(lcShiboken).noquote().nospace() + << QString::fromLatin1("%1:%2 FIXME:\n" + " The code tried to qRegisterMetaType the unqualified name " + "'iterator'. This is currently fixed by a hack(ct) and needs improvement!") + .arg(QFile::decodeName(__FILE__)).arg(__LINE__); + continue; + } + s << INDENT << "qRegisterMetaType< ::" << className << " >(\"" << name << "\");" << endl; + } + } + } + + const AbstractMetaEnumList &enums = metaClass->enums(); + for (AbstractMetaEnum *metaEnum : enums) { + if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) { + for (const QString &name : qAsConst(nameVariants)) + s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << name << "::" << metaEnum->name() << "\");" << endl; + + if (metaEnum->typeEntry()->flags()) { + QString n = metaEnum->typeEntry()->flags()->originalName(); + s << INDENT << "qRegisterMetaType< ::" << n << " >(\"" << n << "\");" << endl; + } + } + } +} + +void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); + + s << "static void* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl; + + if (!polymorphicExpr.isEmpty()) { + polymorphicExpr = polymorphicExpr.replace(QLatin1String("%1"), + QLatin1String(" reinterpret_cast< ::") + + metaClass->qualifiedCppName() + + QLatin1String("*>(cptr)")); + s << INDENT << " if (" << polymorphicExpr << ")" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return cptr;" << endl; + } + } else if (metaClass->isPolymorphic()) { + const AbstractMetaClassList &ancestors = getAllAncestors(metaClass); + for (AbstractMetaClass *ancestor : ancestors) { + if (ancestor->baseClass()) + continue; + if (ancestor->isPolymorphic()) { + s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType< ::" + << ancestor->qualifiedCppName() << " >()))" << endl; + Indentation indent(INDENT); + s << INDENT << "return dynamic_cast< ::" << metaClass->qualifiedCppName() + << "*>(reinterpret_cast< ::"<< ancestor->qualifiedCppName() << "*>(cptr));" << endl; + } else { + qCWarning(lcShiboken).noquote().nospace() + << metaClass->qualifiedCppName() << " inherits from a non polymorphic type (" + << ancestor->qualifiedCppName() << "), type discovery based on RTTI is " + "impossible, write a polymorphic-id-expression for this type."; + } + + } + } + s << INDENT << "return 0;" << endl; + s << "}\n\n"; +} + +QString CppGenerator::writeSmartPointerGetterCast() { + return QLatin1String("const_cast(" SMART_POINTER_GETTER ")"); +} + +void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass* metaClass = context.metaClass(); + s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name, PyObject* value)" << endl; + s << '{' << endl; + if (usePySideExtensions()) { + s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast(PySide::Property::getObject(" PYTHON_SELF_VAR ", name)));" << endl; + s << INDENT << "if (!pp.isNull())" << endl; + Indentation indent(INDENT); + s << INDENT << "return PySide::Property::setValue(reinterpret_cast(pp.object()), " PYTHON_SELF_VAR ", value);" << endl; + } + + if (context.forSmartPointer()) { + s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer." << endl; + s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", " + << writeSmartPointerGetterCast() << ", 0);" << endl; + s << INDENT << "if (rawObj) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "int hasAttribute = PyObject_HasAttr(rawObj, name);" << endl; + s << INDENT << "if (hasAttribute) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return PyObject_GenericSetAttr(rawObj, name, value);" << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "Py_DECREF(rawObj);" << endl; + } + s << INDENT << '}' << endl; + + } + + s << INDENT << "return PyObject_GenericSetAttr(" PYTHON_SELF_VAR ", name, value);" << endl; + s << '}' << endl; +} + +static inline QString qObjectClassName() { return QStringLiteral("QObject"); } +static inline QString qMetaObjectClassName() { return QStringLiteral("QMetaObject"); } + +void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &context) +{ + const AbstractMetaClass* metaClass = context.metaClass(); + s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name)" << endl; + s << '{' << endl; + + QString getattrFunc; + if (usePySideExtensions() && metaClass->isQObject()) { + AbstractMetaClass *qobjectClass = AbstractMetaClass::findClass(classes(), qObjectClassName()); + getattrFunc = QString::fromLatin1("PySide::getMetaDataFromQObject(%1, " PYTHON_SELF_VAR ", name)") + .arg(cpythonWrapperCPtr(qobjectClass, QLatin1String(PYTHON_SELF_VAR))); + } else { + getattrFunc = QLatin1String("PyObject_GenericGetAttr(" PYTHON_SELF_VAR ", name)"); + } + + if (classNeedsGetattroFunction(metaClass)) { + s << INDENT << "if (" PYTHON_SELF_VAR ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "// Search the method in the instance dict" << endl; + s << INDENT << "if (reinterpret_cast(" PYTHON_SELF_VAR ")->ob_dict) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast(" PYTHON_SELF_VAR ")->ob_dict, name);" << endl; + s << INDENT << "if (meth) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Py_INCREF(meth);" << endl; + s << INDENT << "return meth;" << endl; + } + s << INDENT << '}' << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "// Search the method in the type dict" << endl; + s << INDENT << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ")) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* meth = PyDict_GetItem(" PYTHON_SELF_VAR "->ob_type->tp_dict, name);" << endl; + s << INDENT << "if (meth)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return PyFunction_Check(meth) ? SBK_PyMethod_New(meth, " PYTHON_SELF_VAR ") : " << getattrFunc << ';' << endl; + } + } + s << INDENT << '}' << endl; + + const AbstractMetaFunctionList &funcs = getMethodsWithBothStaticAndNonStaticMethods(metaClass); + for (const AbstractMetaFunction *func : funcs) { + QString defName = cpythonMethodDefinitionName(func); + s << INDENT << "static PyMethodDef non_static_" << defName << " = {" << endl; + { + Indentation indent(INDENT); + s << INDENT << defName << ".ml_name," << endl; + s << INDENT << defName << ".ml_meth," << endl; + s << INDENT << defName << ".ml_flags & (~METH_STATIC)," << endl; + s << INDENT << defName << ".ml_doc," << endl; + } + s << INDENT << "};" << endl; + s << INDENT << "if (Shiboken::String::compare(name, \"" << func->name() << "\") == 0)" << endl; + Indentation indent(INDENT); + s << INDENT << "return PyCFunction_NewEx(&non_static_" << defName << ", " PYTHON_SELF_VAR ", 0);" << endl; + } + } + s << INDENT << '}' << endl; + } + + if (context.forSmartPointer()) { + s << INDENT << "PyObject *tmp = " << getattrFunc << ';' << endl; + s << INDENT << "if (tmp) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return tmp;" << endl; + } + s << INDENT << "} else {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL;" << endl; + s << INDENT << "PyErr_Clear();" << endl; + + s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for " + "the corresponding C++ object held by the smart pointer." << endl; + s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", " + << writeSmartPointerGetterCast() << ", 0);" << endl; + s << INDENT << "if (rawObj) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject *attribute = PyObject_GetAttr(rawObj, name);" << endl; + s << INDENT << "if (attribute) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "tmp = attribute;" << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "Py_DECREF(rawObj);" << endl; + } + s << INDENT << '}' << endl; + s << INDENT << "if (!tmp) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl; + s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl; + s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl; + s << INDENT << " tp->tp_name, PyBytes_AS_STRING(name));" << endl; + s << INDENT << "return NULL;" << endl; + } + s << INDENT << "} else {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return tmp;" << endl; + } + s << INDENT << '}' << endl; + + } + s << INDENT << '}' << endl; + + } else { + s << INDENT << "return " << getattrFunc << ';' << endl; + } + s << '}' << endl; +} + +bool CppGenerator::finishGeneration() +{ + //Generate CPython wrapper file + QString classInitDecl; + QTextStream s_classInitDecl(&classInitDecl); + QString classPythonDefines; + QTextStream s_classPythonDefines(&classPythonDefines); + + QSet includes; + QString globalFunctionImpl; + QTextStream s_globalFunctionImpl(&globalFunctionImpl); + QString globalFunctionDecl; + QTextStream s_globalFunctionDef(&globalFunctionDecl); + + Indentation indent(INDENT); + + const FunctionGroupMap &functionGroups = getFunctionGroups(); + for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + AbstractMetaFunctionList overloads; + for (AbstractMetaFunction *func : it.value()) { + if (!func->isModifiedRemoved()) { + overloads.append(func); + if (func->typeEntry()) + includes << func->typeEntry()->include(); + } + } + + if (overloads.isEmpty()) + continue; + + // Dummy context to satisfy the API. + GeneratorContext classContext; + writeMethodWrapper(s_globalFunctionImpl, overloads, classContext); + writeMethodDefinition(s_globalFunctionDef, overloads); + } + + //this is a temporary solution before new type revison implementation + //We need move QMetaObject register before QObject + Dependencies additionalDependencies; + const AbstractMetaClassList &allClasses = classes(); + if (AbstractMetaClass::findClass(allClasses, qObjectClassName()) != Q_NULLPTR + && AbstractMetaClass::findClass(allClasses, qMetaObjectClassName()) != Q_NULLPTR) { + Dependency dependency; + dependency.parent = qMetaObjectClassName(); + dependency.child = qObjectClassName(); + additionalDependencies.append(dependency); + } + const AbstractMetaClassList lst = classesTopologicalSorted(additionalDependencies); + + for (const AbstractMetaClass *cls : lst){ + if (!shouldGenerate(cls)) + continue; + + s_classInitDecl << "void init_" << cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")) << "(PyObject* module);" << endl; + + QString defineStr = QLatin1String("init_") + cls->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_")); + + if (cls->enclosingClass() && (cls->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)) + defineStr += QLatin1Char('(') + cpythonTypeNameExt(cls->enclosingClass()->typeEntry()) + QLatin1String("->tp_dict);"); + else + defineStr += QLatin1String("(module);"); + s_classPythonDefines << INDENT << defineStr << endl; + } + + // Initialize smart pointer types. + const QVector &smartPtrs = instantiatedSmartPointers(); + for (const AbstractMetaType *metaType : smartPtrs) { + GeneratorContext context(0, metaType, true); + QString initFunctionName = getInitFunctionName(context); + s_classInitDecl << "void init_" << initFunctionName << "(PyObject* module);" << endl; + QString defineStr = QLatin1String("init_") + initFunctionName; + defineStr += QLatin1String("(module);"); + s_classPythonDefines << INDENT << defineStr << endl; + } + + QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName())); + moduleFileName += QLatin1Char('/') + moduleName().toLower() + QLatin1String("_module_wrapper.cpp"); + + QFile file(moduleFileName); + verifyDirectoryFor(file); + if (!file.open(QFile::WriteOnly)) { + qCWarning(lcShiboken).noquote().nospace() + << "Error writing file: " << QDir::toNativeSeparators(moduleFileName); + return false; + } + + QTextStream s(&file); + + // write license comment + s << licenseComment() << endl; + + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + if (usePySideExtensions()) { + s << includeQDebug; + s << "#include " << endl; + } + + s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl; + for (const Include &include : qAsConst(includes)) + s << include; + s << endl; + + // Global enums + AbstractMetaEnumList globalEnums = this->globalEnums(); + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { + const AbstractMetaClass* encClass = metaClass->enclosingClass(); + if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) + continue; + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + } + + TypeDatabase* typeDb = TypeDatabase::instance(); + TypeSystemTypeEntry* moduleEntry = reinterpret_cast(typeDb->findType(packageName())); + + //Extra includes + s << endl << "// Extra includes" << endl; + QVector extraIncludes; + if (moduleEntry) + extraIncludes = moduleEntry->extraIncludes(); + for (AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) + extraIncludes.append(cppEnum->typeEntry()->extraIncludes()); + qSort(extraIncludes.begin(), extraIncludes.end()); + for (const Include &inc : qAsConst(extraIncludes)) + s << inc; + s << endl; + + s << "// Current module's type array." << endl; + s << "PyTypeObject** " << cppApiVariableName() << ';' << endl; + + s << "// Current module's converter array." << endl; + s << "SbkConverter** " << convertersVariableName() << ';' << endl; + + CodeSnipList snips; + if (moduleEntry) + snips = moduleEntry->codeSnips(); + + // module inject-code native/beginning + if (!snips.isEmpty()) { + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode); + s << endl; + } + + // cleanup staticMetaObject attribute + if (usePySideExtensions()) { + s << "void cleanTypesAttributes(void) {" << endl; + s << INDENT << "for (int i = 0, imax = SBK_" << moduleName() << "_IDX_COUNT; i < imax; i++) {" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "PyObject *pyType = reinterpret_cast(" << cppApiVariableName() << "[i]);" << endl; + s << INDENT << "if (pyType && PyObject_HasAttrString(pyType, \"staticMetaObject\"))"<< endl; + { + Indentation indentation(INDENT); + s << INDENT << "PyObject_SetAttrString(pyType, \"staticMetaObject\", Py_None);" << endl; + } + } + s << INDENT << "}" << endl; + s << "}" << endl; + } + + s << "// Global functions "; + s << "------------------------------------------------------------" << endl; + s << globalFunctionImpl << endl; + + s << "static PyMethodDef " << moduleName() << "_methods[] = {" << endl; + s << globalFunctionDecl; + s << INDENT << "{0} // Sentinel" << endl << "};" << endl << endl; + + s << "// Classes initialization functions "; + s << "------------------------------------------------------------" << endl; + s << classInitDecl << endl; + + if (!globalEnums.isEmpty()) { + QString converterImpl; + QTextStream convImpl(&converterImpl); + + s << "// Enum definitions "; + s << "------------------------------------------------------------" << endl; + for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) + continue; + writeEnumConverterFunctions(s, cppEnum); + s << endl; + } + + if (!converterImpl.isEmpty()) { + s << "// Enum converters "; + s << "------------------------------------------------------------" << endl; + s << "namespace Shiboken" << endl << '{' << endl; + s << converterImpl << endl; + s << "} // namespace Shiboken" << endl << endl; + } + } + + const QStringList &requiredModules = typeDb->requiredTargetImports(); + if (!requiredModules.isEmpty()) + s << "// Required modules' type and converter arrays." << endl; + for (const QString &requiredModule : requiredModules) { + s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ';' << endl; + s << "SbkConverter** " << convertersVariableName(requiredModule) << ';' << endl; + } + s << endl; + + s << "// Module initialization "; + s << "------------------------------------------------------------" << endl; + ExtendedConverterData extendedConverters = getExtendedConverters(); + if (!extendedConverters.isEmpty()) { + s << endl << "// Extended Converters." << endl << endl; + for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { + const TypeEntry *externalType = it.key(); + s << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl; + for (const AbstractMetaClass *sourceClass : it.value()) { + AbstractMetaType* sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass); + AbstractMetaType* targetType = buildAbstractMetaTypeFromTypeEntry(externalType); + writePythonToCppConversionFunctions(s, sourceType, targetType); + } + } + } + + const QVector &typeConversions = getPrimitiveCustomConversions(); + if (!typeConversions.isEmpty()) { + s << endl << "// Primitive Type converters." << endl << endl; + for (const CustomConversion *conversion : typeConversions) { + s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl; + writeCppToPythonFunction(s, conversion); + writeCustomConverterFunctions(s, conversion); + } + s << endl; + } + + const QVector &containers = instantiatedContainers(); + if (!containers.isEmpty()) { + s << "// Container Type converters." << endl << endl; + for (const AbstractMetaType *container : containers) { + s << "// C++ to Python conversion for type '" << container->cppSignature() << "'." << endl; + writeContainerConverterFunctions(s, container); + } + s << endl; + } + + s << "#if defined _WIN32 || defined __CYGWIN__" << endl; + s << " #define SBK_EXPORT_MODULE __declspec(dllexport)" << endl; + s << "#elif __GNUC__ >= 4" << endl; + s << " #define SBK_EXPORT_MODULE __attribute__ ((visibility(\"default\")))" << endl; + s << "#else" << endl; + s << " #define SBK_EXPORT_MODULE" << endl; + s << "#endif" << endl << endl; + + s << "#ifdef IS_PY3K" << endl; + s << "static struct PyModuleDef moduledef = {" << endl; + s << " /* m_base */ PyModuleDef_HEAD_INIT," << endl; + s << " /* m_name */ \"" << moduleName() << "\"," << endl; + s << " /* m_doc */ 0," << endl; + s << " /* m_size */ -1," << endl; + s << " /* m_methods */ " << moduleName() << "_methods," << endl; + s << " /* m_reload */ 0," << endl; + s << " /* m_traverse */ 0," << endl; + s << " /* m_clear */ 0," << endl; + s << " /* m_free */ 0" << endl; + s << "};" << endl << endl; + s << "#endif" << endl; + s << "SBK_MODULE_INIT_FUNCTION_BEGIN(" << moduleName() << ")" << endl; + + ErrorCode errorCode(QLatin1String("SBK_MODULE_INIT_ERROR")); + // module inject-code target/beginning + if (!snips.isEmpty()) { + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionBeginning, TypeSystem::TargetLangCode); + s << endl; + } + + for (const QString& requiredModule : requiredModules) { + s << INDENT << "{" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "Shiboken::AutoDecRef requiredModule(Shiboken::Module::import(\"" << requiredModule << "\"));" << endl; + s << INDENT << "if (requiredModule.isNull())" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return SBK_MODULE_INIT_ERROR;" << endl; + } + s << INDENT << cppApiVariableName(requiredModule) << " = Shiboken::Module::getTypes(requiredModule);" << endl; + s << INDENT << convertersVariableName(requiredModule) << " = Shiboken::Module::getTypeConverters(requiredModule);" << endl; + } + s << INDENT << "}" << endl << endl; + } + + int maxTypeIndex = getMaxTypeIndex() + instantiatedSmartPointers().size(); + if (maxTypeIndex) { + s << INDENT << "// Create an array of wrapper types for the current module." << endl; + s << INDENT << "static PyTypeObject* cppApi[SBK_" << moduleName() << "_IDX_COUNT];" << endl; + s << INDENT << cppApiVariableName() << " = cppApi;" << endl << endl; + } + + s << INDENT << "// Create an array of primitive type converters for the current module." << endl; + s << INDENT << "static SbkConverter* sbkConverters[SBK_" << moduleName() << "_CONVERTERS_IDX_COUNT" << "];" << endl; + s << INDENT << convertersVariableName() << " = sbkConverters;" << endl << endl; + + s << "#ifdef IS_PY3K" << endl; + s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", &moduledef);" << endl; + s << "#else" << endl; + s << INDENT << "PyObject* module = Shiboken::Module::create(\"" << moduleName() << "\", "; + s << moduleName() << "_methods);" << endl; + s << "#endif" << endl << endl; + + //s << INDENT << "// Initialize converters for primitive types." << endl; + //s << INDENT << "initConverters();" << endl << endl; + + s << INDENT << "// Initialize classes in the type system" << endl; + s << classPythonDefines; + + if (!typeConversions.isEmpty()) { + s << endl; + for (const CustomConversion *conversion : typeConversions) { + writePrimitiveConverterInitialization(s, conversion); + s << endl; + } + } + + if (!containers.isEmpty()) { + s << endl; + for (const AbstractMetaType *container : containers) { + writeContainerConverterInitialization(s, container); + s << endl; + } + } + + if (!extendedConverters.isEmpty()) { + s << endl; + for (ExtendedConverterData::const_iterator it = extendedConverters.cbegin(), end = extendedConverters.cend(); it != end; ++it) { + writeExtendedConverterInitialization(s, it.key(), it.value()); + s << endl; + } + } + + writeEnumsInitialization(s, globalEnums); + + s << INDENT << "// Register primitive types converters." << endl; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *pte : primitiveTypeList) { + if (!pte->generateCode() || !pte->isCppPrimitive()) + continue; + const TypeEntry *referencedType = pte->basicReferencedTypeEntry(); + if (!referencedType) + continue; + QString converter = converterObject(referencedType); + QStringList cppSignature = pte->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + while (!cppSignature.isEmpty()) { + QString signature = cppSignature.join(QLatin1String("::")); + s << INDENT << "Shiboken::Conversions::registerConverterName(" << converter << ", \"" << signature << "\");" << endl; + cppSignature.removeFirst(); + } + } + // Register type resolver for all containers found in signals. + QSet typeResolvers; + + for (AbstractMetaClass *metaClass : classList) { + if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode()) + continue; + const AbstractMetaFunctionList &functions = metaClass->functions(); + for (AbstractMetaFunction *func : functions) { + if (func->isSignal()) { + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + if (arg->type()->isContainer()) { + QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference); + if (value.startsWith(QLatin1String("::"))) + value.remove(0, 2); + typeResolvers << QMetaObject::normalizedType(value.toUtf8().constData()); + } + } + } + } + } + + s << endl; + if (maxTypeIndex) + s << INDENT << "Shiboken::Module::registerTypes(module, " << cppApiVariableName() << ");" << endl; + s << INDENT << "Shiboken::Module::registerTypeConverters(module, " << convertersVariableName() << ");" << endl; + + s << endl << INDENT << "if (PyErr_Occurred()) {" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "PyErr_Print();" << endl; + s << INDENT << "Py_FatalError(\"can't initialize module " << moduleName() << "\");" << endl; + } + s << INDENT << '}' << endl; + + // module inject-code target/end + if (!snips.isEmpty()) { + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::TargetLangCode); + s << endl; + } + + // module inject-code native/end + if (!snips.isEmpty()) { + writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionEnd, TypeSystem::NativeCode); + s << endl; + } + + if (usePySideExtensions()) { + for (AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) + if (!metaEnum->isAnonymous()) { + s << INDENT << "qRegisterMetaType< ::" << metaEnum->typeEntry()->qualifiedCppName() << " >(\"" << metaEnum->name() << "\");" << endl; + } + + // cleanup staticMetaObject attribute + s << INDENT << "PySide::registerCleanupFunction(cleanTypesAttributes);" << endl; + } + + s << "SBK_MODULE_INIT_FUNCTION_END" << endl; + + return true; +} + +static ArgumentOwner getArgumentOwner(const AbstractMetaFunction* func, int argIndex) +{ + ArgumentOwner argOwner = func->argumentOwner(func->ownerClass(), argIndex); + if (argOwner.index == ArgumentOwner::InvalidIndex) + argOwner = func->argumentOwner(func->declaringClass(), argIndex); + return argOwner; +} + +bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy) +{ + const int numArgs = func->arguments().count(); + bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy; + + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this)); + + ArgumentOwner argOwner = getArgumentOwner(func, argIndex); + ArgumentOwner::Action action = argOwner.action; + int parentIndex = argOwner.index; + int childIndex = argIndex; + if (ctorHeuristicEnabled && argIndex > 0 && numArgs) { + AbstractMetaArgument* arg = func->arguments().at(argIndex-1); + if (arg->name() == QLatin1String("parent") && isObjectType(arg->type())) { + action = ArgumentOwner::Add; + parentIndex = argIndex; + childIndex = -1; + } + } + + QString parentVariable; + QString childVariable; + if (action != ArgumentOwner::Invalid) { + if (!usePyArgs && argIndex > 1) + qCWarning(lcShiboken).noquote().nospace() + << "Argument index for parent tag out of bounds: " << func->signature(); + + if (action == ArgumentOwner::Remove) { + parentVariable = QLatin1String("Py_None"); + } else { + if (parentIndex == 0) { + parentVariable = QLatin1String(PYTHON_RETURN_VAR); + } else if (parentIndex == -1) { + parentVariable = QLatin1String(PYTHON_SELF_VAR); + } else { + parentVariable = usePyArgs + ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(parentIndex - 1) + : QLatin1String(PYTHON_ARG); + } + } + + if (childIndex == 0) { + childVariable = QLatin1String(PYTHON_RETURN_VAR); + } else if (childIndex == -1) { + childVariable = QLatin1String(PYTHON_SELF_VAR); + } else { + childVariable = usePyArgs + ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(childIndex - 1) + : QLatin1String(PYTHON_ARG); + } + + s << INDENT << "Shiboken::Object::setParent(" << parentVariable << ", " << childVariable << ");\n"; + return true; + } + + return false; +} + +void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn) +{ + const int numArgs = func->arguments().count(); + + // -1 = return value + // 0 = self + // 1..n = func. args. + for (int i = -1; i <= numArgs; ++i) + writeParentChildManagement(s, func, i, useHeuristicForReturn); + + if (useHeuristicForReturn) + writeReturnValueHeuristics(s, func); +} + +void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self) +{ + AbstractMetaType *type = func->type(); + if (!useReturnValueHeuristic() + || !func->ownerClass() + || !type + || func->isStatic() + || func->isConstructor() + || !func->typeReplaced(0).isEmpty()) { + return; + } + + ArgumentOwner argOwner = getArgumentOwner(func, ArgumentOwner::ReturnIndex); + if (argOwner.action == ArgumentOwner::Invalid || argOwner.index != ArgumentOwner::ThisIndex) { + if (isPointerToWrapperType(type)) + s << INDENT << "Shiboken::Object::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; + } +} + +void CppGenerator::writeHashFunction(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject* self) {" << endl; + writeCppSelfDefinition(s, context); + s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '('; + s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");" << endl; + s << '}' << endl << endl; +} + +void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + ErrorCode errorCode(0); + + // __len__ + s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* " PYTHON_SELF_VAR ")" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, context); + s << INDENT << "return " CPP_SELF_VAR "->size();" << endl; + s << '}' << endl; + + // __getitem__ + s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i)" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, context); + writeIndexError(s, QLatin1String("index out of bounds")); + + s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl; + s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl; + + const AbstractMetaType* itemType = metaClass->templateBaseClassInstantiations().first(); + + s << INDENT << "return "; + writeToPythonConversion(s, itemType, metaClass, QLatin1String("*_item")); + s << ';' << endl; + s << '}' << endl; + + // __setitem__ + ErrorCode errorCode2(-1); + s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* pyArg)" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, context); + writeIndexError(s, QLatin1String("list assignment index out of range")); + + s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl; + s << INDENT << "if (!"; + writeTypeCheck(s, itemType, QLatin1String("pyArg"), isNumber(itemType->typeEntry())); + s << ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_TypeError, \"attributed value with wrong type, '"; + s << itemType->name() << "' or other convertible type expected\");" << endl; + s << INDENT << "return -1;" << endl; + } + s << INDENT << '}' << endl; + writeArgumentConversion(s, itemType, QLatin1String("cppValue"), QLatin1String("pyArg"), metaClass); + + s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl; + s << INDENT << "for (Py_ssize_t pos = 0; pos < _i; pos++) _item++;" << endl; + s << INDENT << "*_item = cppValue;" << endl; + s << INDENT << "return 0;" << endl; + s << '}' << endl; +} +void CppGenerator::writeIndexError(QTextStream& s, const QString& errorMsg) +{ + s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) " CPP_SELF_VAR "->size()) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_SetString(PyExc_IndexError, \"" << errorMsg << "\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } + s << INDENT << '}' << endl; +} + +QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &context) +{ + const AbstractMetaClass *metaClass = context.metaClass(); + QString funcName = cpythonBaseName(metaClass) + QLatin1String("__repr__"); + s << "extern \"C\"" << endl; + s << '{' << endl; + s << "static PyObject* " << funcName << "(PyObject* self)" << endl; + s << '{' << endl; + writeCppSelfDefinition(s, context); + s << INDENT << "QBuffer buffer;" << endl; + s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl; + s << INDENT << "QDebug dbg(&buffer);" << endl; + s << INDENT << "dbg << " << (metaClass->typeEntry()->isValue() ? "*" : "") << CPP_SELF_VAR ";" << endl; + s << INDENT << "buffer.close();" << endl; + s << INDENT << "QByteArray str = buffer.data();" << endl; + s << INDENT << "int idx = str.indexOf('(');" << endl; + s << INDENT << "if (idx >= 0)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "str.replace(0, idx, Py_TYPE(self)->tp_name);" << endl; + } + s << INDENT << "PyObject* mod = PyDict_GetItemString(Py_TYPE(self)->tp_dict, \"__module__\");" << endl; + s << INDENT << "if (mod)" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return Shiboken::String::fromFormat(\"<%s.%s at %p>\", Shiboken::String::toCString(mod), str.constData(), self);" << endl; + } + s << INDENT << "else" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return Shiboken::String::fromFormat(\"<%s at %p>\", str.constData(), self);" << endl; + } + s << '}' << endl; + s << "} // extern C" << endl << endl;; + return funcName; +} diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.h b/sources/shiboken2/generator/shiboken2/cppgenerator.h new file mode 100644 index 000000000..c3ca48307 --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.h @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CPPGENERATOR_H +#define CPPGENERATOR_H + +#include "shibokengenerator.h" + +/** + * The CppGenerator generate the implementations of C++ bindings classes. + */ +class CppGenerator : public ShibokenGenerator +{ +public: + CppGenerator(); +protected: + QString fileNamePrefix() const override; + QString fileNameForContext(GeneratorContext &context) const override; + QVector filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass, + uint query); + void generateClass(QTextStream& s, GeneratorContext &classContext) override; + bool finishGeneration() override; + +private: + void writeConstructorNative(QTextStream& s, const AbstractMetaFunction* func); + void writeDestructorNative(QTextStream& s, const AbstractMetaClass* metaClass); + + QString getVirtualFunctionReturnTypeName(const AbstractMetaFunction* func); + void writeVirtualMethodNative(QTextStream& s, const AbstractMetaFunction* func); + + void writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass* metaClass); + void writeMetaCast(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType); + void writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum); + void writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass, + GeneratorContext &classContext); + void writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion); + void writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass, + GeneratorContext &classContext); + void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar); + void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar); + + void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType); + + void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData, + GeneratorContext &context); + void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, GeneratorContext &classContext); + void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass); + void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, + GeneratorContext &classContext); + void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData); + void writeCppSelfDefinition(QTextStream &s, + const AbstractMetaFunction *func, + GeneratorContext &context, + bool hasStaticOverload = false); + void writeCppSelfDefinition(QTextStream &s, + GeneratorContext &context, + bool hasStaticOverload = false, + bool cppSelfAsReference = false); + + void writeErrorSection(QTextStream& s, OverloadData& overloadData); + void writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue = true); + + /// Writes the check section for the validity of wrapped C++ objects. + void writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj); + + void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = QString(), bool rejectNull = false); + void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName); + + void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeSetattroFunction(QTextStream &s, GeneratorContext &context); + void writeGetattroFunction(QTextStream &s, GeneratorContext &context); + QString writeSmartPointerGetterCast(); + + /** + * Writes Python to C++ conversions for arguments on Python wrappers. + * If implicit conversions, and thus new object allocation, are needed, + * code to deallocate a possible new instance is also generated. + * \param s text stream to write + * \param argType a pointer to the argument type to be converted + * \param argName C++ argument name + * \param pyArgName Python argument name + * \param context the current meta class + * \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(QTextStream& s, const AbstractMetaType* argType, + const QString& argName, const QString& pyArgName, + const AbstractMetaClass* context = 0, + const QString& defaultValue = QString(), + bool castArgumentAsUnused = false); + + /** + * Returns the AbstractMetaType for a function argument. + * If the argument type was modified in the type system, this method will + * try to build a new type based on the type name defined in the type system. + * \param func The function which owns the argument. + * \param argPos Argument position in the function signature. + * Note that the position 0 represents the return value, and the function + * parameters start counting on 1. + * \param newType It is set to true if the type returned is a new object that must be deallocated. + * \return The type of the argument indicated by \p argPos. + */ + const AbstractMetaType* getArgumentType(const AbstractMetaFunction* func, int argPos); + + void writePythonToCppTypeConversion(QTextStream& s, + const AbstractMetaType* type, + const QString& pyIn, + const QString& cppOut, + const AbstractMetaClass* context = 0, + const QString& defaultValue = QString()); + + /// Writes the conversion rule for arguments of regular and virtual methods. + void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language); + /// Writes the conversion rule for the return value of a method. + void writeConversionRule(QTextStream& s, const AbstractMetaFunction* func, TypeSystem::Language language, const QString& outputVar); + + /** + * Set the Python method wrapper return value variable to Py_None if + * there are return types different from void in any of the other overloads + * for the function passed as parameter. + * \param s text stream to write + * \param func a pointer to the function that will possibly return Py_None + * \param thereIsReturnValue indicates if the return type of any of the other overloads + * for this function is different from 'void' + */ + void writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue); + + /** + * Writes the Python function wrapper overload decisor that selects which C++ + * method/function to call with the received Python arguments. + * \param s text stream to write + * \param overloadData the overload data describing all the possible overloads for the function/method + */ + void writeOverloadedFunctionDecisor(QTextStream& s, const OverloadData& overloadData); + /// Recursive auxiliar method to the other writeOverloadedFunctionDecisor. + void writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData); + + /// Writes calls to all the possible method/function overloads. + void writeFunctionCalls(QTextStream &s, + const OverloadData &overloadData, + GeneratorContext &context); + + /// Writes the call to a single function usually from a collection of overloads. + void writeSingleFunctionCall(QTextStream &s, + const OverloadData &overloadData, + const AbstractMetaFunction *func, + GeneratorContext &context); + + /// Returns the name of a C++ to Python conversion function. + static QString cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName = QString()); + + /// 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); + + /// 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); + + /// Writes a C++ to Python conversion function. + void writeCppToPythonFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, QString targetTypeName = QString()); + void writeCppToPythonFunction(QTextStream& s, const CustomConversion* customConversion); + void writeCppToPythonFunction(QTextStream& s, const AbstractMetaType* containerType); + + /// Writes a Python to C++ conversion function. + void writePythonToCppFunction(QTextStream& s, const QString& code, const QString& sourceTypeName, const QString& targetTypeName); + + /// Writes a Python to C++ convertible check function. + void writeIsPythonConvertibleToCppFunction(QTextStream& s, + const QString& sourceTypeName, + const QString& targetTypeName, + const QString& condition, + QString pythonToCppFuncName = QString(), + bool acceptNoneAsCppNull = false); + + /// Writes a pair of Python to C++ conversion and check functions. + void writePythonToCppConversionFunctions(QTextStream& s, + const AbstractMetaType* sourceType, + const AbstractMetaType* targetType, + QString typeCheck = QString(), + QString conversion = QString(), + QString preConversion = QString()); + /// Writes a pair of Python to C++ conversion and check functions for implicit conversions. + void writePythonToCppConversionFunctions(QTextStream& s, + const CustomConversion::TargetToNativeConversion* toNative, + const TypeEntry* targetType); + + /// Writes a pair of Python to C++ conversion and check functions for instantiated container types. + void writePythonToCppConversionFunctions(QTextStream& s, const AbstractMetaType* containerType); + + void writeAddPythonToCppConversion(QTextStream& s, const QString& converterVar, const QString& pythonToCppFunc, const QString& isConvertibleFunc); + + void writeNamedArgumentResolution(QTextStream& s, const AbstractMetaFunction* func, bool usePyArgs); + + /// Returns a string containing the name of an argument for the given function and argument index. + QString argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass); + void writeMethodCall(QTextStream &s, const AbstractMetaFunction *func, + GeneratorContext &context, int maxArgs = 0); + + QString getInitFunctionName(GeneratorContext &context) const; + + void writeClassRegister(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &classContext); + void writeClassDefinition(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &classContext); + void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads); + void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads); + + /// Writes the implementation of all methods part of python sequence protocol + void writeSequenceMethods(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &context); + void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + + /// Writes the PyMappingMethods structure for types that supports the python mapping protocol. + void writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + void writeMappingMethods(QTextStream &s, + const AbstractMetaClass *metaClass, + GeneratorContext &context); + + void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass); + void writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeCopyFunction(QTextStream &s, GeneratorContext &context); + + void writeGetterFunction(QTextStream &s, + const AbstractMetaField *metaField, + GeneratorContext &context); + void writeSetterFunction(QTextStream &s, + const AbstractMetaField *metaField, + GeneratorContext &context); + + void writeRichCompareFunction(QTextStream &s, GeneratorContext &context); + void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums); + void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); + + void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass); + + void writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeFlagsToLong(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeFlagsNonZero(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeFlagsNumberMethodsDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, + QString pyOpName, QString cppOpName); + void writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, + QString pyOpName, QString cppOpName, bool boolResult = false); + + /// Writes the function that registers the multiple inheritance information for the classes that need it. + void writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass); + /// Writes the implementation of special cast functions, used when we need to cast a class with multiple inheritance. + void writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass); + + void writePrimitiveConverterInitialization(QTextStream& s, const CustomConversion* customConversion); + void writeEnumConverterInitialization(QTextStream& s, const TypeEntry* enumType); + void writeEnumConverterInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); + void writeContainerConverterInitialization(QTextStream& s, const AbstractMetaType* type); + void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QVector& conversions); + + void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn); + bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy); + void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = QLatin1String(PYTHON_SELF_VAR)); + void writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const; + + /** + * Returns the multiple inheritance initializer function for the given class. + * \param metaClass the class for whom the function name must be generated. + * \return name of the multiple inheritance information initializer function or + * an empty string if there is no multiple inheritance in its ancestry. + */ + QString multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass); + + /// Returns a list of all classes to which the given class could be cast. + QStringList getAncestorMultipleInheritance(const AbstractMetaClass* metaClass); + + /// Returns true if the given class supports the python number protocol + bool supportsNumberProtocol(const AbstractMetaClass* metaClass); + + /// Returns true if the given class supports the python sequence protocol + bool supportsSequenceProtocol(const AbstractMetaClass* metaClass); + + /// Returns true if the given class supports the python mapping protocol + bool supportsMappingProtocol(const AbstractMetaClass* metaClass); + + /// Returns true if generator should produce getters and setters for the given class. + bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); + + void writeHashFunction(QTextStream &s, GeneratorContext &context); + + /// Write default implementations for sequence protocol + void writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context); + /// Helper function for writeStdListWrapperMethods. + void writeIndexError(QTextStream& s, const QString& errorMsg); + + QString writeReprFunction(QTextStream &s, GeneratorContext &context); + + bool hasBoolCast(const AbstractMetaClass* metaClass) const; + + // Number protocol structure members names. + static QHash m_nbFuncs; + + // Maps special function names to function parameters and return types + // used by CPython API in the sequence protocol. + QHash > m_sequenceProtocol; + // Sequence protocol structure members names. + static QHash m_sqFuncs; + + // Maps special function names to function parameters and return types + // used by CPython API in the mapping protocol. + QHash > m_mappingProtocol; + // Mapping protocol structure members names. + static QHash m_mpFuncs; + + static QString m_currentErrorCode; + + /// Helper class to set and restore the current error code. + class ErrorCode { + public: + explicit ErrorCode(QString errorCode) { + m_savedErrorCode = CppGenerator::m_currentErrorCode; + CppGenerator::m_currentErrorCode = errorCode; + } + explicit ErrorCode(int errorCode) { + m_savedErrorCode = CppGenerator::m_currentErrorCode; + CppGenerator::m_currentErrorCode = QString::number(errorCode); + } + ~ErrorCode() { + CppGenerator::m_currentErrorCode = m_savedErrorCode; + } + private: + QString m_savedErrorCode; + }; +}; + +#endif // CPPGENERATOR_H diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp new file mode 100644 index 000000000..6b8185dc9 --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -0,0 +1,569 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "headergenerator.h" +#include +#include +#include +#include + +#include +#include +#include +#include + +QString HeaderGenerator::fileNamePrefix() const +{ + return QLatin1String("_wrapper.h"); +} + +QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const +{ + const AbstractMetaClass *metaClass = context.metaClass(); + if (!context.forSmartPointer()) { + QString fileNameBase = metaClass->qualifiedCppName().toLower(); + fileNameBase.replace(QLatin1String("::"), QLatin1String("_")); + return fileNameBase + fileNamePrefix(); + } else { + const AbstractMetaType *smartPointerType = context.preciseType(); + QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass); + return fileNameBase + fileNamePrefix(); + } +} + +void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* metaClass) const +{ + s << INDENT << wrapperName(metaClass) << "(const " << metaClass->qualifiedCppName() << "& self)"; + s << " : " << metaClass->qualifiedCppName() << "(self)" << endl; + s << INDENT << "{" << endl; + s << INDENT << "}" << endl << endl; +} + +void HeaderGenerator::writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const +{ + AbstractMetaType *metaType = field->type(); + QString fieldType = metaType->cppSignature(); + QString fieldName = field->enclosingClass()->qualifiedCppName() + QLatin1String("::") + field->name(); + + // Force use of pointer to return internal variable memory + bool useReference = (!metaType->isConstant() && + !metaType->isEnum() && + !metaType->isPrimitive() && + metaType->indirections() == 0); + + + // Get function + s << INDENT << "inline " << fieldType + << (useReference ? '*' : ' ') + << ' ' << protectedFieldGetterName(field) << "()" + << " { return " + << (useReference ? '&' : ' ') << "this->" << fieldName << "; }" << endl; + + // Set function + s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)" + << " { " << fieldName << " = value; }" << endl; +} + +void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) +{ + AbstractMetaClass *metaClass = classContext.metaClass(); + if (ReportHandler::isDebug(ReportHandler::SparseDebug)) + qCDebug(lcShiboken) << "Generating header for " << metaClass->fullName(); + m_inheritedOverloads.clear(); + Indentation indent(INDENT); + + // write license comment + s << licenseComment(); + + QString wrapperName; + if (!classContext.forSmartPointer()) { + wrapperName = HeaderGenerator::wrapperName(metaClass); + } else { + wrapperName = HeaderGenerator::wrapperName(classContext.preciseType()); + } + QString headerGuard = getFilteredCppSignatureString(wrapperName).toUpper(); + + // Header + s << "#ifndef SBK_" << headerGuard << "_H" << endl; + s << "#define SBK_" << headerGuard << "_H" << endl<< endl; + + if (!avoidProtectedHack()) + s << "#define protected public" << endl << endl; + + s << "#include " << endl << endl; + + //Includes + s << metaClass->typeEntry()->include() << endl; + + if (shouldGenerateCppWrapper(metaClass)) { + + if (usePySideExtensions() && metaClass->isQObject()) + s << "namespace PySide { class DynamicQMetaObject; }\n\n"; + + // Class + s << "class " << wrapperName; + s << " : public " << metaClass->qualifiedCppName(); + + s << endl << '{' << endl << "public:" << endl; + + bool hasVirtualFunction = false; + const AbstractMetaFunctionList &funcs = filterFunctions(metaClass); + for (AbstractMetaFunction *func : funcs) { + if (func->isVirtual()) + hasVirtualFunction = true; + writeFunction(s, func); + } + + if (avoidProtectedHack() && metaClass->hasProtectedFields()) { + const AbstractMetaFieldList &fields = metaClass->fields(); + for (AbstractMetaField *field : fields) { + if (!field->isProtected()) + continue; + writeProtectedFieldAccessors(s, field); + } + } + + //destructor + // PYSIDE-504: When C++ 11 is used, then the destructor must always be written. + // See generator.h for further reference. + if (!avoidProtectedHack() || !metaClass->hasPrivateDestructor() || alwaysGenerateDestructor) { + s << INDENT; + if (avoidProtectedHack() && metaClass->hasPrivateDestructor()) + s << "// C++11: need to declare (unimplemented) destructor because " + "the base class destructor is private." << endl; + if (metaClass->hasVirtualDestructor() || hasVirtualFunction) + s << "virtual "; + s << '~' << wrapperName << "();" << endl; + } + + writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionDeclaration, TypeSystem::NativeCode); + + if ((!avoidProtectedHack() || !metaClass->hasPrivateDestructor()) + && usePySideExtensions() && metaClass->isQObject()) { + s << "public:\n"; + s << INDENT << "virtual int qt_metacall(QMetaObject::Call call, int id, void** args);" << endl; + s << INDENT << "virtual void* qt_metacast(const char* _clname);" << endl; + } + + if (m_inheritedOverloads.size()) { + s << INDENT << "// Inherited overloads, because the using keyword sux" << endl; + writeInheritedOverloads(s); + } + + if (usePySideExtensions()) + s << INDENT << "static void pysideInitQtMetaTypes();" << endl; + + s << "};" << endl << endl; + } + + s << "#endif // SBK_" << headerGuard << "_H" << endl << endl; +} + +void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* func) +{ + + // do not write copy ctors here. + if (!func->isPrivate() && func->functionType() == AbstractMetaFunction::CopyConstructorFunction) { + writeCopyCtor(s, func->ownerClass()); + return; + } + if (func->isUserAdded()) + return; + + if (avoidProtectedHack() && func->isProtected() && !func->isConstructor() && !func->isOperatorOverload()) { + s << INDENT << "inline " << (func->isStatic() ? "static " : ""); + s << functionSignature(func, QString(), QLatin1String("_protected"), Generator::EnumAsInts|Generator::OriginalTypeDescription) + << " { "; + s << (func->type() ? "return " : ""); + if (!func->isAbstract()) + s << func->ownerClass()->qualifiedCppName() << "::"; + s << func->originalName() << '('; + QStringList args; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + QString argName = arg->name(); + const TypeEntry* enumTypeEntry = 0; + if (arg->type()->isFlags()) + enumTypeEntry = reinterpret_cast(arg->type()->typeEntry())->originator(); + else if (arg->type()->isEnum()) + enumTypeEntry = arg->type()->typeEntry(); + if (enumTypeEntry) + argName = QString::fromLatin1("%1(%2)").arg(arg->type()->cppSignature(), argName); + args << argName; + } + s << args.join(QLatin1String(", ")) << ')'; + s << "; }" << endl; + } + + // pure virtual functions need a default implementation + if ((func->isPrivate() && !visibilityModifiedToPrivate(func)) + || (func->isModifiedRemoved() && !func->isAbstract())) + return; + + if (avoidProtectedHack() && func->ownerClass()->hasPrivateDestructor() + && (func->isAbstract() || func->isVirtual())) + return; + + if (func->isConstructor() || func->isAbstract() || func->isVirtual()) { + s << INDENT; + Options virtualOption = Generator::OriginalTypeDescription; + + if (func->isVirtual() || func->isAbstract()) + s << "virtual "; + else if (!func->hasSignatureModifications()) + virtualOption = Generator::NoOption; + + s << functionSignature(func, QString(), QString(), virtualOption) << ';' << endl; + + // Check if this method hide other methods in base classes + const AbstractMetaFunctionList &ownerFuncs = func->ownerClass()->functions(); + for (const AbstractMetaFunction *f : ownerFuncs) { + if (f != func + && !f->isConstructor() + && !f->isPrivate() + && !f->isVirtual() + && !f->isAbstract() + && !f->isStatic() + && f->name() == func->name()) { + m_inheritedOverloads << f; + } + } + + // TODO: when modified an abstract method ceases to be virtual but stays abstract + //if (func->isModifiedRemoved() && func->isAbstract()) { + //} + } +} + +static void _writeTypeIndexDefineLine(QTextStream& s, const QString& variableName, int typeIndex) +{ + s << "#define "; + s.setFieldWidth(60); + s << variableName; + s.setFieldWidth(0); + s << ' ' << typeIndex << endl; +} +void HeaderGenerator::writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry) +{ + if (!typeEntry || !typeEntry->generateCode()) + return; + s.setFieldAlignment(QTextStream::AlignLeft); + int typeIndex = getTypeIndex(typeEntry); + _writeTypeIndexDefineLine(s, getTypeIndexVariableName(typeEntry), typeIndex); + if (typeEntry->isComplex()) { + const ComplexTypeEntry* cType = reinterpret_cast(typeEntry); + if (cType->baseContainerType()) { + const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), cType); + if (metaClass->templateBaseClass()) + _writeTypeIndexDefineLine(s, getTypeIndexVariableName(metaClass, true), typeIndex); + } + } + if (typeEntry->isEnum()) { + const EnumTypeEntry* ete = reinterpret_cast(typeEntry); + if (ete->flags()) + writeTypeIndexDefineLine(s, ete->flags()); + } +} + +void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass) +{ + if (!metaClass->typeEntry()->generateCode()) + return; + writeTypeIndexDefineLine(s, metaClass->typeEntry()); + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { + if (metaEnum->isPrivate()) + continue; + writeTypeIndexDefineLine(s, metaEnum->typeEntry()); + } +} + +bool HeaderGenerator::finishGeneration() +{ + // Generate the main header for this module. + // This header should be included by binding modules + // extendind on top of this one. + QSet includes; + QString macros; + QTextStream macrosStream(¯os); + QString sbkTypeFunctions; + QTextStream typeFunctions(&sbkTypeFunctions); + QString protectedEnumSurrogates; + QTextStream protEnumsSurrogates(&protectedEnumSurrogates); + + Indentation indent(INDENT); + + macrosStream << "// Type indices" << endl; + AbstractMetaEnumList globalEnums = this->globalEnums(); + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { + writeTypeIndexDefine(macrosStream, metaClass); + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + } + + for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) + writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry()); + + // Write the smart pointer define indexes. + int smartPointerCountIndex = getMaxTypeIndex(); + int smartPointerCount = 0; + const QVector &instantiatedSmartPtrs = instantiatedSmartPointers(); + for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { + QString variableName = getTypeIndexVariableName(metaType); + macrosStream << "#define "; + macrosStream.setFieldWidth(60); + macrosStream << variableName; + macrosStream.setFieldWidth(0); + macrosStream << ' ' << smartPointerCountIndex << " // " << metaType->cppSignature() + << endl; + ++smartPointerCountIndex; + ++smartPointerCount; + } + + + macrosStream << "#define "; + macrosStream.setFieldWidth(60); + macrosStream << QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT"); + macrosStream.setFieldWidth(0); + macrosStream << ' ' << getMaxTypeIndex() + smartPointerCount << endl << endl; + macrosStream << "// This variable stores all Python types exported by this module." << endl; + macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl; + macrosStream << "// This variable stores all type converters exported by this module." << endl; + macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl; + + // TODO-CONVERTER ------------------------------------------------------------------------------ + // Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex(). + macrosStream << "// Converter indices" << endl; + 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; + + _writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(ptype), pCount++); + } + + const QVector &containers = instantiatedContainers(); + for (const AbstractMetaType *container : containers) { + //_writeTypeIndexDefineLine(macrosStream, getTypeIndexVariableName(container), pCount); + // DEBUG + QString variableName = getTypeIndexVariableName(container); + macrosStream << "#define "; + macrosStream.setFieldWidth(60); + macrosStream << variableName; + macrosStream.setFieldWidth(0); + macrosStream << ' ' << pCount << " // " << container->cppSignature() << endl; + // DEBUG + pCount++; + } + + // Because on win32 the compiler will not accept a zero length array. + if (pCount == 0) + pCount++; + _writeTypeIndexDefineLine(macrosStream, QStringLiteral("SBK_%1_CONVERTERS_IDX_COUNT").arg(moduleName()), pCount); + macrosStream << endl; + // TODO-CONVERTER ------------------------------------------------------------------------------ + + macrosStream << "// Macros for type check" << endl; + for (const AbstractMetaEnum *cppEnum : globalEnums) { + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) + continue; + includes << cppEnum->typeEntry()->include(); + writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); + writeSbkTypeFunction(typeFunctions, cppEnum); + } + + for (AbstractMetaClass *metaClass : classList) { + if (!shouldGenerate(metaClass)) + continue; + + //Includes + const TypeEntry* classType = metaClass->typeEntry(); + includes << classType->include(); + + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *cppEnum : enums) { + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) + continue; + EnumTypeEntry* enumType = cppEnum->typeEntry(); + includes << enumType->include(); + writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); + writeSbkTypeFunction(typeFunctions, cppEnum); + } + + if (!metaClass->isNamespace()) + writeSbkTypeFunction(typeFunctions, metaClass); + } + + for (const AbstractMetaType *metaType : instantiatedSmartPtrs) { + const TypeEntry *classType = metaType->typeEntry(); + includes << classType->include(); + writeSbkTypeFunction(typeFunctions, metaType); + } + + QString moduleHeaderFileName(outputDirectory() + + QDir::separator() + subDirectoryForPackage(packageName()) + + QDir::separator() + getModuleHeaderFileName()); + + QString includeShield(QLatin1String("SBK_") + moduleName().toUpper() + QLatin1String("_PYTHON_H")); + + FileOut file(moduleHeaderFileName); + QTextStream& s = file.stream; + // write license comment + s << licenseComment() << endl << endl; + + s << "#ifndef " << includeShield << endl; + s << "#define " << includeShield << endl<< endl; + if (!avoidProtectedHack()) { + s << "//workaround to access protected functions" << endl; + s << "#define protected public" << endl << endl; + } + + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl << endl; + if (usePySideExtensions()) + s << "#include " << endl; + + QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports(); + if (!requiredTargetImports.isEmpty()) { + s << "// Module Includes" << endl; + for (const QString &requiredModule : qAsConst(requiredTargetImports)) + s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl; + s << endl; + } + + s << "// Binded library includes" << endl; + for (const Include &include : qAsConst(includes)) + s << include; + + if (!primitiveTypes().isEmpty()) { + s << "// Conversion Includes - Primitive Types" << endl; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *ptype : primitiveTypeList) + s << ptype->include(); + s << endl; + } + + if (!containerTypes().isEmpty()) { + s << "// Conversion Includes - Container Types" << endl; + const ContainerTypeEntryList &containerTypeList = containerTypes(); + for (const ContainerTypeEntry *ctype : containerTypeList) + s << ctype->include(); + s << endl; + } + + s << macros << endl; + + if (!protectedEnumSurrogates.isEmpty()) { + s << "// Protected enum surrogates" << endl; + s << protectedEnumSurrogates << endl; + } + + s << "namespace Shiboken" << endl << '{' << endl << endl; + + s << "// PyType functions, to get the PyObjectType for a type T\n"; + s << sbkTypeFunctions << endl; + + s << "} // namespace Shiboken" << endl << endl; + + s << "#endif // " << includeShield << endl << endl; + + return file.done() != FileOut::Failure; +} + +void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + if (avoidProtectedHack() && cppEnum->isProtected()) + s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};" << endl; +} + +void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ + QString enumName; + if (avoidProtectedHack() && cppEnum->isProtected()) { + enumName = protectedEnumSurrogateName(cppEnum); + } else { + enumName = cppEnum->name(); + if (cppEnum->enclosingClass()) + enumName = cppEnum->enclosingClass()->qualifiedCppName() + QLatin1String("::") + enumName; + } + + s << "template<> inline PyTypeObject* SbkType< ::" << enumName << " >() "; + s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n"; + + FlagsTypeEntry* flag = cppEnum->typeEntry()->flags(); + if (flag) { + s << "template<> inline PyTypeObject* SbkType< ::" << flag->name() << " >() " + << "{ return " << cpythonTypeNameExt(flag) << "; }\n"; + } +} + +void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass) +{ + s << "template<> inline PyTypeObject* SbkType< ::" << cppClass->qualifiedCppName() << " >() " + << "{ return reinterpret_cast(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n"; +} + +void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType) +{ + s << "template<> inline PyTypeObject* SbkType< ::" << metaType->cppSignature() << " >() " + << "{ return reinterpret_cast(" << cpythonTypeNameExt(metaType) << "); }\n"; +} + +void HeaderGenerator::writeInheritedOverloads(QTextStream& s) +{ + for (const AbstractMetaFunction *func : qAsConst(m_inheritedOverloads)) { + s << INDENT << "inline "; + s << functionSignature(func, QString(), QString(), Generator::EnumAsInts|Generator::OriginalTypeDescription) << " { "; + s << (func->type() ? "return " : ""); + s << func->ownerClass()->qualifiedCppName() << "::" << func->originalName() << '('; + QStringList args; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + QString argName = arg->name(); + const TypeEntry* enumTypeEntry = 0; + if (arg->type()->isFlags()) + enumTypeEntry = reinterpret_cast(arg->type()->typeEntry())->originator(); + else if (arg->type()->isEnum()) + enumTypeEntry = arg->type()->typeEntry(); + if (enumTypeEntry) + argName = arg->type()->cppSignature() + QLatin1Char('(') + argName + QLatin1Char(')'); + args << argName; + } + s << args.join(QLatin1String(", ")) << ')'; + s << "; }" << endl; + } +} diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.h b/sources/shiboken2/generator/shiboken2/headergenerator.h new file mode 100644 index 000000000..5c1ffec35 --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/headergenerator.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HEADERGENERATOR_H +#define HEADERGENERATOR_H + +#include "shibokengenerator.h" + +#include + +class AbstractMetaFunction; + +/** + * The HeaderGenerator generate the declarations of C++ bindings classes. + */ +class HeaderGenerator : public ShibokenGenerator +{ +public: + QMap options() const override { return QMap(); } +protected: + QString fileNamePrefix() const override; + QString fileNameForContext(GeneratorContext &context) const override; + void generateClass(QTextStream& s, GeneratorContext &classContext) override; + bool finishGeneration() override; + +private: + void writeCopyCtor(QTextStream &s, const AbstractMetaClass* metaClass) const; + void writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const; + void writeFunction(QTextStream& s, const AbstractMetaFunction* func); + void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass); + void writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType); + void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry); + void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass); + void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum); + void writeInheritedOverloads(QTextStream& s); + + QSet m_inheritedOverloads; +}; + +#endif // HEADERGENERATOR_H + diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.cpp b/sources/shiboken2/generator/shiboken2/overloaddata.cpp new file mode 100644 index 000000000..876185cbe --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp @@ -0,0 +1,1092 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "overloaddata.h" +#include "shibokengenerator.h" + +#include +#include +#include + +static const TypeEntry *getReferencedTypeEntry(const TypeEntry *typeEntry) +{ + if (typeEntry->isPrimitive()) { + const PrimitiveTypeEntry* pte = dynamic_cast(typeEntry); + while (pte->referencedTypeEntry()) + pte = pte->referencedTypeEntry(); + typeEntry = pte; + } + return typeEntry; +} + +static QString getTypeName(const AbstractMetaType* type) +{ + const TypeEntry* typeEntry = getReferencedTypeEntry(type->typeEntry()); + QString typeName = typeEntry->name(); + if (typeEntry->isContainer()) { + QStringList types; + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *cType : instantiations) { + const TypeEntry *typeEntry = getReferencedTypeEntry(cType->typeEntry()); + types << typeEntry->name(); + } + typeName += QLatin1Char('<') + types.join(QLatin1Char(',')) + QLatin1String(" >"); + } + return typeName; +} + +static QString getTypeName(const OverloadData* ov) +{ + return ov->hasArgumentTypeReplace() ? ov->argumentTypeReplaced() : getTypeName(ov->argType()); +} + +static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* typeB) +{ + if (typeA->typeEntry() == typeB->typeEntry()) { + if (typeA->isContainer() || typeA->isSmartPointer()) { + if (typeA->instantiations().size() != typeB->instantiations().size()) + return false; + + for (int i = 0; i < typeA->instantiations().size(); ++i) { + if (!typesAreEqual(typeA->instantiations().at(i), typeB->instantiations().at(i))) + return false; + } + return true; + } + + return !(ShibokenGenerator::isCString(typeA) ^ ShibokenGenerator::isCString(typeB)); + } + return false; +} + + +/** + * OverloadSortData just helps writing clearer code in the + * OverloadData::sortNextOverloads method. + */ +struct OverloadSortData +{ + OverloadSortData() : counter(0) {}; + + /** + * Adds a typeName into the type map without associating it with + * a OverloadData. This is done to express type dependencies that could + * or could not appear in overloaded signatures not processed yet. + */ + void mapType(const QString& typeName) + { + if (map.contains(typeName)) + return; + map[typeName] = counter; + if (!reverseMap.contains(counter)) + reverseMap[counter] = 0; + counter++; + } + + void mapType(OverloadData* overloadData) + { + QString typeName = getTypeName(overloadData); + map[typeName] = counter; + reverseMap[counter] = overloadData; + counter++; + } + + int lastProcessedItemId() { return counter - 1; } + + int counter; + QHash map; // typeName -> id + QHash reverseMap; // id -> OverloadData; +}; + +/** + * Helper function that returns the name of a container get from containerType argument and + * an instantiation taken either from an implicit conversion expressed by the function argument, + * or from the string argument implicitConvTypeName. + */ +static QString getImplicitConversionTypeName(const AbstractMetaType* containerType, + const AbstractMetaType* instantiation, + const AbstractMetaFunction* function, + const QString& implicitConvTypeName = QString()) +{ + QString impConv; + if (!implicitConvTypeName.isEmpty()) + impConv = implicitConvTypeName; + else if (function->isConversionOperator()) + impConv = function->ownerClass()->typeEntry()->name(); + else + impConv = getTypeName(function->arguments().first()->type()); + + QStringList types; + const AbstractMetaTypeList &instantiations = containerType->instantiations(); + for (const AbstractMetaType *otherType : instantiations) + types << (otherType == instantiation ? impConv : getTypeName(otherType)); + + const ContainerTypeEntry* containerTypeEntry = dynamic_cast(containerType->typeEntry()); + return containerTypeEntry->qualifiedCppName() + QLatin1Char('<') + + types.join(QLatin1String(", ")) + QLatin1String(" >"); +} + +static QString msgCyclicDependency(const QString &funcName, const QString &graphName, + const OverloadData::MetaFunctionList &involvedConversions) +{ + QString result; + QTextStream str(&result); + str << "Cyclic dependency found on overloaddata for \"" << funcName + << "\" method! The graph boy saved the graph at \"" << QDir::toNativeSeparators(graphName) + << "\"."; + if (const int count = involvedConversions.size()) { + str << " Implicit conversions (" << count << "): "; + for (int i = 0; i < count; ++i) { + if (i) + str << ", \""; + str << involvedConversions.at(i)->signature() << '"'; + if (const AbstractMetaClass *c = involvedConversions.at(i)->implementingClass()) + str << '(' << c->name() << ')'; + } + } + return result; +} + +/** + * Topologically sort the overloads by implicit convertion order + * + * This avoids using an implicit conversion if there's an explicit + * overload for the convertible type. So, if there's an implicit convert + * like TargetType(ConvertibleType foo) and both are in the overload list, + * ConvertibleType is checked before TargetType. + * + * Side effects: Modifies m_nextOverloadData + */ +void OverloadData::sortNextOverloads() +{ + OverloadSortData sortData; + bool checkPyObject = false; + int pyobjectIndex = 0; + bool checkPySequence = false; + int pySeqIndex = 0; + bool checkQString = false; + int qstringIndex = 0; + bool checkQVariant = false; + int qvariantIndex = 0; + bool checkPyBuffer = false; + int pyBufferIndex = 0; + + // Primitive types that are not int, long, short, + // char and their respective unsigned counterparts. + QStringList nonIntegerPrimitives; + nonIntegerPrimitives << QLatin1String("float") << QLatin1String("double") + << QLatin1String("bool"); + + // Signed integer primitive types. + QStringList signedIntegerPrimitives; + signedIntegerPrimitives << QLatin1String("int") << QLatin1String("short") + << QLatin1String("long"); + + // sort the children overloads + for (OverloadData *ov : m_nextOverloadData) + ov->sortNextOverloads(); + + if (m_nextOverloadData.size() <= 1) + return; + + // Populates the OverloadSortData object containing map and reverseMap, to map type names to ids, + // these ids will be used by the topological sort algorithm, because is easier and faster to work + // with graph sorting using integers. + for (OverloadData *ov : m_nextOverloadData) { + sortData.mapType(ov); + + const QString typeName(getTypeName(ov)); + + if (!checkPyObject && typeName.contains(QLatin1String("PyObject"))) { + checkPyObject = true; + pyobjectIndex = sortData.lastProcessedItemId(); + } else if (!checkPySequence && typeName == QLatin1String("PySequence")) { + checkPySequence = true; + pySeqIndex = sortData.lastProcessedItemId(); + } else if (!checkPyBuffer && typeName == QLatin1String("PyBuffer")) { + checkPyBuffer = true; + pyBufferIndex = sortData.lastProcessedItemId(); + } else if (!checkQVariant && typeName == QLatin1String("QVariant")) { + checkQVariant = true; + qvariantIndex = sortData.lastProcessedItemId(); + } else if (!checkQString && typeName == QLatin1String("QString")) { + checkQString = true; + qstringIndex = sortData.lastProcessedItemId(); + } + + const AbstractMetaTypeList &instantiations = ov->argType()->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { + // Add dependencies for type instantiation of container. + QString typeName = getTypeName(instantiation); + sortData.mapType(typeName); + + // Build dependency for implicit conversion types instantiations for base container. + // For example, considering signatures "method(list)" and "method(list)", + // and being PointF implicitly convertible from Point, an list instantiation with T + // as Point must come before the PointF instantiation, or else list will never + // be called. In the case of primitive types, list must come before list. + if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { + for (const QString &primitive : qAsConst(nonIntegerPrimitives)) + sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive)); + } else { + const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); + for (const AbstractMetaFunction *function : funcs) + sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, function)); + } + } + } + + + // Create the graph of type dependencies based on implicit conversions. + Graph graph(sortData.reverseMap.count()); + // All C++ primitive types, add any forgotten type AT THE END OF THIS LIST! + const char* primitiveTypes[] = {"int", + "unsigned int", + "long", + "unsigned long", + "short", + "unsigned short", + "bool", + "unsigned char", + "char", + "float", + "double", + "const char*" + }; + const int numPrimitives = sizeof(primitiveTypes)/sizeof(const char*); + bool hasPrimitive[numPrimitives]; + for (int i = 0; i < numPrimitives; ++i) + hasPrimitive[i] = sortData.map.contains(QLatin1String(primitiveTypes[i])); + + if (checkPySequence && checkPyObject) + graph.addEdge(pySeqIndex, pyobjectIndex); + + QStringList classesWithIntegerImplicitConversion; + + MetaFunctionList involvedConversions; + + for (OverloadData *ov : m_nextOverloadData) { + const AbstractMetaType* targetType = ov->argType(); + const QString targetTypeEntryName(getTypeName(ov)); + int targetTypeId = sortData.map[targetTypeEntryName]; + + // Process implicit conversions + const AbstractMetaFunctionList &functions = m_generator->implicitConversions(targetType); + for (AbstractMetaFunction *function : functions) { + QString convertibleType; + if (function->isConversionOperator()) + convertibleType = function->ownerClass()->typeEntry()->name(); + else + convertibleType = getTypeName(function->arguments().first()->type()); + + if (convertibleType == QLatin1String("int") || convertibleType == QLatin1String("unsigned int")) + classesWithIntegerImplicitConversion << targetTypeEntryName; + + if (!sortData.map.contains(convertibleType)) + continue; + + int convertibleTypeId = sortData.map[convertibleType]; + + // If a reverse pair already exists, remove it. Probably due to the + // container check (This happened to QVariant and QHash) + graph.removeEdge(targetTypeId, convertibleTypeId); + graph.addEdge(convertibleTypeId, targetTypeId); + involvedConversions.append(function); + } + + // Process inheritance relationships + if (targetType->isValue() || targetType->isObject()) { + const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_generator->classes(), targetType->typeEntry()); + const AbstractMetaClassList &ancestors = m_generator->getAllAncestors(metaClass); + for (const AbstractMetaClass *ancestor : ancestors) { + QString ancestorTypeName = ancestor->typeEntry()->name(); + if (!sortData.map.contains(ancestorTypeName)) + continue; + int ancestorTypeId = sortData.map[ancestorTypeName]; + graph.removeEdge(ancestorTypeId, targetTypeId); + graph.addEdge(targetTypeId, ancestorTypeId); + } + } + + // Process template instantiations + const AbstractMetaTypeList &instantiations = targetType->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { + if (sortData.map.contains(getTypeName(instantiation))) { + int convertible = sortData.map[getTypeName(instantiation)]; + + if (!graph.containsEdge(targetTypeId, convertible)) // Avoid cyclic dependency. + graph.addEdge(convertible, targetTypeId); + + if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { + for (const QString &primitive : qAsConst(nonIntegerPrimitives)) { + QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive); + if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) // Avoid cyclic dependency. + graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); + } + + } else { + const AbstractMetaFunctionList &funcs = m_generator->implicitConversions(instantiation); + for (const AbstractMetaFunction *function : funcs) { + QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, function); + if (!graph.containsEdge(targetTypeId, sortData.map[convertibleTypeName])) { // Avoid cyclic dependency. + graph.addEdge(sortData.map[convertibleTypeName], targetTypeId); + involvedConversions.append(function); + } + } + } + } + } + + + if ((checkPySequence || checkPyObject || checkPyBuffer) + && !targetTypeEntryName.contains(QLatin1String("PyObject")) + && !targetTypeEntryName.contains(QLatin1String("PyBuffer")) + && !targetTypeEntryName.contains(QLatin1String("PySequence"))) { + if (checkPySequence) { + // PySequence will be checked after all more specific types, but before PyObject. + graph.addEdge(targetTypeId, pySeqIndex); + } else if (checkPyBuffer) { + // PySequence will be checked after all more specific types, but before PyObject. + graph.addEdge(targetTypeId, pyBufferIndex); + } else { + // Add dependency on PyObject, so its check is the last one (too generic). + graph.addEdge(targetTypeId, pyobjectIndex); + } + } else if (checkQVariant && targetTypeEntryName != QLatin1String("QVariant")) { + if (!graph.containsEdge(qvariantIndex, targetTypeId)) // Avoid cyclic dependency. + graph.addEdge(targetTypeId, qvariantIndex); + } else if (checkQString && ShibokenGenerator::isPointer(ov->argType()) + && targetTypeEntryName != QLatin1String("QString") + && targetTypeEntryName != QLatin1String("QByteArray") + && (!checkPyObject || targetTypeId != pyobjectIndex)) { + if (!graph.containsEdge(qstringIndex, targetTypeId)) // Avoid cyclic dependency. + graph.addEdge(targetTypeId, qstringIndex); + } + + if (targetType->isEnum()) { + // Enum values must precede primitive types. + for (int i = 0; i < numPrimitives; ++i) { + if (hasPrimitive[i]) + graph.addEdge(targetTypeId, sortData.map[QLatin1String(primitiveTypes[i])]); + } + } + } + + // QByteArray args need to be checked after QString args + if (sortData.map.contains(QLatin1String("QString")) && sortData.map.contains(QLatin1String("QByteArray"))) + graph.addEdge(sortData.map[QLatin1String("QString")], sortData.map[QLatin1String("QByteArray")]); + + for (OverloadData *ov : m_nextOverloadData) { + 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)) + graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]); + } + + + // Special case for double(int i) (not tracked by m_generator->implicitConversions + for (const QString &signedIntegerName : qAsConst(signedIntegerPrimitives)) { + if (sortData.map.contains(signedIntegerName)) { + for (const QString &nonIntegerName : qAsConst(nonIntegerPrimitives)) { + if (sortData.map.contains(nonIntegerName)) + graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]); + } + } + } + + // sort the overloads topologically based on the dependency graph. + const QLinkedList unmappedResult = graph.topologicalSort(); + if (unmappedResult.isEmpty()) { + QString funcName = referenceFunction()->name(); + if (referenceFunction()->ownerClass()) + funcName.prepend(referenceFunction()->ownerClass()->name() + QLatin1Char('.')); + + // Dump overload graph + QString graphName = QDir::tempPath() + QLatin1Char('/') + funcName + QLatin1String(".dot"); + QHash::const_iterator it = sortData.map.begin(); + QHash nodeNames; + for (; it != sortData.map.end(); ++it) + nodeNames.insert(it.value(), it.key()); + graph.dumpDot(nodeNames, graphName); + qCWarning(lcShiboken).noquote() << qPrintable(msgCyclicDependency(funcName, graphName, involvedConversions)); + } + + m_nextOverloadData.clear(); + for (int i : unmappedResult) { + if (!sortData.reverseMap[i]) + continue; + m_nextOverloadData << sortData.reverseMap[i]; + } +} + +/** + * Root constructor for OverloadData + * + * This constructor receives the list of overloads for a given function and iterates generating + * the graph of OverloadData instances. Each OverloadData instance references an argument/type + * combination. + * + * Example: + * addStuff(double, PyObject *) + * addStuff(double, int) + * + * Given these two overloads, there will be the following graph: + * + * addStuff - double - PyObject* + * \- int + * + */ +OverloadData::OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator) + : m_minArgs(256), m_maxArgs(0), m_argPos(-1), m_argType(0), + m_headOverloadData(this), m_previousOverloadData(0), m_generator(generator) +{ + for (const AbstractMetaFunction *func : overloads) { + m_overloads.append(func); + int argSize = func->arguments().size() - numberOfRemovedArguments(func); + if (m_minArgs > argSize) + m_minArgs = argSize; + else if (m_maxArgs < argSize) + m_maxArgs = argSize; + OverloadData* currentOverloadData = this; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + currentOverloadData = currentOverloadData->addOverloadData(func, arg); + } + } + + // Sort the overload possibilities so that the overload decisor code goes for the most + // important cases first, based on the topological order of the implicit conversions + sortNextOverloads(); + + // Fix minArgs + if (minArgs() > maxArgs()) + m_headOverloadData->m_minArgs = maxArgs(); +} + +OverloadData::OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func, + const AbstractMetaType* argType, int argPos) + : m_minArgs(256), m_maxArgs(0), m_argPos(argPos), m_argType(argType), + m_headOverloadData(headOverloadData), m_previousOverloadData(0) +{ + if (func) + this->addOverload(func); +} + +void OverloadData::addOverload(const AbstractMetaFunction* func) +{ + int origNumArgs = func->arguments().size(); + int removed = numberOfRemovedArguments(func); + int numArgs = origNumArgs - removed; + + if (numArgs > m_headOverloadData->m_maxArgs) + m_headOverloadData->m_maxArgs = numArgs; + + if (numArgs < m_headOverloadData->m_minArgs) + m_headOverloadData->m_minArgs = numArgs; + + for (int i = 0; m_headOverloadData->m_minArgs > 0 && i < origNumArgs; i++) { + if (func->argumentRemoved(i + 1)) + continue; + if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[i]).isEmpty()) { + int fixedArgIndex = i - removed; + if (fixedArgIndex < m_headOverloadData->m_minArgs) + m_headOverloadData->m_minArgs = fixedArgIndex; + } + } + + m_overloads.append(func); +} + +OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func, + const AbstractMetaArgument* arg) +{ + const AbstractMetaType* argType = arg->type(); + OverloadData* overloadData = 0; + if (!func->isOperatorOverload()) { + for (OverloadData *tmp : qAsConst(m_nextOverloadData)) { + // 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 + // for it, unless the next argument also have a identical type replacement. + QString replacedArg = func->typeReplaced(tmp->m_argPos + 1); + bool argsReplaced = !replacedArg.isEmpty() || !tmp->m_argTypeReplaced.isEmpty(); + if ((!argsReplaced && typesAreEqual(tmp->m_argType, argType)) + || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) { + tmp->addOverload(func); + overloadData = tmp; + } + } + } + + if (!overloadData) { + overloadData = new OverloadData(m_headOverloadData, func, argType, m_argPos + 1); + overloadData->m_previousOverloadData = this; + overloadData->m_generator = this->m_generator; + QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); + + if (!typeReplaced.isEmpty()) + overloadData->m_argTypeReplaced = typeReplaced; + m_nextOverloadData.append(overloadData); + } + + return overloadData; +} + +QStringList OverloadData::returnTypes() const +{ + QSet retTypes; + for (const AbstractMetaFunction *func : m_overloads) { + if (!func->typeReplaced(0).isEmpty()) + retTypes << func->typeReplaced(0); + else if (func->type() && !func->argumentRemoved(0)) + retTypes << func->type()->cppSignature(); + else + retTypes << QLatin1String("void"); + } + return QStringList(retTypes.toList()); +} + +bool OverloadData::hasNonVoidReturnType() const +{ + QStringList retTypes = returnTypes(); + return !retTypes.contains(QLatin1String("void")) || retTypes.size() > 1; +} + +bool OverloadData::hasVarargs() const +{ + for (const AbstractMetaFunction *func : m_overloads) { + AbstractMetaArgumentList args = func->arguments(); + if (args.size() > 1 && args.last()->type()->isVarargs()) + return true; + } + return false; +} + +bool OverloadData::hasAllowThread() const +{ + for (const AbstractMetaFunction *func : m_overloads) { + if (func->allowThread()) + return true; + } + return false; +} + +bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads) +{ + for (const AbstractMetaFunction *func : qAsConst(overloads)) { + if (func->isStatic()) + return true; + } + return false; +} + +bool OverloadData::hasStaticFunction() const +{ + for (const AbstractMetaFunction *func : m_overloads) { + if (func->isStatic()) + return true; + } + return false; +} + +bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads) +{ + for (const AbstractMetaFunction *func : qAsConst(overloads)) { + if (!func->isStatic()) + return true; + } + return false; +} + +bool OverloadData::hasInstanceFunction() const +{ + for (const AbstractMetaFunction *func : m_overloads) { + if (!func->isStatic()) + return true; + } + return false; +} + +bool OverloadData::hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads) +{ + return OverloadData::hasStaticFunction(overloads) && OverloadData::hasInstanceFunction(overloads); +} + +bool OverloadData::hasStaticAndInstanceFunctions() const +{ + return OverloadData::hasStaticFunction() && OverloadData::hasInstanceFunction(); +} + +const AbstractMetaFunction* OverloadData::referenceFunction() const +{ + return m_overloads.first(); +} + +const AbstractMetaArgument* OverloadData::argument(const AbstractMetaFunction* func) const +{ + if (isHeadOverloadData() || !m_overloads.contains(func)) + return 0; + + int argPos = 0; + int removed = 0; + for (int i = 0; argPos <= m_argPos; i++) { + if (func->argumentRemoved(i + 1)) + removed++; + else + argPos++; + } + + return func->arguments()[m_argPos + removed]; +} + +OverloadDataList OverloadData::overloadDataOnPosition(OverloadData* overloadData, int argPos) const +{ + OverloadDataList overloadDataList; + if (overloadData->argPos() == argPos) { + overloadDataList.append(overloadData); + } else if (overloadData->argPos() < argPos) { + const OverloadDataList &data = overloadData->nextOverloadData(); + for (OverloadData *pd : data) + overloadDataList += overloadDataOnPosition(pd, argPos); + } + return overloadDataList; +} + +OverloadDataList OverloadData::overloadDataOnPosition(int argPos) const +{ + OverloadDataList overloadDataList; + overloadDataList += overloadDataOnPosition(m_headOverloadData, argPos); + return overloadDataList; +} + +bool OverloadData::nextArgumentHasDefaultValue() const +{ + for (OverloadData *overloadData : m_nextOverloadData) { + if (overloadData->getFunctionWithDefaultValue()) + return true; + } + return false; +} + +static OverloadData* _findNextArgWithDefault(OverloadData* overloadData) +{ + if (overloadData->getFunctionWithDefaultValue()) + return overloadData; + + OverloadData* result = 0; + const OverloadDataList &data = overloadData->nextOverloadData(); + for (OverloadData *odata : data) { + OverloadData* tmp = _findNextArgWithDefault(odata); + if (!result || (tmp && result->argPos() > tmp->argPos())) + result = tmp; + } + return result; +} + +OverloadData* OverloadData::findNextArgWithDefault() +{ + return _findNextArgWithDefault(this); +} + +bool OverloadData::isFinalOccurrence(const AbstractMetaFunction* func) const +{ + for (const OverloadData *pd : m_nextOverloadData) { + if (pd->overloads().contains(func)) + return false; + } + return true; +} + +OverloadData::MetaFunctionList OverloadData::overloadsWithoutRepetition() const +{ + MetaFunctionList overloads = m_overloads; + for (const AbstractMetaFunction *func : m_overloads) { + if (func->minimalSignature().endsWith(QLatin1String("const"))) + continue; + for (const AbstractMetaFunction *f : qAsConst(overloads)) { + if ((func->minimalSignature() + QLatin1String("const")) == f->minimalSignature()) { + overloads.removeOne(f); + break; + } + } + } + return overloads; +} + +const AbstractMetaFunction* OverloadData::getFunctionWithDefaultValue() const +{ + for (const AbstractMetaFunction *func : m_overloads) { + int removedArgs = 0; + for (int i = 0; i <= m_argPos + removedArgs; i++) { + if (func->argumentRemoved(i + 1)) + removedArgs++; + } + if (!ShibokenGenerator::getDefaultValue(func, func->arguments()[m_argPos + removedArgs]).isEmpty()) + return func; + } + return 0; +} + +QVector OverloadData::invalidArgumentLengths() const +{ + QSet validArgLengths; + + for (const AbstractMetaFunction *func : qAsConst(m_headOverloadData->m_overloads)) { + const AbstractMetaArgumentList args = func->arguments(); + int offset = 0; + for (int i = 0; i < args.size(); ++i) { + if (func->argumentRemoved(i+1)) { + offset++; + } else { + if (!ShibokenGenerator::getDefaultValue(func, args[i]).isEmpty()) + validArgLengths << i-offset; + } + } + validArgLengths << args.size() - offset; + } + + QVector invalidArgLengths; + for (int i = minArgs() + 1; i < maxArgs(); i++) { + if (!validArgLengths.contains(i)) + invalidArgLengths.append(i); + } + + return invalidArgLengths; +} + +int OverloadData::numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos) +{ + int removed = 0; + if (finalArgPos < 0) { + for (int i = 0; i < func->arguments().size(); i++) { + if (func->argumentRemoved(i + 1)) + removed++; + } + } else { + for (int i = 0; i < finalArgPos + removed; i++) { + if (func->argumentRemoved(i + 1)) + removed++; + } + } + return removed; +} + +QPair OverloadData::getMinMaxArguments(const AbstractMetaFunctionList& overloads) +{ + int minArgs = 10000; + int maxArgs = 0; + for (int i = 0; i < overloads.size(); i++) { + const AbstractMetaFunction* func = overloads[i]; + int origNumArgs = func->arguments().size(); + int removed = numberOfRemovedArguments(func); + int numArgs = origNumArgs - removed; + if (maxArgs < numArgs) + maxArgs = numArgs; + if (minArgs > numArgs) + minArgs = numArgs; + for (int j = 0; j < origNumArgs; j++) { + if (func->argumentRemoved(j + 1)) + continue; + int fixedArgIndex = j - removed; + if (fixedArgIndex < minArgs && !ShibokenGenerator::getDefaultValue(func, func->arguments()[j]).isEmpty()) + minArgs = fixedArgIndex; + } + } + return QPair(minArgs, maxArgs); +} + +bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads) +{ + bool singleArgument = true; + for (const AbstractMetaFunction *func : overloads) { + if (func->arguments().size() - numberOfRemovedArguments(func) != 1) { + singleArgument = false; + break; + } + } + return singleArgument; +} + +void OverloadData::dumpGraph(QString filename) const +{ + QFile file(filename); + if (file.open(QFile::WriteOnly)) { + QTextStream s(&file); + s << m_headOverloadData->dumpGraph(); + } +} + +static inline QString toHtml(QString s) +{ + s.replace(QLatin1Char('<'), QLatin1String("<")); + s.replace(QLatin1Char('>'), QLatin1String(">")); + s.replace(QLatin1Char('&'), QLatin1String("&")); + return s; +} + +QString OverloadData::dumpGraph() const +{ + QString indent(4, QLatin1Char(' ')); + QString result; + QTextStream s(&result); + if (m_argPos == -1) { + const AbstractMetaFunction* rfunc = referenceFunction(); + s << "digraph OverloadedFunction {" << endl; + s << indent << "graph [fontsize=12 fontname=freemono labelloc=t splines=true overlap=false rankdir=LR];" << endl; + + // Shows all function signatures + s << "legend [fontsize=9 fontname=freemono shape=rect label=\""; + for (const AbstractMetaFunction *func : m_overloads) { + s << "f" << functionNumber(func) << " : "; + if (func->type()) + s << toHtml(func->type()->cppSignature()); + else + s << "void"; + s << ' ' << toHtml(func->minimalSignature()) << "\\l"; + } + s << "\"];" << endl; + + // Function box title + s << indent << '"' << rfunc->name() << "\" [shape=plaintext style=\"filled,bold\" margin=0 fontname=freemono fillcolor=white penwidth=1 "; + s << "label=<"; + s << ""; + + // Function return type + s << ""; + + // Shows type changes for all function signatures + for (const AbstractMetaFunction *func : m_overloads) { + if (func->typeReplaced(0).isEmpty()) + continue; + s << ""; + } + + // Minimum and maximum number of arguments + s << ""; + s << ""; + + if (rfunc->ownerClass()) { + if (rfunc->implementingClass() != rfunc->ownerClass()) + s << ""; + if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass()) + s << ""; + } + + // Overloads for the signature to present point + s << ""; + + s << "
"; + if (rfunc->ownerClass()) + s << rfunc->ownerClass()->name() << "::"; + s << toHtml(rfunc->name()) << ""; + if (rfunc->isVirtual()) { + s << "
<<"; + if (rfunc->isAbstract()) + s << "pure "; + s << "virtual>>"; + } + s << "
original type"; + if (rfunc->type()) + s << toHtml(rfunc->type()->cppSignature()); + else + s << "void"; + s << "
f" << functionNumber(func); + s << "-type"; + s << toHtml(func->typeReplaced(0)) << "
minArgs"; + s << minArgs() << "
maxArgs"; + s << maxArgs() << "
implementor" << rfunc->implementingClass()->name() << "
declarator" << rfunc->declaringClass()->name() << "
overloads"; + for (const AbstractMetaFunction *func : m_overloads) + s << 'f' << functionNumber(func) << ' '; + s << "
> ];" << endl; + + for (const OverloadData *pd : m_nextOverloadData) + s << indent << '"' << rfunc->name() << "\" -> " << pd->dumpGraph(); + + s << "}" << endl; + } else { + QString argId = QLatin1String("arg_") + QString::number(quintptr(this)); + s << argId << ';' << endl; + + s << indent << '"' << argId << "\" [shape=\"plaintext\" style=\"filled,bold\" margin=\"0\" fontname=\"freemono\" fillcolor=\"white\" penwidth=1 "; + s << "label=<"; + + // Argument box title + s << ""; + + // Argument type information + QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType()->cppSignature(); + s << ""; + if (hasArgumentTypeReplace()) { + s << ""; + } + + // Overloads for the signature to present point + s << ""; + + // Show default values (original and modified) for various functions + for (const AbstractMetaFunction *func : m_overloads) { + const AbstractMetaArgument* arg = argument(func); + if (!arg) + continue; + QString argDefault = ShibokenGenerator::getDefaultValue(func, arg); + if (!argDefault.isEmpty() || + argDefault != arg->originalDefaultValueExpression()) { + s << ""; + } + if (argDefault != arg->originalDefaultValueExpression()) { + s << ""; + } + } + + s << "
"; + s << "arg #" << argPos() << "
type"; + s << toHtml(type) << "
orig. type"; + s << toHtml(argType()->cppSignature()) << "
overloads"; + for (const AbstractMetaFunction *func : m_overloads) + s << 'f' << functionNumber(func) << ' '; + s << "
f" << functionNumber(func); + s << "-default"; + s << argDefault << "
f" << functionNumber(func); + s << "-orig-default"; + s << arg->originalDefaultValueExpression() << "
>];" << endl; + + for (const OverloadData *pd : m_nextOverloadData) + s << indent << argId << " -> " << pd->dumpGraph(); + } + return result; +} + +int OverloadData::functionNumber(const AbstractMetaFunction* func) const +{ + return m_headOverloadData->m_overloads.indexOf(func); +} + +OverloadData::~OverloadData() +{ + while (!m_nextOverloadData.isEmpty()) + delete m_nextOverloadData.takeLast(); +} + +bool OverloadData::hasArgumentTypeReplace() const +{ + return !m_argTypeReplaced.isEmpty(); +} + +QString OverloadData::argumentTypeReplaced() const +{ + return m_argTypeReplaced; +} + +bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads) +{ + if (OverloadData::getMinMaxArguments(overloads).second == 0) + return false; + for (const AbstractMetaFunction *func : overloads) { + if (hasArgumentWithDefaultValue(func)) + return true; + } + return false; +} + +bool OverloadData::hasArgumentWithDefaultValue() const +{ + if (maxArgs() == 0) + return false; + for (const AbstractMetaFunction *func : m_overloads) { + if (hasArgumentWithDefaultValue(func)) + return true; + } + return false; +} + +bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func) +{ + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + if (!ShibokenGenerator::getDefaultValue(func, arg).isEmpty()) + return true; + } + return false; +} + +AbstractMetaArgumentList OverloadData::getArgumentsWithDefaultValues(const AbstractMetaFunction* func) +{ + AbstractMetaArgumentList args; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (AbstractMetaArgument *arg : arguments) { + if (ShibokenGenerator::getDefaultValue(func, arg).isEmpty() + || func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + args << arg; + } + return args; +} + +#ifndef QT_NO_DEBUG_STREAM +void OverloadData::formatDebug(QDebug &d) const +{ + const int count = m_overloads.size(); + d << "argType=" << m_argType << ", minArgs=" << m_minArgs << ", maxArgs=" << m_maxArgs + << ", argPos=" << m_argPos << ", argTypeReplaced=\"" << m_argTypeReplaced + << "\", overloads[" << count << "]=("; + const int oldVerbosity = d.verbosity(); + d.setVerbosity(3); + for (int i = 0; i < count; ++i) { + if (i) + d << '\n'; + d << m_overloads.at(i); + } + d << ')'; + d.setVerbosity(oldVerbosity); +} + +QDebug operator<<(QDebug d, const OverloadData *od) +{ + QDebugStateSaver saver(d); + d.noquote(); + d.nospace(); + d << "OverloadData("; + if (od) + od->formatDebug(d); + else + d << '0'; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/generator/shiboken2/overloaddata.h b/sources/shiboken2/generator/shiboken2/overloaddata.h new file mode 100644 index 000000000..2d815f6bb --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/overloaddata.h @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OVERLOADDATA_H +#define OVERLOADDATA_H + +#include +#include +#include + +QT_FORWARD_DECLARE_CLASS(QDebug) + +class ShibokenGenerator; + +class OverloadData; +typedef QVector OverloadDataList; + +class OverloadData +{ +public: + typedef QVector MetaFunctionList; + + OverloadData(const AbstractMetaFunctionList& overloads, const ShibokenGenerator* generator); + ~OverloadData(); + + int minArgs() const { return m_headOverloadData->m_minArgs; } + int maxArgs() const { return m_headOverloadData->m_maxArgs; } + int argPos() const { return m_argPos; } + + const AbstractMetaType* argType() const { return m_argType; } + + /// Returns a string list containing all the possible return types (including void) for the current OverloadData. + QStringList returnTypes() const; + + /// Returns true if any of the overloads for the current OverloadData has a return type different from void. + bool hasNonVoidReturnType() const; + + /// Returns true if any of the overloads for the current OverloadData has a varargs argument. + bool hasVarargs() const; + + /// Returns true if any of the overloads for the current OverloadData allows threads when called. + bool hasAllowThread() const; + + /// Returns true if any of the overloads for the current OverloadData is static. + bool hasStaticFunction() const; + + /// Returns true if any of the overloads passed as argument is static. + static bool hasStaticFunction(const AbstractMetaFunctionList& overloads); + + /// Returns true if any of the overloads for the current OverloadData is not static. + bool hasInstanceFunction() const; + + /// Returns true if any of the overloads passed as argument is not static. + static bool hasInstanceFunction(const AbstractMetaFunctionList& overloads); + + /// Returns true if among the overloads for the current OverloadData there are static and non-static methods altogether. + bool hasStaticAndInstanceFunctions() const; + + /// Returns true if among the overloads passed as argument there are static and non-static methods altogether. + static bool hasStaticAndInstanceFunctions(const AbstractMetaFunctionList& overloads); + + const AbstractMetaFunction* referenceFunction() const; + const AbstractMetaArgument* argument(const AbstractMetaFunction* func) const; + OverloadDataList overloadDataOnPosition(int argPos) const; + + bool isHeadOverloadData() const { return this == m_headOverloadData; } + + /// Returns the root OverloadData object that represents all the overloads. + OverloadData* headOverloadData() const { return m_headOverloadData; } + + /// Returns the function that has a default value at the current OverloadData argument position, otherwise returns null. + const AbstractMetaFunction* getFunctionWithDefaultValue() const; + + bool nextArgumentHasDefaultValue() const; + /// Returns the nearest occurrence, including this instance, of an argument with a default value. + OverloadData* findNextArgWithDefault(); + bool isFinalOccurrence(const AbstractMetaFunction* func) const; + + /// Returns the list of overloads removing repeated constant functions (ex.: "foo()" and "foo()const", the second is removed). + MetaFunctionList overloadsWithoutRepetition() const; + const MetaFunctionList& overloads() const { return m_overloads; } + OverloadDataList nextOverloadData() const { return m_nextOverloadData; } + OverloadData* previousOverloadData() const { return m_previousOverloadData; } + + QVector invalidArgumentLengths() const; + + static int numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos = -1); + static QPair getMinMaxArguments(const AbstractMetaFunctionList& overloads); + /// Returns true if all overloads have no more than one argument. + static bool isSingleArgument(const AbstractMetaFunctionList& overloads); + + void dumpGraph(QString filename) const; + QString dumpGraph() const; + + bool hasArgumentTypeReplace() const; + QString argumentTypeReplaced() const; + + bool hasArgumentWithDefaultValue() const; + static bool hasArgumentWithDefaultValue(const AbstractMetaFunctionList& overloads); + static bool hasArgumentWithDefaultValue(const AbstractMetaFunction* func); + + /// Returns a list of function arguments which have default values and were not removed. + static AbstractMetaArgumentList getArgumentsWithDefaultValues(const AbstractMetaFunction* func); + +#ifndef QT_NO_DEBUG_STREAM + void formatDebug(QDebug &) const; +#endif + +private: + OverloadData(OverloadData* headOverloadData, const AbstractMetaFunction* func, + const AbstractMetaType* argType, int argPos); + + void addOverload(const AbstractMetaFunction* func); + OverloadData* addOverloadData(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); + + void sortNextOverloads(); + + int functionNumber(const AbstractMetaFunction* func) const; + OverloadDataList overloadDataOnPosition(OverloadData* overloadData, int argPos) const; + + int m_minArgs; + int m_maxArgs; + int m_argPos; + const AbstractMetaType* m_argType; + QString m_argTypeReplaced; + MetaFunctionList m_overloads; + + OverloadData* m_headOverloadData; + OverloadDataList m_nextOverloadData; + OverloadData* m_previousOverloadData; + const ShibokenGenerator* m_generator; +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug, const OverloadData *); +#endif + +#endif // OVERLOADDATA_H diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp new file mode 100644 index 000000000..4768ddc88 --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -0,0 +1,2728 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "shibokengenerator.h" +#include +#include "overloaddata.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#define NULL_VALUE "NULL" +#define AVOID_PROTECTED_HACK "avoid-protected-hack" +#define PARENT_CTOR_HEURISTIC "enable-parent-ctor-heuristic" +#define RETURN_VALUE_HEURISTIC "enable-return-value-heuristic" +#define ENABLE_PYSIDE_EXTENSIONS "enable-pyside-extensions" +#define DISABLE_VERBOSE_ERROR_MESSAGES "disable-verbose-error-messages" +#define USE_ISNULL_AS_NB_NONZERO "use-isnull-as-nb_nonzero" + +//static void dumpFunction(AbstractMetaFunctionList lst); + +QHash ShibokenGenerator::m_pythonPrimitiveTypeName = QHash(); +QHash ShibokenGenerator::m_pythonOperators = QHash(); +QHash ShibokenGenerator::m_formatUnits = QHash(); +QHash ShibokenGenerator::m_tpFuncs = QHash(); +QStringList ShibokenGenerator::m_knownPythonTypes = QStringList(); + +static QRegularExpression placeHolderRegex(int index) +{ + return QRegularExpression(QLatin1Char('%') + QString::number(index) + QStringLiteral("\\b")); +} + +static QString resolveScopePrefix(const AbstractMetaClass* scope, const QString& value) +{ + if (!scope) + return QString(); + + QString name; + QStringList parts = scope->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts); + for(int i = (parts.size() - 1) ; i >= 0; i--) { + if (!value.startsWith(parts[i] + QLatin1String("::"))) + name = parts[i] + QLatin1String("::") + name; + else + name.clear(); + } + + return name; +} +ShibokenGenerator::ShibokenGenerator() : Generator() +{ + if (m_pythonPrimitiveTypeName.isEmpty()) + ShibokenGenerator::initPrimitiveTypesCorrespondences(); + + if (m_tpFuncs.isEmpty()) + ShibokenGenerator::clearTpFuncs(); + + if (m_knownPythonTypes.isEmpty()) + ShibokenGenerator::initKnownPythonTypes(); + + m_metaTypeFromStringCache = AbstractMetaTypeCache(); + + m_typeSystemConvName[TypeSystemCheckFunction] = QLatin1String("checkType"); + m_typeSystemConvName[TypeSystemIsConvertibleFunction] = QLatin1String("isConvertible"); + m_typeSystemConvName[TypeSystemToCppFunction] = QLatin1String("toCpp"); + m_typeSystemConvName[TypeSystemToPythonFunction] = QLatin1String("toPython"); + m_typeSystemConvRegEx[TypeSystemCheckFunction] = QRegularExpression(QLatin1String(CHECKTYPE_REGEX)); + m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegularExpression(QLatin1String(ISCONVERTIBLE_REGEX)); + m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegularExpression(QLatin1String(CONVERTTOPYTHON_REGEX)); + m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegularExpression(QLatin1String(CONVERTTOCPP_REGEX)); +} + +ShibokenGenerator::~ShibokenGenerator() +{ + // TODO-CONVERTER: it must be caching types that were not created here. + //qDeleteAll(m_metaTypeFromStringCache.values()); +} + +void ShibokenGenerator::clearTpFuncs() +{ + m_tpFuncs.insert(QLatin1String("__str__"), QLatin1String("0")); + m_tpFuncs.insert(QLatin1String("__repr__"), QLatin1String("0")); + m_tpFuncs.insert(QLatin1String("__iter__"), QLatin1String("0")); + m_tpFuncs.insert(QLatin1String("__next__"), QLatin1String("0")); +} + +void ShibokenGenerator::initPrimitiveTypesCorrespondences() +{ + // Python primitive types names + m_pythonPrimitiveTypeName.clear(); + + // PyBool + m_pythonPrimitiveTypeName.insert(QLatin1String("bool"), QLatin1String("PyBool")); + + // PyInt + m_pythonPrimitiveTypeName.insert(QLatin1String("char"), QLatin1String("SbkChar")); + m_pythonPrimitiveTypeName.insert(QLatin1String("signed char"), QLatin1String("SbkChar")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned char"), QLatin1String("SbkChar")); + m_pythonPrimitiveTypeName.insert(QLatin1String("int"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("signed int"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("uint"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned int"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("short"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("ushort"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("signed short"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("signed short int"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned short int"), QLatin1String("PyInt")); + m_pythonPrimitiveTypeName.insert(QLatin1String("long"), QLatin1String("PyInt")); + + // PyFloat + m_pythonPrimitiveTypeName.insert(QLatin1String("double"), QLatin1String("PyFloat")); + m_pythonPrimitiveTypeName.insert(QLatin1String("float"), QLatin1String("PyFloat")); + + // PyLong + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("signed long"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("ulong"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long int"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("long long"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("__int64"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned long long"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("unsigned __int64"), QLatin1String("PyLong")); + m_pythonPrimitiveTypeName.insert(QLatin1String("size_t"), QLatin1String("PyLong")); + + // Python operators + m_pythonOperators.clear(); + + // call operator + m_pythonOperators.insert(QLatin1String("operator()"), QLatin1String("call")); + + // Arithmetic operators + m_pythonOperators.insert(QLatin1String("operator+"), QLatin1String("add")); + m_pythonOperators.insert(QLatin1String("operator-"), QLatin1String("sub")); + m_pythonOperators.insert(QLatin1String("operator*"), QLatin1String("mul")); + m_pythonOperators.insert(QLatin1String("operator/"), QLatin1String("div")); + m_pythonOperators.insert(QLatin1String("operator%"), QLatin1String("mod")); + + // Inplace arithmetic operators + m_pythonOperators.insert(QLatin1String("operator+="), QLatin1String("iadd")); + m_pythonOperators.insert(QLatin1String("operator-="), QLatin1String("isub")); + m_pythonOperators.insert(QLatin1String("operator++"), QLatin1String("iadd")); + m_pythonOperators.insert(QLatin1String("operator--"), QLatin1String("isub")); + m_pythonOperators.insert(QLatin1String("operator*="), QLatin1String("imul")); + m_pythonOperators.insert(QLatin1String("operator/="), QLatin1String("idiv")); + m_pythonOperators.insert(QLatin1String("operator%="), QLatin1String("imod")); + + // Bitwise operators + m_pythonOperators.insert(QLatin1String("operator&"), QLatin1String("and")); + m_pythonOperators.insert(QLatin1String("operator^"), QLatin1String("xor")); + m_pythonOperators.insert(QLatin1String("operator|"), QLatin1String("or")); + m_pythonOperators.insert(QLatin1String("operator<<"), QLatin1String("lshift")); + m_pythonOperators.insert(QLatin1String("operator>>"), QLatin1String("rshift")); + m_pythonOperators.insert(QLatin1String("operator~"), QLatin1String("invert")); + + // Inplace bitwise operators + m_pythonOperators.insert(QLatin1String("operator&="), QLatin1String("iand")); + m_pythonOperators.insert(QLatin1String("operator^="), QLatin1String("ixor")); + m_pythonOperators.insert(QLatin1String("operator|="), QLatin1String("ior")); + m_pythonOperators.insert(QLatin1String("operator<<="), QLatin1String("ilshift")); + m_pythonOperators.insert(QLatin1String("operator>>="), QLatin1String("irshift")); + + // Comparison operators + m_pythonOperators.insert(QLatin1String("operator=="), QLatin1String("eq")); + m_pythonOperators.insert(QLatin1String("operator!="), QLatin1String("ne")); + m_pythonOperators.insert(QLatin1String("operator<"), QLatin1String("lt")); + m_pythonOperators.insert(QLatin1String("operator>"), QLatin1String("gt")); + m_pythonOperators.insert(QLatin1String("operator<="), QLatin1String("le")); + m_pythonOperators.insert(QLatin1String("operator>="), QLatin1String("ge")); + + // Initialize format units for C++->Python->C++ conversion + m_formatUnits.clear(); + m_formatUnits.insert(QLatin1String("char"), QLatin1String("b")); + m_formatUnits.insert(QLatin1String("unsigned char"), QLatin1String("B")); + m_formatUnits.insert(QLatin1String("int"), QLatin1String("i")); + m_formatUnits.insert(QLatin1String("unsigned int"), QLatin1String("I")); + m_formatUnits.insert(QLatin1String("short"), QLatin1String("h")); + m_formatUnits.insert(QLatin1String("unsigned short"), QLatin1String("H")); + m_formatUnits.insert(QLatin1String("long"), QLatin1String("l")); + m_formatUnits.insert(QLatin1String("unsigned long"), QLatin1String("k")); + m_formatUnits.insert(QLatin1String("long long"), QLatin1String("L")); + m_formatUnits.insert(QLatin1String("__int64"), QLatin1String("L")); + m_formatUnits.insert(QLatin1String("unsigned long long"), QLatin1String("K")); + m_formatUnits.insert(QLatin1String("unsigned __int64"), QLatin1String("K")); + m_formatUnits.insert(QLatin1String("double"), QLatin1String("d")); + m_formatUnits.insert(QLatin1String("float"), QLatin1String("f")); +} + +void ShibokenGenerator::initKnownPythonTypes() +{ + m_knownPythonTypes.clear(); + m_knownPythonTypes << QLatin1String("PyBool") << QLatin1String("PyInt") + << QLatin1String("PyFloat") << QLatin1String("PyLong") << QLatin1String("PyObject") + << QLatin1String("PyString") << QLatin1String("PyBuffer") << QLatin1String("PySequence") + << QLatin1String("PyTuple") << QLatin1String("PyList") << QLatin1String("PyDict") + << QLatin1String("PyObject*") << QLatin1String("PyObject *") << QLatin1String("PyTupleObject*"); +} + +QString ShibokenGenerator::translateTypeForWrapperMethod(const AbstractMetaType* cType, + const AbstractMetaClass* context, + Options options) const +{ + if (cType->isArray()) + return translateTypeForWrapperMethod(cType->arrayElementType(), context, options) + QLatin1String("[]"); + + if (avoidProtectedHack() && cType->isEnum()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(cType); + if (metaEnum && metaEnum->isProtected()) + return protectedEnumSurrogateName(metaEnum); + } + + return translateType(cType, context, options); +} + +bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const +{ + bool result = metaClass->isPolymorphic() || metaClass->hasVirtualDestructor(); + if (avoidProtectedHack()) { + result = result || metaClass->hasProtectedFields() || metaClass->hasProtectedDestructor(); + if (!result && metaClass->hasProtectedFunctions()) { + int protectedFunctions = 0; + int protectedOperators = 0; + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (const AbstractMetaFunction *func : funcs) { + if (!func->isProtected() || func->isSignal() || func->isModifiedRemoved()) + continue; + else if (func->isOperatorOverload()) + protectedOperators++; + else + protectedFunctions++; + } + result = result || (protectedFunctions > protectedOperators); + } + } else { + result = result && !metaClass->hasPrivateDestructor(); + } + return result && !metaClass->isNamespace(); +} + +void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass) +{ + if (!metaClass) + return; + + if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum *metaEnum : enums) { + if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) + continue; + if (!enumList.contains(const_cast(metaEnum))) + enumList.append(const_cast(metaEnum)); + } + lookForEnumsInClassesNotToBeGenerated(enumList, metaClass->enclosingClass()); + } +} + +static const AbstractMetaClass* getProperEnclosingClass(const AbstractMetaClass* metaClass) +{ + if (!metaClass) + return 0; + + if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) + return metaClass; + + return getProperEnclosingClass(metaClass->enclosingClass()); +} + +const AbstractMetaClass* ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum) +{ + return getProperEnclosingClass(metaEnum->enclosingClass()); +} + +QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const +{ + if (shouldGenerateCppWrapper(metaClass)) { + QString result = metaClass->name(); + if (metaClass->enclosingClass()) // is a inner class + result.replace(QLatin1String("::"), QLatin1String("_")); + + result += QLatin1String("Wrapper"); + return result; + } else { + return metaClass->qualifiedCppName(); + } +} + +QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const +{ + return metaType->cppSignature(); +} + +QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func) +{ + QString funcName; + if (func->isOperatorOverload()) + funcName = ShibokenGenerator::pythonOperatorFunctionName(func); + else + funcName = func->name(); + if (func->ownerClass()) { + QString fullName = func->ownerClass()->fullName(); + if (func->isConstructor()) + funcName = fullName; + else + funcName.prepend(fullName + QLatin1Char('.')); + } + return funcName; +} + +QString ShibokenGenerator::protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum) +{ + return metaEnum->fullName().replace(QLatin1Char('.'), QLatin1Char('_')).replace(QLatin1String("::"), QLatin1String("_")) + QLatin1String("_Surrogate"); +} + +QString ShibokenGenerator::protectedFieldGetterName(const AbstractMetaField* field) +{ + return QStringLiteral("protected_%1_getter").arg(field->name()); +} + +QString ShibokenGenerator::protectedFieldSetterName(const AbstractMetaField* field) +{ + return QStringLiteral("protected_%1_setter").arg(field->name()); +} + +QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func) +{ + QString result; + + // PYSIDE-331: For inherited functions, we need to find the same labels. + // Therefore we use the implementing class. + if (func->implementingClass()) { + result = cpythonBaseName(func->implementingClass()->typeEntry()); + if (func->isConstructor()) { + result += QLatin1String("_Init"); + } else { + result += QLatin1String("Func_"); + if (func->isOperatorOverload()) + result += ShibokenGenerator::pythonOperatorFunctionName(func); + else + result += func->name(); + } + } else { + result = QLatin1String("Sbk") + moduleName() + QLatin1String("Module_") + func->name(); + } + + return result; +} + +QString ShibokenGenerator::cpythonMethodDefinitionName(const AbstractMetaFunction* func) +{ + if (!func->ownerClass()) + return QString(); + return QStringLiteral("%1Method_%2").arg(cpythonBaseName(func->ownerClass()->typeEntry()), func->name()); +} + +QString ShibokenGenerator::cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass) +{ + return cpythonBaseName(metaClass) + QLatin1String("_getsetlist"); +} + +QString ShibokenGenerator::cpythonSetattroFunctionName(const AbstractMetaClass* metaClass) +{ + return cpythonBaseName(metaClass) + QLatin1String("_setattro"); +} + + +QString ShibokenGenerator::cpythonGetattroFunctionName(const AbstractMetaClass* metaClass) +{ + return cpythonBaseName(metaClass) + QLatin1String("_getattro"); +} + +QString ShibokenGenerator::cpythonGetterFunctionName(const AbstractMetaField* metaField) +{ + return QStringLiteral("%1_get_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); +} + +QString ShibokenGenerator::cpythonSetterFunctionName(const AbstractMetaField* metaField) +{ + return QStringLiteral("%1_set_%2").arg(cpythonBaseName(metaField->enclosingClass()), metaField->name()); +} + +static QString cpythonEnumFlagsName(QString moduleName, QString qualifiedCppName) +{ + QString result = QStringLiteral("Sbk%1_%2").arg(moduleName, qualifiedCppName); + result.replace(QLatin1String("::"), QLatin1String("_")); + return result; +} + +static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QString& value) +{ + QString enumValueName = value.trimmed(); + + if (!metaClass) + return QString(); + const AbstractMetaEnumList &enums = metaClass->enums(); + for (const AbstractMetaEnum* metaEnum : enums) { + const AbstractMetaEnumValueList &values = metaEnum->values(); + for (const AbstractMetaEnumValue *enumValue : values) { + if (enumValueName == enumValue->name()) + return metaClass->qualifiedCppName(); + } + } + // PYSIDE-331: We need to also search the base classes. + QString ret = searchForEnumScope(metaClass->enclosingClass(), enumValueName); + if (ret.isEmpty()) + ret = searchForEnumScope(metaClass->baseClass(), enumValueName); + return ret; +} + +/* + * This function uses some heuristics to find out the scope for a given + * argument default value. New situations may arise in the future and + * this method should be updated, do it with care. + */ +QString ShibokenGenerator::guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg) +{ + QString value = getDefaultValue(func, arg); + + if (value.isEmpty()) + return QString(); + + if (isPointer(arg->type())) + return value; + + static const QRegularExpression enumValueRegEx(QStringLiteral("^([A-Za-z_]\\w*)?$")); + Q_ASSERT(enumValueRegEx.isValid()); + // Do not qualify macros by class name, eg QSGGeometry(..., int t = GL_UNSIGNED_SHORT); + static const QRegularExpression macroRegEx(QStringLiteral("^[A-Z_][A-Z0-9_]*$")); + Q_ASSERT(macroRegEx.isValid()); + if (arg->type()->isPrimitive() && macroRegEx.match(value).hasMatch()) + return value; + + QString prefix; + QString suffix; + + if (arg->type()->isEnum()) { + const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(arg->type()); + if (metaEnum) + prefix = resolveScopePrefix(metaEnum->enclosingClass(), value); + } else if (arg->type()->isFlags()) { + static const QRegularExpression numberRegEx(QStringLiteral("^\\d+$")); // Numbers to flags + Q_ASSERT(numberRegEx.isValid()); + if (numberRegEx.match(value).hasMatch()) { + QString typeName = translateTypeForWrapperMethod(arg->type(), func->implementingClass()); + if (arg->type()->isConstant()) + typeName.remove(0, sizeof("const ") / sizeof(char) - 1); + switch (arg->type()->referenceType()) { + case NoReference: + break; + case LValueReference: + typeName.chop(1); + break; + case RValueReference: + typeName.chop(2); + break; + } + prefix = typeName + QLatin1Char('('); + suffix = QLatin1Char(')'); + } + + static const QRegularExpression enumCombinationRegEx(QStringLiteral("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...) + Q_ASSERT(enumCombinationRegEx.isValid()); + const QRegularExpressionMatch match = enumCombinationRegEx.match(value); + if (prefix.isEmpty() && match.hasMatch()) { + QString flagName = match.captured(1); + QStringList enumItems = match.captured(2).split(QLatin1Char('|')); + QString scope = searchForEnumScope(func->implementingClass(), enumItems.first()); + if (!scope.isEmpty()) + scope.append(QLatin1String("::")); + + QStringList fixedEnumItems; + for (const QString &enumItem : qAsConst(enumItems)) + fixedEnumItems << QString(scope + enumItem); + + if (!fixedEnumItems.isEmpty()) { + prefix = flagName + QLatin1Char('('); + value = fixedEnumItems.join(QLatin1Char('|')); + suffix = QLatin1Char(')'); + } + } + } else if (arg->type()->typeEntry()->isValue()) { + const AbstractMetaClass *metaClass = AbstractMetaClass::findClass(classes(), arg->type()->typeEntry()); + if (enumValueRegEx.match(value).hasMatch() && value != QLatin1String("NULL")) + prefix = resolveScopePrefix(metaClass, value); + } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) { + if (enumValueRegEx.match(value).hasMatch() && func->implementingClass()) + prefix = resolveScopePrefix(func->implementingClass(), value); + } else if(arg->type()->isPrimitive()) { + static const QRegularExpression unknowArgumentRegEx(QStringLiteral("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)] + Q_ASSERT(unknowArgumentRegEx.isValid()); + const QRegularExpressionMatch match = unknowArgumentRegEx.match(value); + if (match.hasMatch() && func->implementingClass()) { + const AbstractMetaFieldList &fields = func->implementingClass()->fields(); + for (const AbstractMetaField *field : fields) { + if (match.captured(1).trimmed() == field->name()) { + QString fieldName = field->name(); + if (field->isStatic()) { + prefix = resolveScopePrefix(func->implementingClass(), value); + fieldName.prepend(prefix); + prefix.clear(); + } else { + fieldName.prepend(QLatin1String(CPP_SELF_VAR "->")); + } + value.replace(match.captured(1), fieldName); + break; + } + } + } + } + + if (!prefix.isEmpty()) + value.prepend(prefix); + if (!suffix.isEmpty()) + value.append(suffix); + + return value; +} + +QString ShibokenGenerator::cpythonEnumName(const EnumTypeEntry* enumEntry) +{ + QString p = enumEntry->targetLangPackage(); + p.replace(QLatin1Char('.'), QLatin1Char('_')); + return cpythonEnumFlagsName(p, enumEntry->qualifiedCppName()); +} + +QString ShibokenGenerator::cpythonEnumName(const AbstractMetaEnum *metaEnum) +{ + return cpythonEnumName(metaEnum->typeEntry()); +} + +QString ShibokenGenerator::cpythonFlagsName(const FlagsTypeEntry* flagsEntry) +{ + QString p = flagsEntry->targetLangPackage(); + p.replace(QLatin1Char('.'), QLatin1Char('_')); + return cpythonEnumFlagsName(p, flagsEntry->originalName()); +} + +QString ShibokenGenerator::cpythonFlagsName(const AbstractMetaEnum *metaEnum) +{ + const FlagsTypeEntry *flags = metaEnum->typeEntry()->flags(); + if (!flags) + return QString(); + return cpythonFlagsName(flags); +} + +QString ShibokenGenerator::cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass) +{ + return cpythonBaseName(metaClass->typeEntry()) + QLatin1String("SpecialCastFunction"); +} + +QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName) +{ + return cpythonWrapperCPtr(metaClass->typeEntry(), argName); +} + +QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName) +{ + if (!ShibokenGenerator::isWrapperType(metaType->typeEntry())) + return QString(); + return QLatin1String("reinterpret_cast< ::") + metaType->cppSignature() + + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(metaType) + + QLatin1String(", reinterpret_cast(") + argName + QLatin1String(")))"); +} + +QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName) +{ + if (!ShibokenGenerator::isWrapperType(type)) + return QString(); + return QLatin1String("reinterpret_cast< ::") + type->qualifiedCppName() + + QLatin1String(" *>(Shiboken::Conversions::cppPointer(") + cpythonTypeNameExt(type) + + QLatin1String(", reinterpret_cast(") + argName + QLatin1String(")))"); +} + +QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* func, Options) const +{ + if (func->ownerClass() && func->isConstructor()) + return func->ownerClass()->qualifiedCppName() + QLatin1Char('*'); + + return translateTypeForWrapperMethod(func->type(), func->implementingClass()); +} + +void ShibokenGenerator::writeToPythonConversion(QTextStream & s, const AbstractMetaType* type, + const AbstractMetaClass * /* context */, + const QString& argumentName) +{ + s << cpythonToPythonConversionFunction(type) << argumentName << ')'; +} + +void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, + const QString& inArgName, const QString& outArgName) +{ + s << cpythonToCppConversionFunction(metaClass) << inArgName << ", &" << outArgName << ')'; +} + +void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context, + const QString& inArgName, const QString& outArgName) +{ + s << cpythonToCppConversionFunction(type, context) << inArgName << ", &" << outArgName << ')'; +} + +bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex) +{ + if (argIndex < 0 || argIndex >= func->arguments().count()) + return false; + + const AbstractMetaArgument* arg = func->arguments().at(argIndex); + if (isValueTypeWithCopyConstructorOnly(arg->type())) + return true; + + // Argument type is not a pointer, a None rejection should not be + // necessary because the type checking would handle that already. + if (!isPointer(arg->type())) + return false; + if (func->argumentRemoved(argIndex + 1)) + return false; + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &funcMod : mods) { + for (const ArgumentModification &argMod : funcMod.argument_mods) { + if (argMod.index == argIndex + 1 && argMod.noNullPointers) + return true; + } + } + return false; +} + +QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, bool incRef) const +{ + QString result; + const char objType = (incRef ? 'O' : 'N'); + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + + if (!func->typeReplaced(arg->argumentIndex() + 1).isEmpty()) { + result += QLatin1Char(objType); + } else if (arg->type()->isQObject() + || arg->type()->isObject() + || arg->type()->isValue() + || arg->type()->isValuePointer() + || arg->type()->isNativePointer() + || arg->type()->isEnum() + || arg->type()->isFlags() + || arg->type()->isContainer() + || arg->type()->isSmartPointer() + || arg->type()->referenceType() == LValueReference) { + result += QLatin1Char(objType); + } else if (arg->type()->isPrimitive()) { + const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); + if (ptype->basicReferencedTypeEntry()) + ptype = ptype->basicReferencedTypeEntry(); + if (m_formatUnits.contains(ptype->name())) + result += m_formatUnits[ptype->name()]; + else + result += QLatin1Char(objType); + } else if (isCString(arg->type())) { + result += QLatin1Char('z'); + } else { + qCWarning(lcShiboken).noquote().nospace() + << "Method: " << func->ownerClass()->qualifiedCppName() + << "::" << func->signature() << " => Arg:" + << arg->name() << "index: " << arg->argumentIndex() + << " - cannot be handled properly. Use an inject-code to fix it!"; + result += QLatin1Char('?'); + } + } + return result; +} + +QString ShibokenGenerator::cpythonBaseName(const AbstractMetaType* type) +{ + if (isCString(type)) + return QLatin1String("PyString"); + return cpythonBaseName(type->typeEntry()); +} + +QString ShibokenGenerator::cpythonBaseName(const AbstractMetaClass* metaClass) +{ + return cpythonBaseName(metaClass->typeEntry()); +} + +QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) +{ + QString baseName; + if (ShibokenGenerator::isWrapperType(type) || type->isNamespace()) { // && type->referenceType() == NoReference) { + baseName = QLatin1String("Sbk_") + type->name(); + } else if (type->isPrimitive()) { + const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type; + while (ptype->basicReferencedTypeEntry()) + ptype = ptype->basicReferencedTypeEntry(); + if (ptype->targetLangApiName() == ptype->name()) + baseName = pythonPrimitiveTypeName(ptype->name()); + else + baseName = ptype->targetLangApiName(); + } else if (type->isEnum()) { + baseName = cpythonEnumName((const EnumTypeEntry*) type); + } else if (type->isFlags()) { + baseName = cpythonFlagsName((const FlagsTypeEntry*) type); + } else if (type->isContainer()) { + const ContainerTypeEntry* ctype = (const ContainerTypeEntry*) type; + switch (ctype->type()) { + case ContainerTypeEntry::ListContainer: + case ContainerTypeEntry::StringListContainer: + case ContainerTypeEntry::LinkedListContainer: + case ContainerTypeEntry::VectorContainer: + case ContainerTypeEntry::StackContainer: + case ContainerTypeEntry::QueueContainer: + //baseName = "PyList"; + //break; + case ContainerTypeEntry::PairContainer: + //baseName = "PyTuple"; + baseName = QLatin1String("PySequence"); + break; + case ContainerTypeEntry::SetContainer: + baseName = QLatin1String("PySet"); + break; + case ContainerTypeEntry::MapContainer: + case ContainerTypeEntry::MultiMapContainer: + case ContainerTypeEntry::HashContainer: + case ContainerTypeEntry::MultiHashContainer: + baseName = QLatin1String("PyDict"); + break; + default: + Q_ASSERT(false); + } + } else { + baseName = QLatin1String("PyObject"); + } + return baseName.replace(QLatin1String("::"), QLatin1String("_")); +} + +QString ShibokenGenerator::cpythonTypeName(const AbstractMetaClass* metaClass) +{ + return cpythonTypeName(metaClass->typeEntry()); +} + +QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type) +{ + return cpythonBaseName(type) + QLatin1String("_Type"); +} + +QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type) +{ + return cppApiVariableName(type->targetLangPackage()) + QLatin1Char('[') + + getTypeIndexVariableName(type) + QLatin1Char(']'); +} + +QString ShibokenGenerator::converterObject(const AbstractMetaType* type) +{ + if (isCString(type)) + return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter()"); + if (isVoidPointer(type)) + return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter()"); + if (type->typeEntry()->isContainer()) { + return convertersVariableName(type->typeEntry()->targetLangPackage()) + + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); + } + return converterObject(type->typeEntry()); +} + +QString ShibokenGenerator::converterObject(const TypeEntry* type) +{ + if (isCppPrimitive(type)) + return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName()); + if (isWrapperType(type) || type->isEnum() || type->isFlags()) + return QString::fromLatin1("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type)); + + if (type->isArray()) { + qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName(); + return QString::null; + } + + /* the typedef'd primitive types case */ + const PrimitiveTypeEntry* pte = dynamic_cast(type); + if (!pte) { + qDebug() << "Warning: the Qt5 primitive type is unknown" << type->qualifiedCppName(); + return QString::null; + } + if (pte->basicReferencedTypeEntry()) + pte = pte->basicReferencedTypeEntry(); + if (pte->isPrimitive() && !pte->isCppPrimitive() && !pte->customConversion()) + return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(pte->qualifiedCppName()); + + return convertersVariableName(type->targetLangPackage()) + + QLatin1Char('[') + getTypeIndexVariableName(type) + QLatin1Char(']'); +} + +QString ShibokenGenerator::cpythonTypeNameExt(const AbstractMetaType* type) +{ + return cppApiVariableName(type->typeEntry()->targetLangPackage()) + QLatin1Char('[') + + getTypeIndexVariableName(type) + QLatin1Char(']'); +} + +static QString msgUnknownOperator(const AbstractMetaFunction* func) +{ + QString result = QLatin1String("Unknown operator: \"") + func->originalName() + QLatin1Char('"'); + if (const AbstractMetaClass *c = func->implementingClass()) + result += QLatin1String(" in class: ") + c->name(); + return result; +} + +static inline QString unknownOperator() { return QStringLiteral("__UNKNOWN_OPERATOR__"); } + +QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func) +{ + if (!func->isOperatorOverload()) + return QString(); + const QString pythonOp = pythonOperatorFunctionName(func->originalName()); + if (pythonOp == unknownOperator()) + qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func); + return QLatin1String("Sbk") + func->ownerClass()->name() + + QLatin1Char('_') + pythonOp; +} + +QString ShibokenGenerator::fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative) +{ + if (toNative->sourceType()) + return fixedCppTypeName(toNative->sourceType()); + return toNative->sourceTypeName(); +} +QString ShibokenGenerator::fixedCppTypeName(const AbstractMetaType* type) +{ + return fixedCppTypeName(type->typeEntry(), type->cppSignature()); +} + +static QString _fixedCppTypeName(QString typeName) +{ + typeName.remove(QLatin1Char(' ')); + typeName.replace(QLatin1Char('.'), QLatin1Char('_')); + typeName.replace(QLatin1Char(','), QLatin1Char('_')); + typeName.replace(QLatin1Char('<'), QLatin1Char('_')); + typeName.replace(QLatin1Char('>'), QLatin1Char('_')); + typeName.replace(QLatin1String("::"), QLatin1String("_")); + typeName.replace(QLatin1String("*"), QLatin1String("PTR")); + typeName.replace(QLatin1String("&"), QLatin1String("REF")); + return typeName; +} +QString ShibokenGenerator::fixedCppTypeName(const TypeEntry* type, QString typeName) +{ + if (typeName.isEmpty()) + typeName = type->qualifiedCppName(); + if (!(type->codeGeneration() & TypeEntry::GenerateTargetLang)) { + typeName.prepend(QLatin1Char('_')); + typeName.prepend(type->targetLangPackage()); + } + return _fixedCppTypeName(typeName); +} + +QString ShibokenGenerator::pythonPrimitiveTypeName(const QString& cppTypeName) +{ + QString rv = ShibokenGenerator::m_pythonPrimitiveTypeName.value(cppTypeName, QString()); + if (rv.isEmpty()) { + // activate this when some primitive types are missing, + // i.e. when shiboken itself fails to build. + // In general, this is valid while just called by isNumeric() + // used on Qt5, 2015-09-20 + if (false) { + std::cerr << "primitive type not found: " << qPrintable(cppTypeName) << std::endl; + abort(); + } + } + return rv; +} + +QString ShibokenGenerator::pythonPrimitiveTypeName(const PrimitiveTypeEntry* type) +{ + while (type->basicReferencedTypeEntry()) + type = type->basicReferencedTypeEntry(); + return pythonPrimitiveTypeName(type->name()); +} + +QString ShibokenGenerator::pythonOperatorFunctionName(QString cppOpFuncName) +{ + QString value = m_pythonOperators.value(cppOpFuncName); + if (value.isEmpty()) + return unknownOperator(); + value.prepend(QLatin1String("__")); + value.append(QLatin1String("__")); + return value; +} + +QString ShibokenGenerator::pythonOperatorFunctionName(const AbstractMetaFunction* func) +{ + QString op = pythonOperatorFunctionName(func->originalName()); + if (op == unknownOperator()) + qCWarning(lcShiboken).noquote().nospace() << msgUnknownOperator(func); + if (func->arguments().isEmpty()) { + if (op == QLatin1String("__sub__")) + op = QLatin1String("__neg__"); + else if (op == QLatin1String("__add__")) + op = QLatin1String("__pos__"); + } else if (func->isStatic() && func->arguments().size() == 2) { + // If a operator overload function has 2 arguments and + // is static we assume that it is a reverse operator. + op = op.insert(2, QLatin1Char('r')); + } + return op; +} + +QString ShibokenGenerator::pythonRichCompareOperatorId(QString cppOpFuncName) +{ + return QLatin1String("Py_") + m_pythonOperators.value(cppOpFuncName).toUpper(); +} + +QString ShibokenGenerator::pythonRichCompareOperatorId(const AbstractMetaFunction* func) +{ + return pythonRichCompareOperatorId(func->originalName()); +} + +bool ShibokenGenerator::isNumber(QString cpythonApiName) +{ + return cpythonApiName == QLatin1String("PyInt") + || cpythonApiName == QLatin1String("PyFloat") + || cpythonApiName == QLatin1String("PyLong") + || cpythonApiName == QLatin1String("PyBool"); +} + +bool ShibokenGenerator::isNumber(const TypeEntry* type) +{ + if (!type->isPrimitive()) + return false; + return isNumber(pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type)); +} + +bool ShibokenGenerator::isNumber(const AbstractMetaType* type) +{ + return isNumber(type->typeEntry()); +} + +bool ShibokenGenerator::isPyInt(const TypeEntry* type) +{ + if (!type->isPrimitive()) + return false; + return pythonPrimitiveTypeName((const PrimitiveTypeEntry*) type) == QLatin1String("PyInt"); +} + +bool ShibokenGenerator::isPyInt(const AbstractMetaType* type) +{ + return isPyInt(type->typeEntry()); +} + +bool ShibokenGenerator::isPairContainer(const AbstractMetaType* type) +{ + return type->isContainer() + && static_cast(type->typeEntry())->type() == ContainerTypeEntry::PairContainer; +} + +bool ShibokenGenerator::isWrapperType(const TypeEntry* type) +{ + if (type->isComplex()) + return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type); + return type->isObject() || type->isValue() || type->isSmartPointer(); +} +bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type) +{ + return isObjectType(type) || type->isValue() || type->isSmartPointer(); +} +bool ShibokenGenerator::isWrapperType(const AbstractMetaType* metaType) +{ + return isObjectType(metaType) + || metaType->typeEntry()->isValue() + || metaType->typeEntry()->isSmartPointer(); +} + +bool ShibokenGenerator::isPointerToWrapperType(const AbstractMetaType* type) +{ + return (isObjectType(type) && type->indirections() == 1) || type->isValuePointer(); +} + +bool ShibokenGenerator::isObjectTypeUsedAsValueType(const AbstractMetaType* type) +{ + return type->typeEntry()->isObject() && type->referenceType() == NoReference && type->indirections() == 0; +} + +bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass) +{ + if (!metaClass || !metaClass->typeEntry()->isValue()) + return false; + AbstractMetaFunctionList ctors = metaClass->queryFunctions(AbstractMetaClass::Constructors); + if (ctors.count() != 1) + return false; + return ctors.first()->functionType() == AbstractMetaFunction::CopyConstructorFunction; +} + +bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const +{ + if (!type || !type->isValue()) + return false; + return isValueTypeWithCopyConstructorOnly(AbstractMetaClass::findClass(classes(), type)); +} + +bool ShibokenGenerator::isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const +{ + if (!type || !type->typeEntry()->isValue()) + return false; + return isValueTypeWithCopyConstructorOnly(type->typeEntry()); +} + +bool ShibokenGenerator::isUserPrimitive(const TypeEntry* type) +{ + if (!type->isPrimitive()) + return false; + const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + if (trueType->basicReferencedTypeEntry()) + trueType = trueType->basicReferencedTypeEntry(); + return trueType->isPrimitive() && !trueType->isCppPrimitive() + && trueType->qualifiedCppName() != QLatin1String("std::string"); +} + +bool ShibokenGenerator::isUserPrimitive(const AbstractMetaType* type) +{ + if (type->indirections() != 0) + return false; + return isUserPrimitive(type->typeEntry()); +} + +bool ShibokenGenerator::isCppPrimitive(const TypeEntry* type) +{ + if (type->isCppPrimitive()) + return true; + if (!type->isPrimitive()) + return false; + const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + if (trueType->basicReferencedTypeEntry()) + trueType = trueType->basicReferencedTypeEntry(); + return trueType->qualifiedCppName() == QLatin1String("std::string"); +} + +bool ShibokenGenerator::isCppPrimitive(const AbstractMetaType* type) +{ + if (isCString(type) || isVoidPointer(type)) + return true; + if (type->indirections() != 0) + return false; + return isCppPrimitive(type->typeEntry()); +} + +bool ShibokenGenerator::shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg) +{ + return shouldDereferenceAbstractMetaTypePointer(arg->type()); +} + +bool ShibokenGenerator::shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType) +{ + return metaType->referenceType() == LValueReference && isWrapperType(metaType) && !isPointer(metaType); +} + +bool ShibokenGenerator::visibilityModifiedToPrivate(const AbstractMetaFunction* func) +{ + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &mod : mods) { + if (mod.modifiers & Modification::Private) + return true; + } + return false; +} + +QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType) +{ + QString customCheck; + if (metaType->typeEntry()->isCustom()) { + AbstractMetaType* type; + customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type); + if (type) + metaType = type; + if (!customCheck.isEmpty()) + return customCheck; + } + + if (isCppPrimitive(metaType)) { + if (isCString(metaType)) + return QLatin1String("Shiboken::String::check"); + if (isVoidPointer(metaType)) + return QLatin1String("PyObject_Check"); + return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); + } else if (metaType->typeEntry()->isContainer()) { + QString typeCheck = QLatin1String("Shiboken::Conversions::"); + ContainerTypeEntry::Type type = ((const ContainerTypeEntry*)metaType->typeEntry())->type(); + if (type == ContainerTypeEntry::ListContainer + || type == ContainerTypeEntry::StringListContainer + || type == ContainerTypeEntry::LinkedListContainer + || type == ContainerTypeEntry::VectorContainer + || type == ContainerTypeEntry::StackContainer + || type == ContainerTypeEntry::SetContainer + || type == ContainerTypeEntry::QueueContainer) { + const AbstractMetaType* type = metaType->instantiations().first(); + if (isPointerToWrapperType(type)) { + typeCheck += QString::fromLatin1("checkSequenceTypes(%1, ").arg(cpythonTypeNameExt(type)); + } else if (isWrapperType(type)) { + typeCheck += QLatin1String("convertibleSequenceTypes(reinterpret_cast("); + typeCheck += cpythonTypeNameExt(type); + typeCheck += QLatin1String("), "); + } else { + typeCheck += QString::fromLatin1("convertibleSequenceTypes(%1, ").arg(converterObject(type)); + } + } else if (type == ContainerTypeEntry::MapContainer + || type == ContainerTypeEntry::MultiMapContainer + || type == ContainerTypeEntry::HashContainer + || type == ContainerTypeEntry::MultiHashContainer + || type == ContainerTypeEntry::PairContainer) { + QString pyType = (type == ContainerTypeEntry::PairContainer) ? QLatin1String("Pair") : QLatin1String("Dict"); + const AbstractMetaType* firstType = metaType->instantiations().first(); + const AbstractMetaType* secondType = metaType->instantiations().last(); + if (isPointerToWrapperType(firstType) && isPointerToWrapperType(secondType)) { + typeCheck += QString::fromLatin1("check%1Types(%2, %3, ").arg(pyType) + .arg(cpythonTypeNameExt(firstType), cpythonTypeNameExt(secondType)); + } else { + typeCheck += QString::fromLatin1("convertible%1Types(%2, %3, %4, %5, ") + .arg(pyType, converterObject(firstType), + isPointerToWrapperType(firstType) ? QLatin1String("true") : QLatin1String("false"), + converterObject(secondType), + isPointerToWrapperType(secondType) ? QLatin1String("true") : QLatin1String("false")); + } + } + return typeCheck; + } + return cpythonCheckFunction(metaType->typeEntry(), genericNumberType); +} + +QString ShibokenGenerator::cpythonCheckFunction(const TypeEntry* type, bool genericNumberType) +{ + QString customCheck; + if (type->isCustom()) { + AbstractMetaType* metaType; + customCheck = guessCPythonCheckFunction(type->name(), &metaType); + if (metaType) + return cpythonCheckFunction(metaType, genericNumberType); + return customCheck; + } + + if (type->isEnum() || type->isFlags() || isWrapperType(type)) + return QString::fromLatin1("SbkObject_TypeCheck(%1, ").arg(cpythonTypeNameExt(type)); + else if (isCppPrimitive(type)) + return pythonPrimitiveTypeName((const PrimitiveTypeEntry*)type) + QLatin1String("_Check"); + QString typeCheck; + if (type->targetLangApiName() == type->name()) + typeCheck = cpythonIsConvertibleFunction(type); + else if (type->targetLangApiName() == QLatin1String("PyUnicode")) + typeCheck = QLatin1String("Shiboken::String::check"); + else + typeCheck = type->targetLangApiName() + QLatin1String("_Check"); + return typeCheck; +} + +QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType) +{ + *metaType = 0; + if (type == QLatin1String("PyTypeObject")) + return QLatin1String("PyType_Check"); + + if (type == QLatin1String("PyBuffer")) + return QLatin1String("Shiboken::Buffer::checkType"); + + if (type == QLatin1String("str")) + return QLatin1String("Shiboken::String::check"); + + *metaType = buildAbstractMetaTypeFromString(type); + if (*metaType && !(*metaType)->typeEntry()->isCustom()) + return QString(); + + return type + QLatin1String("_Check"); +} + +QString ShibokenGenerator::guessCPythonIsConvertible(const QString& type) +{ + if (type == QLatin1String("PyTypeObject")) + return QLatin1String("PyType_Check"); + + AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type); + if (metaType && !metaType->typeEntry()->isCustom()) + return cpythonIsConvertibleFunction(metaType); + + return type + QLatin1String("_Check"); +} + +QString ShibokenGenerator::cpythonIsConvertibleFunction(const TypeEntry* type, + bool /* genericNumberType */, + bool /* checkExact */) +{ + if (isWrapperType(type)) { + QString result = QLatin1String("Shiboken::Conversions::"); + result += (type->isValue() && !isValueTypeWithCopyConstructorOnly(type)) + ? QLatin1String("isPythonToCppValueConvertible") + : QLatin1String("isPythonToCppPointerConvertible"); + result += QLatin1String("(reinterpret_cast(") + + cpythonTypeNameExt(type) + QLatin1String("), "); + return result; + } + return QString::fromLatin1("Shiboken::Conversions::isPythonToCppConvertible(%1, ") + .arg(converterObject(type)); +} +QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaType* metaType, + bool /* genericNumberType */) +{ + QString customCheck; + if (metaType->typeEntry()->isCustom()) { + AbstractMetaType* type; + customCheck = guessCPythonCheckFunction(metaType->typeEntry()->name(), &type); + if (type) + metaType = type; + if (!customCheck.isEmpty()) + return customCheck; + } + + if (isWrapperType(metaType)) { + QString result = QLatin1String("Shiboken::Conversions::"); + if (isPointer(metaType) || isValueTypeWithCopyConstructorOnly(metaType)) + result += QLatin1String("isPythonToCppPointerConvertible"); + else if (metaType->referenceType() == LValueReference) + result += QLatin1String("isPythonToCppReferenceConvertible"); + else + result += QLatin1String("isPythonToCppValueConvertible"); + result += QLatin1String("(reinterpret_cast(") + + cpythonTypeNameExt(metaType) + QLatin1String("), "); + return result; + } + return QStringLiteral("Shiboken::Conversions::isPythonToCppConvertible(%1, ") + .arg(converterObject(metaType)); +} + +QString ShibokenGenerator::cpythonIsConvertibleFunction(const AbstractMetaArgument *metaArg, bool genericNumberType) +{ + return cpythonIsConvertibleFunction(metaArg->type(), genericNumberType); +} + +QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaClass* metaClass) +{ + return QLatin1String("Shiboken::Conversions::pythonToCppPointer(reinterpret_cast(") + + cpythonTypeNameExt(metaClass->typeEntry()) + QLatin1String("), "); +} + +QString ShibokenGenerator::cpythonToCppConversionFunction(const AbstractMetaType *type, + const AbstractMetaClass * /* context */) +{ + if (isWrapperType(type)) { + return QLatin1String("Shiboken::Conversions::pythonToCpp") + + (isPointer(type) ? QLatin1String("Pointer") : QLatin1String("Copy")) + + QLatin1String("(reinterpret_cast(") + + cpythonTypeNameExt(type) + QLatin1String("), "); + } + return QStringLiteral("Shiboken::Conversions::pythonToCppCopy(%1, ") + .arg(converterObject(type)); +} + +QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaType *type, + const AbstractMetaClass * /* context */) +{ + if (isWrapperType(type)) { + QString conversion; + if (type->referenceType() == LValueReference && !(type->isValue() && type->isConstant()) && !isPointer(type)) + conversion = QLatin1String("reference"); + else if (type->isValue() || type->isSmartPointer()) + conversion = QLatin1String("copy"); + else + conversion = QLatin1String("pointer"); + QString result = QLatin1String("Shiboken::Conversions::") + conversion + + QLatin1String("ToPython(reinterpret_cast(") + + cpythonTypeNameExt(type) + QLatin1String("), "); + if (conversion != QLatin1String("pointer")) + result += QLatin1Char('&'); + return result; + } + return QStringLiteral("Shiboken::Conversions::copyToPython(%1, %2") + .arg(converterObject(type), + (isCString(type) || isVoidPointer(type)) ? QString() : QLatin1String("&")); +} + +QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass) +{ + return cpythonToPythonConversionFunction(metaClass->typeEntry()); +} + +QString ShibokenGenerator::cpythonToPythonConversionFunction(const TypeEntry* type) +{ + if (isWrapperType(type)) { + const QString conversion = type->isValue() ? QLatin1String("copy") : QLatin1String("pointer"); + QString result = QLatin1String("Shiboken::Conversions::") + conversion + + QLatin1String("ToPython(reinterpret_cast(") + cpythonTypeNameExt(type) + + QLatin1String("), "); + if (conversion != QLatin1String("pointer")) + result += QLatin1Char('&'); + return result; + } + + return QStringLiteral("Shiboken::Conversions::copyToPython(%1, &").arg(converterObject(type)); +} + +QString ShibokenGenerator::argumentString(const AbstractMetaFunction *func, + const AbstractMetaArgument *argument, + Options options) const +{ + QString modified_type; + if (!(options & OriginalTypeDescription)) + modified_type = func->typeReplaced(argument->argumentIndex() + 1); + QString arg; + + if (modified_type.isEmpty()) + arg = translateType(argument->type(), func->implementingClass(), options); + else + arg = modified_type.replace(QLatin1Char('$'), QLatin1Char('.')); + + if (!(options & Generator::SkipName)) { + arg += QLatin1Char(' '); + arg += argument->name(); + } + + if ((options & Generator::SkipDefaultValues) != Generator::SkipDefaultValues && + !argument->originalDefaultValueExpression().isEmpty()) + { + QString default_value = argument->originalDefaultValueExpression(); + if (default_value == QLatin1String("NULL")) + default_value = QLatin1String(NULL_VALUE); + + //WORKAROUND: fix this please + if (default_value.startsWith(QLatin1String("new "))) + default_value.remove(0, 4); + + arg += QLatin1String(" = ") + default_value; + } + + return arg; +} + +void ShibokenGenerator::writeArgument(QTextStream &s, + const AbstractMetaFunction *func, + const AbstractMetaArgument *argument, + Options options) const +{ + s << argumentString(func, argument, options); +} + +void ShibokenGenerator::writeFunctionArguments(QTextStream &s, + const AbstractMetaFunction *func, + Options options) const +{ + AbstractMetaArgumentList arguments = func->arguments(); + + if (options & Generator::WriteSelf) { + s << func->implementingClass()->name() << '&'; + if (!(options & SkipName)) + s << " " PYTHON_SELF_VAR; + } + + int argUsed = 0; + for (int i = 0; i < arguments.size(); ++i) { + if ((options & Generator::SkipRemovedArguments) && func->argumentRemoved(i+1)) + continue; + + if ((options & Generator::WriteSelf) || argUsed != 0) + s << ", "; + writeArgument(s, func, arguments[i], options); + argUsed++; + } +} + +QString ShibokenGenerator::functionReturnType(const AbstractMetaFunction* func, Options options) const +{ + QString modifiedReturnType = QString(func->typeReplaced(0)); + if (!modifiedReturnType.isNull() && !(options & OriginalTypeDescription)) + return modifiedReturnType; + else + return translateType(func->type(), func->implementingClass(), options); +} + +QString ShibokenGenerator::functionSignature(const AbstractMetaFunction *func, + QString prepend, + QString append, + Options options, + int /* argCount */) const +{ + QString result; + QTextStream s(&result); + // The actual function + if (!(func->isEmptyFunction() || + func->isNormal() || + func->isSignal())) { + options |= Generator::SkipReturnType; + } else { + s << functionReturnType(func, options) << ' '; + } + + // name + QString name(func->originalName()); + if (func->isConstructor()) + name = wrapperName(func->ownerClass()); + + s << prepend << name << append << '('; + writeFunctionArguments(s, func, options); + s << ')'; + + if (func->isConstant() && !(options & Generator::ExcludeMethodConst)) + s << " const"; + + return result; +} + +void ShibokenGenerator::writeArgumentNames(QTextStream &s, + const AbstractMetaFunction *func, + Options options) const +{ + AbstractMetaArgumentList arguments = func->arguments(); + int argCount = 0; + for (int j = 0, max = arguments.size(); j < max; j++) { + + if ((options & Generator::SkipRemovedArguments) && (func->argumentRemoved(arguments.at(j)->argumentIndex()+1))) + continue; + + s << ((argCount > 0) ? ", " : "") << arguments.at(j)->name(); + + if (((options & Generator::VirtualCall) == 0) + && (!func->conversionRule(TypeSystem::NativeCode, arguments.at(j)->argumentIndex() + 1).isEmpty() + || !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty()) + && !func->isConstructor()) { + s << CONV_RULE_OUT_VAR_SUFFIX; + } + + argCount++; + } +} + +void ShibokenGenerator::writeFunctionCall(QTextStream& s, + const AbstractMetaFunction* func, + Options options) const +{ + if (!(options & Generator::SkipName)) + s << (func->isConstructor() ? func->ownerClass()->qualifiedCppName() : func->originalName()); + s << '('; + writeArgumentNames(s, func, options); + s << ')'; +} + +void ShibokenGenerator::writeUnusedVariableCast(QTextStream& s, const QString& variableName) +{ + s << INDENT << "SBK_UNUSED(" << variableName<< ')' << endl; +} + +AbstractMetaFunctionList ShibokenGenerator::filterFunctions(const AbstractMetaClass* metaClass) +{ + AbstractMetaFunctionList result; + const AbstractMetaFunctionList &funcs = metaClass->functions(); + for (AbstractMetaFunction *func : funcs) { + if (func->isSignal() || func->isDestructor() || func->usesRValueReferences() + || (func->isModifiedRemoved() && !func->isAbstract() + && (!avoidProtectedHack() || !func->isProtected()))) + continue; + result << func; + } + return result; +} + +ShibokenGenerator::ExtendedConverterData ShibokenGenerator::getExtendedConverters() const +{ + ExtendedConverterData extConvs; + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) { + // Use only the classes for the current module. + if (!shouldGenerate(metaClass)) + continue; + const AbstractMetaFunctionList &overloads = metaClass->operatorOverloads(AbstractMetaClass::ConversionOp); + for (AbstractMetaFunction *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(); + if ((convType->codeGeneration() & TypeEntry::GenerateTargetLang) + || !convType->isValue() + || convOp->isModifiedRemoved()) + continue; + extConvs[convType].append(convOp->ownerClass()); + } + } + return extConvs; +} + +QVector ShibokenGenerator::getPrimitiveCustomConversions() +{ + QVector conversions; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) { + if (!shouldGenerateTypeEntry(type) || !isUserPrimitive(type) || !type->customConversion()) + continue; + + conversions << type->customConversion(); + } + return conversions; +} + +static QString getArgumentsFromMethodCall(const QString& str) +{ + // It would be way nicer to be able to use a Perl like + // regular expression that accepts temporary variables + // to count the parenthesis. + // 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); + if (pos == -1) + return QString(); + pos = pos + funcCall.size(); + while (str.at(pos) == QLatin1Char(' ') || str.at(pos) == QLatin1Char('\t')) + ++pos; + if (str.at(pos) == QLatin1Char('(')) + ++pos; + int begin = pos; + int counter = 1; + while (counter != 0) { + if (str.at(pos) == QLatin1Char('(')) + ++counter; + else if (str.at(pos) == QLatin1Char(')')) + --counter; + ++pos; + } + return str.mid(begin, pos-begin-1); +} + +QString ShibokenGenerator::getCodeSnippets(const CodeSnipList& codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language) +{ + QString code; + QTextStream c(&code); + for (const CodeSnip &snip : codeSnips) { + if ((position != TypeSystem::CodeSnipPositionAny && snip.position != position) || !(snip.language & language)) + continue; + QString snipCode; + QTextStream sc(&snipCode); + formatCode(sc, snip.code(), INDENT); + c << snipCode; + } + return code; +} +void ShibokenGenerator::processCodeSnip(QString& code, const AbstractMetaClass* context) +{ + if (context) { + // Replace template variable by the Python Type object + // for the class context in which the variable is used. + code.replace(QLatin1String("%PYTHONTYPEOBJECT"), + cpythonTypeName(context) + QLatin1String(".super.ht_type")); + code.replace(QLatin1String("%TYPE"), wrapperName(context)); + code.replace(QLatin1String("%CPPTYPE"), context->name()); + } + + // replace "toPython" converters + replaceConvertToPythonTypeSystemVariable(code); + + // replace "toCpp" converters + replaceConvertToCppTypeSystemVariable(code); + + // replace "isConvertible" check + replaceIsConvertibleToCppTypeSystemVariable(code); + + // replace "checkType" check + replaceTypeCheckTypeSystemVariable(code); +} + +ShibokenGenerator::ArgumentVarReplacementList ShibokenGenerator::getArgumentReplacement(const AbstractMetaFunction* func, + bool usePyArgs, TypeSystem::Language language, + const AbstractMetaArgument* lastArg) +{ + ArgumentVarReplacementList argReplacements; + TypeSystem::Language convLang = (language == TypeSystem::TargetLangCode) + ? TypeSystem::NativeCode : TypeSystem::TargetLangCode; + int removed = 0; + for (int i = 0; i < func->arguments().size(); ++i) { + const AbstractMetaArgument* arg = func->arguments().at(i); + QString argValue; + if (language == TypeSystem::TargetLangCode) { + bool hasConversionRule = !func->conversionRule(convLang, i+1).isEmpty(); + bool argRemoved = func->argumentRemoved(i+1); + removed = removed + (int) argRemoved; + if (argRemoved && hasConversionRule) + argValue = arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX); + else if (argRemoved || (lastArg && arg->argumentIndex() > lastArg->argumentIndex())) + argValue = QLatin1String(CPP_ARG_REMOVED) + QString::number(i); + if (!argRemoved && argValue.isEmpty()) { + int argPos = i - removed; + const AbstractMetaType* type = arg->type(); + QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); + if (!typeReplaced.isEmpty()) { + AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced); + if (builtType) + type = builtType; + } + if (type->typeEntry()->isCustom()) { + argValue = usePyArgs + ? QString::fromLatin1(PYTHON_ARGS "[%1]").arg(argPos) + : QLatin1String(PYTHON_ARG); + } else { + argValue = hasConversionRule + ? arg->name() + QLatin1String(CONV_RULE_OUT_VAR_SUFFIX) + : QLatin1String(CPP_ARG) + QString::number(argPos); + if (isWrapperType(type)) { + if (type->referenceType() == LValueReference && !isPointer(type)) + argValue.prepend(QLatin1Char('*')); + } + } + } + } else { + argValue = arg->name(); + } + if (!argValue.isEmpty()) + argReplacements << ArgumentVarReplacementPair(arg, argValue); + + } + return argReplacements; +} + +void ShibokenGenerator::writeCodeSnips(QTextStream& s, + const CodeSnipList& codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const AbstractMetaClass* context) +{ + QString code = getCodeSnippets(codeSnips, position, language); + if (code.isEmpty()) + return; + processCodeSnip(code, context); + s << INDENT << "// Begin code injection" << endl; + s << code; + s << INDENT << "// End of code injection" << endl; +} + +static QString msgWrongIndex(const char *varName, const QString &capture, const AbstractMetaFunction *func) +{ + QString result; + QTextStream str(&result); + str << "Wrong index for " << varName << " variable (" << capture << ") on "; + if (const AbstractMetaClass *c = func->implementingClass()) + str << c->name() << "::"; + str << func->signature(); + return result; +} + +void ShibokenGenerator::writeCodeSnips(QTextStream& s, + const CodeSnipList& codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const AbstractMetaFunction* func, + const AbstractMetaArgument* lastArg) +{ + QString code = getCodeSnippets(codeSnips, position, language); + if (code.isEmpty()) + return; + + // Calculate the real number of arguments. + int argsRemoved = 0; + for (int i = 0; i < func->arguments().size(); i++) { + if (func->argumentRemoved(i+1)) + argsRemoved++; + } + + OverloadData od(getFunctionGroups(func->implementingClass())[func->name()], this); + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(od); + + // Replace %PYARG_# variables. + code.replace(QLatin1String("%PYARG_0"), QLatin1String(PYTHON_RETURN_VAR)); + + static const QRegularExpression pyArgsRegex(QStringLiteral("%PYARG_(\\d+)")); + Q_ASSERT(pyArgsRegex.isValid()); + if (language == TypeSystem::TargetLangCode) { + if (usePyArgs) { + code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]")); + } else { + static const QRegularExpression pyArgsRegexCheck(QStringLiteral("%PYARG_([2-9]+)")); + Q_ASSERT(pyArgsRegexCheck.isValid()); + const QRegularExpressionMatch match = pyArgsRegexCheck.match(code); + if (match.hasMatch()) { + qCWarning(lcShiboken).noquote().nospace() + << msgWrongIndex("%PYARG", match.captured(1), func); + return; + } + code.replace(QLatin1String("%PYARG_1"), QLatin1String(PYTHON_ARG)); + } + } 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*([^;]+)")); + Q_ASSERT(pyArgsAttributionRegex.isValid()); + code.replace(pyArgsAttributionRegex, QLatin1String("PyTuple_SET_ITEM(" PYTHON_ARGS ", \\1-1, \\2)")); + code.replace(pyArgsRegex, QLatin1String("PyTuple_GET_ITEM(" PYTHON_ARGS ", \\1-1)")); + } + + // Replace %ARG#_TYPE variables. + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1); + QString argTypeVal = arg->type()->cppSignature(); + code.replace(argTypeVar, argTypeVal); + } + + static const QRegularExpression cppArgTypeRegexCheck(QStringLiteral("%ARG(\\d+)_TYPE")); + 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); + } + + // Replace template variable for return variable name. + if (func->isConstructor()) { + code.replace(QLatin1String("%0."), QLatin1String("cptr->")); + code.replace(QLatin1String("%0"), QLatin1String("cptr")); + } else if (func->type()) { + QString returnValueOp = isPointerToWrapperType(func->type()) + ? QLatin1String("%1->") : QLatin1String("%1."); + if (ShibokenGenerator::isWrapperType(func->type())) + code.replace(QLatin1String("%0."), returnValueOp.arg(QLatin1String(CPP_RETURN_VAR))); + code.replace(QLatin1String("%0"), QLatin1String(CPP_RETURN_VAR)); + } + + // Replace template variable for self Python object. + QString pySelf = (language == TypeSystem::NativeCode) ? QLatin1String("pySelf") : QLatin1String(PYTHON_SELF_VAR); + code.replace(QLatin1String("%PYSELF"), pySelf); + + // Replace template variable for a pointer to C++ of this object. + if (func->implementingClass()) { + QString replacement = func->isStatic() ? QLatin1String("%1::") : QLatin1String("%1->"); + QString cppSelf; + if (func->isStatic()) + cppSelf = func->ownerClass()->qualifiedCppName(); + else if (language == TypeSystem::NativeCode) + cppSelf = QLatin1String("this"); + else + cppSelf = QLatin1String(CPP_SELF_VAR); + + // On comparison operator CPP_SELF_VAR is always a reference. + if (func->isComparisonOperator()) + replacement = QLatin1String("%1."); + + if (func->isVirtual() && !func->isAbstract() && (!avoidProtectedHack() || !func->isProtected())) { + QString methodCallArgs = getArgumentsFromMethodCall(code); + if (!methodCallArgs.isNull()) { + const QString pattern = QStringLiteral("%CPPSELF.%FUNCTION_NAME(%1)").arg(methodCallArgs); + if (func->name() == QLatin1String("metaObject")) { + QString wrapperClassName = wrapperName(func->ownerClass()); + QString cppSelfVar = avoidProtectedHack() + ? QLatin1String("%CPPSELF") + : QStringLiteral("reinterpret_cast<%1*>(%CPPSELF)").arg(wrapperClassName); + code.replace(pattern, + QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast(%1))" + " ? %2->::%3::%FUNCTION_NAME(%4)" + " : %CPPSELF.%FUNCTION_NAME(%4))").arg(pySelf, cppSelfVar, wrapperClassName, methodCallArgs)); + } else { + code.replace(pattern, + QString::fromLatin1("(Shiboken::Object::hasCppWrapper(reinterpret_cast(%1))" + " ? %CPPSELF->::%TYPE::%FUNCTION_NAME(%2)" + " : %CPPSELF.%FUNCTION_NAME(%2))").arg(pySelf, methodCallArgs)); + } + } + } + + code.replace(QLatin1String("%CPPSELF."), replacement.arg(cppSelf)); + code.replace(QLatin1String("%CPPSELF"), cppSelf); + + if (code.indexOf(QLatin1String("%BEGIN_ALLOW_THREADS")) > -1) { + if (code.count(QLatin1String("%BEGIN_ALLOW_THREADS")) == code.count(QLatin1String("%END_ALLOW_THREADS"))) { + code.replace(QLatin1String("%BEGIN_ALLOW_THREADS"), QLatin1String(BEGIN_ALLOW_THREADS)); + code.replace(QLatin1String("%END_ALLOW_THREADS"), QLatin1String(END_ALLOW_THREADS)); + } else { + qCWarning(lcShiboken) << "%BEGIN_ALLOW_THREADS and %END_ALLOW_THREADS mismatch"; + } + } + + // replace template variable for the Python Type object for the + // class implementing the method in which the code snip is written + if (func->isStatic()) { + code.replace(QLatin1String("%PYTHONTYPEOBJECT"), + cpythonTypeName(func->implementingClass()) + QLatin1String(".super.ht_type")); + } else { + code.replace(QLatin1String("%PYTHONTYPEOBJECT."), pySelf + QLatin1String("->ob_type->")); + code.replace(QLatin1String("%PYTHONTYPEOBJECT"), pySelf + QLatin1String("->ob_type")); + } + } + + // Replaces template %ARGUMENT_NAMES and %# variables by argument variables and values. + // Replaces template variables %# for individual arguments. + const ArgumentVarReplacementList &argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg); + + QStringList args; + for (const ArgumentVarReplacementPair &pair : argReplacements) { + if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED))) + continue; + args << pair.second; + } + code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", "))); + + for (const ArgumentVarReplacementPair &pair : argReplacements) { + const AbstractMetaArgument* arg = pair.first; + int idx = arg->argumentIndex() + 1; + AbstractMetaType* type = arg->type(); + QString typeReplaced = func->typeReplaced(arg->argumentIndex() + 1); + if (!typeReplaced.isEmpty()) { + AbstractMetaType* builtType = buildAbstractMetaTypeFromString(typeReplaced); + if (builtType) + type = builtType; + } + if (isWrapperType(type)) { + QString replacement = pair.second; + if (type->referenceType() == LValueReference && !isPointer(type)) + replacement.remove(0, 1); + if (type->referenceType() == LValueReference || isPointer(type)) + code.replace(QString::fromLatin1("%%1.").arg(idx), replacement + QLatin1String("->")); + } + code.replace(placeHolderRegex(idx), pair.second); + } + + if (language == TypeSystem::NativeCode) { + // Replaces template %PYTHON_ARGUMENTS variable with a pointer to the Python tuple + // containing the converted virtual method arguments received from C++ to be passed + // to the Python override. + code.replace(QLatin1String("%PYTHON_ARGUMENTS"), QLatin1String(PYTHON_ARGS)); + + // replace variable %PYTHON_METHOD_OVERRIDE for a pointer to the Python method + // override for the C++ virtual method in which this piece of code was inserted + code.replace(QLatin1String("%PYTHON_METHOD_OVERRIDE"), QLatin1String(PYTHON_OVERRIDE_VAR)); + } + + if (avoidProtectedHack()) { + // If the function being processed was added by the user via type system, + // Shiboken needs to find out if there are other overloads for the same method + // name and if any of them is of the protected visibility. This is used to replace + // calls to %FUNCTION_NAME on user written custom code for calls to the protected + // dispatcher. + bool hasProtectedOverload = false; + if (func->isUserAdded()) { + const AbstractMetaFunctionList &funcs = getFunctionOverloads(func->ownerClass(), func->name()); + for (const AbstractMetaFunction *f : funcs) + hasProtectedOverload |= f->isProtected(); + } + + if (func->isProtected() || hasProtectedOverload) { + code.replace(QLatin1String("%TYPE::%FUNCTION_NAME"), + QStringLiteral("%1::%2_protected") + .arg(wrapperName(func->ownerClass()), func->originalName())); + code.replace(QLatin1String("%FUNCTION_NAME"), + func->originalName() + QLatin1String("_protected")); + } + } + + if (func->isConstructor() && shouldGenerateCppWrapper(func->ownerClass())) + code.replace(QLatin1String("%TYPE"), wrapperName(func->ownerClass())); + + if (func->ownerClass()) + code.replace(QLatin1String("%CPPTYPE"), func->ownerClass()->name()); + + replaceTemplateVariables(code, func); + + processCodeSnip(code); + s << INDENT << "// Begin code injection" << endl; + s << code; + s << INDENT << "// End of code injection" << endl; +} + +// Returns true if the string is an expression, +// 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*(?:\\[[^\\[]+\\])*$")); + Q_ASSERT(expr.isValid()); + return expr.match(code.trimmed()).hasMatch(); +} + +// A miniature normalizer that puts a type string into a format +// suitable for comparison with AbstractMetaType::cppSignature() +// result. +static QString miniNormalizer(const QString& varType) +{ + QString normalized = varType.trimmed(); + if (normalized.isEmpty()) + return normalized; + if (normalized.startsWith(QLatin1String("::"))) + normalized.remove(0, 2); + QString suffix; + while (normalized.endsWith(QLatin1Char('*')) || normalized.endsWith(QLatin1Char('&'))) { + suffix.prepend(normalized.at(normalized.count() - 1)); + normalized.chop(1); + normalized = normalized.trimmed(); + } + const QString result = normalized + QLatin1Char(' ') + suffix; + return result.trimmed(); +} +// The position must indicate the first character after the opening '('. +// ATTENTION: do not modify this function to trim any resulting string! +// This must be done elsewhere. +static QString getConverterTypeSystemVariableArgument(const QString& code, int pos) +{ + QString arg; + int parenthesisDepth = 0; + int count = 0; + while (pos + count < code.count()) { + char c = code.at(pos+count).toLatin1(); // toAscii is gone + if (c == '(') { + ++parenthesisDepth; + } else if (c == ')') { + if (parenthesisDepth == 0) { + arg = code.mid(pos, count).trimmed(); + break; + } + --parenthesisDepth; + } + ++count; + } + if (parenthesisDepth != 0) + qFatal("Unbalanced parenthesis on type system converter variable call."); + return arg; +} +typedef QPair StringPair; +void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code) +{ + QVector replacements; + QRegularExpressionMatchIterator rit = m_typeSystemConvRegEx[converterVariable].globalMatch(code); + while (rit.hasNext()) { + const QRegularExpressionMatch match = rit.next(); + const QStringList list = match.capturedTexts(); + QString conversionString = list.first(); + QString conversionTypeName = list.last(); + const AbstractMetaType* conversionType = buildAbstractMetaTypeFromString(conversionTypeName); + if (!conversionType) { + qFatal(qPrintable(QString::fromLatin1("Could not find type '%1' for use in '%2' conversion. " + "Make sure to use the full C++ name, e.g. 'Namespace::Class'.") + .arg(conversionTypeName).arg(m_typeSystemConvName[converterVariable])), NULL); + + } + QString conversion; + QTextStream c(&conversion); + switch (converterVariable) { + case TypeSystemToCppFunction: { + int end = match.capturedStart(); + int start = end; + while (start > 0 && code.at(start) != QLatin1Char('\n')) + --start; + while (code.at(start).isSpace()) + ++start; + QString varType = code.mid(start, end - start); + conversionString = varType + list.first(); + varType = miniNormalizer(varType); + QString varName = list.at(1).trimmed(); + if (!varType.isEmpty()) { + if (varType != conversionType->cppSignature()) { + qFatal(qPrintable(QString::fromLatin1("Types of receiver variable ('%1') and %CONVERTTOCPP type system variable ('%2') differ.") + .arg(varType, conversionType->cppSignature())), NULL); + } + c << getFullTypeName(conversionType) << ' ' << varName; + writeMinimalConstructorExpression(c, conversionType); + c << ';' << endl; + Indentation indent(INDENT); + c << INDENT; + } + c << cpythonToCppConversionFunction(conversionType); + QString prefix; + if (varName.startsWith(QLatin1Char('*'))) { + varName.remove(0, 1); + varName = varName.trimmed(); + } else { + prefix = QLatin1Char('&'); + } + QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); + conversionString += arg; + c << arg << ", " << prefix << '(' << varName << ')'; + break; + } + case TypeSystemCheckFunction: + conversion = cpythonCheckFunction(conversionType); + if (conversionType->typeEntry()->isPrimitive() + && (conversionType->typeEntry()->name() == QLatin1String("PyObject") + || !conversion.endsWith(QLatin1Char(' ')))) { + c << '('; + break; + } + case TypeSystemIsConvertibleFunction: + if (conversion.isEmpty()) + conversion = cpythonIsConvertibleFunction(conversionType); + case TypeSystemToPythonFunction: + if (conversion.isEmpty()) + conversion = cpythonToPythonConversionFunction(conversionType); + default: { + QString arg = getConverterTypeSystemVariableArgument(code, match.capturedEnd()); + conversionString += arg; + if (converterVariable == TypeSystemToPythonFunction && !isVariable(arg)) { + qFatal(qPrintable(QString::fromLatin1("Only variables are acceptable as argument to %%CONVERTTOPYTHON type system variable on code snippet: '%1'") + .arg(code)), NULL); + } + if (conversion.contains(QLatin1String("%in"))) { + conversion.prepend(QLatin1Char('(')); + conversion.replace(QLatin1String("%in"), arg); + } else { + c << arg; + } + } + } + replacements.append(qMakePair(conversionString, conversion)); + } + for (const StringPair &rep : qAsConst(replacements)) + code.replace(rep.first, rep.second); +} + +bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func) +{ + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(QLatin1String("%CPPSELF"))) + return true; + } + return false; +} + +bool ShibokenGenerator::injectedCodeUsesPySelf(const AbstractMetaFunction* func) +{ + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(QLatin1String("%PYSELF"))) + return true; + } + return false; +} + +bool ShibokenGenerator::injectedCodeCallsCppFunction(const AbstractMetaFunction* func) +{ + QString funcCall = func->originalName() + QLatin1Char('('); + QString wrappedCtorCall; + if (func->isConstructor()) { + funcCall.prepend(QLatin1String("new ")); + wrappedCtorCall = QStringLiteral("new %1(").arg(wrapperName(func->ownerClass())); + } + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode); + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(QLatin1String("%FUNCTION_NAME(")) || snip.code().contains(funcCall) + || (func->isConstructor() + && ((func->ownerClass()->isPolymorphic() && snip.code().contains(wrappedCtorCall)) + || snip.code().contains(QLatin1String("new %TYPE(")))) + ) + return true; + } + return false; +} + +bool ShibokenGenerator::injectedCodeCallsPythonOverride(const AbstractMetaFunction* func) +{ + static const QRegularExpression overrideCallRegexCheck(QStringLiteral("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,")); + Q_ASSERT(overrideCallRegexCheck.isValid()); + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode); + for (const CodeSnip &snip : qAsConst(snips)) { + if (snip.code().contains(overrideCallRegexCheck)) + return true; + } + return false; +} + +bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language) +{ + static const QRegularExpression retValAttributionRegexCheck_native(QStringLiteral("%0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_native.isValid()); + static const QRegularExpression retValAttributionRegexCheck_target(QStringLiteral("%PYARG_0\\s*=[^=]\\s*.+")); + Q_ASSERT(retValAttributionRegexCheck_target.isValid()); + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language); + for (const CodeSnip &snip : qAsConst(snips)) { + if (language == TypeSystem::TargetLangCode) { + if (snip.code().contains(retValAttributionRegexCheck_target)) + return true; + } else { + if (snip.code().contains(retValAttributionRegexCheck_native)) + return true; + } + } + return false; +} + +bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex) +{ + CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny); + const QRegularExpression argRegEx = placeHolderRegex(argumentIndex + 1); + for (const CodeSnip &snip : qAsConst(snips)) { + QString code = snip.code(); + if (code.contains(QLatin1String("%ARGUMENT_NAMES")) || code.contains(argRegEx)) + return true; + } + return false; +} + +bool ShibokenGenerator::hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass) +{ + if (!metaClass || metaClass->baseClassNames().isEmpty()) + return false; + if (metaClass->baseClassNames().size() > 1) + return true; + return hasMultipleInheritanceInAncestry(metaClass->baseClass()); +} + +typedef QMap FunctionGroupMap; +typedef FunctionGroupMap::const_iterator FunctionGroupMapIt; + +bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* metaClass) +{ + if (!metaClass) + return false; + if (metaClass->typeEntry()->isSmartPointer()) + return true; + const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass); + for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) { + AbstractMetaFunctionList overloads; + for (AbstractMetaFunction *func : qAsConst(it.value())) { + if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() + || func->isPrivate() || func->ownerClass() != func->implementingClass() + || func->isConstructor() || func->isOperatorOverload()) + continue; + overloads.append(func); + } + if (overloads.isEmpty()) + continue; + if (OverloadData::hasStaticAndInstanceFunctions(overloads)) + return true; + } + return false; +} + +bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *metaClass) +{ + if (!metaClass) + return false; + if (metaClass->typeEntry()->isSmartPointer()) + return true; + return false; +} + +AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass) +{ + AbstractMetaFunctionList methods; + if (metaClass) { + const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); + for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + AbstractMetaFunctionList overloads; + for (AbstractMetaFunction *func : qAsConst(it.value())) { + if (func->isAssignmentOperator() || func->isCastOperator() || func->isModifiedRemoved() + || func->isPrivate() || func->ownerClass() != func->implementingClass() + || func->isConstructor() || func->isOperatorOverload()) + continue; + overloads.append(func); + } + if (overloads.isEmpty()) + continue; + if (OverloadData::hasStaticAndInstanceFunctions(overloads)) + methods.append(overloads.first()); + } + } + return methods; +} + +AbstractMetaClassList ShibokenGenerator::getBaseClasses(const AbstractMetaClass* metaClass) const +{ + AbstractMetaClassList baseClasses; + if (metaClass) { + const QStringList &baseClassNames = metaClass->baseClassNames(); + for (const QString &parent : baseClassNames) { + AbstractMetaClass *clazz = AbstractMetaClass::findClass(classes(), parent); + if (clazz) + baseClasses << clazz; + } + } + return baseClasses; +} + +const AbstractMetaClass* ShibokenGenerator::getMultipleInheritingClass(const AbstractMetaClass* metaClass) +{ + if (!metaClass || metaClass->baseClassNames().isEmpty()) + return 0; + if (metaClass->baseClassNames().size() > 1) + return metaClass; + return getMultipleInheritingClass(metaClass->baseClass()); +} + +AbstractMetaClassList ShibokenGenerator::getAllAncestors(const AbstractMetaClass* metaClass) const +{ + AbstractMetaClassList result; + if (metaClass) { + AbstractMetaClassList baseClasses = getBaseClasses(metaClass); + for (AbstractMetaClass *base : qAsConst(baseClasses)) { + result.append(base); + result.append(getAllAncestors(base)); + } + } + return result; +} + +QString ShibokenGenerator::getModuleHeaderFileName(const QString& moduleName) const +{ + QString result = moduleName.isEmpty() ? packageName() : moduleName; + result.replace(QLatin1Char('.'), QLatin1Char('_')); + return result.toLower() + QLatin1String("_python.h"); +} + +QString ShibokenGenerator::extendedIsConvertibleFunctionName(const TypeEntry* targetType) const +{ + QString p = targetType->targetLangPackage(); + p.replace(QLatin1Char('.'), QLatin1Char('_')); + return QStringLiteral("ExtendedIsConvertible_%1_%2").arg(p, targetType->name()); +} + +QString ShibokenGenerator::extendedToCppFunctionName(const TypeEntry* targetType) const +{ + QString p = targetType->targetLangPackage(); + p.replace(QLatin1Char('.'), QLatin1Char('_')); + return QStringLiteral("ExtendedToCpp_%1_%2").arg(p, targetType->name()); +} + +bool ShibokenGenerator::isCopyable(const AbstractMetaClass *metaClass) + +{ + if (metaClass->isNamespace() || isObjectType(metaClass)) + return false; + else if (metaClass->typeEntry()->copyable() == ComplexTypeEntry::Unknown) + return metaClass->hasCloneOperator(); + else + return (metaClass->typeEntry()->copyable() == ComplexTypeEntry::CopyableSet); + + return false; +} + +AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromString(QString typeSignature) +{ + typeSignature = typeSignature.trimmed(); + if (typeSignature.startsWith(QLatin1String("::"))) + typeSignature.remove(0, 2); + + if (m_metaTypeFromStringCache.contains(typeSignature)) + return m_metaTypeFromStringCache.value(typeSignature); + + QString typeString = typeSignature; + bool isConst = typeString.startsWith(QLatin1String("const ")); + if (isConst) + typeString.remove(0, sizeof("const ") / sizeof(char) - 1); + + ReferenceType refType = NoReference; + if (typeString.endsWith(QLatin1String("&&"))) { + refType = RValueReference; + typeString.chop(2); + typeString = typeString.trimmed(); + } else if (typeString.endsWith(QLatin1Char('&'))) { + refType = LValueReference; + typeString.chop(1); + typeString = typeString.trimmed(); + } + + int indirections = 0; + while (typeString.endsWith(QLatin1Char('*'))) { + ++indirections; + typeString.chop(1); + typeString = typeString.trimmed(); + } + + if (typeString.startsWith(QLatin1String("::"))) + typeString.remove(0, 2); + + QString adjustedTypeName = typeString; + QStringList instantiatedTypes; + int lpos = typeString.indexOf(QLatin1Char('<')); + if (lpos > -1) { + int rpos = typeString.lastIndexOf(QLatin1Char('>')); + if ((lpos != -1) && (rpos != -1)) { + QString type = typeString.mid(lpos + 1, rpos - lpos - 1); + int depth = 0; + int start = 0; + for (int i = 0; i < type.count(); ++i) { + if (type.at(i) == QLatin1Char('<')) { + ++depth; + } else if (type.at(i) == QLatin1Char('>')) { + --depth; + } else if (type.at(i) == QLatin1Char(',') && depth == 0) { + instantiatedTypes << type.mid(start, i - start).trimmed(); + start = i + 1; + } + } + instantiatedTypes << type.mid(start).trimmed(); + adjustedTypeName.truncate(lpos); + } + } + + TypeEntry* typeEntry = TypeDatabase::instance()->findType(adjustedTypeName); + + AbstractMetaType* metaType = 0; + if (typeEntry) { + metaType = new AbstractMetaType(); + metaType->setTypeEntry(typeEntry); + metaType->setIndirections(indirections); + metaType->setReferenceType(refType); + metaType->setConstant(isConst); + metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern); + for (const QString &instantiation : qAsConst(instantiatedTypes)) { + AbstractMetaType* tmplArgType = buildAbstractMetaTypeFromString(instantiation); + metaType->addInstantiation(tmplArgType); + } + metaType->decideUsagePattern(); + m_metaTypeFromStringCache.insert(typeSignature, metaType); + } + return metaType; +} + +AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry) +{ + QString typeName = typeEntry->qualifiedCppName(); + if (typeName.startsWith(QLatin1String("::"))) + typeName.remove(0, 2); + if (m_metaTypeFromStringCache.contains(typeName)) + return m_metaTypeFromStringCache.value(typeName); + AbstractMetaType* metaType = new AbstractMetaType; + metaType->setTypeEntry(typeEntry); + metaType->setIndirections(0); + metaType->setReferenceType(NoReference); + metaType->setConstant(false); + metaType->decideUsagePattern(); + m_metaTypeFromStringCache.insert(typeName, metaType); + return metaType; +} +AbstractMetaType* ShibokenGenerator::buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass) +{ + return ShibokenGenerator::buildAbstractMetaTypeFromTypeEntry(metaClass->typeEntry()); +} + +/* +static void dumpFunction(AbstractMetaFunctionList lst) +{ + qDebug() << "DUMP FUNCTIONS: "; + for (AbstractMetaFunction *func : qAsConst(lst)) + qDebug() << "*" << func->ownerClass()->name() + << func->signature() + << "Private: " << func->isPrivate() + << "Empty: " << func->isEmptyFunction() + << "Static:" << func->isStatic() + << "Signal:" << func->isSignal() + << "ClassImplements: " << (func->ownerClass() != func->implementingClass()) + << "is operator:" << func->isOperatorOverload() + << "is global:" << func->isInGlobalScope(); +} +*/ + +static bool isGroupable(const AbstractMetaFunction* func) +{ + if (func->isSignal() || func->isDestructor() || (func->isModifiedRemoved() && !func->isAbstract())) + return false; + // weird operator overloads + if (func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) // FIXME: what about cast operators? + return false;; + return true; +} + +QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(const AbstractMetaClass* scope) +{ + AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); + + QMap results; + for (AbstractMetaFunction *func : qAsConst(lst)) { + if (isGroupable(func)) + results[func->name()].append(func); + } + return results; +} + +AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet *seen) +{ + AbstractMetaFunctionList results; + AbstractMetaClass* basis; + if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) { + for (; basis; basis = basis->baseClass()) { + const AbstractMetaFunction* inFunc = basis->findFunction(func->name()); + if (inFunc && !seen->contains(inFunc->minimalSignature())) { + seen->insert(inFunc->minimalSignature()); + AbstractMetaFunction* newFunc = inFunc->copy(); + newFunc->setImplementingClass(func->implementingClass()); + results << newFunc; + } + } + } + return results; +} + +AbstractMetaFunctionList ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet *seen) +{ + AbstractMetaFunctionList results; + seen->insert(func->minimalSignature()); + results << const_cast(func) << getInheritedOverloads(func, seen); + return results; +} + +AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName) +{ + AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); + + AbstractMetaFunctionList results; + QSet seenSignatures; + for (AbstractMetaFunction *func : qAsConst(lst)) { + if (func->name() != functionName) + continue; + if (isGroupable(func)) { + // PYSIDE-331: look also into base classes. + results << getFunctionAndInheritedOverloads(func, &seenSignatures); + } + } + return results; +} + +QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction) +{ + AbstractMetaFunctionList overloads = getFunctionOverloads(metaFunction->ownerClass(), metaFunction->name()); + + int minArgs = std::numeric_limits::max(); + int maxArgs = 0; + for (const AbstractMetaFunction* func : qAsConst(overloads)) { + int numArgs = 0; + const AbstractMetaArgumentList &arguments = func->arguments(); + for (const AbstractMetaArgument *arg : arguments) { + if (!func->argumentRemoved(arg->argumentIndex() + 1)) + numArgs++; + } + maxArgs = std::max(maxArgs, numArgs); + minArgs = std::min(minArgs, numArgs); + } + return qMakePair(minArgs, maxArgs); +} + +QMap ShibokenGenerator::options() const +{ + QMap opts(Generator::options()); + opts.insert(QLatin1String(AVOID_PROTECTED_HACK), + QLatin1String("Avoid the use of the '#define protected public' hack.")); + opts.insert(QLatin1String(PARENT_CTOR_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on constructors.")); + opts.insert(QLatin1String(RETURN_VALUE_HEURISTIC), + QLatin1String("Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!)")); + opts.insert(QLatin1String(ENABLE_PYSIDE_EXTENSIONS), + QLatin1String("Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt-based library.")); + opts.insert(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES), + QLatin1String("Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings.")); + opts.insert(QLatin1String(USE_ISNULL_AS_NB_NONZERO), + QLatin1String("If a class have an isNull()const method, it will be used to compute the value of boolean casts")); + return opts; +} + +static void getCode(QStringList& code, const CodeSnipList& codeSnips) +{ + for (const CodeSnip &snip : qAsConst(codeSnips)) + code.append(snip.code()); +} + +static void getCode(QStringList& code, const TypeEntry* type) +{ + getCode(code, type->codeSnips()); + + CustomConversion* customConversion = type->customConversion(); + if (!customConversion) + return; + + if (!customConversion->nativeToTargetConversion().isEmpty()) + code.append(customConversion->nativeToTargetConversion()); + + const CustomConversion::TargetToNativeConversions& toCppConversions = customConversion->targetToNativeConversions(); + if (toCppConversions.isEmpty()) + return; + + for (CustomConversion::TargetToNativeConversion *toNative : qAsConst(toCppConversions)) + code.append(toNative->conversion()); +} + +bool ShibokenGenerator::doSetup(const QMap& args) +{ + m_useCtorHeuristic = args.contains(QLatin1String(PARENT_CTOR_HEURISTIC)); + m_usePySideExtensions = args.contains(QLatin1String(ENABLE_PYSIDE_EXTENSIONS)); + m_userReturnValueHeuristic = args.contains(QLatin1String(RETURN_VALUE_HEURISTIC)); + m_verboseErrorMessagesDisabled = args.contains(QLatin1String(DISABLE_VERBOSE_ERROR_MESSAGES)); + m_useIsNullAsNbNonZero = args.contains(QLatin1String(USE_ISNULL_AS_NB_NONZERO)); + m_avoidProtectedHack = args.contains(QLatin1String(AVOID_PROTECTED_HACK)); + + TypeDatabase* td = TypeDatabase::instance(); + QStringList snips; + const PrimitiveTypeEntryList &primitiveTypeList = primitiveTypes(); + for (const PrimitiveTypeEntry *type : primitiveTypeList) + getCode(snips, type); + const ContainerTypeEntryList &containerTypeList = containerTypes(); + for (const ContainerTypeEntry *type : containerTypeList) + getCode(snips, type); + const AbstractMetaClassList &classList = classes(); + for (const AbstractMetaClass *metaClass : classList) + getCode(snips, metaClass->typeEntry()); + getCode(snips, td->findType(packageName())); + const FunctionGroupMap &functionGroups = getFunctionGroups(); + for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { + for (AbstractMetaFunction *func : it.value()) + getCode(snips, func->injectedCodeSnips()); + } + + for (const QString &code : qAsConst(snips)) { + collectContainerTypesFromConverterMacros(code, true); + collectContainerTypesFromConverterMacros(code, false); + } + + return true; +} + +void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro) +{ + QString convMacro = toPythonMacro ? QLatin1String("%CONVERTTOPYTHON[") : QLatin1String("%CONVERTTOCPP["); + int offset = toPythonMacro ? sizeof("%CONVERTTOPYTHON") : sizeof("%CONVERTTOCPP"); + int start = 0; + while ((start = code.indexOf(convMacro, start)) != -1) { + int end = code.indexOf(QLatin1Char(']'), start); + start += offset; + if (code.at(start) != QLatin1Char('%')) { + QString typeString = code.mid(start, end - start); + AbstractMetaType* type = buildAbstractMetaTypeFromString(typeString); + addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription()); + } + start = end; + } +} + +bool ShibokenGenerator::useCtorHeuristic() const +{ + return m_useCtorHeuristic; +} + +bool ShibokenGenerator::useReturnValueHeuristic() const +{ + return m_userReturnValueHeuristic; +} + +bool ShibokenGenerator::usePySideExtensions() const +{ + return m_usePySideExtensions; +} + +bool ShibokenGenerator::useIsNullAsNbNonZero() const +{ + return m_useIsNullAsNbNonZero; +} + +bool ShibokenGenerator::avoidProtectedHack() const +{ + return m_avoidProtectedHack; +} + +QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const +{ + QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName; + result.replace(QLatin1Char('.'), QLatin1Char('_')); + result.prepend(QLatin1String("Sbk")); + result.append(QLatin1String("Types")); + return result; +} + +QString ShibokenGenerator::convertersVariableName(const QString& moduleName) const +{ + QString result = cppApiVariableName(moduleName); + result.chop(1); + result.append(QLatin1String("Converters")); + return result; +} + +static QString processInstantiationsVariableName(const AbstractMetaType* type) +{ + QString res = QLatin1Char('_') + _fixedCppTypeName(type->typeEntry()->qualifiedCppName()).toUpper(); + const AbstractMetaTypeList &instantiations = type->instantiations(); + for (const AbstractMetaType *instantiation : instantiations) { + res += instantiation->isContainer() + ? processInstantiationsVariableName(instantiation) + : QLatin1Char('_') + _fixedCppTypeName(instantiation->cppSignature()).toUpper(); + } + return res; +} +QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName) +{ + if (alternativeTemplateName) { + const AbstractMetaClass* templateBaseClass = metaClass->templateBaseClass(); + if (!templateBaseClass) + return QString(); + QString base = _fixedCppTypeName(templateBaseClass->typeEntry()->qualifiedCppName()).toUpper(); + QString instantiations; + const AbstractMetaTypeList &templateBaseClassInstantiations = metaClass->templateBaseClassInstantiations(); + for (const AbstractMetaType *instantiation : templateBaseClassInstantiations) + instantiations += processInstantiationsVariableName(instantiation); + return QString::fromLatin1("SBK_%1%2_IDX").arg(base, instantiations); + } + return getTypeIndexVariableName(metaClass->typeEntry()); +} +QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* type) +{ + if (type->isCppPrimitive()) { + const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + if (trueType->basicReferencedTypeEntry()) + type = trueType->basicReferencedTypeEntry(); + } + return QString::fromLatin1("SBK_%1_IDX").arg(_fixedCppTypeName(type->qualifiedCppName()).toUpper()); +} +QString ShibokenGenerator::getTypeIndexVariableName(const AbstractMetaType* type) +{ + return QString::fromLatin1("SBK%1%2_IDX") + .arg(type->typeEntry()->isContainer() ? QLatin1Char('_') + moduleName().toUpper() : QString(), + processInstantiationsVariableName(type)); +} + +bool ShibokenGenerator::verboseErrorMessagesDisabled() const +{ + return m_verboseErrorMessagesDisabled; +} + +bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData) +{ + if (overloadData.referenceFunction()->isCallOperator()) + return true; + if (overloadData.referenceFunction()->isOperatorOverload()) + return false; + int maxArgs = overloadData.maxArgs(); + int minArgs = overloadData.minArgs(); + return (minArgs != maxArgs) + || (maxArgs > 1) + || overloadData.referenceFunction()->isConstructor() + || overloadData.hasArgumentWithDefaultValue(); +} + +Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType* metaType) +{ + // exclude const on Objects + Options flags; + const TypeEntry* type = metaType->typeEntry(); + bool isCStr = isCString(metaType); + if (metaType->indirections() && !isCStr) { + flags = ExcludeConst; + } else if (metaType->isContainer() + || (type->isPrimitive() && !isCStr) + // const refs become just the value, but pure refs must remain pure. + || (type->isValue() && metaType->isConstant() && metaType->referenceType() == LValueReference)) { + flags = ExcludeConst | ExcludeReference; + } + return flags; +} + +QString ShibokenGenerator::getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg) +{ + if (!arg->defaultValueExpression().isEmpty()) + return arg->defaultValueExpression(); + + //Check modifications + const FunctionModificationList &mods = func->modifications(); + for (const FunctionModification &m : mods) { + for (const ArgumentModification &am : m.argument_mods) { + if (am.index == (arg->argumentIndex() + 1)) + return am.replacedDefaultExpression; + } + } + return QString(); +} + +void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor) +{ + if (defaultCtor.isEmpty() && isCppPrimitive(type)) + return; + QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; + if (ctor.isEmpty()) { + const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->cppSignature()); + qCWarning(lcShiboken()).noquote() << message; + s << ";\n#error " << message << '\n'; + } else { + s << " = " << ctor; + } +} + +void ShibokenGenerator::writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor) +{ + if (defaultCtor.isEmpty() && isCppPrimitive(type)) + return; + QString ctor = defaultCtor.isEmpty() ? minimalConstructor(type) : defaultCtor; + + if (ctor.isEmpty()) { + const QString message = msgCouldNotFindMinimalConstructor(QLatin1String(__FUNCTION__), type->qualifiedCppName()); + qCWarning(lcShiboken()).noquote() << message; + s << ";\n#error " << message << endl; + } else { + s << " = " << ctor; + } +} + +bool ShibokenGenerator::isCppIntegralPrimitive(const TypeEntry* type) +{ + if (!type->isCppPrimitive()) + return false; + const PrimitiveTypeEntry* trueType = (const PrimitiveTypeEntry*) type; + if (trueType->basicReferencedTypeEntry()) + trueType = trueType->basicReferencedTypeEntry(); + QString typeName = trueType->qualifiedCppName(); + return !typeName.contains(QLatin1String("double")) + && !typeName.contains(QLatin1String("float")) + && !typeName.contains(QLatin1String("wchar")); +} +bool ShibokenGenerator::isCppIntegralPrimitive(const AbstractMetaType* type) +{ + return isCppIntegralPrimitive(type->typeEntry()); +} + +QString ShibokenGenerator::msgCouldNotFindMinimalConstructor(const QString &where, const QString &type) +{ + return where + QLatin1String(": Could not find a minimal constructor for type '") + type + + QLatin1String("'. This will result in a compilation error."); +} diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h new file mode 100644 index 000000000..1be56edc8 --- /dev/null +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -0,0 +1,556 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIBOKENGENERATOR_H +#define SHIBOKENGENERATOR_H + +#define CONV_RULE_OUT_VAR_SUFFIX "_out" +#define CPP_ARG "cppArg" +#define CPP_ARG0 CPP_ARG"0" +#define CPP_ARG_REMOVED "removed_" CPP_ARG +#define CPP_RETURN_VAR "cppResult" +#define CPP_SELF_VAR "cppSelf" +#define PYTHON_ARG "pyArg" +#define PYTHON_ARGS PYTHON_ARG "s" +#define PYTHON_OVERRIDE_VAR "pyOverride" +#define PYTHON_RETURN_VAR "pyResult" +#define PYTHON_SELF_VAR "self" +#define THREAD_STATE_SAVER_VAR "threadStateSaver" +#define BEGIN_ALLOW_THREADS "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS" +#define END_ALLOW_THREADS "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS" +#define PYTHON_TO_CPP_VAR "pythonToCpp" +#define SMART_POINTER_GETTER "kSmartPointerGetter" + +#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\(" +#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\(" +#define CONVERTTOPYTHON_REGEX "%CONVERTTOPYTHON\\[([^\\[]*)\\]\\(" +#define CONVERTTOCPP_REGEX "(\\*?%?[a-zA-Z_][\\w\\.]*(?:\\[[^\\[^<^>]+\\])*)"\ + "(?:\\s+)=(?:\\s+)%CONVERTTOCPP\\[([^\\[]*)\\]\\(" + +#include + +#include "typesystem.h" + +#include + +class DocParser; +class CodeSnip; +class OverloadData; + +QT_FORWARD_DECLARE_CLASS(QTextStream) + +/** + * Abstract generator that contains common methods used in CppGenerator and HeaderGenerator. + */ +class ShibokenGenerator : public Generator +{ +public: + ShibokenGenerator(); + virtual ~ShibokenGenerator(); + + QString translateTypeForWrapperMethod(const AbstractMetaType* cType, + const AbstractMetaClass* context, Options opt = NoOption) const; + + /** + * Returns a map with all functions grouped, the function name is used as key. + * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} + * \param scope Where to search for functions, null means all global functions. + */ + QMap getFunctionGroups(const AbstractMetaClass* scope = 0); + + /** + * Returns all different inherited overloads of func. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func, QSet *seen); + + /** + * Returns all different inherited overloads of func, and includes func as well. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet *seen); + + /** + * Returns all overloads for a function named \p functionName. + * \param scope scope used to search for overloads. + * \param functionName the function name. + */ + AbstractMetaFunctionList getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName); + /** + * Returns the minimun and maximun number of arguments which this function and all overloads + * can accept. Arguments removed by typesystem are considered as well. + */ + QPair getMinMaxArguments(const AbstractMetaFunction* metaFunction); + /** + * Write a function argument in the C++ in the text stream \p s. + * This function just call \code s << argumentString(); \endcode + * \param s text stream used to write the output. + * \param func the current metafunction. + * \param argument metaargument information to be parsed. + * \param options some extra options. + */ + void writeArgument(QTextStream &s, + const AbstractMetaFunction* func, + const AbstractMetaArgument* argument, + Options options = NoOption) const; + /** + * Create a QString in the C++ format to an function argument. + * \param func the current metafunction. + * \param argument metaargument information to be parsed. + * \param options some extra options. + */ + QString argumentString(const AbstractMetaFunction* func, + const AbstractMetaArgument* argument, + Options options = NoOption) const; + + void writeArgumentNames(QTextStream &s, + const AbstractMetaFunction* func, + Options options = NoOption) const override; + + /** + * Function used to write the fucntion arguments on the class buffer. + * \param s the class output buffer + * \param func the pointer to metafunction information + * \param count the number of function arguments + * \param options some extra options used during the parser + */ + void writeFunctionArguments(QTextStream &s, + const AbstractMetaFunction* func, + Options options = NoOption) const override; + QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; + + /// Utility function for writeCodeSnips. + typedef QPair ArgumentVarReplacementPair; + typedef QVector ArgumentVarReplacementList; + ArgumentVarReplacementList getArgumentReplacement(const AbstractMetaFunction* func, + bool usePyArgs, TypeSystem::Language language, + const AbstractMetaArgument* lastArg); + + /// Write user's custom code snippets at class or module level. + void writeCodeSnips(QTextStream& s, + const QVector & codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const AbstractMetaClass* context = 0); + /// Write user's custom code snippets at function level. + void writeCodeSnips(QTextStream& s, + const QVector & codeSnips, + TypeSystem::CodeSnipPosition position, + TypeSystem::Language language, + const AbstractMetaFunction* func, + const AbstractMetaArgument* lastArg = 0); + + /// Returns a string with the user's custom code snippets that comply with \p position and \p language. + QString getCodeSnippets(const QVector & codeSnips, TypeSystem::CodeSnipPosition position, TypeSystem::Language language); + + /// Replaces variables for the user's custom code at global or class level. + void processCodeSnip(QString& code, const AbstractMetaClass* context = 0); + + /// Replaces the %CONVERTTOPYTHON type system variable. + inline void replaceConvertToPythonTypeSystemVariable(QString& code) + { + replaceConverterTypeSystemVariable(TypeSystemToPythonFunction, code); + } + /// Replaces the %CONVERTTOCPP type system variable. + inline void replaceConvertToCppTypeSystemVariable(QString& code) + { + replaceConverterTypeSystemVariable(TypeSystemToCppFunction, code); + } + /// Replaces the %ISCONVERTIBLE type system variable. + inline void replaceIsConvertibleToCppTypeSystemVariable(QString& code) + { + replaceConverterTypeSystemVariable(TypeSystemIsConvertibleFunction, code); + } + /// Replaces the %CHECKTYPE type system variable. + inline void replaceTypeCheckTypeSystemVariable(QString& code) + { + replaceConverterTypeSystemVariable(TypeSystemCheckFunction, code); + } + + /** + * Verifies if any of the function's code injections of the "target" + * type needs the type system variable "%CPPSELF". + * \param func the function to check + * \return true if the function's target code snippets use "%CPPSELF" + */ + bool injectedCodeUsesCppSelf(const AbstractMetaFunction* func); + + /** + * Verifies if any of the function's code injections of the "native" + * type needs the type system variable "%PYSELF". + * \param func the function to check + * \return true if the function's native code snippets use "%PYSELF" + */ + bool injectedCodeUsesPySelf(const AbstractMetaFunction* func); + + /** + * Verifies if any of the function's code injections makes a call + * to the C++ method. This is used by the generator to avoid writing calls + * to C++ when the user custom code already does this. + * \param func the function to check + * \return true if the function's code snippets call the wrapped C++ function + */ + bool injectedCodeCallsCppFunction(const AbstractMetaFunction* func); + + /** + * Verifies if any of the function's code injections of the "native" class makes a + * call to the C++ method. This is used by the generator to avoid writing calls to + * Python overrides of C++ virtual methods when the user custom code already does this. + * \param func the function to check + * \return true if the function's code snippets call the Python override for a C++ virtual method + */ + bool injectedCodeCallsPythonOverride(const AbstractMetaFunction* func); + + /** + * Verifies if any of the function's code injections attributes values to + * the return variable (%0 or %PYARG_0). + * \param func the function to check + * \param language the kind of code snip + * \return true if the function's code attributes values to "%0" or "%PYARG_0" + */ + bool injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language = TypeSystem::TargetLangCode); + + /** + * Verifies if any of the function's code injections uses the type system variable + * for function arguments of a given index. + */ + bool injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex); + + /** + * Function which parse the metafunction information + * \param func the function witch will be parserd + * \param option some extra options + * \param arg_count the number of function arguments + */ + QString functionSignature(const AbstractMetaFunction* func, + QString prepend = QString(), + QString append = QString(), + Options options = NoOption, + int arg_count = -1) const; + + /// Returns true if there are cases of multiple inheritance in any of its ancestors. + bool hasMultipleInheritanceInAncestry(const AbstractMetaClass* metaClass); + + /// Returns true if the class needs to have a getattro function. + bool classNeedsGetattroFunction(const AbstractMetaClass* metaClass); + + /// Returns true if the class needs to have a setattro function. + bool classNeedsSetattroFunction(const AbstractMetaClass *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. + AbstractMetaFunctionList getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass); + + /// Returns a list of parent classes for a given class. + AbstractMetaClassList getBaseClasses(const AbstractMetaClass* metaClass) const; + + /// Returns a list of all ancestor classes for the given class. + AbstractMetaClassList getAllAncestors(const AbstractMetaClass* metaClass) const; + + const AbstractMetaClass* getMultipleInheritingClass(const AbstractMetaClass* metaClass); + + void writeToPythonConversion(QTextStream& s, const AbstractMetaType* type, + const AbstractMetaClass* context, const QString& argumentName); + void writeToCppConversion(QTextStream& s, const AbstractMetaType* type, const AbstractMetaClass* context, const QString& inArgName, const QString& outArgName); + void writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, const QString& inArgName, const QString& outArgName); + + /// Returns true if the argument is a pointer that rejects NULL values. + bool shouldRejectNullPointerArgument(const AbstractMetaFunction* 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; + + /// Adds enums eligible for generation from classes/namespaces marked not to be generated. + static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass); + /// Returns the enclosing class for an enum, or NULL if it should be global. + const AbstractMetaClass* getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum); + + QString wrapperName(const AbstractMetaClass* metaClass) const; + QString wrapperName(const AbstractMetaType *metaType) const; + + static QString fullPythonFunctionName(const AbstractMetaFunction* func); + static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum); + static QString protectedFieldGetterName(const AbstractMetaField* field); + static QString protectedFieldSetterName(const AbstractMetaField* field); + + static QString pythonPrimitiveTypeName(const QString& cppTypeName); + static QString pythonPrimitiveTypeName(const PrimitiveTypeEntry* type); + + static QString pythonOperatorFunctionName(QString cppOpFuncName); + static QString pythonOperatorFunctionName(const AbstractMetaFunction* func); + static QString pythonRichCompareOperatorId(QString cppOpFuncName); + static QString pythonRichCompareOperatorId(const AbstractMetaFunction* func); + + static QString cpythonOperatorFunctionName(const AbstractMetaFunction* func); + + static QString fixedCppTypeName(const CustomConversion::TargetToNativeConversion* toNative); + static QString fixedCppTypeName(const AbstractMetaType* type); + static QString fixedCppTypeName(const TypeEntry* type, QString typeName = QString()); + + static bool isNumber(QString cpythonApiName); + static bool isNumber(const TypeEntry* type); + static bool isNumber(const AbstractMetaType* type); + static bool isPyInt(const TypeEntry* type); + static bool isPyInt(const AbstractMetaType* type); + static bool isPairContainer(const AbstractMetaType* type); + + /** + * Returns true if the type passed has a Python wrapper for it. + * Although namespace has a Python wrapper, it's not considered a type. + */ + static bool isWrapperType(const TypeEntry* type); + static bool isWrapperType(const ComplexTypeEntry* type); + static bool isWrapperType(const AbstractMetaType* metaType); + + /** + * Checks if the type is an Object/QObject or pointer to Value Type. + * In other words, tells if the type is "T*" and T has a Python wrapper. + */ + static bool isPointerToWrapperType(const AbstractMetaType* type); + + /** + * Returns true if \p type is an Object Type used as a value. + */ + static bool isObjectTypeUsedAsValueType(const AbstractMetaType* type); + + static bool isValueTypeWithCopyConstructorOnly(const AbstractMetaClass* metaClass); + bool isValueTypeWithCopyConstructorOnly(const TypeEntry* type) const; + bool isValueTypeWithCopyConstructorOnly(const AbstractMetaType* type) const; + + /// Returns true if the type is a primitive but not a C++ primitive. + static bool isUserPrimitive(const TypeEntry* type); + static bool isUserPrimitive(const AbstractMetaType* type); + + /// Returns true if the type is a C++ primitive, a void*, a const char*, or a std::string. + static bool isCppPrimitive(const TypeEntry* type); + static bool isCppPrimitive(const AbstractMetaType* type); + + /// Returns true if the type is a C++ integral primitive, i.e. bool, char, int, long, and their unsigned counterparts. + static bool isCppIntegralPrimitive(const TypeEntry* type); + static bool isCppIntegralPrimitive(const AbstractMetaType* type); + + /// Checks if an argument type should be dereferenced by the Python method wrapper before calling the C++ method. + static bool shouldDereferenceArgumentPointer(const AbstractMetaArgument* arg); + /// Checks if a meta type should be dereferenced by the Python method wrapper passing it to C++. + static bool shouldDereferenceAbstractMetaTypePointer(const AbstractMetaType* metaType); + + static bool visibilityModifiedToPrivate(const AbstractMetaFunction* func); + + QString converterObject(const AbstractMetaType* type); + QString converterObject(const TypeEntry* type); + + QString cpythonBaseName(const AbstractMetaClass* metaClass); + QString cpythonBaseName(const TypeEntry* type); + QString cpythonBaseName(const AbstractMetaType* type); + QString cpythonTypeName(const AbstractMetaClass* metaClass); + QString cpythonTypeName(const TypeEntry* type); + QString cpythonTypeNameExt(const TypeEntry* type); + QString cpythonTypeNameExt(const AbstractMetaType* type); + QString cpythonCheckFunction(const TypeEntry* type, bool genericNumberType = false); + QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false); + /** + * Receives the argument \p type and tries to find the appropriate AbstractMetaType for it + * or a custom type check. + * \param type A string representing the type to be discovered. + * \param metaType A pointer to an AbstractMetaType pointer, to where write a new meta type object + * if one is produced from the \p type string. This object must be deallocated by + * the caller. It will set the target variable to NULL, is \p type is a Python type. + * \return A custom check if \p type is a custom type, or an empty string if \p metaType + * receives an existing type object. + */ + QString guessCPythonCheckFunction(const QString& type, AbstractMetaType** metaType); + QString cpythonIsConvertibleFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false); + QString cpythonIsConvertibleFunction(const AbstractMetaType* metaType, bool genericNumberType = false); + QString cpythonIsConvertibleFunction(const AbstractMetaArgument* metaArg, bool genericNumberType = false); + QString guessCPythonIsConvertible(const QString& type); + + QString cpythonToCppConversionFunction(const AbstractMetaClass* metaClass); + QString cpythonToCppConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0); + QString cpythonToPythonConversionFunction(const AbstractMetaType* type, const AbstractMetaClass* context = 0); + QString cpythonToPythonConversionFunction(const AbstractMetaClass* metaClass); + QString cpythonToPythonConversionFunction(const TypeEntry* type); + + QString cpythonFunctionName(const AbstractMetaFunction* func); + QString cpythonMethodDefinitionName(const AbstractMetaFunction* func); + QString cpythonGettersSettersDefinitionName(const AbstractMetaClass* metaClass); + QString cpythonGetattroFunctionName(const AbstractMetaClass* metaClass); + QString cpythonSetattroFunctionName(const AbstractMetaClass* metaClass); + QString cpythonGetterFunctionName(const AbstractMetaField* metaField); + QString cpythonSetterFunctionName(const AbstractMetaField* metaField); + QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName = QLatin1String(PYTHON_SELF_VAR)); + QString cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName); + QString cpythonWrapperCPtr(const TypeEntry* type, QString argName); + + /// Guesses the scope to where belongs an argument's default value. + QString guessScopeForDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); + + QString cpythonEnumName(const EnumTypeEntry* enumEntry); + QString cpythonEnumName(const AbstractMetaEnum* metaEnum); + + QString cpythonFlagsName(const FlagsTypeEntry* flagsEntry); + QString cpythonFlagsName(const AbstractMetaEnum* metaEnum); + /// Returns the special cast function name, the function used to proper cast class with multiple inheritance. + QString cpythonSpecialCastFunctionName(const AbstractMetaClass* metaClass); + + QString getFunctionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const; + QString getFormatUnitString(const AbstractMetaFunction* func, bool incRef = false) const; + + /// Returns the file name for the module global header. If no module name is provided the current will be used. + QString getModuleHeaderFileName(const QString& moduleName = QString()) const; + + QString extendedIsConvertibleFunctionName(const TypeEntry* targetType) const; + QString extendedToCppFunctionName(const TypeEntry* targetType) const; + + QMap< QString, QString > options() const override; + + /// Returns true if the user enabled the so called "parent constructor heuristic". + bool useCtorHeuristic() const; + /// Returns true if the user enabled the so called "return value heuristic". + bool useReturnValueHeuristic() const; + /// Returns true if the user enabled PySide extensions. + bool usePySideExtensions() const; + /// Returns true if the generator should use the result of isNull()const to compute boolean casts. + bool useIsNullAsNbNonZero() const; + /// Returns true if the generated code should use the "#define protected public" hack. + bool avoidProtectedHack() const; + QString cppApiVariableName(const QString& moduleName = QString()) const; + QString convertersVariableName(const QString& moduleName = QString()) const; + /** + * Returns the type index variable name for a given class. If \p alternativeTemplateName is true + * and the class is a typedef for a template class instantiation, it will return an alternative name + * made of the template class and the instantiation values, or an empty string if the class isn't + * derived from a template class at all. + */ + QString getTypeIndexVariableName(const AbstractMetaClass* metaClass, bool alternativeTemplateName = false); + QString getTypeIndexVariableName(const TypeEntry* type); + QString getTypeIndexVariableName(const AbstractMetaType* type); + + /// Returns true if the user don't want verbose error messages on the generated bindings. + bool verboseErrorMessagesDisabled() const; + + /** + * Builds an AbstractMetaType object from a QString. + * Returns NULL if no type could be built from the string. + * \param typeSignature The string describing the type to be built. + * \return A new AbstractMetaType object that must be deleted by the caller, or a NULL pointer in case of failure. + */ + AbstractMetaType* buildAbstractMetaTypeFromString(QString typeSignature); + + /// Creates an AbstractMetaType object from a TypeEntry. + AbstractMetaType* buildAbstractMetaTypeFromTypeEntry(const TypeEntry* typeEntry); + /// Creates an AbstractMetaType object from an AbstractMetaClass. + AbstractMetaType* buildAbstractMetaTypeFromAbstractMetaClass(const AbstractMetaClass* metaClass); + + void writeMinimalConstructorExpression(QTextStream& s, const AbstractMetaType* type, const QString& defaultCtor = QString()); + void writeMinimalConstructorExpression(QTextStream& s, const TypeEntry* type, const QString& defaultCtor = QString()); + + /** + * Helper function to return the flags to be used by a meta type when + * it needs to write some converter code. + */ + static Options getConverterOptions(const AbstractMetaType* metaType); + + /** + * Helper function to find for argument default value + */ + static QString getDefaultValue(const AbstractMetaFunction* func, const AbstractMetaArgument* arg); +protected: + bool doSetup(const QMap& args); + void collectContainerTypesFromConverterMacros(const QString& code, bool toPythonMacro); + // verify whether the class is copyable + bool isCopyable(const AbstractMetaClass* metaClass); + + bool m_native_jump_table; + static QHash m_pythonPrimitiveTypeName; + static QHash m_pythonOperators; + static QHash m_formatUnits; + static QHash m_tpFuncs; + static QStringList m_knownPythonTypes; + + void clearTpFuncs(); + + const char* name() const { return "Shiboken"; } + + /// Initializes correspondences between primitive and Python types. + static void initPrimitiveTypesCorrespondences(); + /// Initializes a list of Python known type names. + static void initKnownPythonTypes(); + + void writeFunctionCall(QTextStream& s, + const AbstractMetaFunction* metaFunc, + Options options = NoOption) const; + + void writeUnusedVariableCast(QTextStream& s, const QString& variableName); + + AbstractMetaFunctionList filterFunctions(const AbstractMetaClass* metaClass); + + // All data about extended converters: the type entries of the target type, and a + // list of AbstractMetaClasses accepted as argument for the conversion. + typedef QHash > ExtendedConverterData; + /// 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. + QVector getPrimitiveCustomConversions(); + + /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. + static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); + + Indentor INDENT; + + enum TypeSystemConverterVariable { + TypeSystemCheckFunction = 0, + TypeSystemIsConvertibleFunction, + TypeSystemToCppFunction, + TypeSystemToPythonFunction, + TypeSystemConverterVariables + }; + void replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code); + + static QString msgCouldNotFindMinimalConstructor(const QString &where, const QString &type); + +private: + bool m_useCtorHeuristic; + bool m_userReturnValueHeuristic; + bool m_usePySideExtensions; + bool m_verboseErrorMessagesDisabled; + bool m_useIsNullAsNbNonZero; + bool m_avoidProtectedHack; + + typedef QHash AbstractMetaTypeCache; + AbstractMetaTypeCache m_metaTypeFromStringCache; + + /// Type system converter variable replacement names and regular expressions. + QString m_typeSystemConvName[TypeSystemConverterVariables]; + QRegularExpression m_typeSystemConvRegEx[TypeSystemConverterVariables]; +}; + +#endif // SHIBOKENGENERATOR_H diff --git a/sources/shiboken2/generator/shibokenconfig.h.in b/sources/shiboken2/generator/shibokenconfig.h.in new file mode 100644 index 000000000..2c86a4a3c --- /dev/null +++ b/sources/shiboken2/generator/shibokenconfig.h.in @@ -0,0 +1,6 @@ +#ifndef SHIBOKENCONFIG_H +#define SHIBOKENCONFIG_H + +#define SHIBOKEN_VERSION "@shiboken2_VERSION@" + +#endif diff --git a/sources/shiboken2/generatorrunnerconfig.h.in b/sources/shiboken2/generatorrunnerconfig.h.in new file mode 100644 index 000000000..d291fcc53 --- /dev/null +++ b/sources/shiboken2/generatorrunnerconfig.h.in @@ -0,0 +1,13 @@ +#ifndef GENERATORRUNNERCONFIG_H +#define GENERATORRUNNERCONFIG_H + +// generatorrunner version +#define GENERATORRUNNER_VERSION "@generator_VERSION@" + +// generatorrunner plugin dir +#define GENERATORRUNNER_PLUGIN_DIR "@generator_plugin_DIR@" + +// module extension +#define MODULE_EXTENSION "@CMAKE_SHARED_LIBRARY_SUFFIX@" + +#endif diff --git a/sources/shiboken2/generatorrunnermacros.h b/sources/shiboken2/generatorrunnermacros.h new file mode 100644 index 000000000..d54ed3b9a --- /dev/null +++ b/sources/shiboken2/generatorrunnermacros.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GENERATORRUNNERMACROS_H +#define GENERATORRUNNERMACROS_H + +// GENRUNNER_API is used for the public API symbols. +#if defined _WIN32 + #define GENRUNNER_EXPORT __declspec(dllexport) + #if GENRUNNER_EXPORTS + #define GENRUNNER_API GENRUNNER_EXPORT + #endif +#elif __GNUC__ >= 4 + #define GENRUNNER_EXPORT __attribute__ ((visibility("default"))) + #define GENRUNNER_API GENRUNNER_EXPORT +#elif __GNUC__ < 4 + #define GENRUNNER_EXPORT +#endif + +#ifndef GENRUNNER_API + #define GENRUNNER_API +#endif +#endif diff --git a/sources/shiboken2/generators/shiboken/shiboken.cpp b/sources/shiboken2/generators/shiboken/shiboken.cpp new file mode 100644 index 000000000..829862f19 --- /dev/null +++ b/sources/shiboken2/generators/shiboken/shiboken.cpp @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "cppgenerator.h" +#include "headergenerator.h" + +EXPORT_GENERATOR_PLUGIN(new CppGenerator << new HeaderGenerator) diff --git a/sources/shiboken2/header.COMM b/sources/shiboken2/header.COMM new file mode 100644 index 000000000..1c8cb00e7 --- /dev/null +++ b/sources/shiboken2/header.COMM @@ -0,0 +1,20 @@ +/****************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the module. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ diff --git a/sources/shiboken2/header.LGPL-ONLY b/sources/shiboken2/header.LGPL-ONLY new file mode 100644 index 000000000..9a676032e --- /dev/null +++ b/sources/shiboken2/header.LGPL-ONLY @@ -0,0 +1,22 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL-ONLY$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you have questions regarding the use of this file, please contact +** us via http://www.qt.io/contact-us/. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ diff --git a/sources/shiboken2/header.LGPL21 b/sources/shiboken2/header.LGPL21 new file mode 100644 index 000000000..533390b07 --- /dev/null +++ b/sources/shiboken2/header.LGPL21 @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + diff --git a/sources/shiboken2/header.LGPL3 b/sources/shiboken2/header.LGPL3 new file mode 100644 index 000000000..d9a65c2e4 --- /dev/null +++ b/sources/shiboken2/header.LGPL3 @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + diff --git a/sources/shiboken2/header.LGPL3-COMM b/sources/shiboken2/header.LGPL3-COMM new file mode 100644 index 000000000..b5dc15d38 --- /dev/null +++ b/sources/shiboken2/header.LGPL3-COMM @@ -0,0 +1,28 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3-COMM$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + diff --git a/sources/shiboken2/icecc.cmake b/sources/shiboken2/icecc.cmake new file mode 100644 index 000000000..b2bf071aa --- /dev/null +++ b/sources/shiboken2/icecc.cmake @@ -0,0 +1,11 @@ +include (CMakeForceCompiler) +option(ENABLE_ICECC "Enable icecc checking, for distributed compilation") +if (ENABLE_ICECC) + find_program(ICECC icecc) + if (ICECC) + message(STATUS "icecc found! Distributed compilation for all!! huhuhu.") + cmake_force_cxx_compiler(${ICECC} icecc) + else(ICECC) + message(FATAL_ERROR "icecc NOT found! re-run cmake without -DENABLE_ICECC") + endif(ICECC) +endif(ENABLE_ICECC) diff --git a/sources/shiboken2/libshiboken/CMakeLists.txt b/sources/shiboken2/libshiboken/CMakeLists.txt new file mode 100644 index 000000000..e2e5eb427 --- /dev/null +++ b/sources/shiboken2/libshiboken/CMakeLists.txt @@ -0,0 +1,69 @@ +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) +if(ENABLE_VERSION_SUFFIX) + set(shiboken2_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") +else() + set(shiboken2_SUFFIX "") +endif() + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/sbkversion.h.in" + "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" @ONLY) + +set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) +set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) +set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION}) +set(libshiboken_VERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}.${libshiboken_MICRO_VERSION}") +set(libshiboken_SOVERSION "${libshiboken_MAJOR_VERSION}.${libshiboken_MINOR_VERSION}") + +set(libshiboken_SRC +basewrapper.cpp +debugfreehook.cpp +gilstate.cpp +helper.cpp +sbkconverter.cpp +sbkenum.cpp +sbkmodule.cpp +sbkstring.cpp +bindingmanager.cpp +threadstatesaver.cpp +typeresolver.cpp +shibokenbuffer.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR} + ${SBK_PYTHON_INCLUDE_DIR}) +add_library(libshiboken SHARED ${libshiboken_SRC}) +target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES}) +set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken2${shiboken2_SUFFIX}${PYTHON_EXTENSION_SUFFIX}" + VERSION ${libshiboken_VERSION} + SOVERSION ${libshiboken_SOVERSION} + CXX_STANDARD 11 + DEFINE_SYMBOL LIBSHIBOKEN_EXPORTS) + +install(FILES + autodecref.h + basewrapper.h + bindingmanager.h + conversions.h + gilstate.h + helper.h + sbkconverter.h + sbkenum.h + sbkmodule.h + python25compat.h + sbkdbg.h + sbkstring.h + shiboken.h + shibokenmacros.h + threadstatesaver.h + typeresolver.h + shibokenbuffer.h + sbkpython.h + "${CMAKE_CURRENT_BINARY_DIR}/sbkversion.h" + DESTINATION include/shiboken2${shiboken2_SUFFIX}) +install(TARGETS libshiboken EXPORT shiboken2 + LIBRARY DESTINATION "${LIB_INSTALL_DIR}" + ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" + RUNTIME DESTINATION bin) diff --git a/sources/shiboken2/libshiboken/autodecref.h b/sources/shiboken2/libshiboken/autodecref.h new file mode 100644 index 000000000..1fefcc259 --- /dev/null +++ b/sources/shiboken2/libshiboken/autodecref.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef AUTODECREF_H +#define AUTODECREF_H + +#include "sbkpython.h" +#include "basewrapper.h" + +struct SbkObject; +namespace Shiboken +{ + +/** + * AutoDecRef holds a PyObject pointer and decrement its reference counter when destroyed. + */ +struct LIBSHIBOKEN_API AutoDecRef +{ +public: + /** + * 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(pyObj)) {} + + /// Decref the borrowed python reference + ~AutoDecRef() + { + Py_XDECREF(m_pyObj); + } + + inline bool isNull() const { return m_pyObj == 0; } + /// Returns the pointer of the Python object being held. + inline PyObject* object() { return m_pyObj; } + inline operator PyObject*() { return m_pyObj; } + inline operator PyTupleObject*() { return reinterpret_cast(m_pyObj); } + inline operator bool() const { return m_pyObj; } + inline PyObject* operator->() { return m_pyObj; } + + template + T cast() + { + return reinterpret_cast(m_pyObj); + } + + /** + * Decref the current borrowed python reference and take the reference + * borrowed by \p other, so other.isNull() will return true. + */ + void operator=(AutoDecRef& other) + { + Py_XDECREF(m_pyObj); + m_pyObj = other.m_pyObj; + other.m_pyObj = 0; + } + + /** + * Decref the current borrowed python reference and borrow \p other. + */ + void operator=(PyObject* other) + { + Py_XDECREF(m_pyObj); + m_pyObj = other; + } +private: + PyObject* m_pyObj; + AutoDecRef(const AutoDecRef&); + AutoDecRef& operator=(const AutoDecRef&); +}; + +} // namespace Shiboken + +#endif // AUTODECREF_H + diff --git a/sources/shiboken2/libshiboken/basewrapper.cpp b/sources/shiboken2/libshiboken/basewrapper.cpp new file mode 100644 index 000000000..5ecda1eaf --- /dev/null +++ b/sources/shiboken2/libshiboken/basewrapper.cpp @@ -0,0 +1,1516 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "basewrapper.h" +#include "basewrapper_p.h" +#include "sbkconverter.h" +#include "sbkenum.h" +#include "autodecref.h" +#include "typeresolver.h" +#include "gilstate.h" +#include +#include +#include +#include +#include +#include +#include "threadstatesaver.h" + +namespace { + void _destroyParentInfo(SbkObject* obj, bool keepReference); +} + +extern "C" +{ + +static void SbkObjectTypeDealloc(PyObject* pyObj); +static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); + +PyTypeObject SbkObjectType_Type = { + PyVarObject_HEAD_INIT(0, 0) + /*tp_name*/ "Shiboken.ObjectType", + /*tp_basicsize*/ sizeof(SbkObjectType), + /*tp_itemsize*/ 0, + /*tp_dealloc*/ SbkObjectTypeDealloc, + /*tp_print*/ 0, + /*tp_getattr*/ 0, + /*tp_setattr*/ 0, + /*tp_compare*/ 0, + /*tp_repr*/ 0, + /*tp_as_number*/ 0, + /*tp_as_sequence*/ 0, + /*tp_as_mapping*/ 0, + /*tp_hash*/ 0, + /*tp_call*/ 0, + /*tp_str*/ 0, + /*tp_getattro*/ 0, + /*tp_setattro*/ PyObject_GenericSetAttr, + /*tp_as_buffer*/ 0, + /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, + /*tp_doc*/ 0, + /*tp_traverse*/ 0, + /*tp_clear*/ 0, + /*tp_richcompare*/ 0, + /*tp_weaklistoffset*/ 0, + /*tp_iter*/ 0, + /*tp_iternext*/ 0, + /*tp_methods*/ 0, + /*tp_members*/ 0, + /*tp_getset*/ 0, + /*tp_base*/ &PyType_Type, + /*tp_dict*/ 0, + /*tp_descr_get*/ 0, + /*tp_descr_set*/ 0, + /*tp_dictoffset*/ 0, + /*tp_init*/ 0, + /*tp_alloc*/ PyType_GenericAlloc, + /*tp_new*/ SbkObjectTypeTpNew, + /*tp_free*/ PyObject_GC_Del, + /*tp_is_gc*/ 0, + /*tp_bases*/ 0, + /*tp_mro*/ 0, + /*tp_cache*/ 0, + /*tp_subclasses*/ 0, + /*tp_weaklist*/ 0, + /*tp_del*/ 0, + /*tp_version_tag*/ 0 +}; + +static PyObject *SbkObjectGetDict(PyObject* pObj, void *) +{ + SbkObject *obj = reinterpret_cast(pObj); + if (!obj->ob_dict) + obj->ob_dict = PyDict_New(); + if (!obj->ob_dict) + return 0; + Py_INCREF(obj->ob_dict); + return obj->ob_dict; +} + +static PyGetSetDef SbkObjectGetSetList[] = { + {const_cast("__dict__"), SbkObjectGetDict, 0, 0, 0}, + {0, 0, 0, 0, 0} // Sentinel +}; + +static int SbkObject_traverse(PyObject* self, visitproc visit, void* arg) +{ + SbkObject* sbkSelf = reinterpret_cast(self); + + //Visit children + Shiboken::ParentInfo* pInfo = sbkSelf->d->parentInfo; + if (pInfo) { + std::set::const_iterator it = pInfo->children.begin(); + for(; it != pInfo->children.end(); ++it) + Py_VISIT(*it); + } + + //Visit refs + Shiboken::RefCountMap* rInfo = sbkSelf->d->referredObjects; + if (rInfo) { + Shiboken::RefCountMap::const_iterator it = rInfo->begin(); + for (; it != rInfo->end(); ++it) { + std::list::const_iterator ref = it->second.begin(); + for(; ref != it->second.end(); ++ref) + Py_VISIT(*ref); + } + } + + if (sbkSelf->ob_dict) + Py_VISIT(sbkSelf->ob_dict); + return 0; +} + +static int SbkObject_clear(PyObject* self) +{ + SbkObject* sbkSelf = reinterpret_cast(self); + + Shiboken::Object::removeParent(sbkSelf); + + if (sbkSelf->d->parentInfo) + _destroyParentInfo(sbkSelf, true); + + Shiboken::Object::clearReferences(sbkSelf); + + if (sbkSelf->ob_dict) + Py_CLEAR(sbkSelf->ob_dict); + return 0; +} + +SbkObjectType SbkObject_Type = { { { + PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0) + /*tp_name*/ "Shiboken.Object", + /*tp_basicsize*/ sizeof(SbkObject), + /*tp_itemsize*/ 0, + /*tp_dealloc*/ SbkDeallocWrapperWithPrivateDtor, + /*tp_print*/ 0, + /*tp_getattr*/ 0, + /*tp_setattr*/ 0, + /*tp_compare*/ 0, + /*tp_repr*/ 0, + /*tp_as_number*/ 0, + /*tp_as_sequence*/ 0, + /*tp_as_mapping*/ 0, + /*tp_hash*/ 0, + /*tp_call*/ 0, + /*tp_str*/ 0, + /*tp_getattro*/ 0, + /*tp_setattro*/ 0, + /*tp_as_buffer*/ 0, + /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, + /*tp_doc*/ 0, + /*tp_traverse*/ SbkObject_traverse, + /*tp_clear*/ SbkObject_clear, + /*tp_richcompare*/ 0, + /*tp_weaklistoffset*/ offsetof(SbkObject, weakreflist), + /*tp_iter*/ 0, + /*tp_iternext*/ 0, + /*tp_methods*/ 0, + /*tp_members*/ 0, + /*tp_getset*/ SbkObjectGetSetList, + /*tp_base*/ 0, + /*tp_dict*/ 0, + /*tp_descr_get*/ 0, + /*tp_descr_set*/ 0, + /*tp_dictoffset*/ offsetof(SbkObject, ob_dict), + /*tp_init*/ 0, + /*tp_alloc*/ 0, + /*tp_new*/ 0, + /*tp_free*/ 0, + /*tp_is_gc*/ 0, + /*tp_bases*/ 0, + /*tp_mro*/ 0, + /*tp_cache*/ 0, + /*tp_subclasses*/ 0, + /*tp_weaklist*/ 0, + /*tp_del*/ 0, + /*tp_version_tag*/ 0 +}, }, + /*priv_data*/ 0 +}; + + +static void SbkDeallocWrapperCommon(PyObject* pyObj, bool canDelete) +{ + SbkObject* sbkObj = reinterpret_cast(pyObj); + PyTypeObject* pyType = Py_TYPE(pyObj); + + // Need to decref the type if this is the dealloc func; if type + // is subclassed, that dealloc func will decref (see subtype_dealloc + // in typeobject.c in the python sources) + bool needTypeDecref = (pyType->tp_dealloc == SbkDeallocWrapper + || pyType->tp_dealloc == SbkDeallocWrapperWithPrivateDtor); + + // Ensure that the GC is no longer tracking this object to avoid a + // possible reentrancy problem. Since there are multiple steps involved + // in deallocating a SbkObject it is possible for the garbage collector to + // be invoked and it trying to delete this object while it is still in + // progress from the first time around, resulting in a double delete and a + // crash. + PyObject_GC_UnTrack(pyObj); + + // Check that Python is still initialized as sometimes this is called by a static destructor + // after Python interpeter is shutdown. + if (sbkObj->weakreflist && Py_IsInitialized()) + PyObject_ClearWeakRefs(pyObj); + + // If I have ownership and is valid delete C++ pointer + if (canDelete && sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { + SbkObjectType* sbkType = reinterpret_cast(pyType); + if (sbkType->d->is_multicpp) { + Shiboken::DeallocVisitor visitor(sbkObj); + Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); + } else { + void* cptr = sbkObj->d->cptr[0]; + Shiboken::Object::deallocData(sbkObj, true); + + Shiboken::ThreadStateSaver threadSaver; + if (Py_IsInitialized()) + threadSaver.save(); + sbkType->d->cpp_dtor(cptr); + } + } else { + Shiboken::Object::deallocData(sbkObj, true); + } + + if (needTypeDecref) + Py_DECREF(pyType); +} + +void SbkDeallocWrapper(PyObject* pyObj) +{ + SbkDeallocWrapperCommon(pyObj, true); +} + +void SbkDeallocWrapperWithPrivateDtor(PyObject* self) +{ + SbkDeallocWrapperCommon(self, false); +} + +void SbkObjectTypeDealloc(PyObject* pyObj) +{ + SbkObjectType* sbkType = reinterpret_cast(pyObj); + + PyObject_GC_UnTrack(pyObj); + Py_TRASHCAN_SAFE_BEGIN(pyObj); + if (sbkType->d) { + if(sbkType->d->user_data && sbkType->d->d_func) { + sbkType->d->d_func(sbkType->d->user_data); + sbkType->d->user_data = 0; + } + free(sbkType->d->original_name); + sbkType->d->original_name = 0; + if (!Shiboken::ObjectType::isUserType(reinterpret_cast(sbkType))) + Shiboken::Conversions::deleteConverter(sbkType->d->converter); + delete sbkType->d; + sbkType->d = 0; + } + Py_TRASHCAN_SAFE_END(pyObj); +} + +PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +{ +#ifndef IS_PY3K + // Check if all bases are new style before calling type.tp_new + // Was causing gc assert errors in test_bug704.py when + // this check happened after creating the type object. + // Argument parsing take from type.tp_new code. + PyObject* name; + PyObject* pyBases; + PyObject* dict; + static const char* kwlist[] = { "name", "bases", "dict", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "SO!O!:sbktype", (char**)kwlist, + &name, + &PyTuple_Type, &pyBases, + &PyDict_Type, &dict)) + return NULL; + + for(int i=0, i_max=PyTuple_GET_SIZE(pyBases); i < i_max; i++) { + PyObject* baseType = PyTuple_GET_ITEM(pyBases, i); + if (PyClass_Check(baseType)) { + PyErr_Format(PyExc_TypeError, "Invalid base class used in type %s. PySide only support multiple inheritance from python new style class.", metatype->tp_name); + return 0; + } + } +#endif + + // The meta type creates a new type when the Python programmer extends a wrapped C++ class. + SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + if (!newType) + return 0; + + Shiboken::ObjectType::initPrivateData(newType); + SbkObjectTypePrivate* d = newType->d; + + std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); + if (bases.size() == 1) { + SbkObjectTypePrivate* parentType = bases.front()->d; + d->mi_offsets = parentType->mi_offsets; + d->mi_init = parentType->mi_init; + d->mi_specialcast = parentType->mi_specialcast; + d->type_discovery = parentType->type_discovery; + d->cpp_dtor = parentType->cpp_dtor; + d->is_multicpp = 0; + d->converter = parentType->converter; + } else { + d->mi_offsets = 0; + d->mi_init = 0; + d->mi_specialcast = 0; + d->type_discovery = 0; + d->cpp_dtor = 0; + d->is_multicpp = 1; + d->converter = 0; + } + if (bases.size() == 1) + d->original_name = strdup(bases.front()->d->original_name); + else + d->original_name = strdup("object"); + d->user_data = 0; + d->d_func = 0; + d->is_user_type = 1; + + std::list::const_iterator it = bases.begin(); + for (; it != bases.end(); ++it) { + if ((*it)->d->subtype_init) + (*it)->d->subtype_init(newType, args, kwds); + } + + return reinterpret_cast(newType); +} + +PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) +{ + SbkObject* self = PyObject_GC_New(SbkObject, subtype); + Py_INCREF(reinterpret_cast(subtype)); + SbkObjectPrivate* d = new SbkObjectPrivate; + + SbkObjectType* sbkType = reinterpret_cast(subtype); + int numBases = ((sbkType->d && sbkType->d->is_multicpp) ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1); + d->cptr = new void*[numBases]; + std::memset(d->cptr, 0, sizeof(void*)*numBases); + d->hasOwnership = 1; + d->containsCppWrapper = 0; + d->validCppObject = 0; + d->parentInfo = 0; + d->referredObjects = 0; + d->cppObjectCreated = 0; + self->ob_dict = 0; + self->weakreflist = 0; + self->d = d; + PyObject_GC_Track(reinterpret_cast(self)); + return reinterpret_cast(self); +} + + +} //extern "C" + + +namespace +{ + +void _destroyParentInfo(SbkObject* obj, bool keepReference) +{ + Shiboken::ParentInfo* pInfo = obj->d->parentInfo; + if (pInfo) { + while(!pInfo->children.empty()) { + SbkObject* first = *pInfo->children.begin(); + // Mark child as invalid + Shiboken::Object::invalidate(first); + Shiboken::Object::removeParent(first, false, keepReference); + } + Shiboken::Object::removeParent(obj, false); + } +} + +} + +namespace Shiboken +{ + +static void decRefPyObjectList(const std::list &pyObj, PyObject* skip = 0); + +static void _walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) +{ + PyObject* bases = currentType->tp_bases; + Py_ssize_t numBases = PyTuple_GET_SIZE(bases); + for (int i = 0; i < numBases; ++i) { + PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); + + if (!PyType_IsSubtype(type, reinterpret_cast(&SbkObject_Type))) { + continue; + } else { + SbkObjectType* sbkType = reinterpret_cast(type); + if (sbkType->d->is_user_type) + _walkThroughClassHierarchy(type, visitor); + else + visitor->visit(sbkType); + } + if (visitor->wasFinished()) + break; + } +} + +void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) +{ + _walkThroughClassHierarchy(currentType, visitor); + visitor->done(); +} + + +bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) +{ + PyObject* sysModules = PyImport_GetModuleDict(); + PyObject* module = PyDict_GetItemString(sysModules, moduleName); + if (!module) { + module = PyImport_ImportModule(moduleName); + if (!module) + return false; + } else { + Py_INCREF(module); + } + + Shiboken::AutoDecRef cppApi(PyObject_GetAttrString(module, "_Cpp_Api")); + Py_DECREF(module); + + if (cppApi.isNull()) + return false; + +#ifdef IS_PY3K + if (PyCapsule_CheckExact(cppApi)) + *cppApiPtr = reinterpret_cast(PyCapsule_GetPointer(cppApi, 0)); +#else + // Python 2.6 doesn't have PyCapsule API, so let's keep usign PyCObject on all Python 2.x + if (PyCObject_Check(cppApi)) + *cppApiPtr = reinterpret_cast(PyCObject_AsVoidPtr(cppApi)); +#endif + return true; +} + +// Wrapper metatype and base type ---------------------------------------------------------- + +void DtorCallerVisitor::visit(SbkObjectType* node) +{ + m_ptrs.push_back(std::make_pair(m_pyObj->d->cptr[m_ptrs.size()], node)); +} + +void DtorCallerVisitor::done() +{ + std::list >::const_iterator it = m_ptrs.begin(); + for (; it != m_ptrs.end(); ++it) { + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); + it->second->d->cpp_dtor(it->first); + } +} + +void DeallocVisitor::done() +{ + Shiboken::Object::deallocData(m_pyObj, true); + DtorCallerVisitor::done(); +} + +namespace Conversions { void init(); } + +void init() +{ + static bool shibokenAlreadInitialised = false; + if (shibokenAlreadInitialised) + return; + + Conversions::init(); + + initTypeResolver(); + PyEval_InitThreads(); + + //Init private data + Shiboken::ObjectType::initPrivateData(&SbkObject_Type); + + if (PyType_Ready(&SbkEnumType_Type) < 0) + Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); + + if (PyType_Ready(&SbkObjectType_Type) < 0) + Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); + + if (PyType_Ready(reinterpret_cast(&SbkObject_Type)) < 0) + Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type."); + + shibokenAlreadInitialised = true; +} + +void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads) +{ + std::string msg; + std::string params; + if (args) { + if (PyTuple_Check(args)) { + for (Py_ssize_t i = 0, max = PyTuple_GET_SIZE(args); i < max; ++i) { + if (i) + params += ", "; + PyObject* arg = PyTuple_GET_ITEM(args, i); + params += arg->ob_type->tp_name; + } + } else { + params = args->ob_type->tp_name; + } + } + + if (!cppOverloads) { + msg = "'" + std::string(funcName) + "' called with wrong argument types: " + params; + } else { + msg = "'" + std::string(funcName) + "' called with wrong argument types:\n "; + msg += funcName; + msg += '('; + msg += params; + msg += ")\n"; + msg += "Supported signatures:"; + for (int i = 0; cppOverloads[i]; ++i) { + msg += "\n "; + msg += funcName; + msg += '('; + msg += cppOverloads[i]; + msg += ')'; + } + } + PyErr_SetString(PyExc_TypeError, msg.c_str()); + +} + +class FindBaseTypeVisitor : public HierarchyVisitor +{ + public: + FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {} + virtual void visit(SbkObjectType* node) + { + if (reinterpret_cast(node) == m_typeToFind) { + m_found = true; + finish(); + } + } + bool found() const { return m_found; } + + private: + bool m_found; + PyTypeObject* m_typeToFind; +}; + +std::list splitPyObject(PyObject* pyObj) +{ + std::list result; + if (PySequence_Check(pyObj)) { + AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); + if (!lst.isNull()) { + for (Py_ssize_t i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; ++i) { + PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); + if (Object::checkType(item)) + result.push_back(reinterpret_cast(item)); + } + } + } else { + result.push_back(reinterpret_cast(pyObj)); + } + return result; +} + +static void decRefPyObjectList(const std::list& lst, PyObject *skip) +{ + std::list::const_iterator iter = lst.begin(); + while(iter != lst.end()) { + if (*iter != skip) + Py_DECREF(*iter); + ++iter; + } +} + +namespace ObjectType +{ + +bool checkType(PyTypeObject* type) +{ + return PyType_IsSubtype(type, reinterpret_cast(&SbkObject_Type)); +} + +bool isUserType(PyTypeObject* type) +{ + return checkType(type) && reinterpret_cast(type)->d->is_user_type; +} + +bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) +{ + FindBaseTypeVisitor visitor(ctorType); + walkThroughClassHierarchy(myType, &visitor); + if (!visitor.found()) { + PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name); + return false; + } + return true; +} + + +bool hasExternalCppConversions(SbkObjectType*) { return false; } // DEPRECATED. +bool isExternalConvertible(SbkObjectType *, PyObject *) { return false; } // DEPRECATED. +void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc) {} // DEPRECATED. +void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc) {} // DEPRECATED. +void* callExternalCppConversion(SbkObjectType*, PyObject*) { return 0; } // DEPRECATED. + + +bool hasCast(SbkObjectType* type) +{ + return type->d->mi_specialcast; +} + +void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType) +{ + return sourceType->d->mi_specialcast(Object::cppPointer(obj, targetType), reinterpret_cast(targetType)); +} + +void setCastFunction(SbkObjectType* type, SpecialCastFunction func) +{ + type->d->mi_specialcast = func; +} + +void setOriginalName(SbkObjectType* self, const char* name) +{ + if (self->d->original_name) + free(self->d->original_name); + self->d->original_name = strdup(name); +} + +const char* getOriginalName(SbkObjectType* self) +{ + return self->d->original_name; +} + +void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func) +{ + self->d->type_discovery = func; +} + +void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func) +{ + self->d->type_discovery = (TypeDiscoveryFuncV2)func; +} + +TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self) +{ + // This is an illegal cast because the return value is different, + // but nobody ever used this function, so... =] + return (TypeDiscoveryFunc)self->d->type_discovery; +} + +void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other) +{ + self->d->mi_init = other->d->mi_init; + self->d->mi_offsets = other->d->mi_offsets; + self->d->mi_specialcast = other->d->mi_specialcast; +} + +void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction function) +{ + self->d->mi_init = function; +} + +MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self) +{ + return self->d->mi_init; +} + +void setDestructorFunction(SbkObjectType* self, ObjectDestructor func) +{ + self->d->cpp_dtor = func; +} + +void initPrivateData(SbkObjectType* self) +{ + self->d = new SbkObjectTypePrivate; + memset(self->d, 0, sizeof(SbkObjectTypePrivate)); +} + +bool introduceWrapperType(PyObject* enclosingObject, + const char* typeName, const char* originalName, + SbkObjectType* type, ObjectDestructor cppObjDtor, + SbkObjectType* baseType, PyObject* baseTypes, + bool isInnerClass) +{ + initPrivateData(type); + setOriginalName(type, originalName); + setDestructorFunction(type, cppObjDtor); + + if (baseType) { + type->super.ht_type.tp_base = reinterpret_cast(baseType); + if (baseTypes) { + for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i) + BindingManager::instance().addClassInheritance(reinterpret_cast(PySequence_Fast_GET_ITEM(baseTypes, i)), type); + type->super.ht_type.tp_bases = baseTypes; + } else { + BindingManager::instance().addClassInheritance(baseType, type); + } + } + + if (PyType_Ready(reinterpret_cast(type)) < 0) + return false; + + if (isInnerClass) + return PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast(type)) == 0; + + //PyModule_AddObject steals type's reference. + Py_INCREF(reinterpret_cast(type)); + return PyModule_AddObject(enclosingObject, typeName, reinterpret_cast(type)) == 0; +} + +void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func) +{ + self->d->subtype_init = func; +} + +void* getTypeUserData(SbkObjectType* self) +{ + return self->d->user_data; +} + +void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func) +{ + self->d->user_data = userData; + self->d->d_func = d_func; +} + +} // namespace ObjectType + + +namespace Object +{ + +static void recursive_invalidate(SbkObject* self, std::set& seen); + +bool checkType(PyObject* pyObj) +{ + return ObjectType::checkType(pyObj->ob_type); +} + +bool isUserType(PyObject* pyObj) +{ + return ObjectType::isUserType(pyObj->ob_type); +} + +Py_hash_t hash(PyObject* pyObj) +{ + assert(Shiboken::Object::checkType(pyObj)); + return reinterpret_cast(pyObj); +} + +static void setSequenceOwnership(PyObject* pyObj, bool owner) +{ + if (PySequence_Check(pyObj)) { + std::list objs = splitPyObject(pyObj); + std::list::const_iterator it = objs.begin(); + for(; it != objs.end(); ++it) { + if (owner) + getOwnership(*it); + else + releaseOwnership(*it); + } + } else if (Object::checkType(pyObj)) { + if (owner) + getOwnership(reinterpret_cast(pyObj)); + else + releaseOwnership(reinterpret_cast(pyObj)); + } +} + +void setValidCpp(SbkObject* pyObj, bool value) +{ + pyObj->d->validCppObject = value; +} + +void setHasCppWrapper(SbkObject* pyObj, bool value) +{ + pyObj->d->containsCppWrapper = value; +} + +bool hasCppWrapper(SbkObject* pyObj) +{ + return pyObj->d->containsCppWrapper; +} + +bool wasCreatedByPython(SbkObject* pyObj) +{ + return pyObj->d->cppObjectCreated; +} + +void callCppDestructors(SbkObject* pyObj) +{ + SbkObjectType* sbkType = reinterpret_cast(Py_TYPE(pyObj)); + if (sbkType->d->is_multicpp) { + Shiboken::DtorCallerVisitor visitor(pyObj); + Shiboken::walkThroughClassHierarchy(Py_TYPE(pyObj), &visitor); + } else { + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); + sbkType->d->cpp_dtor(pyObj->d->cptr[0]); + } + + /* invalidate needs to be called before deleting pointer array because + it needs to delete entries for them from the BindingManager hash table; + also release wrapper explicitly if object contains C++ wrapper because + invalidate doesn't */ + invalidate(pyObj); + if (pyObj->d->validCppObject && pyObj->d->containsCppWrapper) { + BindingManager::instance().releaseWrapper(pyObj); + } + + delete[] pyObj->d->cptr; + pyObj->d->cptr = 0; + pyObj->d->validCppObject = false; +} + +bool hasOwnership(SbkObject* pyObj) +{ + return pyObj->d->hasOwnership; +} + +void getOwnership(SbkObject* self) +{ + // skip if already have the ownership + if (self->d->hasOwnership) + return; + + // skip if this object has parent + if (self->d->parentInfo && self->d->parentInfo->parent) + return; + + // Get back the ownership + self->d->hasOwnership = true; + + if (self->d->containsCppWrapper) + Py_DECREF(reinterpret_cast(self)); // Remove extra ref + else + makeValid(self); // Make the object valid again +} + +void getOwnership(PyObject* pyObj) +{ + if (pyObj) + setSequenceOwnership(pyObj, true); +} + +void releaseOwnership(SbkObject* self) +{ + // skip if the ownership have already moved to c++ + SbkObjectType* selfType = reinterpret_cast(Py_TYPE(self)); + if (!self->d->hasOwnership || Shiboken::Conversions::pythonTypeIsValueType(selfType->d->converter)) + return; + + // remove object ownership + self->d->hasOwnership = false; + + // If We have control over object life + if (self->d->containsCppWrapper) + Py_INCREF(reinterpret_cast(self)); // keep the python object alive until the wrapper destructor call + else + invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after +} + +void releaseOwnership(PyObject* self) +{ + setSequenceOwnership(self, false); +} + +/* Needed forward declarations */ +static void recursive_invalidate(PyObject* pyobj, std::set& seen); +static void recursive_invalidate(SbkObject* self, std::set& seen); + +void invalidate(PyObject* pyobj) +{ + std::set seen; + recursive_invalidate(pyobj, seen); +} + +void invalidate(SbkObject* self) +{ + std::set seen; + recursive_invalidate(self, seen); +} + +static void recursive_invalidate(PyObject* pyobj, std::set& seen) +{ + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it = objs.begin(); + for (; it != objs.end(); it++) + recursive_invalidate(*it, seen); +} + +static void recursive_invalidate(SbkObject* self, std::set& seen) +{ + // Skip if this object not is a valid object or if it's already been seen + if (!self || reinterpret_cast(self) == Py_None || seen.find(self) != seen.end()) + return; + seen.insert(self); + + if (!self->d->containsCppWrapper) { + self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class + BindingManager::instance().releaseWrapper(self); + } + + // If it is a parent invalidate all children. + if (self->d->parentInfo) { + // Create a copy because this list can be changed during the process + ChildrenList copy = self->d->parentInfo->children; + ChildrenList::iterator it = copy.begin(); + + for (; it != copy.end(); ++it) { + // invalidate the child + recursive_invalidate(*it, seen); + + // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed + if (!self->d->validCppObject) + removeParent(*it, true, true); + } + } + + // If has ref to other objects invalidate all + if (self->d->referredObjects) { + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter; + for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) { + const std::list lst = iter->second; + std::list::const_iterator it = lst.begin(); + while(it != lst.end()) { + recursive_invalidate(*it, seen); + ++it; + } + } + } +} + +void makeValid(SbkObject* self) +{ + // Skip if this object not is a valid object + if (!self || reinterpret_cast(self) == Py_None || self->d->validCppObject) + return; + + // Mark object as invalid only if this is not a wrapper class + self->d->validCppObject = true; + + // If it is a parent make all children valid + if (self->d->parentInfo) { + ChildrenList::iterator it = self->d->parentInfo->children.begin(); + for (; it != self->d->parentInfo->children.end(); ++it) + makeValid(*it); + } + + // If has ref to other objects make all valid again + if (self->d->referredObjects) { + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter; + for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) { + const std::list lst = iter->second; + std::list::const_iterator it = lst.begin(); + while(it != lst.end()) { + if (Shiboken::Object::checkType(*it)) + makeValid(reinterpret_cast(*it)); + ++it; + } + } + } +} + +bool hasParentInfo(SbkObject* pyObj) +{ + return pyObj->d->parentInfo; +} + +void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) +{ + PyTypeObject* type = Py_TYPE(pyObj); + int idx = 0; + if (reinterpret_cast(type)->d->is_multicpp) + idx = getTypeIndexOnHierarchy(type, desiredType); + if (pyObj->d->cptr) + return pyObj->d->cptr[idx]; + return 0; +} + +std::vector cppPointers(SbkObject* pyObj) +{ + int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj)); + std::vector ptrs(n); + for (int i = 0; i < n; ++i) + ptrs[i] = pyObj->d->cptr[i]; + return ptrs; +} + + +bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) +{ + int idx = 0; + if (reinterpret_cast(Py_TYPE(sbkObj))->d->is_multicpp) + idx = getTypeIndexOnHierarchy(Py_TYPE(sbkObj), desiredType); + + bool alreadyInitialized = sbkObj->d->cptr[idx]; + if (alreadyInitialized) + PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); + else + sbkObj->d->cptr[idx] = cptr; + + sbkObj->d->cppObjectCreated = true; + return !alreadyInitialized; +} + +bool isValid(PyObject* pyObj) +{ + if (!pyObj || pyObj == Py_None + || Py_TYPE(pyObj->ob_type) != &SbkObjectType_Type) { + return true; + } + + SbkObjectPrivate* priv = reinterpret_cast(pyObj)->d; + + if (!priv->cppObjectCreated && isUserType(pyObj)) { + PyErr_Format(PyExc_RuntimeError, "'__init__' method of object's base class (%s) not called.", pyObj->ob_type->tp_name); + return false; + } + + if (!priv->validCppObject) { + PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->tp_name); + return false; + } + + return true; +} + +bool isValid(SbkObject* pyObj, bool throwPyError) +{ + if (!pyObj) + return false; + + SbkObjectPrivate* priv = pyObj->d; + if (!priv->cppObjectCreated && isUserType(reinterpret_cast(pyObj))) { + if (throwPyError) + PyErr_Format(PyExc_RuntimeError, "Base constructor of the object (%s) not called.", Py_TYPE(pyObj)->tp_name); + return false; + } + + if (!priv->validCppObject) { + if (throwPyError) + PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", Py_TYPE(pyObj)->tp_name); + return false; + } + + return true; +} + +bool isValid(PyObject* pyObj, bool throwPyError) +{ + if (!pyObj || pyObj == Py_None || + !PyType_IsSubtype(pyObj->ob_type, reinterpret_cast(&SbkObject_Type))) { + return true; + } + return isValid(reinterpret_cast(pyObj), throwPyError); +} + +SbkObject *findColocatedChild(SbkObject *wrapper, + const SbkObjectType *instanceType) +{ + // Degenerate case, wrapper is the correct wrapper. + if (reinterpret_cast(Py_TYPE(wrapper)) == reinterpret_cast(instanceType)) + return wrapper; + + if (!(wrapper->d && wrapper->d->cptr)) + return 0; + + ParentInfo* pInfo = wrapper->d->parentInfo; + if (!pInfo) + return 0; + + ChildrenList& children = pInfo->children; + + ChildrenList::iterator childrenEnd = children.end(); + for (ChildrenList::iterator iChild = children.begin(); iChild != childrenEnd; ++iChild) { + if (!((*iChild)->d && (*iChild)->d->cptr)) + continue; + if ((*iChild)->d->cptr[0] == wrapper->d->cptr[0]) { + if (reinterpret_cast(Py_TYPE(*iChild)) == reinterpret_cast(instanceType)) + return const_cast((*iChild)); + else + return findColocatedChild(const_cast(*iChild), instanceType); + } + } + return 0; +} + + +PyObject *newObject(SbkObjectType* instanceType, + void* cptr, + bool hasOwnership, + bool isExactType, + const char* typeName) +{ + // Try to find the exact type of cptr. + if (!isExactType) { + PyTypeObject* exactType = 0; + if (typeName) { + exactType = Shiboken::Conversions::getPythonTypeObject(typeName); + if (exactType) + instanceType = reinterpret_cast(exactType); + } + if (!exactType) + instanceType = BindingManager::instance().resolveType(&cptr, instanceType); + } + + bool shouldCreate = true; + bool shouldRegister = true; + SbkObject* self = 0; + + // Some logic to ensure that colocated child field does not overwrite the parent + if (BindingManager::instance().hasWrapper(cptr)) { + SbkObject* existingWrapper = BindingManager::instance().retrieveWrapper(cptr); + + self = findColocatedChild(existingWrapper, instanceType); + if (self) { + // Wrapper already registered for cptr. + // This should not ideally happen, binding code should know when a wrapper + // already exists and retrieve it instead. + shouldRegister = shouldCreate = false; + } else if (hasOwnership && + (!(Shiboken::Object::hasCppWrapper(existingWrapper) || + Shiboken::Object::hasOwnership(existingWrapper)))) { + // Old wrapper is likely junk, since we have ownership and it doesn't. + BindingManager::instance().releaseWrapper(existingWrapper); + } else { + // Old wrapper may be junk caused by some bug in identifying object deletion + // but it may not be junk when a colocated field is accessed for an + // object which was not created by python (returned from c++ factory function). + // Hence we cannot release the wrapper confidently so we do not register. + shouldRegister = false; + } + } + + if (shouldCreate) { + self = reinterpret_cast(SbkObjectTpNew(reinterpret_cast(instanceType), 0, 0)); + self->d->cptr[0] = cptr; + self->d->hasOwnership = hasOwnership; + self->d->validCppObject = 1; + if (shouldRegister) { + BindingManager::instance().registerWrapper(self, cptr); + } + } else { + Py_IncRef(reinterpret_cast(self)); + } + return reinterpret_cast(self); +} + +void destroy(SbkObject* self) +{ + destroy(self, 0); +} + +void destroy(SbkObject* self, void* cppData) +{ + // Skip if this is called with NULL pointer this can happen in derived classes + if (!self) + return; + + // This can be called in c++ side + Shiboken::GilState gil; + + // Remove all references attached to this object + clearReferences(self); + + // Remove the object from parent control + + // Verify if this object has parent + bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent); + + if (self->d->parentInfo) { + // Check for children information and make all invalid if they exists + _destroyParentInfo(self, true); + // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent + } + + //if !hasParent this object could still alive + if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) { + // Remove extra ref used by c++ object this will case the pyobject destruction + // This can cause the object death + Py_DECREF(reinterpret_cast(self)); + } + + //Python Object is not destroyed yet + if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) { + // Remove from BindingManager + Shiboken::BindingManager::instance().releaseWrapper(self); + self->d->hasOwnership = false; + + // the cpp object instance was deleted + delete[] self->d->cptr; + self->d->cptr = 0; + } + + // After this point the object can be death do not use the self pointer bellow +} + +void removeParent(SbkObject* child, bool giveOwnershipBack, bool keepReference) +{ + ParentInfo* pInfo = child->d->parentInfo; + if (!pInfo || !pInfo->parent) { + if (pInfo && pInfo->hasWrapperRef) { + pInfo->hasWrapperRef = false; + } + return; + } + + ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; + // Verify if this child is part of parent list + ChildrenList::iterator iChild = std::find(oldBrothers.begin(), oldBrothers.end(), child); + if (iChild == oldBrothers.end()) + return; + + oldBrothers.erase(iChild); + + pInfo->parent = 0; + + // This will keep the wrapper reference, will wait for wrapper destruction to remove that + if (keepReference && + child->d->containsCppWrapper) { + //If have already a extra ref remove this one + if (pInfo->hasWrapperRef) + Py_DECREF(child); + else + pInfo->hasWrapperRef = true; + return; + } + + // Transfer ownership back to Python + child->d->hasOwnership = giveOwnershipBack; + + // Remove parent ref + Py_DECREF(child); +} + +void setParent(PyObject* parent, PyObject* child) +{ + if (!child || child == Py_None || child == parent) + return; + + /* + * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken + * like tuple and list. + * + * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, + * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString + * follows the sequence protocol. + */ + if (PySequence_Check(child) && !Object::checkType(child)) { + Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); + for (Py_ssize_t i = 0, max = PySequence_Size(seq); i < max; ++i) + setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); + return; + } + + bool parentIsNull = !parent || parent == Py_None; + SbkObject* parent_ = reinterpret_cast(parent); + SbkObject* child_ = reinterpret_cast(child); + + if (!parentIsNull) { + if (!parent_->d->parentInfo) + parent_->d->parentInfo = new ParentInfo; + + // do not re-add a child + if (child_->d->parentInfo && (child_->d->parentInfo->parent == parent_)) + return; + } + + ParentInfo* pInfo = child_->d->parentInfo; + bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; + + //Avoid destroy child during reparent operation + Py_INCREF(child); + + // check if we need to remove this child from the old parent + if (parentIsNull || hasAnotherParent) + removeParent(child_); + + // Add the child to the new parent + pInfo = child_->d->parentInfo; + if (!parentIsNull) { + if (!pInfo) + pInfo = child_->d->parentInfo = new ParentInfo; + + pInfo->parent = parent_; + parent_->d->parentInfo->children.insert(child_); + + // Add Parent ref + Py_INCREF(child_); + + // Remove ownership + child_->d->hasOwnership = false; + } + + // Remove previous safe ref + Py_DECREF(child); +} + +void deallocData(SbkObject* self, bool cleanup) +{ + // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor + if(cleanup) { + removeParent(self); + + if (self->d->parentInfo) + _destroyParentInfo(self, true); + + clearReferences(self); + } + + if (self->d->cptr) { + // Remove from BindingManager + Shiboken::BindingManager::instance().releaseWrapper(self); + delete[] self->d->cptr; + self->d->cptr = 0; + // delete self->d; PYSIDE-205: wrong! + } + delete self->d; // PYSIDE-205: always delete d. + Py_XDECREF(self->ob_dict); + Py_TYPE(self)->tp_free(self); +} + +void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func) +{ + SbkObjectType* ob_type = reinterpret_cast(Py_TYPE(wrapper)); + if (ob_type->d->user_data) + ob_type->d->d_func(ob_type->d->user_data); + + ob_type->d->d_func = d_func; + ob_type->d->user_data = userData; +} + +void* getTypeUserData(SbkObject* wrapper) +{ + return reinterpret_cast(Py_TYPE(wrapper))->d->user_data; +} + +void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) +{ + bool isNone = (!referredObject || (referredObject == Py_None)); + + if (!self->d->referredObjects) + self->d->referredObjects = new Shiboken::RefCountMap; + + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter = refCountMap.find(key); + std::list objects; + if (iter != refCountMap.end()) { + objects = (*iter).second; + std::list::const_iterator found = std::find(objects.begin(), objects.end(), referredObject); + + // skip if objects already exists + if (found != objects.end()) + return; + } + + if (append && !isNone) { + refCountMap[key].push_back(referredObject); + Py_INCREF(referredObject); + } else if (!append) { + if (objects.size() > 0) + decRefPyObjectList(objects, isNone ? 0 : referredObject); + if (isNone) { + if (iter != refCountMap.end()) + refCountMap.erase(iter); + } else { + objects.clear(); + objects.push_back(referredObject); + refCountMap[key] = objects; + Py_INCREF(referredObject); + } + } +} + +void removeReference(SbkObject* self, const char* key, PyObject* referredObject) +{ + if (!referredObject || (referredObject == Py_None)) + return; + + if (!self->d->referredObjects) + return; + + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter = refCountMap.find(key); + if (iter != refCountMap.end()) { + decRefPyObjectList(iter->second); + refCountMap.erase(iter); + } +} + +void clearReferences(SbkObject* self) +{ + if (!self->d->referredObjects) + return; + + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter; + for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) + decRefPyObjectList(iter->second); + self->d->referredObjects->clear(); +} + +std::string info(SbkObject* self) +{ + std::ostringstream s; + std::list bases; + + if (self->d && self->d->cptr) { + if (ObjectType::isUserType(Py_TYPE(self))) + bases = getCppBaseClasses(Py_TYPE(self)); + else + bases.push_back(reinterpret_cast(Py_TYPE(self))); + + s << "C++ address....... "; + std::list::const_iterator it = bases.begin(); + for (int i = 0; it != bases.end(); ++it, ++i) + s << reinterpret_cast(*it)->tp_name << '/' << self->d->cptr[i] << ' '; + s << "\n"; + } + else { + s << "C++ address....... <>\n"; + } + + s << "hasOwnership...... " << bool(self->d->hasOwnership) << "\n" + "containsCppWrapper " << self->d->containsCppWrapper << "\n" + "validCppObject.... " << self->d->validCppObject << "\n" + "wasCreatedByPython " << self->d->cppObjectCreated << "\n"; + + + if (self->d->parentInfo && self->d->parentInfo->parent) { + s << "parent............ "; + Shiboken::AutoDecRef parent(PyObject_Str(reinterpret_cast(self->d->parentInfo->parent))); + s << String::toCString(parent) << "\n"; + } + + if (self->d->parentInfo && self->d->parentInfo->children.size()) { + s << "children.......... "; + ChildrenList& children = self->d->parentInfo->children; + for (ChildrenList::const_iterator it = children.begin(); it != children.end(); ++it) { + Shiboken::AutoDecRef child(PyObject_Str(reinterpret_cast(*it))); + s << String::toCString(child) << ' '; + } + s << '\n'; + } + + if (self->d->referredObjects && self->d->referredObjects->size()) { + Shiboken::RefCountMap& map = *self->d->referredObjects; + s << "referred objects.. "; + Shiboken::RefCountMap::const_iterator it = map.begin(); + for (; it != map.end(); ++it) { + if (it != map.begin()) + s << " "; + s << '"' << it->first << "\" => "; + std::list::const_iterator j = it->second.begin(); + for (; j != it->second.end(); ++j) { + Shiboken::AutoDecRef obj(PyObject_Str(*j)); + s << String::toCString(obj) << ' '; + } + s << ' '; + } + s << '\n'; + } + return s.str(); +} + +} // namespace Object + +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/basewrapper.h b/sources/shiboken2/libshiboken/basewrapper.h new file mode 100644 index 000000000..002337f3c --- /dev/null +++ b/sources/shiboken2/libshiboken/basewrapper.h @@ -0,0 +1,451 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BASEWRAPPER_H +#define BASEWRAPPER_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +#include +#include + +extern "C" +{ + +struct SbkConverter; +struct SbkObjectPrivate; + +/// Base Python object for all the wrapped C++ classes. +struct LIBSHIBOKEN_API SbkObject +{ + PyObject_HEAD + /// Instance dictionary. + PyObject* ob_dict; + /// List of weak references + PyObject* weakreflist; + SbkObjectPrivate* d; +}; + + +/// Dealloc the python object \p pyObj and the C++ object represented by it. +LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); +LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); + +struct SbkObjectType; + +/// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. +typedef int* (*MultipleInheritanceInitFunction)(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*, SbkObjectType*); +typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); +typedef void* (*TypeDiscoveryFuncV2)(void*, SbkObjectType*); + +typedef void* (*ExtendedToCppFunc)(PyObject*); // DEPRECATED. +typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); // DEPRECATED. + +// Used in userdata dealloc function +typedef void (*DeleteUserDataFunc)(void*); + +typedef void (*ObjectDestructor)(void*); + +typedef void (*SubTypeInitHook)(SbkObjectType*, PyObject*, PyObject*); + +extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; +extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; + + +struct SbkObjectTypePrivate; +/// PyTypeObject extended with C++ multiple inheritance information. +struct LIBSHIBOKEN_API SbkObjectType +{ + PyHeapTypeObject super; + SbkObjectTypePrivate* d; +}; + +LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*); + +} // extern "C" + +namespace Shiboken +{ + +/** +* Init shiboken library. +*/ +LIBSHIBOKEN_API void init(); + + +/// Delete the class T allocated on \p cptr. +template +void callCppDestructor(void* cptr) +{ + delete reinterpret_cast(cptr); +} + +/** + * Shiboken::importModule is DEPRECATED. Use Shiboken::Module::import() instead. + */ +SBK_DEPRECATED(LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr)); +LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); + +namespace ObjectType { + +/** +* Returns true if the object is an instance of a type created by the Shiboken generator. +*/ +LIBSHIBOKEN_API bool checkType(PyTypeObject* pyObj); + +/** +* Returns true if this object is an instance of an user defined type derived from an Shiboken type. +*/ +LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj); + +/** +* Returns true if the constructor of \p ctorType can be called for a instance of type \p myType. +* \note This function set a python error when returning false. +*/ +LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); + + +LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType*); // DEPRECATED. +LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType*, PyObject*); // DEPRECATED. +LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType*, ExtendedToCppFunc); // DEPRECATED. +LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType*, ExtendedIsConvertibleFunc); // DEPRECATED. +LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType*, PyObject*); // DEPRECATED. + + +/** + * Tells if the \p type represents an object of a class with multiple inheritance in C++. + * When this occurs, the C++ pointer held by the Python wrapper will need to be cast when + * passed as a parameter that expects a type of its ancestry. + * \returns true if a call to ObjectType::cast() is needed to obtain the correct + * C++ pointer for Python objects of type \p type. + */ +LIBSHIBOKEN_API bool hasCast(SbkObjectType* type); +/** + * Cast the C++ pointer held by a Python object \p obj of type \p sourceType, + * to a C++ pointer of a C++ class indicated by type \p targetType. + * \returns The cast C++ pointer. + */ +LIBSHIBOKEN_API void* cast(SbkObjectType* sourceType, SbkObject* obj, PyTypeObject* targetType); +/// Set the C++ cast function for \p type. +LIBSHIBOKEN_API void setCastFunction(SbkObjectType* type, SpecialCastFunction func); + +LIBSHIBOKEN_API void setOriginalName(SbkObjectType* self, const char* name); +LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self); + +LIBSHIBOKEN_API void setTypeDiscoveryFunctionV2(SbkObjectType* self, TypeDiscoveryFuncV2 func); +LIBSHIBOKEN_API SBK_DEPRECATED(void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func)); +LIBSHIBOKEN_API SBK_DEPRECATED(TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self)); + +LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other); +LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func); +LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self); + +LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func); + +LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); + +/** + * Initializes a Shiboken wrapper type and adds it to the module, + * or to the enclosing class if the type is an inner class. + * This function also calls initPrivateData and setDestructorFunction. + * \param enclosingObject The module or enclosing class to where the new \p type will be added. + * \param typeName Name by which the type will be known in Python. + * \param originalName Original C++ name of the type. + * \param type The new type to be initialized and added to the module. + * \param cppObjDtor Memory deallocation function for the C++ object held by \p type. + * Should not be used if the underlying C++ class has a private destructor. + * \param baseType Base type from whom the new \p type inherits. + * \param baseTypes Other base types from whom the new \p type inherits. + * \param isInnerClass Tells if the new \p type is an inner class (the default is that it isn't). + * If false then the \p enclosingObject is a module, otherwise it is another + * wrapper type. + * \returns true if the initialization went fine, false otherwise. + */ +LIBSHIBOKEN_API bool introduceWrapperType(PyObject* enclosingObject, + const char* typeName, const char* originalName, + SbkObjectType* type, ObjectDestructor cppObjDtor = 0, + SbkObjectType* baseType = 0, PyObject* baseTypes = 0, + bool isInnerClass = false); + +/** + * Set the subtype init hook for a type. + * + * This hook will be invoked every time the user creates a sub-type inherited from a Shiboken based type. + * The hook gets 3 params, they are: The new type being created, args and kwds. The last two are the very + * same got from tp_new. + */ +LIBSHIBOKEN_API void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func); + +/** + * Get the user data previously set by Shiboken::Object::setTypeUserData + */ +LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* self); +LIBSHIBOKEN_API void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func); + +} + +namespace Object { + +/** + * Returns a string with information about the internal state of the instance object, useful for debug purposes. + */ +LIBSHIBOKEN_API std::string info(SbkObject* self); + +/** +* Returns true if the object is an instance of a type created by the Shiboken generator. +*/ +LIBSHIBOKEN_API bool checkType(PyObject* pyObj); + +/** + * Returns true if this object type is an instance of an user defined type derived from an Shiboken type. + * \see Shiboken::ObjectType::isUserType + */ +LIBSHIBOKEN_API bool isUserType(PyObject* pyObj); + +/** + * Generic function used to make ObjectType hashable, the C++ pointer is used as hash value. + */ +LIBSHIBOKEN_API Py_hash_t hash(PyObject* pyObj); + +/** + * Find a child of given wrapper having same address having the specified type. + */ +LIBSHIBOKEN_API SbkObject *findColocatedChild(SbkObject *wrapper, + const SbkObjectType *instanceType); + +/** + * Bind a C++ object to Python. + * \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++ + * object, in any case you must provide \p instanceType, it'll be used as search starting point + * and as fallback. + * \param typeName If non-null, this will be used as helper to find the correct Python type for this object. + */ +LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, + void* cptr, + bool hasOwnership = true, + bool isExactType = false, + const char* typeName = 0); + +/** + * Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it. + */ +LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); +/** + * Tells shiboken the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. + */ +LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); +/** + * Return true if the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. + */ +LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); + +/** + * Return true if the Python object was created by Python, false otherwise. + * \note This function was added to libshiboken only to be used by shiboken.wasCreatedByPython() + */ +LIBSHIBOKEN_API bool wasCreatedByPython(SbkObject* pyObj); + +/** + * Call the C++ object destructor and invalidates the Python object. + * \note This function was added to libshiboken only to be used by shiboken.delete() + */ +LIBSHIBOKEN_API void callCppDestructors(SbkObject* pyObj); + +/** + * Return true if the Python is responsible for deleting the underlying C++ object. + */ +LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); + +/** + * Sets python as responsible to delete the underlying C++ object. + * \note You this overload only when the PyObject can be a sequence and you want to + * call this function for every item in the sequence. + * \see getOwnership(SbkObject*) + */ +LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); + +/** + * Sets python as responsible to delete the underlying C++ object. + */ +LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); + +/** + * Release the ownership, so Python will not delete the underlying C++ object. + * \note You this overload only when the PyObject can be a sequence and you want to + * call this function for every item in the sequence. + * \see releaseOwnership(SbkObject*) + */ +LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); +/** + * Release the ownership, so Python will not delete the underlying C++ object. + */ +LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); + +/** + * Returns true if the pyObj holds information about their parents. + */ +LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); + +/** + * Get the C++ pointer of type \p desiredType from a Python object. + */ +LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); + +/** + * Return a list with all C++ pointers held from a Python object. + * \note This function was added to libshiboken only to be used by shiboken.getCppPointer() + */ +LIBSHIBOKEN_API std::vector cppPointers(SbkObject* pyObj); + +/** + * Set the C++ pointer of type \p desiredType of a Python object. + */ +LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); + +/** + * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. + */ +LIBSHIBOKEN_API bool isValid(PyObject* pyObj); + +/** + * Returns false if the Python wrapper is not marked as valid. + * \param pyObj the object. + * \param throwPyError sets a Python RuntimeError when the object isn't valid. + */ +LIBSHIBOKEN_API bool isValid(SbkObject* pyObj, bool throwPyError = true); + +/** + * Returns false if the Python wrapper is not marked as valid. + * \param pyObj the object. + * \param throwPyError sets a Python RuntimeError when the object isn't valid. + */ +LIBSHIBOKEN_API bool isValid(PyObject* pyObj, bool throwPyError); + +/** +* Set the parent of \p child to \p parent. +* When an object dies, all their children, grandchildren, etc, are tagged as invalid. +* \param parent the parent object, if null, the child will have no parents. +* \param child the child. +*/ +LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); + +/** +* Remove this child from their parent, if any. +* \param child the child. +*/ +LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); + +/** +* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons. +* \note Do not call this function inside your bindings. +*/ +LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); + +/** + * Mark the object as invalid + */ +LIBSHIBOKEN_API void invalidate(SbkObject* self); + +/** + * Help function can be used to invalidate a sequence of object + **/ +LIBSHIBOKEN_API void invalidate(PyObject* pyobj); + +/** + * Make the object valid again + */ +LIBSHIBOKEN_API void makeValid(SbkObject* self); + +/// \deprecated Use destroy(SbkObject*, void*) +SBK_DEPRECATED(LIBSHIBOKEN_API void destroy(SbkObject* self)); + +/** + * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership + */ +LIBSHIBOKEN_API void destroy(SbkObject* self, void* cppData); + +/** + * Set user data on type of \p wrapper. + * \param wrapper instance object, the user data will be set on his type + * \param userData the user data + * \param d_func a function used to delete the user data + */ +LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func); +/** + * Get the user data previously set by Shiboken::Object::setTypeUserData + */ +LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); + +/** + * Increments the reference count of the referred Python object. + * A previous Python object in the same position identified by the 'key' parameter + * will have its reference counter decremented automatically when replaced. + * All the kept references should be decremented when the Python wrapper indicated by + * 'self' dies. + * No checking is done for any of the passed arguments, since it is meant to be used + * by generated code it is supposed that the generator is correct. + * \param self the wrapper instance that keeps references to other objects. + * \param key a key that identifies the C++ method signature and argument where the referred Object came from. + * \param referredObject the object whose reference is used by the self object. + */ +LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append = false); + +/** + * Removes any reference previously added by keepReference function + * \param self the wrapper instance that keeps references to other objects. + * \param key a key that identifies the C++ method signature and argument from where the referred Object came. + * \param referredObject the object whose reference is used by the self object. + */ +LIBSHIBOKEN_API void removeReference(SbkObject* self, const char* key, PyObject* referredObject); + +} // namespace Object + +} // namespace Shiboken + +#endif // BASEWRAPPER_H diff --git a/sources/shiboken2/libshiboken/basewrapper_p.h b/sources/shiboken2/libshiboken/basewrapper_p.h new file mode 100644 index 000000000..129322246 --- /dev/null +++ b/sources/shiboken2/libshiboken/basewrapper_p.h @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BASEWRAPPER_P_H +#define BASEWRAPPER_P_H + +#include "sbkpython.h" +#include "basewrapper.h" + +#include +#include +#include +#include + +struct SbkObject; +struct SbkObjectType; +struct SbkConverter; + +namespace Shiboken +{ +/** + * This mapping associates a method and argument of an wrapper object with the wrapper of + * said argument when it needs the binding to help manage its reference count. + */ +typedef std::map > RefCountMap; + +/// Linked list of SbkBaseWrapper pointers +typedef std::set ChildrenList; + +/// Structure used to store information about object parent and children. +struct ParentInfo +{ + /// Default ctor. + ParentInfo() : parent(0), hasWrapperRef(false) {} + /// Pointer to parent object. + SbkObject* parent; + /// List of object children. + ChildrenList children; + /// has internal ref + bool hasWrapperRef; +}; + +} // namespace Shiboken + +extern "C" +{ + +/** + * \internal + * Private data for SbkBaseWrapper + */ +struct SbkObjectPrivate +{ + /// Pointer to the C++ class. + void** cptr; + /// True when Python is responsible for freeing the used memory. + unsigned int hasOwnership : 1; + /// This is true when the C++ class of the wrapped object has a virtual destructor AND was created by Python. + unsigned int containsCppWrapper : 1; + /// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not. + unsigned int validCppObject : 1; + /// Marked as true when the object constructor was called + unsigned int cppObjectCreated : 1; + /// Information about the object parents and children, may be null. + Shiboken::ParentInfo* parentInfo; + /// Manage reference count of objects that are referred to but not owned from. + Shiboken::RefCountMap* referredObjects; + + ~SbkObjectPrivate() + { + delete parentInfo; + parentInfo = 0; + delete referredObjects; + referredObjects = 0; + } +}; + +// TODO-CONVERTERS: to be deprecated/removed +/// The type behaviour was not defined yet +#define BEHAVIOUR_UNDEFINED 0 +/// The type is a value type +#define BEHAVIOUR_VALUETYPE 1 +/// The type is an object type +#define BEHAVIOUR_OBJECTTYPE 2 + +struct SbkObjectTypePrivate +{ + SbkConverter* converter; + int* mi_offsets; + MultipleInheritanceInitFunction mi_init; + + /// Special cast function, null if this class doesn't have multiple inheritance. + SpecialCastFunction mi_specialcast; + TypeDiscoveryFuncV2 type_discovery; + /// Pointer to a function responsible for deletion of the C++ instance calling the proper destructor. + ObjectDestructor cpp_dtor; + /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. + int is_multicpp : 1; + /// True if this type was defined by the user. + int is_user_type : 1; + /// Tells is the type is a value type or an object-type, see BEHAVIOUR_* constants. + // TODO-CONVERTERS: to be deprecated/removed + int type_behaviour : 2; + /// C++ name + char* original_name; + /// Type user data + void* user_data; + DeleteUserDataFunc d_func; + void (*subtype_init)(SbkObjectType*, PyObject*, PyObject*); +}; + + +} // extern "C" + +namespace Shiboken +{ +/** + * Utility function used to transform a PyObject that implements sequence protocol into a std::list. + **/ +std::list splitPyObject(PyObject* pyObj); + +/** +* Visitor class used by walkOnClassHierarchy function. +*/ +class HierarchyVisitor +{ +public: + HierarchyVisitor() : m_wasFinished(false) {} + virtual ~HierarchyVisitor() {} + virtual void visit(SbkObjectType* node) = 0; + virtual void done() {} + void finish() { m_wasFinished = true; }; + bool wasFinished() const { return m_wasFinished; } +private: + bool m_wasFinished; +}; + +class BaseCountVisitor : public HierarchyVisitor +{ +public: + BaseCountVisitor() : m_count(0) {} + + void visit(SbkObjectType*) + { + m_count++; + } + + int count() const { return m_count; } +private: + int m_count; +}; + +class BaseAccumulatorVisitor : public HierarchyVisitor +{ +public: + BaseAccumulatorVisitor() {} + + void visit(SbkObjectType* node) + { + m_bases.push_back(node); + } + + std::list bases() const { return m_bases; } +private: + std::list m_bases; +}; + +class GetIndexVisitor : public HierarchyVisitor +{ +public: + GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {} + virtual void visit(SbkObjectType* node) + { + m_index++; + if (PyType_IsSubtype(reinterpret_cast(node), m_desiredType)) + finish(); + } + int index() const { return m_index; } + +private: + int m_index; + PyTypeObject* m_desiredType; +}; + +/// Call the destructor of each C++ object held by a Python object +class DtorCallerVisitor : public HierarchyVisitor +{ +public: + DtorCallerVisitor(SbkObject* pyObj) : m_pyObj(pyObj) {} + void visit(SbkObjectType* node); + void done(); +protected: + std::list > m_ptrs; + SbkObject* m_pyObj; +}; + +/// Dealloc of each C++ object held by a Python object, this implies a call to the C++ object destructor +class DeallocVisitor : public DtorCallerVisitor +{ +public: + DeallocVisitor(SbkObject* pyObj) : DtorCallerVisitor(pyObj) {} + void done(); +}; + +/// \internal Internal function used to walk on classes inheritance trees. +/** +* Walk on class hierarchy using a DFS algorithm. +* For each pure Shiboken type found, HiearchyVisitor::visit is called and the algorithm consider +* all children of this type as visited. +*/ +void 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::list getCppBaseClasses(PyTypeObject* baseType) +{ + BaseAccumulatorVisitor visitor; + walkThroughClassHierarchy(baseType, &visitor); + return visitor.bases(); +} + +namespace Object +{ +/** +* Decrements the reference counters of every object referred by self. +* \param self the wrapper instance that keeps references to other objects. +*/ +void clearReferences(SbkObject* self); + +/** + * Destroy internal data + **/ +void deallocData(SbkObject* self, bool doCleanup); + +} // namespace Object + +} // namespace Shiboken + +#endif diff --git a/sources/shiboken2/libshiboken/bindingmanager.cpp b/sources/shiboken2/libshiboken/bindingmanager.cpp new file mode 100644 index 000000000..3308ef972 --- /dev/null +++ b/sources/shiboken2/libshiboken/bindingmanager.cpp @@ -0,0 +1,341 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "basewrapper.h" +#include "basewrapper_p.h" +#include "bindingmanager.h" +#include "sbkdbg.h" +#include "gilstate.h" +#include "sbkstring.h" +#include "debugfreehook.h" + +#include +#include +#include + +namespace Shiboken +{ + +typedef std::unordered_map WrapperMap; + +class Graph +{ +public: + typedef std::list NodeList; + typedef std::unordered_map Edges; + + Edges m_edges; + + Graph() + { + } + + void addEdge(SbkObjectType* from, SbkObjectType* to) + { + m_edges[from].push_back(to); + } + +#ifndef NDEBUG + void dumpDotGraph() + { + std::ofstream file("/tmp/shiboken_graph.dot"); + + file << "digraph D {\n"; + + Edges::const_iterator i = m_edges.begin(); + for (; i != m_edges.end(); ++i) { + SbkObjectType* node1 = i->first; + const NodeList& nodeList = i->second; + NodeList::const_iterator j = nodeList.begin(); + for (; j != nodeList.end(); ++j) + file << '"' << (*j)->super.ht_type.tp_name << "\" -> \"" << node1->super.ht_type.tp_name << "\"\n"; + } + file << "}\n"; + } +#endif + + SbkObjectType* identifyType(void** cptr, SbkObjectType* type, SbkObjectType* baseType) const + { + Edges::const_iterator edgesIt = m_edges.find(type); + if (edgesIt != m_edges.end()) { + const NodeList& adjNodes = m_edges.find(type)->second; + NodeList::const_iterator i = adjNodes.begin(); + for (; i != adjNodes.end(); ++i) { + SbkObjectType* newType = identifyType(cptr, *i, baseType); + if (newType) + return newType; + } + } + void* typeFound = ((type->d && type->d->type_discovery) ? type->d->type_discovery(*cptr, baseType) : 0); + 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 SbkObjectType* instead of + // a possible variation of the C++ instance pointer (*cptr). + if (typeFound != type) + *cptr = typeFound; + return type; + } else { + return 0; + } + } +}; + + +#ifndef NDEBUG +static void showWrapperMap(const WrapperMap& wrapperMap) +{ + if (Py_VerboseFlag > 0) { + fprintf(stderr, "-------------------------------\n"); + fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); + WrapperMap::const_iterator iter; + for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) { + const SbkObject *sbkObj = iter->second; + fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", iter->first, + static_cast(sbkObj), + Py_TYPE(sbkObj)->tp_name, + int(reinterpret_cast(sbkObj)->ob_refcnt)); + } + fprintf(stderr, "-------------------------------\n"); + } +} +#endif + +struct BindingManager::BindingManagerPrivate { + WrapperMap wrapperMapper; + Graph classHierarchy; + bool destroying; + + BindingManagerPrivate() : destroying(false) {} + bool releaseWrapper(void* cptr, SbkObject* wrapper); + void assignWrapper(SbkObject* wrapper, const void* cptr); + +}; + +bool BindingManager::BindingManagerPrivate::releaseWrapper(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. + WrapperMap::iterator iter = wrapperMapper.find(cptr); + if (iter != wrapperMapper.end() && (wrapper == 0 || iter->second == wrapper)) { + wrapperMapper.erase(iter); + return true; + } + return false; +} + +void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, const void* cptr) +{ + assert(cptr); + WrapperMap::iterator iter = wrapperMapper.find(cptr); + if (iter == wrapperMapper.end()) + wrapperMapper.insert(std::make_pair(cptr, wrapper)); +} + +BindingManager::BindingManager() +{ + m_d = new BindingManager::BindingManagerPrivate; + +#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK + debugInstallFreeHook(); +#endif +} + +BindingManager::~BindingManager() +{ +#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK + debugRemoveFreeHook(); +#endif +#ifndef NDEBUG + showWrapperMap(m_d->wrapperMapper); +#endif + /* Cleanup hanging references. We just invalidate them as when + * the BindingManager is being destroyed the interpreter is alredy + * shutting down. */ + if (Py_IsInitialized()) { // ensure the interpreter is still valid + while (!m_d->wrapperMapper.empty()) { + Object::destroy(m_d->wrapperMapper.begin()->second, const_cast(m_d->wrapperMapper.begin()->first)); + } + assert(m_d->wrapperMapper.size() == 0); + } + delete m_d; +} + +BindingManager& BindingManager::instance() { + static BindingManager singleton; + return singleton; +} + +bool BindingManager::hasWrapper(const void* cptr) +{ + return m_d->wrapperMapper.find(cptr) != m_d->wrapperMapper.end(); +} + +void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) +{ + SbkObjectType* instanceType = reinterpret_cast(Py_TYPE(pyObj)); + SbkObjectTypePrivate* d = instanceType->d; + + if (!d) + return; + + 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((std::size_t) cptr + (*offset))); + offset++; + } + } +} + +void BindingManager::releaseWrapper(SbkObject* sbkObj) +{ + SbkObjectType* sbkType = reinterpret_cast(Py_TYPE(sbkObj)); + SbkObjectTypePrivate* d = sbkType->d; + int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1); + + void** cptrs = reinterpret_cast(sbkObj)->d->cptr; + for (int i = 0; i < numBases; ++i) { + unsigned char *cptr = reinterpret_cast(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((std::size_t) cptr + (*offset)), sbkObj); + offset++; + } + } + } + sbkObj->d->validCppObject = false; +} + +SbkObject* BindingManager::retrieveWrapper(const void* cptr) +{ + WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); + if (iter == m_d->wrapperMapper.end()) + return 0; + return iter->second; +} + +PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) +{ + 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(wrapper)->ob_refcnt == 0) + return 0; + + if (wrapper->ob_dict) { + PyObject* method = PyDict_GetItemString(wrapper->ob_dict, methodName); + if (method) { + Py_INCREF(reinterpret_cast(method)); + return method; + } + } + + PyObject* pyMethodName = Shiboken::String::fromCString(methodName); + PyObject *method = PyObject_GetAttr(reinterpret_cast(wrapper), pyMethodName); + + if (method && PyMethod_Check(method) + && reinterpret_cast(method)->im_self == reinterpret_cast(wrapper)) { + PyObject* defaultMethod; + PyObject* mro = Py_TYPE(wrapper)->tp_mro; + + // 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 i = 1; i < PyTuple_GET_SIZE(mro) - 1; i++) { + PyTypeObject* parent = reinterpret_cast(PyTuple_GET_ITEM(mro, i)); + if (parent->tp_dict) { + defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName); + if (defaultMethod && reinterpret_cast(method)->im_func != defaultMethod) { + Py_DECREF(pyMethodName); + return method; + } + } + } + } + + Py_XDECREF(method); + Py_DECREF(pyMethodName); + return 0; +} + +void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) +{ + m_d->classHierarchy.addEdge(parent, child); +} + +SbkObjectType* BindingManager::resolveType(void* cptr, SbkObjectType* type) +{ + return resolveType(&cptr, type); +} + +SbkObjectType* BindingManager::resolveType(void** cptr, SbkObjectType* type) +{ + SbkObjectType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); + return identifiedType ? identifiedType : type; +} + +std::set BindingManager::getAllPyObjects() +{ + std::set pyObjects; + const WrapperMap& wrappersMap = m_d->wrapperMapper; + WrapperMap::const_iterator it = wrappersMap.begin(); + for (; it != wrappersMap.end(); ++it) + pyObjects.insert(reinterpret_cast(it->second)); + + return pyObjects; +} + +void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void* data) +{ + WrapperMap copy = m_d->wrapperMapper; + for (WrapperMap::iterator it = copy.begin(); it != copy.end(); ++it) { + if (hasWrapper(it->first)) + visitor(it->second, data); + } +} + +} // namespace Shiboken + diff --git a/sources/shiboken2/libshiboken/bindingmanager.h b/sources/shiboken2/libshiboken/bindingmanager.h new file mode 100644 index 000000000..80c5add2f --- /dev/null +++ b/sources/shiboken2/libshiboken/bindingmanager.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BINDINGMANAGER_H +#define BINDINGMANAGER_H + +#include "sbkpython.h" +#include +#include "shibokenmacros.h" + +struct SbkObject; +struct SbkObjectType; + +namespace Shiboken +{ + +typedef void (*ObjectVisitor)(SbkObject*, void*); + +class LIBSHIBOKEN_API BindingManager +{ +public: + static BindingManager& instance(); + + bool hasWrapper(const void *cptr); + + void registerWrapper(SbkObject* pyObj, void* cptr); + void releaseWrapper(SbkObject* wrapper); + + SbkObject* retrieveWrapper(const void* cptr); + PyObject* getOverride(const void* cptr, const char* methodName); + + void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); + /** + * \deprecated Use \fn resolveType(void**, SbkObjectType*), this version is broken when used with multiple inheritance + * because the \p cptr pointer of the discovered type may be different of the given \p cptr in case + * of multiple inheritance + */ + SBK_DEPRECATED(SbkObjectType* resolveType(void* cptr, SbkObjectType* type)); + /** + * 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. + * \param cptr a pointer to a pointer to the instance of type \p type + * \param type type of *cptr + * \warning This function is slow, use it only as last resort. + */ + SbkObjectType* resolveType(void** cptr, SbkObjectType* type); + + std::set getAllPyObjects(); + + /** + * Calls the function \p visitor for each object registered on binding manager. + * \note As various C++ pointers can point to the same PyObject due to multiple inheritance + * a PyObject can be called more than one time for each PyObject. + * \param visitor function called for each object. + * \param data user data passed as second argument to the visitor function. + */ + void visitAllPyObjects(ObjectVisitor visitor, void* data); + +private: + ~BindingManager(); + // disable copy + BindingManager(); + BindingManager(const BindingManager&); + BindingManager& operator=(const BindingManager&); + + struct BindingManagerPrivate; + BindingManagerPrivate* m_d; +}; + +} // namespace Shiboken + +#endif // BINDINGMANAGER_H + diff --git a/sources/shiboken2/libshiboken/conversions.h b/sources/shiboken2/libshiboken/conversions.h new file mode 100644 index 000000000..f0af2be8e --- /dev/null +++ b/sources/shiboken2/libshiboken/conversions.h @@ -0,0 +1,731 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONVERSIONS_H +#define CONVERSIONS_H + +#include "sbkpython.h" +#include +#include + +#include "sbkstring.h" +#include "sbkenum.h" +#include "basewrapper.h" +#include "bindingmanager.h" +#include "sbkdbg.h" + +// When the user adds a function with an argument unknown for the typesystem, the generator writes type checks as +// TYPENAME_Check, so this macro allows users to add PyObject arguments to their added functions. +#define PyObject_Check(X) true +#define SbkChar_Check(X) (SbkNumber_Check(X) || Shiboken::String::checkChar(X)) +#include "autodecref.h" + +namespace Shiboken +{ +/** +* This function template is used to get the PyTypeObject of a C++ type T. +* All implementations should be provided by template specializations generated by the generator when +* T isn't a C++ primitive type. +* \see SpecialCastFunction +*/ +template +PyTypeObject* SbkType() +{ + return 0; +} + +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } + +/** + * Convenience template to create wrappers using the proper Python type for a given C++ class instance. + */ +template +inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false) +{ + const char* typeName = 0; + if (!isExactType) + typeName = typeid(*const_cast(cppobj)).name(); + return Object::newObject(reinterpret_cast(SbkType()), + const_cast(cppobj), hasOwnership, isExactType, typeName); +} + +// Base Conversions ---------------------------------------------------------- +// The basic converter must be empty to avoid object types being converted by value. +template struct Converter {}; + +// Pointer conversion specialization for value types. +template +struct Converter +{ + static inline bool checkType(PyObject* pyObj) + { + return Converter::checkType(pyObj); + } + + static inline bool isConvertible(PyObject* pyObj) + { + return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); + } + + static PyObject* toPython(const T* cppobj) + { + if (!cppobj) + Py_RETURN_NONE; + PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); + if (pyobj) + Py_INCREF(pyobj); + else + pyobj = createWrapper(cppobj); + return pyobj; + } + + static T* toCpp(PyObject* pyobj) + { + if (PyObject_TypeCheck(pyobj, SbkType())) + return reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); + else if (Converter::isConvertible(pyobj)) + return new T(Converter::toCpp(pyobj)); + else if (pyobj == Py_None) + return 0; + + assert(false); + return 0; + } +}; +template struct Converter : Converter {}; + +// Specialization for reference conversions. +template +struct Converter +{ + static inline bool checkType(PyObject* pyObj) { return Converter::checkType(pyObj); } + static inline bool isConvertible(PyObject* pyObj) { return Converter::isConvertible(pyObj); } + static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } + static inline T& toCpp(PyObject* pyobj) { return *Converter::toCpp(pyobj); } +}; + +// Void pointer conversions. +template<> +struct Converter +{ + static inline bool checkType(PyObject *) { return false; } + static inline bool isConvertible(PyObject *) { return true; } + static PyObject* toPython(void* cppobj) + { + if (!cppobj) + Py_RETURN_NONE; + PyObject *result = reinterpret_cast(cppobj); + Py_INCREF(result); + return result; + } + static void* toCpp(PyObject* pyobj) { return pyobj; } +}; + +// Base converter meant to be inherited by converters for classes that could be +// passed by value. +// Example: "struct Converter : ValueTypeConverter" +template +struct ValueTypeConverter +{ + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + + // The basic version of this method also tries to use the extended 'isConvertible' method. + static inline bool isConvertible(PyObject* pyobj) + { + if (PyObject_TypeCheck(pyobj, SbkType())) + return true; + SbkObjectType* shiboType = reinterpret_cast(SbkType()); + return ObjectType::isExternalConvertible(shiboType, pyobj); + } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(const T& cppobj) + { + PyObject* obj = createWrapper(new T(cppobj), true, true); +// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo::isCppWrapper); + return obj; + } + // Classes with implicit conversions are expected to reimplement 'toCpp' to build T from + // its various implicit constructors. Even classes without implicit conversions could + // get some of those via other modules defining conversion operator for them, thus + // the basic Converter for value types checks for extended conversion and tries to + // use them if it is the case. + static inline T toCpp(PyObject* pyobj) + { + if (!PyObject_TypeCheck(pyobj, SbkType())) { + SbkObjectType* shiboType = reinterpret_cast(SbkType()); + if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { + T* cptr = reinterpret_cast(ObjectType::callExternalCppConversion(shiboType, pyobj)); + const T result = *cptr; + delete cptr; + return result; + } + assert(false); + } + return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); + } +}; + +// Base converter meant to be inherited by converters for abstract classes and object types +// (i.e. classes with private copy constructors and = operators). +// Example: "struct Converter : ObjectTypeConverter" +template +struct ObjectTypeConverter +{ + static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } + /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer). + static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } + /// Convenience overload that calls "toPython(const T*)" method. + static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } + /// Returns a new Python wrapper for the C++ object or an existing one with its reference counter incremented. + static PyObject* toPython(const T* cppobj) + { + if (!cppobj) + Py_RETURN_NONE; + PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); + if (pyobj) + Py_INCREF(pyobj); + else + pyobj = createWrapper(cppobj); + return pyobj; + } + /// Returns the wrapped C++ pointer casted properly, or a NULL pointer if the argument is a Py_None. + static T* toCpp(PyObject* pyobj) + { + if (pyobj == Py_None) + return 0; + SbkObject *sbkObj = reinterpret_cast(pyobj); + SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); + if (ObjectType::hasCast(shiboType)) + return reinterpret_cast(ObjectType::cast(shiboType, sbkObj, SbkType())); + return reinterpret_cast(Object::cppPointer(sbkObj, SbkType())); + } +}; + +template +struct ObjectTypeReferenceConverter : ObjectTypeConverter +{ + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + static inline PyObject* toPython(const T& cppobj) { return Converter::toPython(&cppobj); } + static inline T& toCpp(PyObject* pyobj) + { + T* t = Converter::toCpp(pyobj); + assert(t); + return *t; + } +}; + +// PyObject* specialization to avoid converting what doesn't need to be converted. +template<> +struct Converter : ObjectTypeConverter +{ + static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } +}; + +// Primitive Conversions ------------------------------------------------------ +template <> +struct Converter +{ + static inline bool checkType(PyObject* pyobj) { return PyBool_Check(pyobj); } + static inline bool isConvertible(PyObject* pyobj) { return PyInt_Check(pyobj); } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(bool cppobj) { return PyBool_FromLong(cppobj); } + static inline bool toCpp(PyObject* pyobj) { return PyInt_AS_LONG(pyobj); } +}; + +/** + * Helper template for checking if a value overflows when casted to type T + */ +template::is_signed > +struct OverFlowChecker; + +template +struct OverFlowChecker +{ + static bool check(const PY_LONG_LONG& value) + { + return value < std::numeric_limits::min() || value > std::numeric_limits::max(); + } +}; + +template +struct OverFlowChecker +{ + static bool check(const PY_LONG_LONG& value) + { + return value < 0 || static_cast(value) > std::numeric_limits::max(); + } +}; + +template<> +struct OverFlowChecker +{ + static bool check(const PY_LONG_LONG &) + { + return false; + } +}; + +template<> +struct OverFlowChecker +{ + static bool check(const double &) + { + return false; + } +}; + +template<> +struct OverFlowChecker +{ + static bool check(const double& value) + { + return value < std::numeric_limits::min() || value > std::numeric_limits::max(); + } +}; + +template +struct Converter_PyInt +{ + static inline bool checkType(PyObject* pyobj) { return PyInt_Check(pyobj); } + static inline bool isConvertible(PyObject* pyobj) { return SbkNumber_Check(pyobj); } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(const PyIntEquiv& cppobj) { return PyInt_FromLong((long) cppobj); } + static PyIntEquiv toCpp(PyObject* pyobj) + { + if (PyFloat_Check(pyobj)) { + double d_result = PyFloat_AS_DOUBLE(pyobj); + // If cast to long directly it could overflow silently + if (OverFlowChecker::check(d_result)) + PyErr_SetObject(PyExc_OverflowError, 0); + return static_cast(d_result); + } else { + PY_LONG_LONG result = PyLong_AsLongLong(pyobj); + if (OverFlowChecker::check(result)) + PyErr_SetObject(PyExc_OverflowError, 0); + return static_cast(result); + } + } +}; + +template +struct Converter_PyULongInt : Converter_PyInt +{ + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(const T& cppobj) { return PyLong_FromUnsignedLong(cppobj); } +}; + +/// Specialization to convert char and unsigned char, it accepts Python numbers and strings with just one character. +template +struct CharConverter +{ + static inline bool checkType(PyObject* pyobj) { return SbkChar_Check(pyobj); } + static inline bool isConvertible(PyObject* pyobj) { return SbkChar_Check(pyobj); } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(const CharType& cppobj) { return PyInt_FromLong(cppobj); } + static CharType toCpp(PyObject* pyobj) + { + if (PyBytes_Check(pyobj)) { + assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check + return PyBytes_AS_STRING(pyobj)[0]; + } else if (PyInt_Check(pyobj)) { + PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); + if (OverFlowChecker::check(result)) + PyErr_SetObject(PyExc_OverflowError, 0); + return result; + } else if (Shiboken::String::check(pyobj)) { + return Shiboken::String::toCString(pyobj)[0]; + } else { + return 0; + } + } +}; + +template <> struct Converter : Converter_PyULongInt {}; +template <> struct Converter : Converter_PyULongInt {}; +template <> struct Converter : CharConverter +{ + // Should we really return a string? + using CharConverter::toPython; + using CharConverter::isConvertible; + using CharConverter::toCpp; + + + static inline bool isConvertible(PyObject* pyobj) { + return SbkChar_Check(pyobj); + } + + static inline PyObject* toPython(const char& cppObj) { + return Shiboken::String::fromFormat("%c", cppObj); + } + + static char toCpp(PyObject* pyobj) + { + if (PyBytes_Check(pyobj)) { + assert(PyBytes_GET_SIZE(pyobj) == 1); // This check is made on SbkChar_Check + return PyBytes_AS_STRING(pyobj)[0]; + } else if (PyInt_Check(pyobj)) { + PY_LONG_LONG result = PyInt_AsUnsignedLongLongMask(pyobj); + if (OverFlowChecker::check(result)) + PyErr_SetObject(PyExc_OverflowError, 0); + return char(result); + } else if (Shiboken::String::check(pyobj)) { + return Shiboken::String::toCString(pyobj)[0]; + } else { + return 0; + } + } +}; +template <> struct Converter : CharConverter {}; +template <> struct Converter : CharConverter {}; +template <> struct Converter : Converter_PyInt {}; +template <> struct Converter : Converter_PyInt {}; +template <> struct Converter : Converter_PyInt {}; +template <> struct Converter : Converter_PyInt {}; + +template <> +struct Converter +{ + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(PY_LONG_LONG cppobj) { return PyLong_FromLongLong(cppobj); } + static inline PY_LONG_LONG toCpp(PyObject* pyobj) { return (PY_LONG_LONG) PyLong_AsLongLong(pyobj); } +}; + +template <> +struct Converter +{ + static inline PyObject* toPython(void* cppobj) + { + return toPython(*reinterpret_cast(cppobj)); + } + static inline PyObject* toPython(unsigned PY_LONG_LONG cppobj) + { + return PyLong_FromUnsignedLongLong(cppobj); + } + static inline unsigned PY_LONG_LONG toCpp(PyObject* pyobj) + { +#if PY_MAJOR_VERSION >= 3 + if (!PyLong_Check(pyobj)) { + PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); + return 0; + } + + return PyLong_AsUnsignedLongLong(pyobj); +#else + if (PyInt_Check(pyobj)) { + long result = (unsigned PY_LONG_LONG) PyInt_AsLong(pyobj); + if (result < 0) { + PyErr_SetObject(PyExc_OverflowError, 0); + return 0; + } else + return (unsigned PY_LONG_LONG) result; + } else if (PyLong_Check(pyobj)) { + return (unsigned PY_LONG_LONG) PyLong_AsUnsignedLongLong(pyobj); + } else { + PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); + return 0; + } +#endif // Python 2 + } +}; + +template +struct Converter_PyFloat +{ + static inline bool checkType(PyObject* obj) { return PyFloat_Check(obj); } + static inline bool isConvertible(PyObject* obj) { return SbkNumber_Check(obj); } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(PyFloatEquiv cppobj) { return PyFloat_FromDouble((double) cppobj); } + static inline PyFloatEquiv toCpp(PyObject* pyobj) + { + if (PyInt_Check(pyobj) || PyLong_Check(pyobj)) + return (PyFloatEquiv) PyLong_AsLong(pyobj); + return (PyFloatEquiv) PyFloat_AsDouble(pyobj); + } +}; + +template <> struct Converter : Converter_PyFloat {}; +template <> struct Converter : Converter_PyFloat {}; + +// PyEnum Conversions --------------------------------------------------------- +template +struct EnumConverter +{ + static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(CppEnum cppenum) + { + return Shiboken::Enum::newItem(Shiboken::SbkType(), (long) cppenum); + } + static inline CppEnum toCpp(PyObject* pyObj) + { + return (CppEnum) Shiboken::Enum::getValue(pyObj);; + } +}; + +// C Sting Types -------------------------------------------------------------- +template +struct Converter_CString +{ + // Note: 0 is also a const char* in C++, so None is accepted in checkType + static inline bool checkType(PyObject* pyObj) { + return Shiboken::String::check(pyObj); + } + static inline bool isConvertible(PyObject* pyObj) { + return Shiboken::String::isConvertible(pyObj); + } + static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } + static inline PyObject* toPython(CString cppobj) + { + if (!cppobj) + Py_RETURN_NONE; + return Shiboken::String::fromCString(cppobj); + } + static inline CString toCpp(PyObject* pyobj) { + if (pyobj == Py_None) + return 0; + return Shiboken::String::toCString(pyobj); + } +}; + +template <> struct Converter : Converter_CString {}; + +template <> struct Converter : Converter_CString +{ + static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } + static inline PyObject* toPython(std::string cppObj) + { + return Shiboken::String::fromCString(cppObj.c_str()); + } + + static inline std::string toCpp(PyObject* pyobj) + { + if (pyobj == Py_None) + return 0; + return std::string(Shiboken::String::toCString(pyobj)); + } +}; + +// C++ containers ------------------------------------------------------------- +// The following container converters are meant to be used for pairs, lists and maps +// that are similar to the STL containers of the same name. + +// For example to create a converter for a std::list the following code is enough: +// template struct Converter > : StdListConverter > {}; + +// And this for a std::map: +// template +// struct Converter > : StdMapConverter > {}; + +template +struct StdListConverter +{ + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + + static inline bool isConvertible(PyObject* pyObj) + { + if (PyObject_TypeCheck(pyObj, SbkType())) + return true; + // Sequence conversion are made ONLY for python sequences, not for + // binded types implementing sequence protocol, otherwise this will + // cause a mess like QBitArray being accepted by someone expecting a + // QStringList. + if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj)) + return false; + for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { + AutoDecRef item(PySequence_GetItem(pyObj, i)); + if (!Converter::isConvertible(item)) + return false; + } + return true; + } + static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } + static PyObject* toPython(const StdList& cppobj) + { + PyObject* result = PyList_New((int) cppobj.size()); + typename StdList::const_iterator it = cppobj.begin(); + for (int idx = 0; it != cppobj.end(); ++it, ++idx) { + typename StdList::value_type vh(*it); + PyList_SET_ITEM(result, idx, Converter::toPython(vh)); + } + return result; + } + static StdList toCpp(PyObject* pyobj) + { + if (PyObject_TypeCheck(pyobj, SbkType())) + return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); + + StdList result; + for (int i = 0; i < PySequence_Size(pyobj); i++) { + AutoDecRef pyItem(PySequence_GetItem(pyobj, i)); + result.push_back(Converter::toCpp(pyItem)); + } + return result; + } +}; + +template +struct StdPairConverter +{ + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + + static inline bool isConvertible(PyObject* pyObj) + { + if (PyObject_TypeCheck(pyObj, SbkType())) + return true; + if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) + return false; + + AutoDecRef item1(PySequence_GetItem(pyObj, 0)); + AutoDecRef item2(PySequence_GetItem(pyObj, 1)); + + if (!Converter::isConvertible(item1) + && !Converter::isConvertible(item2)) { + return false; + } + return true; + } + static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } + static PyObject* toPython(const StdPair& cppobj) + { + typename StdPair::first_type first(cppobj.first); + typename StdPair::second_type second(cppobj.second); + PyObject* tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, Converter::toPython(first)); + PyTuple_SET_ITEM(tuple, 1, Converter::toPython(second)); + return tuple; + } + static StdPair toCpp(PyObject* pyobj) + { + StdPair result; + AutoDecRef pyFirst(PySequence_GetItem(pyobj, 0)); + AutoDecRef pySecond(PySequence_GetItem(pyobj, 1)); + result.first = Converter::toCpp(pyFirst); + result.second = Converter::toCpp(pySecond); + return result; + } +}; + +template +struct StdMapConverter +{ + static inline bool checkType(PyObject* pyObj) + { + return isConvertible(pyObj); + } + + static inline bool isConvertible(PyObject* pyObj) + { + if (PyObject_TypeCheck(pyObj, SbkType())) + return true; + if ((SbkType() && Object::checkType(pyObj)) || !PyDict_Check(pyObj)) + return false; + + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + + while (PyDict_Next(pyObj, &pos, &key, &value)) { + if (!Converter::isConvertible(key) + || !Converter::isConvertible(value)) { + return false; + } + } + return true; + } + + static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast(cppObj)); } + static PyObject* toPython(const StdMap& cppobj) + { + PyObject* result = PyDict_New(); + typename StdMap::const_iterator it = cppobj.begin(); + + for (; it != cppobj.end(); ++it) { + PyDict_SetItem(result, + Converter::toPython(it->first), + Converter::toPython(it->second)); + } + + return result; + } + static StdMap toCpp(PyObject* pyobj) + { + StdMap result; + + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + + while (PyDict_Next(pyobj, &pos, &key, &value)) { + result.insert(typename StdMap::value_type( + Converter::toCpp(key), + Converter::toCpp(value))); + } + return result; + } +}; + + +// class used to translate python objects to another type +template struct PythonConverter {}; + +} // namespace Shiboken + +#endif // CONVERSIONS_H + diff --git a/sources/shiboken2/libshiboken/debugfreehook.cpp b/sources/shiboken2/libshiboken/debugfreehook.cpp new file mode 100644 index 000000000..f5757a70f --- /dev/null +++ b/sources/shiboken2/libshiboken/debugfreehook.cpp @@ -0,0 +1,194 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "debugfreehook.h" +#include "bindingmanager.h" +#include "gilstate.h" + +#if defined(_WIN32) && defined(_DEBUG) +#include +#include +#endif + +#ifdef __GLIBC__ +#include +#endif + +#ifdef __APPLE__ +#include +#include +#include +#endif + +#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK +extern "C" { + +static int testPointerBeingFreed(void *ptr) +{ + // It is an error for a deleted pointer address to still be registered + // in the BindingManager + if (Shiboken::BindingManager::instance().hasWrapper(ptr)) { + Shiboken::GilState state; + + SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(ptr); + + fprintf(stderr, "SbkObject still in binding map when deleted: "); + PyObject_Print(reinterpret_cast(wrapper), stderr, 0); + fprintf(stderr, "\n"); + +#ifdef _WIN32 + DebugBreak(); +#else + assert(0); +#endif + return FALSE; + } + + return TRUE; +} + +#if defined(_WIN32) && defined(_DEBUG) +static _CRT_ALLOC_HOOK lastCrtAllocHook; +static int DebugAllocHook(int nAllocType, void *pvData, + size_t nSize, int nBlockUse, long lRequest, + const unsigned char * szFileName, int nLine) +{ + // It is an error for a deleted pointer address to still be registered + // in the BindingManager + if ( nAllocType == _HOOK_FREE) { + if ( !testPointerBeingFreed(pvData) ) { + return 0; + } + } + + if ( lastCrtAllocHook != NULL ) { + return lastCrtAllocHook(nAllocType, pvData, nSize, nBlockUse, lRequest, + szFileName, nLine); + } + + return 1; +} +#endif // _WIN32 && _DEBUG + +#ifdef __GLIBC__ +static void (*lastFreeHook)(void* ptr, const void* caller); +static void DebugFreeHook(void* ptr, const void* caller) +{ + testPointerBeingFreed(ptr); + + if ( lastFreeHook != NULL ) + lastFreeHook(ptr, caller); +} +#endif // __GLIBC__ + +#ifdef __APPLE__ +static malloc_zone_t lastMallocZone; +static void DebugFreeHook(malloc_zone_t *zone, void *ptr) +{ + testPointerBeingFreed(ptr); + + if ( lastMallocZone.free != NULL ) + lastMallocZone.free(zone, ptr); +} +static void DebugFreeDefiniteSizeHook(malloc_zone_t *zone, void *ptr, size_t size) +{ + testPointerBeingFreed(ptr); + + if ( lastMallocZone.free_definite_size != NULL ) + lastMallocZone.free_definite_size(zone, ptr, size); +} +#endif __APPLE__ + +void debugInstallFreeHook(void) +{ +#if defined(_WIN32) && defined(_DEBUG) + lastCrtAllocHook = _CrtSetAllocHook(DebugAllocHook); +#endif + +#ifdef __GLIBC__ + // __free_hook is not thread safe so it marked as deprecated. Use here + // is hopefully safe and should catch errors in a single threaded program + // and only miss some in a multithreaded program + lastFreeHook = __free_hook; + __free_hook = DebugFreeHook; +#endif + +#ifdef __APPLE__ + malloc_zone_t* zone = malloc_default_zone(); + assert(zone != NULL); + //remove the write protection from the zone struct + if (zone->version >= 8) { + vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); + } + lastMallocZone = *zone; + zone->free = DebugFreeHook; + zone->free_definite_size = DebugFreeDefiniteSizeHook; + if (zone->version >= 8) { + vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); + } +#endif +} + +void debugRemoveFreeHook(void) +{ +#if defined(_WIN32) && defined(_DEBUG) + _CrtSetAllocHook(lastCrtAllocHook); +#endif + +#ifdef __GLIBC__ + __free_hook = lastFreeHook; +#endif + +#ifdef __APPLE__ + malloc_zone_t* zone = malloc_default_zone(); + assert(zone != NULL); + //remove the write protection from the zone struct + if (zone->version >= 8) { + vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ | VM_PROT_WRITE); + } + zone->free = lastMallocZone.free; + zone->free_definite_size = lastMallocZone.free_definite_size; + if (zone->version >= 8) { + vm_protect(mach_task_self(), (uintptr_t)zone, sizeof(*zone), 0, VM_PROT_READ); + } +#endif +} + +} // extern "C" +#endif // SHIBOKEN_INSTALL_DEBUG_FREE_HOOK diff --git a/sources/shiboken2/libshiboken/debugfreehook.h b/sources/shiboken2/libshiboken/debugfreehook.h new file mode 100644 index 000000000..743d56e4c --- /dev/null +++ b/sources/shiboken2/libshiboken/debugfreehook.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DEBUGFREEHOOK_H +#define DEBUGFREEHOOK_H + +// These functions enable C library runtime hooks to try to catch cases where +// C++ object addresses remain in hash table of valid wrappers when the address +// is passed to free. The hooks are probably not thread safe and thus +// should only be enabled in single threaded environments + +// To enable the hook, uncomment the following define. +//#define SHIBOKEN_INSTALL_FREE_DEBUG_HOOK + +#ifdef SHIBOKEN_INSTALL_FREE_DEBUG_HOOK +extern "C" { + +void debugInstallFreeHook(void); +void debugRemoveFreeHook(void); + +} // extern "C" + +#endif // SHIBOKEN_INSTALL_FREE_DEBUG_HOOK + +#endif // DEBUGFREEHOOK_H diff --git a/sources/shiboken2/libshiboken/gilstate.cpp b/sources/shiboken2/libshiboken/gilstate.cpp new file mode 100644 index 000000000..e7406fdd6 --- /dev/null +++ b/sources/shiboken2/libshiboken/gilstate.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gilstate.h" + +namespace Shiboken +{ + +GilState::GilState() + : m_locked(false) +{ + if (Py_IsInitialized()) { + m_gstate = PyGILState_Ensure(); + m_locked = true; + } +} + +GilState::~GilState() +{ + release(); +} + +void GilState::release() +{ + if (m_locked && Py_IsInitialized()) { + PyGILState_Release(m_gstate); + m_locked = false; + } +} + +} // namespace Shiboken + diff --git a/sources/shiboken2/libshiboken/gilstate.h b/sources/shiboken2/libshiboken/gilstate.h new file mode 100644 index 000000000..e0f18a814 --- /dev/null +++ b/sources/shiboken2/libshiboken/gilstate.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GILSTATE_H +#define GILSTATE_H + +#include +#include "sbkpython.h" + +namespace Shiboken +{ + +class LIBSHIBOKEN_API GilState +{ +public: + GilState(); + ~GilState(); + void release(); +private: + PyGILState_STATE m_gstate; + bool m_locked; +}; + +} // namespace Shiboken + +#endif // GILSTATE_H + diff --git a/sources/shiboken2/libshiboken/helper.cpp b/sources/shiboken2/libshiboken/helper.cpp new file mode 100644 index 000000000..9709d0776 --- /dev/null +++ b/sources/shiboken2/libshiboken/helper.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "helper.h" +#include + +namespace Shiboken +{ + +bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) +{ + if (!PySequence_Check(argList)) + return false; + + if (!defaultAppName) + defaultAppName = "PySideApplication"; + + // Check all items + Shiboken::AutoDecRef args(PySequence_Fast(argList, 0)); + int numArgs = PySequence_Fast_GET_SIZE(argList); + for (int i = 0; i < numArgs; ++i) { + PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); + if (!PyBytes_Check(item) && !PyUnicode_Check(item)) + return false; + } + + bool hasEmptyArgList = numArgs == 0; + if (hasEmptyArgList) + numArgs = 1; + + *argc = numArgs; + *argv = new char*[*argc]; + + if (hasEmptyArgList) { + // Try to get the script name + PyObject* globals = PyEval_GetGlobals(); + PyObject* appName = PyDict_GetItemString(globals, "__file__"); + (*argv)[0] = strdup(appName ? Shiboken::String::toCString(appName) : defaultAppName); + } else { + for (int i = 0; i < numArgs; ++i) { + PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); + char* string = 0; + if (Shiboken::String::check(item)) { + string = strdup(Shiboken::String::toCString(item)); + } + (*argv)[i] = string; + } + } + + return true; +} + +int* sequenceToIntArray(PyObject* obj, bool zeroTerminated) +{ + AutoDecRef seq(PySequence_Fast(obj, "Sequence of ints expected")); + if (seq.isNull()) + return 0; + + Py_ssize_t size = PySequence_Fast_GET_SIZE(seq.object()); + int* array = new int[size + (zeroTerminated ? 1 : 0)]; + + for (int i = 0; i < size; i++) { + PyObject* item = PySequence_Fast_GET_ITEM(seq.object(), i); + if (!PyInt_Check(item)) { + PyErr_SetString(PyExc_TypeError, "Sequence of ints expected"); + delete[] array; + return 0; + } else { + array[i] = PyInt_AsLong(item); + } + } + + if (zeroTerminated) + array[size] = 0; + + return array; +} + + +int warning(PyObject* category, int stacklevel, const char* format, ...) +{ + va_list args; + va_start(args, format); +#if _WIN32 + va_list args2 = args; +#else + va_list args2; + va_copy(args2, args); +#endif + + // check the necessary memory + int size = vsnprintf(NULL, 0, format, args) + 1; + char* message = new char[size]; + int result = 0; + if (message) { + // format the message + vsnprintf(message, size, format, args2); + result = PyErr_WarnEx(category, message, stacklevel); + delete [] message; + } + va_end(args2); + va_end(args); + return result; +} + +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/helper.h b/sources/shiboken2/libshiboken/helper.h new file mode 100644 index 000000000..f2061b667 --- /dev/null +++ b/sources/shiboken2/libshiboken/helper.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HELPER_H +#define HELPER_H + +#include "sbkpython.h" +#include "shibokenmacros.h" +#include "conversions.h" +#include "autodecref.h" + +#define SBK_UNUSED(x) (void)x; + +namespace Shiboken +{ + +template +inline PyObject* makeTuple(const A& a) +{ + return PyTuple_Pack(1, AutoDecRef(Converter::toPython(a)).object()); +} + +template +inline PyObject* makeTuple(const A& a, const B& b) +{ + return PyTuple_Pack(2, AutoDecRef(Converter::toPython(a)).object(), + AutoDecRef(Converter::toPython(b)).object()); +} + +template +inline PyObject* makeTuple(const A& a, const B& b, const C& c) +{ + return PyTuple_Pack(3, AutoDecRef(Converter::toPython(a)).object(), + AutoDecRef(Converter::toPython(b)).object(), + AutoDecRef(Converter::toPython(c)).object()); +} + +template +inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d) +{ + return PyTuple_Pack(4, AutoDecRef(Converter::toPython(a)).object(), + AutoDecRef(Converter::toPython(b)).object(), + AutoDecRef(Converter::toPython(c)).object(), + AutoDecRef(Converter::toPython(d)).object()); +} + +template +inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e) +{ + return PyTuple_Pack(5, AutoDecRef(Converter::toPython(a)).object(), + AutoDecRef(Converter::toPython(b)).object(), + AutoDecRef(Converter::toPython(c)).object(), + AutoDecRef(Converter::toPython(d)).object(), + AutoDecRef(Converter::toPython(e)).object()); +} + +/** +* It transforms a python sequence into two C variables, argc and argv. +* This function tries to find the application (script) name and put it into argv[0], if +* the application name can't be guessed, defaultAppName will be used. +* +* No memory is allocated is an error occur. +* +* \note argc must be a valid address. +* \note The argv array is allocated using new operator and each item is allocated using malloc. +* \returns True on sucess, false otherwise. +*/ +LIBSHIBOKEN_API bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); + +/** + * Convert a python sequence into a heap-allocated array of ints. + * + * \returns The newly allocated array or NULL in case of error or empty sequence. Check with PyErr_Occurred + * if it was successfull. + */ +LIBSHIBOKEN_API int* sequenceToIntArray(PyObject* obj, bool zeroTerminated = false); + +/** + * Creates and automatically deallocates C++ arrays. + */ +template +class AutoArrayPointer +{ + public: + AutoArrayPointer(int size) { data = new T[size]; } + T& operator[](int pos) { return data[pos]; } + operator T*() const { return data; } + ~AutoArrayPointer() { delete[] data; } + private: + T* data; +}; + +/** + * An utility function used to call PyErr_WarnEx with a formatted message. + */ +LIBSHIBOKEN_API int warning(PyObject* category, int stacklevel, const char* format, ...); + +} // namespace Shiboken + +#endif // HELPER_H diff --git a/sources/shiboken2/libshiboken/python25compat.h b/sources/shiboken2/libshiboken/python25compat.h new file mode 100644 index 000000000..71c88d86a --- /dev/null +++ b/sources/shiboken2/libshiboken/python25compat.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PYTHON25COMPAT_H +#define PYTHON25COMPAT_H +#include +#include + +/* + *The #defines below were taken from Cython-generated code to allow shiboken to be used with python2.5. + * Maybe not all of these defines are useful to us, time will tell which ones are really needed or not. + */ + +#if PY_VERSION_HEX < 0x02060000 +#define Py_REFCNT(ob) (((PyObject*)(ob))->ob_refcnt) +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) +#define PyVarObject_HEAD_INIT(type, size) \ + PyObject_HEAD_INIT(type) size, +#define PyType_Modified(t) + +typedef struct { + void *buf; + PyObject *obj; + Py_ssize_t len; + Py_ssize_t itemsize; + int readonly; + int ndim; + char *format; + Py_ssize_t *shape; + Py_ssize_t *strides; + Py_ssize_t *suboffsets; + void *internal; +} Py_buffer; + +#define PyBUF_SIMPLE 0 +#define PyBUF_WRITABLE 0x0001 +#define PyBUF_LOCK 0x0002 +#define PyBUF_FORMAT 0x0004 +#define PyBUF_ND 0x0008 +#define PyBUF_STRIDES (0x0010 | PyBUF_ND) +#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES) +#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES) +#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES) +#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES) + +#define PyBytes_Check PyString_Check +#define PyBytes_FromString PyString_FromString +#define PyBytes_FromFormat PyString_FromFormat +#define PyBytes_FromStringAndSize PyString_FromStringAndSize +#define PyBytes_GET_SIZE PyString_GET_SIZE +#define PyBytes_AS_STRING PyString_AS_STRING +#define PyBytes_AsString PyString_AsString +#define PyBytes_Concat PyString_Concat +#define PyBytes_Size PyString_Size + +inline PyObject* PyUnicode_FromString(const char* s) +{ + std::size_t len = std::strlen(s); + return PyUnicode_DecodeUTF8(s, len, 0); +} + +#define PyLong_FromSize_t _PyLong_FromSize_t +#define PyLong_AsSsize_t _PyLong_AsSsize_t + +#endif + +#endif diff --git a/sources/shiboken2/libshiboken/sbkconverter.cpp b/sources/shiboken2/libshiboken/sbkconverter.cpp new file mode 100644 index 000000000..b22b33705 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkconverter.cpp @@ -0,0 +1,571 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkconverter.h" +#include "sbkconverter_p.h" +#include "basewrapper_p.h" +#include "autodecref.h" +#include "sbkdbg.h" +#include "helper.h" + +#include + +static SbkConverter** PrimitiveTypeConverters; + +typedef std::unordered_map ConvertersMap; +static ConvertersMap converters; + +namespace Shiboken { +namespace Conversions { + +void init() +{ + static SbkConverter* primitiveTypeConverters[] = { + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter(), + Primitive::createConverter() + }; + PrimitiveTypeConverters = primitiveTypeConverters; + + assert(converters.empty()); + converters["PY_LONG_LONG"] = primitiveTypeConverters[SBK_PY_LONG_LONG_IDX]; + converters["bool"] = primitiveTypeConverters[SBK_BOOL_IDX_1]; + converters["char"] = primitiveTypeConverters[SBK_CHAR_IDX]; + converters["const char *"] = primitiveTypeConverters[SBK_CONSTCHARPTR_IDX]; + converters["double"] = primitiveTypeConverters[SBK_DOUBLE_IDX]; + converters["float"] = primitiveTypeConverters[SBK_FLOAT_IDX]; + converters["int"] = primitiveTypeConverters[SBK_INT_IDX]; + converters["long"] = primitiveTypeConverters[SBK_LONG_IDX]; + converters["short"] = primitiveTypeConverters[SBK_SHORT_IDX]; + converters["signed char"] = primitiveTypeConverters[SBK_SIGNEDCHAR_IDX]; + converters["std::string"] = primitiveTypeConverters[SBK_STD_STRING_IDX]; + converters["unsigned PY_LONG_LONG"] = primitiveTypeConverters[SBK_UNSIGNEDPY_LONG_LONG_IDX]; + converters["unsigned char"] = primitiveTypeConverters[SBK_UNSIGNEDCHAR_IDX]; + converters["unsigned int"] = primitiveTypeConverters[SBK_UNSIGNEDINT_IDX]; + converters["unsigned long"] = primitiveTypeConverters[SBK_UNSIGNEDLONG_IDX]; + converters["unsigned short"] = primitiveTypeConverters[SBK_UNSIGNEDSHORT_IDX]; + converters["void*"] = primitiveTypeConverters[SBK_VOIDPTR_IDX]; +} + +static SbkConverter* createConverterObject(PyTypeObject* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc) +{ + SbkConverter* converter = new SbkConverter; + converter->pythonType = type; + + converter->pointerToPython = pointerToPythonFunc; + converter->copyToPython = copyToPythonFunc; + + if (toCppPointerCheckFunc && toCppPointerConvFunc) + converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); + converter->toCppConversions.clear(); + + return converter; +} + +SbkConverter* createConverter(SbkObjectType* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc) +{ + SbkConverter *converter = + createConverterObject(reinterpret_cast(type), + toCppPointerConvFunc, toCppPointerCheckFunc, + pointerToPythonFunc, copyToPythonFunc); + type->d->converter = converter; + return converter; +} + +SbkConverter* createConverter(PyTypeObject* type, CppToPythonFunc toPythonFunc) +{ + return createConverterObject(type, 0, 0, 0, toPythonFunc); +} + +void deleteConverter(SbkConverter* converter) +{ + if (converter) { + converter->toCppConversions.clear(); + delete converter; + } +} + +void setCppPointerToPythonFunction(SbkConverter* converter, CppToPythonFunc pointerToPythonFunc) +{ + converter->pointerToPython = pointerToPythonFunc; +} + +void setPythonToCppPointerFunctions(SbkConverter* converter, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc) +{ + converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); +} + +void addPythonToCppValueConversion(SbkConverter* converter, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc) +{ + converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); +} +void addPythonToCppValueConversion(SbkObjectType* type, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc) +{ + addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); +} + +PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn) +{ + return pointerToPython(type->d->converter, cppIn); +} + +PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn) +{ + assert(converter); + if (!cppIn) + Py_RETURN_NONE; + if (!converter->pointerToPython) { + warning(PyExc_RuntimeWarning, 0, "pointerToPython(): SbkConverter::pointerToPython is null for \"%s\".", + converter->pythonType->tp_name); + Py_RETURN_NONE; + } + return converter->pointerToPython(cppIn); +} + +PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn) +{ + return referenceToPython(type->d->converter, cppIn); +} + +PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn) +{ + assert(cppIn); + + PyObject *pyOut = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppIn)); + if (pyOut) { + Py_INCREF(pyOut); + return pyOut; + } + if (!converter->pointerToPython) { + warning(PyExc_RuntimeWarning, 0, "referenceToPython(): SbkConverter::pointerToPython is null for \"%s\".", + converter->pythonType->tp_name); + Py_RETURN_NONE; + } + return converter->pointerToPython(cppIn); +} + +static inline PyObject* CopyCppToPython(const SbkConverter *converter, const void *cppIn) +{ + if (!cppIn) + Py_RETURN_NONE; + if (!converter->copyToPython) { + warning(PyExc_RuntimeWarning, 0, "CopyCppToPython(): SbkConverter::copyToPython is null for \"%s\".", + converter->pythonType->tp_name); + Py_RETURN_NONE; + } + return converter->copyToPython(cppIn); +} +PyObject* copyToPython(const SbkObjectType *type, const void *cppIn) +{ + return CopyCppToPython(type->d->converter, cppIn); +} +PyObject* copyToPython(const SbkConverter *converter, const void *cppIn) +{ + return CopyCppToPython(converter, cppIn); +} + +PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn) +{ + assert(pyIn); + return type->d->converter->toCppPointerConversion.first(pyIn); +} + +static inline PythonToCppFunc IsPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) +{ + assert(pyIn); + const ToCppConversionList& convs = converter->toCppConversions; + for (ToCppConversionList::const_iterator conv = convs.begin(), end = convs.end(); conv != end; ++conv) { + PythonToCppFunc toCppFunc = 0; + if ((toCppFunc = (*conv).first(pyIn))) + return toCppFunc; + } + return 0; +} +PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn) +{ + return IsPythonToCppConvertible(type->d->converter, pyIn); +} +PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn) +{ + return IsPythonToCppConvertible(converter, pyIn); +} + +PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn) +{ + if (pyIn != Py_None) { + PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); + if (toCpp) + return toCpp; + } + return isPythonToCppValueConvertible(type, pyIn); +} + +void nonePythonToCppNullPtr(PyObject*, void* cppOut) +{ + assert(cppOut); + *((void**)cppOut) = 0; +} + +void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn) +{ + assert(pyIn); + if (!ObjectType::checkType(desiredType)) + return pyIn; + SbkObjectType *inType = reinterpret_cast(Py_TYPE(pyIn)); + if (ObjectType::hasCast(inType)) + return ObjectType::cast(inType, pyIn, desiredType); + return Object::cppPointer(pyIn, desiredType); +} + +void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut) +{ + assert(type); + assert(pyIn); + assert(cppOut); + *reinterpret_cast(cppOut) = pyIn == Py_None + ? 0 + : cppPointer(reinterpret_cast(type), reinterpret_cast(pyIn)); +} + +void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut) +{ + assert(converter); + assert(pyIn); + assert(cppOut); + *reinterpret_cast(cppOut) = pyIn == Py_None + ? 0 + : cppPointer(reinterpret_cast(converter->pythonType), reinterpret_cast(pyIn)); +} + +static void _pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) +{ + assert(converter); + assert(pyIn); + assert(cppOut); + PythonToCppFunc toCpp = IsPythonToCppConvertible(converter, pyIn); + if (toCpp) + toCpp(pyIn, cppOut); +} + +void pythonToCppCopy(const SbkObjectType *type, PyObject *pyIn, void *cppOut) +{ + assert(type); + _pythonToCppCopy(type->d->converter, pyIn, cppOut); +} + +void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut) +{ + _pythonToCppCopy(converter, pyIn, cppOut); +} + +bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCppFunc) +{ + // This is the Object Type or Value Type conversion that only + // retrieves the C++ pointer held in the Python wrapper. + if (toCppFunc == type->d->converter->toCppPointerConversion.second) + return false; + + // Object Types doesn't have any kind of value conversion, + // only C++ pointer retrieval. + if (type->d->converter->toCppConversions.empty()) + return false; + + // The first conversion of the non-pointer conversion list is + // a Value Type's copy to C++ function, which is not an implicit + // conversion. + // Otherwise it must be one of the implicit conversions. + // Note that we don't check if the Python to C++ conversion is in + // the list of the type's conversions, for it is expected that the + // caller knows what he's doing. + ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); + return toCppFunc != (*conv).second; +} + +void registerConverterName(SbkConverter* converter , const char* typeName) +{ + ConvertersMap::iterator iter = converters.find(typeName); + if (iter == converters.end()) + converters.insert(std::make_pair(typeName, converter)); +} + +SbkConverter* getConverter(const char* typeName) +{ + ConvertersMap::const_iterator it = converters.find(typeName); + if (it != converters.end()) + return it->second; + if (Py_VerboseFlag > 0) + SbkDbg() << "Can't find type resolver for type '" << typeName << "'."; + return 0; +} + +SbkConverter* primitiveTypeConverter(int index) +{ + return PrimitiveTypeConverters[index]; +} + +bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn) +{ + assert(type); + assert(pyIn); + if (!PySequence_Check(pyIn)) + return false; + const Py_ssize_t size = PySequence_Size(pyIn); + for (Py_ssize_t i = 0; i < size; ++i) { + if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, i)), type)) + return false; + } + return true; +} +bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn) +{ + assert(converter); + assert(pyIn); + if (!PySequence_Check(pyIn)) + return false; + const Py_ssize_t size = PySequence_Size(pyIn); + for (Py_ssize_t i = 0; i < size; ++i) { + if (!isPythonToCppConvertible(converter, AutoDecRef(PySequence_GetItem(pyIn, i)))) + return false; + } + return true; +} +bool convertibleSequenceTypes(const SbkObjectType *type, PyObject *pyIn) +{ + assert(type); + return convertibleSequenceTypes(type->d->converter, pyIn); +} + +bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn) +{ + assert(firstType); + assert(secondType); + assert(pyIn); + if (!PySequence_Check(pyIn)) + return false; + if (PySequence_Size(pyIn) != 2) + return false; + if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 0)), firstType)) + return false; + if (!PyObject_TypeCheck(AutoDecRef(PySequence_GetItem(pyIn, 1)), secondType)) + return false; + return true; +} +bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, + const SbkConverter *secondConverter, bool secondCheckExact, + PyObject *pyIn) +{ + assert(firstConverter); + assert(secondConverter); + assert(pyIn); + if (!PySequence_Check(pyIn)) + return false; + if (PySequence_Size(pyIn) != 2) + return false; + AutoDecRef firstItem(PySequence_GetItem(pyIn, 0)); + if (firstCheckExact) { + if (!PyObject_TypeCheck(firstItem, firstConverter->pythonType)) + return false; + } else if (!isPythonToCppConvertible(firstConverter, firstItem)) { + return false; + } + AutoDecRef secondItem(PySequence_GetItem(pyIn, 1)); + if (secondCheckExact) { + if (!PyObject_TypeCheck(secondItem, secondConverter->pythonType)) + return false; + } else if (!isPythonToCppConvertible(secondConverter, secondItem)) { + return false; + } + + return true; +} + +bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn) +{ + assert(keyType); + assert(valueType); + assert(pyIn); + if (!PyDict_Check(pyIn)) + return false; + + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while (PyDict_Next(pyIn, &pos, &key, &value)) { + if (!PyObject_TypeCheck(key, keyType)) + return false; + if (!PyObject_TypeCheck(value, valueType)) + return false; + } + return true; +} + +bool convertibleDictTypes(const SbkConverter * keyConverter, bool keyCheckExact, const SbkConverter *valueConverter, + bool valueCheckExact, PyObject *pyIn) +{ + assert(keyConverter); + assert(valueConverter); + assert(pyIn); + if (!PyDict_Check(pyIn)) + return false; + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while (PyDict_Next(pyIn, &pos, &key, &value)) { + if (keyCheckExact) { + if (!PyObject_TypeCheck(key, keyConverter->pythonType)) + return false; + } else if (!isPythonToCppConvertible(keyConverter, key)) { + return false; + } + if (valueCheckExact) { + if (!PyObject_TypeCheck(value, valueConverter->pythonType)) + return false; + } else if (!isPythonToCppConvertible(valueConverter, value)) { + return false; + } + } + return true; +} + +PyTypeObject* getPythonTypeObject(const SbkConverter *converter) +{ + if (converter) + return converter->pythonType; + return 0; +} + +PyTypeObject* getPythonTypeObject(const char* typeName) +{ + return getPythonTypeObject(getConverter(typeName)); +} + +bool pythonTypeIsValueType(const SbkConverter *converter) +{ + assert(converter); + return converter->pointerToPython && converter->copyToPython; +} + +bool pythonTypeIsObjectType(const SbkConverter *converter) +{ + return converter->pointerToPython && !converter->copyToPython; +} + +bool pythonTypeIsWrapperType(const SbkConverter *converter) +{ + return converter->pointerToPython; +} + +SpecificConverter::SpecificConverter(const char* typeName) + : m_type(InvalidConversion) +{ + m_converter = getConverter(typeName); + if (!m_converter) + return; + const Py_ssize_t len = strlen(typeName); + char lastChar = typeName[len -1]; + if (lastChar == '&') { + m_type = ReferenceConversion; + } else if (lastChar == '*' || pythonTypeIsObjectType(m_converter)) { + m_type = PointerConversion; + } else { + m_type = CopyConversion; + } +} + +PyObject* SpecificConverter::toPython(const void* cppIn) +{ + switch (m_type) { + case CopyConversion: + return copyToPython(m_converter, cppIn); + case PointerConversion: + return pointerToPython(m_converter, *((const void**)cppIn)); + case ReferenceConversion: + return referenceToPython(m_converter, cppIn); + default: + PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'C++ to Python' conversion"); + } + return 0; +} + +void SpecificConverter::toCpp(PyObject* pyIn, void* cppOut) +{ + switch (m_type) { + case CopyConversion: + pythonToCppCopy(m_converter, pyIn, cppOut); + break; + case PointerConversion: + pythonToCppPointer(m_converter, pyIn, cppOut); + break; + case ReferenceConversion: + pythonToCppPointer(m_converter, pyIn, &cppOut); + break; + default: + PyErr_SetString(PyExc_RuntimeError, "tried to use invalid converter in 'Python to C++' conversion"); + } +} + +} } // namespace Shiboken::Conversions diff --git a/sources/shiboken2/libshiboken/sbkconverter.h b/sources/shiboken2/libshiboken/sbkconverter.h new file mode 100644 index 000000000..7489b930d --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkconverter.h @@ -0,0 +1,367 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBK_CONVERTER_H +#define SBK_CONVERTER_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +#include +#include + +struct SbkObject; +struct SbkObjectType; + +/** + * This is a convenience macro identical to Python's PyObject_TypeCheck, + * except that the arguments have swapped places, for the great convenience + * of generator. + */ +#define SbkObject_TypeCheck(tp, ob) \ + (Py_TYPE(ob) == (tp) || PyType_IsSubtype(Py_TYPE(ob), (tp))) + +extern "C" +{ + +/** + * SbkConverter is used to perform type conversions from C++ + * to Python and vice-versa;.and it is also used for type checking. + * SbkConverter is a private structure that must be accessed + * using the functions provided by the converter API. + */ +struct SbkConverter; + +/** + * Given a void pointer to a C++ object, this function must return + * the proper Python object. It may be either an existing wrapper + * for the C++ object, or a newly create one. Or even the Python + * equivalent of the C++ value passed in the argument. + * + * C++ -> Python + */ +typedef PyObject* (*CppToPythonFunc)(const void*); + +/** + * This function converts a Python object to a C++ value, it may be + * a pointer, value, class, container or primitive type, passed via + * a void pointer, that will be cast properly inside the function. + * This function is usually returned by an IsConvertibleToCppFunc + * function, or obtained knowing the type of the Python object input, + * thus it will not check the Python object type, and will expect + * the void pointer to be pointing to a proper variable. + * + * Python -> C++ + */ +typedef void (*PythonToCppFunc)(PyObject*,void*); + +/** + * Checks if the Python object passed in the argument is convertible to a + * C++ type defined inside the function, it returns the converter function + * that will transform a Python argument into a C++ value. + * It returns NULL if the Python object is not convertible to the C++ type + * that the function represents. + * + * Python -> C++ ? + */ +typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*); + +} // extern "C" + +namespace Shiboken { +namespace Conversions { + + +class LIBSHIBOKEN_API SpecificConverter +{ +public: + enum Type + { + InvalidConversion, + CopyConversion, + PointerConversion, + ReferenceConversion + }; + + explicit SpecificConverter(const char* typeName); + + inline SbkConverter* converter() { return m_converter; } + inline operator SbkConverter*() const { return m_converter; } + + inline bool isValid() { return m_type != InvalidConversion; } + inline operator bool() const { return m_type != InvalidConversion; } + + inline Type conversionType() { return m_type; } + + PyObject* toPython(const void* cppIn); + void toCpp(PyObject* pyIn, void* cppOut); +private: + SbkConverter* m_converter; + Type m_type; +}; + + +/** + * Creates a converter for a wrapper type. + * \param type A Shiboken.ObjectType that will receive the new converter. + * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. + * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. + * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. + * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. + * \returns The new converter referred by the wrapper \p type. + */ +LIBSHIBOKEN_API SbkConverter* createConverter(SbkObjectType* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc = 0); + +/** + * Creates a converter for a non wrapper type (primitive or container type). + * \param type Python type representing to the new converter. + * \param toPythonFunc Function to convert a C++ object to a Python \p type. + * \returns A new type converter. + */ +LIBSHIBOKEN_API SbkConverter* createConverter(PyTypeObject* type, CppToPythonFunc toPythonFunc); + +LIBSHIBOKEN_API void deleteConverter(SbkConverter* converter); + +/// Sets the Python object to C++ pointer conversion function. +LIBSHIBOKEN_API void setCppPointerToPythonFunction(SbkConverter* converter, CppToPythonFunc pointerToPythonFunc); + +/// Sets the C++ pointer to Python object conversion functions. +LIBSHIBOKEN_API void setPythonToCppPointerFunctions(SbkConverter* converter, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc); + +/** + * Adds a new conversion of a Python object to a C++ value. + * This is used in copy and implicit conversions. + */ +LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter* converter, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc); +LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc); + +// C++ -> Python --------------------------------------------------------------------------- + +/** + * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. + * This function is used only for Value and Object Types. + * Example usage: + * TYPE* var; + * PyObject* pyVar = pointerToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* pointerToPython(const SbkObjectType *type, const void *cppIn); +LIBSHIBOKEN_API PyObject* pointerToPython(const SbkConverter *converter, const void *cppIn); + +/** + * For the given \p cppIn C++ reference it returns the Python wrapper object, + * always for Object Types, and when they already exist for reference types; + * for when the latter doesn't have an existing wrapper type, the C++ object + * is copied to Python. + * Example usage: + * TYPE& var = SOMETHING; + * PyObject* pyVar = referenceToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* referenceToPython(const SbkObjectType *type, const void *cppIn); +LIBSHIBOKEN_API PyObject* referenceToPython(const SbkConverter *converter, const void *cppIn); + +/** + * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. + * This function is used only for Value Types. + * Example usage: + * TYPE var; + * PyObject* pyVar = copyToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* copyToPython(const SbkObjectType *type, const void *cppIn); +LIBSHIBOKEN_API PyObject* copyToPython(const SbkConverter *converter, const void *cppIn); + +// Python -> C++ --------------------------------------------------------------------------- + +/** + * Returns a Python to C++ conversion function if the Python object is convertible to a C++ pointer. + * It returns NULL if the Python object is not convertible to \p type. + */ +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(const SbkObjectType *type, PyObject *pyIn); + +/** + * Returns a Python to C++ conversion function if the Python object is convertible to a C++ value. + * The resulting converter function will create a copy of the Python object in C++, or implicitly + * convert the object to the expected \p type. + * It returns NULL if the Python object is not convertible to \p type. + */ +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(const SbkObjectType *type, PyObject *pyIn); + +/** + * Returns a Python to C++ conversion function if the Python object is convertible to a C++ reference. + * The resulting converter function will return the underlying C++ object held by the Python wrapper, + * or a new C++ value if it must be a implicit conversion. + * It returns NULL if the Python object is not convertible to \p type. + */ +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(const SbkObjectType *type, PyObject *pyIn); + +/// This is the same as isPythonToCppValueConvertible function. +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(const SbkConverter *converter, PyObject *pyIn); + +/** + * Returns the C++ pointer for the \p pyIn object cast to the type passed via \p desiredType. + * It differs from Shiboken::Object::cppPointer because it casts the pointer to a proper + * memory offset depending on the desired type. + */ +LIBSHIBOKEN_API void* cppPointer(PyTypeObject* desiredType, SbkObject* pyIn); + +/// Converts a Python object \p pyIn to C++ and stores the result in the C++ pointer passed in \p cppOut. +LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut); +LIBSHIBOKEN_API void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut); + +/// Converts a Python object \p pyIn to C++, and copies the result in the C++ variable passed in \p cppOut. +LIBSHIBOKEN_API void pythonToCppCopy(const SbkObjectType *type, PyObject *pyIn, void *cppOut); +LIBSHIBOKEN_API void pythonToCppCopy(const SbkConverter *converter, PyObject *pyIn, void *cppOut); + +/** + * Helper function returned by generated convertible checking functions + * that returns a C++ NULL when the input Python object is None. + */ +LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut); + +/** + * Returns true if the \p toCpp function passed is an implicit conversion of Python \p type. + * It is used when C++ expects a reference argument, so it may be the same object received + * from Python, or another created through implicit conversion. + */ +LIBSHIBOKEN_API bool isImplicitConversion(const SbkObjectType *type, PythonToCppFunc toCpp); + +/// Registers a converter with a type name that may be used to retrieve the converter. +LIBSHIBOKEN_API void registerConverterName(SbkConverter* converter, const char* typeName); + +/// Returns the converter for a given type name, or NULL if it wasn't registered before. +LIBSHIBOKEN_API SbkConverter* getConverter(const char* typeName); + +/// Returns the converter for a primitive type. +LIBSHIBOKEN_API SbkConverter* primitiveTypeConverter(int index); + +/// Returns true if a Python sequence is comprised of objects of the given \p type. +LIBSHIBOKEN_API bool checkSequenceTypes(PyTypeObject* type, PyObject* pyIn); + +/// Returns true if a Python sequence is comprised of objects of a type convertible to the one represented by the given \p converter. +LIBSHIBOKEN_API bool convertibleSequenceTypes(const SbkConverter *converter, PyObject *pyIn); + +/// Returns true if a Python sequence is comprised of objects of a type convertible to \p type. +LIBSHIBOKEN_API bool convertibleSequenceTypes(const SbkObjectType *type, PyObject *pyIn); + +/// Returns true if a Python sequence can be converted to a C++ pair. +LIBSHIBOKEN_API bool checkPairTypes(PyTypeObject* firstType, PyTypeObject* secondType, PyObject* pyIn); + +/// Returns true if a Python sequence can be converted to a C++ pair. +LIBSHIBOKEN_API bool convertiblePairTypes(const SbkConverter *firstConverter, bool firstCheckExact, + const SbkConverter *secondConverter, bool secondCheckExact, + PyObject *pyIn); + +/// Returns true if a Python dictionary can be converted to a C++ hash or map. +LIBSHIBOKEN_API bool checkDictTypes(PyTypeObject* keyType, PyTypeObject* valueType, PyObject* pyIn); + +/// Returns true if a Python dictionary can be converted to a C++ hash or map. +LIBSHIBOKEN_API bool convertibleDictTypes(const SbkConverter *keyConverter, bool keyCheckExact, + const SbkConverter *valueConverter, bool valueCheckExact, + PyObject *pyIn); + +/// Returns the Python type object associated with the given \p converter. +LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(const SbkConverter *converter); + +/// Returns the Python type object for the given \p typeName. +LIBSHIBOKEN_API PyTypeObject* getPythonTypeObject(const char* typeName); + +/// Returns true if the Python type associated with the converter is a value type. +LIBSHIBOKEN_API bool pythonTypeIsValueType(const SbkConverter *converter); + +/// Returns true if the Python type associated with the converter is an object type. +LIBSHIBOKEN_API bool pythonTypeIsObjectType(const SbkConverter *converter); + +/// Returns true if the Python type associated with the converter is a wrapper type. +LIBSHIBOKEN_API bool pythonTypeIsWrapperType(const SbkConverter *converter); + +#define SBK_PY_LONG_LONG_IDX 0 +// Qt5: name collision in QtCore after QBool is replaced by bool +#define SBK_BOOL_IDX_1 1 +#define SBK_CHAR_IDX 2 +#define SBK_CONSTCHARPTR_IDX 3 +#define SBK_DOUBLE_IDX 4 +#define SBK_FLOAT_IDX 5 +#define SBK_INT_IDX 6 +#define SBK_SIGNEDINT_IDX 6 +#define SBK_LONG_IDX 7 +#define SBK_SHORT_IDX 8 +#define SBK_SIGNEDCHAR_IDX 9 +#define SBK_STD_STRING_IDX 10 +#define SBK_UNSIGNEDPY_LONG_LONG_IDX 11 +#define SBK_UNSIGNEDCHAR_IDX 12 +#define SBK_UNSIGNEDINT_IDX 13 +#define SBK_UNSIGNEDLONG_IDX 14 +#define SBK_UNSIGNEDSHORT_IDX 15 +#define SBK_VOIDPTR_IDX 16 + +template SbkConverter* PrimitiveTypeConverter() { return 0; } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_BOOL_IDX_1); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_CHAR_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_DOUBLE_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_FLOAT_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_INT_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_LONG_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_SHORT_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_STD_STRING_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); } +template<> inline SbkConverter* PrimitiveTypeConverter() { return primitiveTypeConverter(SBK_VOIDPTR_IDX); } + +} } // namespace Shiboken::Conversions + +struct _SbkGenericType { PyHeapTypeObject super; SbkConverter** converter; }; +#define SBK_CONVERTER(pyType) (*reinterpret_cast<_SbkGenericType*>(pyType)->converter) + + +#endif // SBK_CONVERTER_H diff --git a/sources/shiboken2/libshiboken/sbkconverter_p.h b/sources/shiboken2/libshiboken/sbkconverter_p.h new file mode 100644 index 000000000..b38561780 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkconverter_p.h @@ -0,0 +1,574 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBK_CONVERTER_P_H +#define SBK_CONVERTER_P_H + +#include "sbkpython.h" +#include "sbkconverter.h" +#include "sbkstring.h" +#include +#include +#include +#include +#include + +#include "sbkdbg.h" + +extern "C" +{ + +typedef std::pair ToCppConversion; +typedef std::list ToCppConversionList; + +/** + * \internal + * Private structure of SbkConverter. + */ +struct SbkConverter +{ + /** + * Python type associated with this converter. If the type is a Shiboken + * wrapper, then it must be a SbkObjectType; otherwise it will be the + * Python type to which the C++ value will be converted (note that the + * C++ type could be produced from various Python types). + */ + PyTypeObject* pythonType; + /** + * This function converts a C++ object to a Python object of the type + * indicated in pythonType. The identity of the C++ object is kept, + * because it looks for an already existing Python wrapper associated + * with the C++ instance. + * It is used to convert C++ pointers and references to Python objects. + */ + CppToPythonFunc pointerToPython; + /** + * This function converts a C++ object to a Python object of the type + * indicated in pythonType. The identity of the object is not kept, + * because a new instance of the C++ object is created. + * It is used to convert objects passed by value, or reference, if said + * reference can't be traced to an object that already has a Python + * wrapper assigned for it. + */ + CppToPythonFunc copyToPython; + /** + * This is a special case of a Python to C++ conversion. It returns + * the underlying C++ pointer of a Python wrapper passed as parameter + * or NULL if the Python object is a None value. + * It comes separated from the other toCppConversions because if you + * have a Python object representing a Value Type the type checking + * for both ValueType and ValueType* would be the same, thus the first + * check would be true and the second would never be reached. + */ + ToCppConversion toCppPointerConversion; + /** + * This is a list of type checking functions that return the + * proper Python to C++ conversion function, for the given Python + * object. + * For Object Types, that never have implicit conversions, this + * list is always empty. + */ + ToCppConversionList toCppConversions; +}; + +} // extern "C" + +template +struct OverFlowCheckerBase { + static void formatOverFlowMessage(const MaxLimitType& value, + const std::string *valueAsString = 0) + { + std::ostringstream str; + str << "libshiboken: Overflow: Value "; + if (valueAsString != 0 && !valueAsString->empty()) + str << *valueAsString; + else + str << value; + str << " exceeds limits of type " + << " [" << (isSigned ? "signed" : "unsigned") + << "] \"" << typeid(T).name() + << "\" (" << sizeof(T) << "bytes)."; + const std::string message = str.str(); + PyErr_WarnEx(PyExc_RuntimeWarning, message.c_str(), 0); + } + + // Checks if an overflow occurred inside Python code. + // Precondition: use after calls like PyLong_AsLongLong or PyLong_AsUnsignedLongLong. + // Postcondition: if error ocurred, sets the string reference to the string representation of + // the passed value. + static bool checkForInternalPyOverflow(PyObject *pyIn, std::string &valueAsString) + { + if (PyErr_Occurred()) { + PyErr_Print(); + PyObject *stringRepresentation = PyObject_Str(pyIn); + const char *cString = Shiboken::String::toCString(stringRepresentation); + valueAsString.assign(cString); + Py_DECREF(stringRepresentation); + return true; + } + return false; + } +}; + +// Helper template for checking if a value overflows when cast to type T. +// The MaxLimitType size is usually >= than type T size, so that it can still represent values that +// can't be stored in T (unless the types are of course the same). +// TLDR: MaxLimitType is either long long or unsigned long long. +template::is_signed > +struct OverFlowChecker; + +template +struct OverFlowChecker : + public OverFlowCheckerBase { + static bool check(const MaxLimitType& value, PyObject *pyIn) + { + std::string valueAsString; + const bool isOverflow = + OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) + || value < std::numeric_limits::min() + || value > std::numeric_limits::max(); + if (isOverflow) + OverFlowChecker::formatOverFlowMessage(value, &valueAsString); + return isOverflow; + } +}; + +template +struct OverFlowChecker + : public OverFlowCheckerBase { + static bool check(const MaxLimitType& value, PyObject *pyIn) + { + std::string valueAsString; + const bool isOverflow = + OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString) + || value < 0 + || static_cast(value) > std::numeric_limits::max(); + if (isOverflow) + OverFlowChecker::formatOverFlowMessage(value, &valueAsString); + return isOverflow; + } +}; +template<> +struct OverFlowChecker : + public OverFlowCheckerBase { + static bool check(const PY_LONG_LONG &value, PyObject *pyIn) { + std::string valueAsString; + const bool isOverflow = checkForInternalPyOverflow(pyIn, valueAsString); + if (isOverflow) + OverFlowChecker::formatOverFlowMessage(value, &valueAsString); + return isOverflow; + + } +}; +template<> +struct OverFlowChecker { + static bool check(const double &, PyObject *) { return false; } +}; +template<> +struct OverFlowChecker : + public OverFlowCheckerBase { + static bool check(const double& value, PyObject *) + { + const bool result = value < std::numeric_limits::min() + || value > std::numeric_limits::max(); + if (result) + formatOverFlowMessage(value); + return result; + } +}; + +// Basic primitive type converters --------------------------------------------------------- +template PyTypeObject* SbkType() { return 0; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyBool_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyString_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyFloat_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyLong_Type; } +template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } + +template struct Primitive {}; + +template +struct OnePrimitive +{ + static PyObject* toPython(const void*) { return 0; } + static PythonToCppFunc isConvertible(PyObject*) { return 0; } + static void toCpp(PyObject*, void*) {} + static SbkConverter* createConverter() + { + SbkConverter* converter = Shiboken::Conversions::createConverter(SbkType(), Primitive::toPython); + Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::toCpp, Primitive::isConvertible); + return converter; + } +}; +template +struct TwoPrimitive : OnePrimitive +{ + static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; } + static void otherToCpp(PyObject*, void*) {} + static SbkConverter* createConverter() + { + SbkConverter* converter = OnePrimitive::createConverter(); + Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive::otherToCpp, Primitive::isOtherConvertible); + return converter; + } +}; + +// Integers -------------------------------------------------------------------------------- + +template +struct IntPrimitive : TwoPrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyInt_FromLong(*reinterpret_cast(cppIn)); + } + static void toCpp(PyObject* pyIn, void* cppOut) + { + double result = PyFloat_AS_DOUBLE(pyIn); + // If cast to long directly it could overflow silently. + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = static_cast(result); + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (PyFloat_Check(pyIn)) + return toCpp; + return 0; + } + static void otherToCpp(PyObject* pyIn, void* cppOut) + { + PY_LONG_LONG result = PyLong_AsLongLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = static_cast(result); + } + static PythonToCppFunc isOtherConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return otherToCpp; + return 0; + } +}; +template <> struct Primitive : IntPrimitive {}; +template <> struct Primitive : IntPrimitive {}; +template <> struct Primitive : IntPrimitive {}; +template <> struct Primitive : IntPrimitive {}; + +// Unsigned Long Integers ------------------------------------------------------------------ + +template +struct UnsignedLongPrimitive : IntPrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyLong_FromUnsignedLong(*reinterpret_cast(cppIn)); + } +}; +template <> struct Primitive : UnsignedLongPrimitive {}; +template <> struct Primitive : UnsignedLongPrimitive {}; + +// Big integers ---------------------------------------------------------------------------- + +template <> +struct Primitive : OnePrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyLong_FromLongLong(*((PY_LONG_LONG*)cppIn)); + } + static void toCpp(PyObject* pyIn, void* cppOut) + { + PY_LONG_LONG result = PyLong_AsLongLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = result; + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return toCpp; + return 0; + } +}; + +template <> +struct Primitive : OnePrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyLong_FromUnsignedLongLong(*((unsigned PY_LONG_LONG*)cppIn)); + } + static void toCpp(PyObject* pyIn, void* cppOut) + { +#if PY_MAJOR_VERSION >= 3 + if (PyLong_Check(pyIn)) { + unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = result; + } + else { + PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); + } +#else + if (PyInt_Check(pyIn)) { + long result = PyInt_AsLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = + static_cast(result); + } else if (PyLong_Check(pyIn)) { + unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = result; + } else { + PyErr_SetString(PyExc_TypeError, "Invalid type for unsigned long long conversion"); + } +#endif // Python 2 + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return toCpp; + return 0; + } +}; + +// Floating point -------------------------------------------------------------------------- + +template +struct FloatPrimitive : TwoPrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyFloat_FromDouble(*reinterpret_cast(cppIn)); + } + static void toCpp(PyObject* pyIn, void* cppOut) + { + *reinterpret_cast(cppOut) = FLOAT(PyLong_AsLong(pyIn)); + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (PyInt_Check(pyIn) || PyLong_Check(pyIn)) + return toCpp; + return 0; + } + static void otherToCpp(PyObject* pyIn, void* cppOut) + { + *reinterpret_cast(cppOut) = FLOAT(PyFloat_AsDouble(pyIn)); + } + static PythonToCppFunc isOtherConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return otherToCpp; + return 0; + } +}; +template <> struct Primitive : FloatPrimitive {}; +template <> struct Primitive : FloatPrimitive {}; + +// Boolean --------------------------------------------------------------------------------- + +template <> +struct Primitive : OnePrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return PyBool_FromLong(*reinterpret_cast(cppIn)); + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return toCpp; + return 0; + } + static void toCpp(PyObject* pyIn, void* cppOut) + { + *reinterpret_cast(cppOut) = PyInt_AS_LONG(pyIn) != 0; + } +}; + +// Characters ------------------------------------------------------------------------------ + +template +struct CharPrimitive : IntPrimitive +{ + static void toCpp(PyObject* pyIn, void* cppOut) + { + *reinterpret_cast(cppOut) = CHAR(Shiboken::String::toCString(pyIn)[0]); + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (Shiboken::String::checkChar(pyIn)) + return toCpp; + return 0; + } + static void otherToCpp(PyObject* pyIn, void* cppOut) + { + PY_LONG_LONG result = PyLong_AsLongLong(pyIn); + if (OverFlowChecker::check(result, pyIn)) + PyErr_SetObject(PyExc_OverflowError, 0); + *reinterpret_cast(cppOut) = CHAR(result); + } + static PythonToCppFunc isOtherConvertible(PyObject* pyIn) + { + if (SbkNumber_Check(pyIn)) + return otherToCpp; + return 0; + } + static SbkConverter* createConverter() + { + SbkConverter* converter = IntPrimitive::createConverter(); + Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive::otherToCpp, CharPrimitive::isOtherConvertible); + return converter; + } + +}; +template <> struct Primitive : CharPrimitive {}; +template <> struct Primitive : CharPrimitive {}; +template <> struct Primitive : CharPrimitive { + using CharPrimitive::toPython; + static PyObject* toPython(const void* cppIn) { + return Shiboken::String::fromCString((const char*)cppIn, 1); + } +}; + + + +// Strings --------------------------------------------------------------------------------- + +template <> +struct Primitive : TwoPrimitive +{ + static PyObject* toPython(const void* cppIn) + { + if (!cppIn) + Py_RETURN_NONE; + return Shiboken::String::fromCString((const char*)cppIn); + } + static void toCpp(PyObject *, void *cppOut) + { + *((const char**)cppOut) = 0; + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (pyIn == Py_None) + return toCpp; + return 0; + } + static void otherToCpp(PyObject* pyIn, void* cppOut) + { + *((const char**)cppOut) = (const char*) Shiboken::String::toCString(pyIn); + } + static PythonToCppFunc isOtherConvertible(PyObject* pyIn) + { + if (Shiboken::String::check(pyIn)) + return otherToCpp; + return 0; + } +}; + +template <> +struct Primitive : TwoPrimitive +{ + static PyObject* toPython(const void* cppIn) + { + return Shiboken::String::fromCString(((std::string*)cppIn)->c_str()); + } + static void toCpp(PyObject *, void *cppOut) + { + *((std::string*)cppOut) = std::string(); + } + static PythonToCppFunc isConvertible(PyObject* pyIn) + { + if (pyIn == Py_None) + return toCpp; + return 0; + } + static void otherToCpp(PyObject* pyIn, void* cppOut) + { + *((std::string*)cppOut) = Shiboken::String::toCString(pyIn); + } + static PythonToCppFunc isOtherConvertible(PyObject* pyIn) + { + if (Shiboken::String::check(pyIn)) + return otherToCpp; + return 0; + } +}; + +// Void pointer ---------------------------------------------------------------------------- + +template <> +struct Primitive : OnePrimitive +{ + static PyObject* toPython(const void* cppIn) + { + SbkDbg() << cppIn; + if (!cppIn) + Py_RETURN_NONE; + PyObject *result = reinterpret_cast(const_cast(cppIn)); + Py_INCREF(result); + return result; + } + static void toCpp(PyObject* pyIn, void* cppOut) + { + SbkDbg() << pyIn; + *reinterpret_cast(cppOut) = pyIn; + } + static PythonToCppFunc isConvertible(PyObject *) + { + return toCpp; + } +}; + +#endif // SBK_CONVERTER_P_H diff --git a/sources/shiboken2/libshiboken/sbkdbg.h b/sources/shiboken2/libshiboken/sbkdbg.h new file mode 100644 index 000000000..937153adf --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkdbg.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKDBG_H +#define SBKDBG_H + +#include "sbkpython.h" +#include "basewrapper.h" +#include + +#ifndef NOCOLOR + #define COLOR_END "\033[0m" + #define COLOR_WHITE "\033[1;37m" + #define COLOR_YELLOW "\033[1;33m" + #define COLOR_GREEN "\033[0;32m" + #define COLOR_RED "\033[0;31m" +#else + #define COLOR_END "" + #define COLOR_WHITE "" + #define COLOR_YELLOW "" + #define COLOR_GREEN "" + #define COLOR_RED "" +#endif + +#ifndef NDEBUG + +class BaseLogger +{ +public: + BaseLogger(std::ostream& output, const char* function, const char* context) + : m_stream(output), m_function(function), m_context(context) {} + ~BaseLogger() + { + m_stream << std::endl; + } + std::ostream& operator()() { return m_stream; }; + template + std::ostream& operator<<(const T& t) + { + m_stream << '['; + if (m_context[0]) + m_stream << COLOR_GREEN << m_context << COLOR_END << "|"; + return m_stream << COLOR_WHITE << m_function << COLOR_END << "] " << t; + } +private: + std::ostream& m_stream; + const char* m_function; + const char* m_context; +}; + +inline std::ostream& operator<<(std::ostream& out, PyObject* obj) +{ + PyObject* repr = Shiboken::Object::isValid(obj, false) ? PyObject_Repr(obj) : 0; + if (repr) { +#ifdef IS_PY3K + PyObject* str = PyUnicode_AsUTF8String(repr); + Py_DECREF(repr); + repr = str; +#endif + out << PyBytes_AS_STRING(repr); + Py_DECREF(repr); + } else { + out << reinterpret_cast(obj); + } + return out; +} + +class _SbkDbg : public BaseLogger +{ +public: + _SbkDbg(const char* function, const char* context = "") : BaseLogger(std::cout, function, context) {} +}; + +#ifdef __GNUG__ +#define SbkDbg(X) _SbkDbg(__PRETTY_FUNCTION__, X"") +#else +#define SbkDbg(X) _SbkDbg(__FUNCTION__, X"") +#endif + +#else + +struct SbkDbg { + template + SbkDbg& operator<<(const T&) { return *this; } +}; + +#endif +#endif // LOGGER_H diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp new file mode 100644 index 000000000..0902077ed --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkenum.cpp @@ -0,0 +1,618 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkenum.h" +#include "sbkstring.h" +#include "sbkconverter.h" +#include "basewrapper.h" +#include "sbkdbg.h" +#include "autodecref.h" +#include "typeresolver.h" +#include "sbkpython.h" + +#include +#include +#include + +#define SBK_ENUM(ENUM) reinterpret_cast(ENUM) + +extern "C" +{ + +struct SbkEnumType +{ + PyHeapTypeObject super; + SbkConverter** converterPtr; + SbkConverter* converter; + const char* cppName; +}; + +struct SbkEnumObject +{ + PyObject_HEAD + long ob_value; + PyObject* ob_name; +}; + +static PyObject* SbkEnumObject_repr(PyObject* self) +{ + const SbkEnumObject *enumObj = reinterpret_cast(self); + if (enumObj->ob_name) + return Shiboken::String::fromFormat("%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name)); + else + return Shiboken::String::fromFormat("%s(%ld)", self->ob_type->tp_name, enumObj->ob_value); +} + +static int SbkEnumObject_print(PyObject* self, FILE* fp, int) +{ + Py_BEGIN_ALLOW_THREADS + const SbkEnumObject *enumObj = reinterpret_cast(self); + if (enumObj->ob_name) + fprintf(fp, "%s.%s", self->ob_type->tp_name, PyBytes_AS_STRING(enumObj->ob_name)); + else + fprintf(fp, "%s(%ld)", self->ob_type->tp_name, enumObj->ob_value); + Py_END_ALLOW_THREADS + return 0; +} + +static PyObject* SbkEnumObject_name(PyObject* self, void*) +{ + SbkEnumObject *enum_self = reinterpret_cast(self); + + if (enum_self->ob_name == NULL) + 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 0; + + SbkEnumObject* self = PyObject_New(SbkEnumObject, type); + if (!self) + return 0; + self->ob_value = itemValue; + PyObject* item = Shiboken::Enum::getEnumItemFromValue(type, itemValue); + if (item) { + self->ob_name = SbkEnumObject_name(item, 0); + Py_XDECREF(item); + } else { + self->ob_name = 0; + } + return reinterpret_cast(self); +} + +/* 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 PyInt_FromLong() will result in calling PyLong_FromLong in + * Py3k. + */ +static PyObject* enum_int(PyObject* v) +{ + return PyInt_FromLong(SBK_ENUM(v)->ob_value); +} + +static long getNumberValue(PyObject* v) +{ + PyObject* number = PyNumber_Long(v); + long result = PyLong_AsLong(number); + Py_XDECREF(number); + return result; +} + +static PyObject* enum_and(PyObject* self, PyObject* b) +{ + if (!PyNumber_Check(b)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(b); + return PyInt_FromLong(valA & valB); +} + +static PyObject* enum_or(PyObject* self, PyObject* b) +{ + if (!PyNumber_Check(b)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(b); + return PyInt_FromLong(valA | valB); +} + +static PyObject* enum_xor(PyObject* self, PyObject* b) +{ + if (!PyNumber_Check(b)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(b); + return PyInt_FromLong(valA ^ valB); +} + +static int enum_bool(PyObject* v) +{ + return (SBK_ENUM(v)->ob_value > 0); +} + +static PyObject* enum_add(PyObject* self, PyObject* v) +{ + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(v); + return PyInt_FromLong(valA + valB); +} + +static PyObject* enum_subtract(PyObject* self, PyObject* v) +{ + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(v); + return PyInt_FromLong(valA - valB); +} + +static PyObject* enum_multiply(PyObject* self, PyObject* v) +{ + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(v); + return PyInt_FromLong(valA * valB); +} + +#ifndef IS_PY3K +static PyObject* enum_divide(PyObject* self, PyObject* v) +{ + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(v); + return PyLong_FromLong(valA / valB); +} +#endif + +static PyObject* enum_richcompare(PyObject* self, PyObject* other, int op) +{ + int result = 0; + if (!PyNumber_Check(other)) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + long valA = SBK_ENUM(self)->ob_value; + long valB = getNumberValue(other); + + switch (op) { + case Py_EQ: + result = (valA == valB); + break; + case Py_NE: + result = (valA != valB); + break; + case Py_LE: + result = (valA <= valB); + break; + case Py_GE: + result = (valA >= valB); + break; + case Py_LT: + result = (valA < valB); + break; + case Py_GT: + result = (valA > valB); + break; + default: + PyErr_BadArgument(); + return NULL; + } + if (result) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} + +static Py_hash_t enum_hash(PyObject* pyObj) +{ + Py_hash_t val = reinterpret_cast(pyObj)->ob_value; + if (val == -1) + val = -2; + return val; +} + +static PyGetSetDef SbkEnumGetSetList[] = { + {const_cast("name"), &SbkEnumObject_name, 0, 0, 0}, + {0, 0, 0, 0, 0} // Sentinel +}; + +static PyNumberMethods enum_as_number = { + /* nb_add */ enum_add, + /* nb_subtract */ enum_subtract, + /* nb_multiply */ enum_multiply, +#ifndef IS_PY3K + /* nb_divide */ enum_divide, +#endif + /* nb_remainder */ 0, + /* nb_divmod */ 0, + /* nb_power */ 0, + /* nb_negative */ 0, + /* nb_positive */ enum_int, + /* nb_absolute */ 0, + /* nb_bool/nb_nonzero */ enum_bool, + /* nb_invert */ 0, + /* nb_lshift */ 0, + /* nb_rshift */ 0, + /* nb_and */ enum_and, + /* nb_xor */ enum_xor, + /* nb_or */ enum_or, +#ifndef IS_PY3K + /* nb_coerce */ 0, +#endif + /* nb_int */ enum_int, +#ifdef IS_PY3K + /* nb_reserved */ 0, + /* nb_float */ 0, +#else + /* nb_long */ enum_int, + /* nb_float */ 0, + /* nb_oct */ 0, + /* nb_hex */ 0, +#endif + + /* nb_inplace_add */ 0, + /* nb_inplace_subtract */ 0, + /* nb_inplace_multiply */ 0, +#ifndef IS_PY3K + /* nb_inplace_div */ 0, +#endif + /* nb_inplace_remainder */ 0, + /* nb_inplace_power */ 0, + /* nb_inplace_lshift */ 0, + /* nb_inplace_rshift */ 0, + /* nb_inplace_and */ 0, + /* nb_inplace_xor */ 0, + /* nb_inplace_or */ 0, + + /* nb_floor_divide */ 0, + /* nb_true_divide */ 0, + /* nb_inplace_floor_divide */ 0, + /* nb_inplace_true_divide */ 0, + + /* nb_index */ enum_int +}; + +static void SbkEnumTypeDealloc(PyObject* pyObj); +static PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); + +PyTypeObject SbkEnumType_Type = { + PyVarObject_HEAD_INIT(0, 0) + /*tp_name*/ "Shiboken.EnumType", + /*tp_basicsize*/ sizeof(SbkEnumType), + /*tp_itemsize*/ 0, + /*tp_dealloc*/ SbkEnumTypeDealloc, + /*tp_print*/ 0, + /*tp_getattr*/ 0, + /*tp_setattr*/ 0, + /*tp_compare*/ 0, + /*tp_repr*/ 0, + /*tp_as_number*/ &enum_as_number, + /*tp_as_sequence*/ 0, + /*tp_as_mapping*/ 0, + /*tp_hash*/ 0, + /*tp_call*/ 0, + /*tp_str*/ 0, + /*tp_getattro*/ 0, + /*tp_setattro*/ 0, + /*tp_as_buffer*/ 0, + /*tp_flags*/ Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_CHECKTYPES, + /*tp_doc*/ 0, + /*tp_traverse*/ 0, + /*tp_clear*/ 0, + /*tp_richcompare*/ 0, + /*tp_weaklistoffset*/ 0, + /*tp_iter*/ 0, + /*tp_iternext*/ 0, + /*tp_methods*/ 0, + /*tp_members*/ 0, + /*tp_getset*/ 0, + /*tp_base*/ &PyType_Type, + /*tp_dict*/ 0, + /*tp_descr_get*/ 0, + /*tp_descr_set*/ 0, + /*tp_dictoffset*/ 0, + /*tp_init*/ 0, + /*tp_alloc*/ PyType_GenericAlloc, + /*tp_new*/ SbkEnumTypeTpNew, + /*tp_free*/ PyObject_GC_Del, + /*tp_is_gc*/ 0, + /*tp_bases*/ 0, + /*tp_mro*/ 0, + /*tp_cache*/ 0, + /*tp_subclasses*/ 0, + /*tp_weaklist*/ 0, + /*tp_del*/ 0, + /*tp_version_tag*/ 0 +}; + +void SbkEnumTypeDealloc(PyObject* pyObj) +{ + SbkEnumType* sbkType = reinterpret_cast(pyObj); + + PyObject_GC_UnTrack(pyObj); + Py_TRASHCAN_SAFE_BEGIN(pyObj); + if (sbkType->converter) { + Shiboken::Conversions::deleteConverter(sbkType->converter); + } + Py_TRASHCAN_SAFE_END(pyObj); +} + +PyObject* SbkEnumTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +{ + SbkEnumType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + if (!newType) + return 0; + return reinterpret_cast(newType); +} + +} // extern "C" + +namespace Shiboken { + +class DeclaredEnumTypes +{ +public: + DeclaredEnumTypes(); + ~DeclaredEnumTypes(); + static DeclaredEnumTypes& instance(); + void addEnumType(PyTypeObject* type); + +private: + DeclaredEnumTypes(const DeclaredEnumTypes&); + DeclaredEnumTypes& operator=(const DeclaredEnumTypes&); + std::list m_enumTypes; +}; + +namespace Enum { + +bool check(PyObject* pyObj) +{ + return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type; +} + +PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue) +{ + PyObject *key, *value; + Py_ssize_t pos = 0; + PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast("values")); + + while (PyDict_Next(values, &pos, &key, &value)) { + SbkEnumObject *obj = reinterpret_cast(value); + if (obj->ob_value == itemValue) { + Py_INCREF(obj); + return value; + } + } + return 0; +} + +static PyTypeObject* createEnum(const char* fullName, const char* cppName, const char* shortName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = newTypeWithName(fullName, cppName); + if (flagsType) + enumType->tp_as_number = flagsType->tp_as_number; + if (PyType_Ready(enumType) < 0) + return 0; + Shiboken::TypeResolver::createValueTypeResolver(cppName); + if (shortName) + Shiboken::TypeResolver::createValueTypeResolver(shortName); + return enumType; +} + +PyTypeObject* createGlobalEnum(PyObject* module, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType); + Shiboken::TypeResolver::createValueTypeResolver("Qt::WindowType"); + Shiboken::TypeResolver::createValueTypeResolver("WindowType"); + if (enumType && PyModule_AddObject(module, name, reinterpret_cast(enumType)) < 0) + return 0; + if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast(flagsType)) < 0) + return 0; + return enumType; +} + +PyTypeObject* createScopedEnum(SbkObjectType* scope, const char* name, const char* fullName, const char* cppName, PyTypeObject* flagsType) +{ + PyTypeObject* enumType = createEnum(fullName, cppName, name, flagsType); + if (enumType && PyDict_SetItemString(scope->super.ht_type.tp_dict, name, reinterpret_cast(enumType)) < 0) + return 0; + if (flagsType && PyDict_SetItemString(scope->super.ht_type.tp_dict, flagsType->tp_name, reinterpret_cast(flagsType)) < 0) + return 0; + return enumType; +} + +static PyObject* createEnumItem(PyTypeObject* enumType, const char* itemName, long itemValue) +{ + PyObject* enumItem = newItem(enumType, itemValue, itemName); + if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0) + return 0; + Py_DECREF(enumItem); + return enumItem; +} + +bool createGlobalEnumItem(PyTypeObject* enumType, PyObject* module, const char* itemName, long itemValue) +{ + PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); + if (enumItem) { + if (PyModule_AddObject(module, itemName, enumItem) < 0) + return false; + Py_DECREF(enumItem); + return true; + } + return false; +} + +bool createScopedEnumItem(PyTypeObject* enumType, SbkObjectType* scope, const char* itemName, long itemValue) +{ + PyObject* enumItem = createEnumItem(enumType, itemName, itemValue); + if (enumItem) { + if (PyDict_SetItemString(scope->super.ht_type.tp_dict, itemName, enumItem) < 0) + return false; + Py_DECREF(enumItem); + return true; + } + return false; +} + +PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) +{ + bool newValue = true; + SbkEnumObject* enumObj; + if (!itemName) { + enumObj = reinterpret_cast(getEnumItemFromValue(enumType, itemValue)); + if (enumObj) + return reinterpret_cast(enumObj); + + newValue = false; + } + + enumObj = PyObject_New(SbkEnumObject, enumType); + if (!enumObj) + return 0; + + enumObj->ob_name = itemName ? PyBytes_FromString(itemName) : 0; + enumObj->ob_value = itemValue; + + if (newValue) { + PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast("values")); + if (!values) { + values = PyDict_New(); + PyDict_SetItemString(enumType->tp_dict, const_cast("values"), values); + Py_DECREF(values); // ^ values still alive, because setitemstring incref it + } + PyDict_SetItemString(values, itemName, reinterpret_cast(enumObj)); + } + + return reinterpret_cast(enumObj); +} + +PyTypeObject* newType(const char* name) +{ + return newTypeWithName(name, ""); +} + +PyTypeObject* newTypeWithName(const char* name, const char* cppName) +{ + PyTypeObject* type = reinterpret_cast(new SbkEnumType); + ::memset(type, 0, sizeof(SbkEnumType)); + Py_TYPE(type) = &SbkEnumType_Type; + type->tp_basicsize = sizeof(SbkEnumObject); + type->tp_print = &SbkEnumObject_print; + type->tp_repr = &SbkEnumObject_repr; + type->tp_str = &SbkEnumObject_repr; + type->tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES; + type->tp_name = name; + type->tp_getset = SbkEnumGetSetList; + type->tp_new = SbkEnum_tp_new; + type->tp_as_number = &enum_as_number; + type->tp_richcompare = &enum_richcompare; + type->tp_hash = &enum_hash; + + SbkEnumType* enumType = reinterpret_cast(type); + enumType->cppName = cppName; + enumType->converterPtr = &enumType->converter; + DeclaredEnumTypes::instance().addEnumType(type); + return type; +} + +const char* getCppName(PyTypeObject* enumType) +{ + assert(Py_TYPE(enumType) == &SbkEnumType_Type); + return reinterpret_cast(enumType)->cppName;; +} + +long int getValue(PyObject* enumItem) +{ + assert(Shiboken::Enum::check(enumItem)); + return reinterpret_cast(enumItem)->ob_value; +} + +void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter) +{ + //reinterpret_cast(enumType)->converter = converter; + SBK_CONVERTER(enumType) = converter; +} + +SbkConverter* getTypeConverter(PyTypeObject* enumType) +{ + //return reinterpret_cast(enumType)->converter; + return SBK_CONVERTER(enumType); +} + +} // namespace Enum + +DeclaredEnumTypes& DeclaredEnumTypes::instance() +{ + static DeclaredEnumTypes me; + return me; +} + +DeclaredEnumTypes::DeclaredEnumTypes() +{ +} + +DeclaredEnumTypes::~DeclaredEnumTypes() +{ + std::list::const_iterator it = m_enumTypes.begin(); + for (; it != m_enumTypes.end(); ++it) + delete *it; + m_enumTypes.clear(); +} + +void DeclaredEnumTypes::addEnumType(PyTypeObject* type) +{ + m_enumTypes.push_back(type); +} + +} diff --git a/sources/shiboken2/libshiboken/sbkenum.h b/sources/shiboken2/libshiboken/sbkenum.h new file mode 100644 index 000000000..4b572dbcc --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkenum.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKENUM_H +#define SBKENUM_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +extern "C" +{ + +extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type; +struct SbkObjectType; +struct SbkConverter; + +} // extern "C" + +namespace Shiboken +{ + +inline bool isShibokenEnum(PyObject* pyObj) +{ + return Py_TYPE(pyObj->ob_type) == &SbkEnumType_Type; +} + +namespace Enum +{ + 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 = 0); + /// This function does the same as createGlobalEnum, but adds the enum to a Shiboken type or namespace. + LIBSHIBOKEN_API PyTypeObject* createScopedEnum(SbkObjectType* scope, + const char* name, + const char* fullName, + const char* cppName, + PyTypeObject* flagsType = 0); + + /** + * 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, SbkObjectType* scope, const char* itemName, long itemValue); + + LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); + + /// \deprecated Use 'newTypeWithName' + SBK_DEPRECATED(LIBSHIBOKEN_API PyTypeObject* newType(const char* name)); + LIBSHIBOKEN_API PyTypeObject* newTypeWithName(const char* name, const char* cppName); + LIBSHIBOKEN_API const char* getCppName(PyTypeObject* type); + + LIBSHIBOKEN_API long getValue(PyObject* enumItem); + LIBSHIBOKEN_API PyObject* getEnumItemFromValue(PyTypeObject* enumType, long itemValue); + + /// Sets the enum's type converter. + LIBSHIBOKEN_API void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter); + /// Returns the converter assigned to the enum \p type. + LIBSHIBOKEN_API SbkConverter* getTypeConverter(PyTypeObject* enumType); +} + +} // namespace Shiboken + +#endif // SKB_PYENUM_H diff --git a/sources/shiboken2/libshiboken/sbkmodule.cpp b/sources/shiboken2/libshiboken/sbkmodule.cpp new file mode 100644 index 000000000..2ea9d56ac --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkmodule.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkmodule.h" +#include "basewrapper.h" +#include "bindingmanager.h" +#include + +/// This hash maps module objects to arrays of Python types. +typedef std::unordered_map ModuleTypesMap; + +/// This hash maps module objects to arrays of converters. +typedef std::unordered_map ModuleConvertersMap; + +/// All types produced in imported modules are mapped here. +static ModuleTypesMap moduleTypes; +static ModuleConvertersMap moduleConverters; + +namespace Shiboken +{ +namespace Module +{ + +PyObject* import(const char* moduleName) +{ + PyObject* sysModules = PyImport_GetModuleDict(); + PyObject* module = PyDict_GetItemString(sysModules, moduleName); + if (module) + Py_INCREF(module); + else + module = PyImport_ImportModule(moduleName); + + if (!module) + PyErr_Format(PyExc_ImportError,"could not import module '%s'", moduleName); + + return module; +} + +PyObject* create(const char* moduleName, void* moduleData) +{ + Shiboken::init(); +#ifndef IS_PY3K + return Py_InitModule(moduleName, reinterpret_cast(moduleData)); +#else + return PyModule_Create(reinterpret_cast(moduleData)); +#endif +} + +void registerTypes(PyObject* module, PyTypeObject** types) +{ + ModuleTypesMap::iterator iter = moduleTypes.find(module); + if (iter == moduleTypes.end()) + moduleTypes.insert(std::make_pair(module, types)); +} + +PyTypeObject** getTypes(PyObject* module) +{ + ModuleTypesMap::iterator iter = moduleTypes.find(module); + return (iter == moduleTypes.end()) ? 0 : iter->second; +} + +void registerTypeConverters(PyObject* module, SbkConverter** converters) +{ + ModuleConvertersMap::iterator iter = moduleConverters.find(module); + if (iter == moduleConverters.end()) + moduleConverters.insert(std::make_pair(module, converters)); +} + +SbkConverter** getTypeConverters(PyObject* module) +{ + ModuleConvertersMap::iterator iter = moduleConverters.find(module); + return (iter == moduleConverters.end()) ? 0 : iter->second; +} + +} } // namespace Shiboken::Module diff --git a/sources/shiboken2/libshiboken/sbkmodule.h b/sources/shiboken2/libshiboken/sbkmodule.h new file mode 100644 index 000000000..e1ec7a860 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkmodule.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBK_MODULE_H +#define SBK_MODULE_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +#if PY_MAJOR_VERSION >= 3 + #define SBK_MODULE_INIT_ERROR 0 + #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ + extern "C" SBK_EXPORT_MODULE PyObject* PyInit_##ModuleName() { + + #define SBK_MODULE_INIT_FUNCTION_END \ + return module; } +#else + #define SBK_MODULE_INIT_ERROR + #define SBK_MODULE_INIT_FUNCTION_BEGIN(ModuleName) \ + extern "C" SBK_EXPORT_MODULE void init##ModuleName() { + + #define SBK_MODULE_INIT_FUNCTION_END \ + } +#endif + +extern "C" +{ +struct SbkConverter; +} + +namespace Shiboken { +namespace Module { + +/** + * Imports and returns the module named \p moduleName, or a NULL pointer in case of failure. + * If the module is already imported, it increments its reference count before returning it. + * \returns the module specified in \p moduleName or NULL if an error occurs. + */ +LIBSHIBOKEN_API PyObject* import(const char* moduleName); + +/** + * Creates a new Python module named \p moduleName using the information passed in \p moduleData. + * In fact, \p moduleData expects a "PyMethodDef*" object, but that's for Python 2. A void* + * was preferred to make this work with future Python 3 support. + * \returns a newly created module. + */ +LIBSHIBOKEN_API PyObject* create(const char* moduleName, void* moduleData); + +/** + * 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); + +/** + * 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); + +/** + * Registers the list of converters created by \p module for non-wrapper types. + * \param module Module where the converters were created. + * \param converters Array of SbkConverter* objects representing the converters created on \p module. + */ +LIBSHIBOKEN_API void registerTypeConverters(PyObject* module, SbkConverter** converters); + +/** + * Retrieves the array of converters. + * \param module Module where the converters were created. + * \returns A pointer to the SbkConverter* array of converters. + */ +LIBSHIBOKEN_API SbkConverter** getTypeConverters(PyObject* module); + +} } // namespace Shiboken::Module + +#endif // SBK_MODULE_H diff --git a/sources/shiboken2/libshiboken/sbkpython.h b/sources/shiboken2/libshiboken/sbkpython.h new file mode 100644 index 000000000..208618d50 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkpython.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKPYTHON_H +#define SBKPYTHON_H + +#include "Python.h" +#include "python25compat.h" + +#if PY_MAJOR_VERSION >= 3 + #define IS_PY3K + + #define PyInt_Type PyLong_Type + #define PyInt_Check PyLong_Check + #define PyInt_AS_LONG PyLong_AS_LONG + #define PyInt_AsUnsignedLongLongMask PyLong_AsLongLong + #define PyInt_FromLong PyLong_FromLong + #define PyInt_AsLong PyLong_AsLong + #define SbkNumber_Check PyNumber_Check + #define Py_TPFLAGS_CHECKTYPES 0 + + #define SBK_NB_BOOL(x) (x).nb_bool + #define SBK_PyMethod_New PyMethod_New + #define PyInt_AsSsize_t(x) PyLong_AsSsize_t(x) + #define PyString_Type PyUnicode_Type + +#else + // Note: if there wasn't for the old-style classes, only a PyNumber_Check would suffice. + #define SbkNumber_Check(X) \ + (PyNumber_Check(X) && (!PyInstance_Check(X) || PyObject_HasAttrString(X, "__trunc__"))) + #define SBK_NB_BOOL(x) (x).nb_nonzero + #define SBK_STR_NAME "str" + #define SBK_PyMethod_New(X, Y) PyMethod_New(X, Y, reinterpret_cast(Py_TYPE(Y))) + + #define Py_hash_t long +#endif + +#endif diff --git a/sources/shiboken2/libshiboken/sbkstring.cpp b/sources/shiboken2/libshiboken/sbkstring.cpp new file mode 100644 index 000000000..598bccc46 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkstring.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkstring.h" +#include "autodecref.h" + +namespace Shiboken +{ + +namespace String +{ + +bool checkType(PyTypeObject* type) +{ + return type == &PyUnicode_Type +#if PY_MAJOR_VERSION < 3 + || type == &PyString_Type +#endif + ; +} + +bool check(PyObject* obj) +{ + return obj == Py_None || +#if PY_MAJOR_VERSION < 3 + PyString_Check(obj) || +#endif + PyUnicode_Check(obj); +} + +bool checkChar(PyObject* pyobj) +{ + if (check(pyobj) && (len(pyobj) == 1)) + return true; + + return false; +} + +bool isConvertible(PyObject* obj) +{ + return check(obj); +} + +PyObject* fromCString(const char* value) +{ +#ifdef IS_PY3K + return PyUnicode_FromString(value); +#else + return PyBytes_FromString(value); +#endif +} + +PyObject* fromCString(const char* value, int len) +{ +#ifdef IS_PY3K + return PyUnicode_FromStringAndSize(value, len); +#else + return PyBytes_FromStringAndSize(value, len); +#endif +} + +const char* toCString(PyObject* str, Py_ssize_t* len) +{ + if (str == Py_None) + return NULL; +#ifdef IS_PY3K + if (PyUnicode_Check(str)) { + if (len) { + // We need to encode the unicode string into utf8 to know the size of returned char*. + Shiboken::AutoDecRef uniStr(PyUnicode_AsUTF8String(str)); + *len = PyBytes_GET_SIZE(uniStr.object()); + } + // Return unicode from str instead of uniStr, because the lifetime of the returned pointer + // depends on the lifetime of str. + return _PyUnicode_AsString(str); + } +#endif + if (PyBytes_Check(str)) { + if (len) + *len = PyBytes_GET_SIZE(str); + return PyBytes_AS_STRING(str); + } + return 0; +} + +bool concat(PyObject** val1, PyObject* val2) +{ + if (PyUnicode_Check(*val1) && PyUnicode_Check(val2)) { + PyObject* result = PyUnicode_Concat(*val1, val2); + Py_DECREF(*val1); + *val1 = result; + return true; + } + + if (PyBytes_Check(*val1) && PyBytes_Check(val2)) { + PyBytes_Concat(val1, val2); + return true; + } + +#if PY_MAJOR_VERSION < 3 + if (PyString_Check(*val1) && PyString_Check(val2)) { + PyString_Concat(val1, val2); + return true; + } +#endif + return false; +} + +PyObject* fromFormat(const char* format, ...) +{ + va_list argp; + va_start(argp, format); + PyObject* result = 0; +#ifdef IS_PY3K + result = PyUnicode_FromFormatV(format, argp); +#else + result = PyString_FromFormatV(format, argp); +#endif + va_end(argp); + return result; +} + +PyObject* fromStringAndSize(const char* str, Py_ssize_t size) +{ +#ifdef IS_PY3K + return PyUnicode_FromStringAndSize(str, size); +#else + return PyString_FromStringAndSize(str, size); +#endif +} + +int compare(PyObject* val1, const char* val2) +{ + if (PyUnicode_Check(val1)) +#ifdef IS_PY3K + return PyUnicode_CompareWithASCIIString(val1, val2); +#else + { + PyObject* uVal2 = PyUnicode_FromString(val2); + bool result = PyUnicode_Compare(val1, uVal2); + Py_XDECREF(uVal2); + return result; + } + if (PyString_Check(val1)) + return strcmp(PyString_AS_STRING(val1), val2); +#endif + return 0; + +} + +Py_ssize_t len(PyObject* str) +{ + if (str == Py_None) + return 0; + + if (PyUnicode_Check(str)) + return PyUnicode_GET_SIZE(str); + + if (PyBytes_Check(str)) + return PyBytes_GET_SIZE(str); + return 0; +} + +} // namespace String + +} // namespace Shiboken diff --git a/sources/shiboken2/libshiboken/sbkstring.h b/sources/shiboken2/libshiboken/sbkstring.h new file mode 100644 index 000000000..0d498da6d --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkstring.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKSTRING_H +#define SBKSTRING_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +#if PY_MAJOR_VERSION >= 3 + #define SBK_STR_NAME "unicode" +#else + #define SBK_STR_NAME "str" +#endif + +namespace Shiboken +{ +namespace String +{ + LIBSHIBOKEN_API bool check(PyObject* obj); + LIBSHIBOKEN_API bool checkType(PyTypeObject* obj); + LIBSHIBOKEN_API bool checkChar(PyObject* obj); + LIBSHIBOKEN_API bool isConvertible(PyObject* obj); + LIBSHIBOKEN_API PyObject* fromCString(const char* value); + LIBSHIBOKEN_API PyObject* fromCString(const char* value, int len); + LIBSHIBOKEN_API const char* toCString(PyObject* str, Py_ssize_t* len = 0); + LIBSHIBOKEN_API bool concat(PyObject** val1, PyObject* val2); + LIBSHIBOKEN_API PyObject* fromFormat(const char* format, ...); + LIBSHIBOKEN_API PyObject* fromStringAndSize(const char* str, Py_ssize_t size); + LIBSHIBOKEN_API int compare(PyObject* val1, const char* val2); + LIBSHIBOKEN_API Py_ssize_t len(PyObject* str); + +} // namespace String +} // namespace Shiboken + + +#endif + + diff --git a/sources/shiboken2/libshiboken/sbkversion.h.in b/sources/shiboken2/libshiboken/sbkversion.h.in new file mode 100644 index 000000000..589c5ac26 --- /dev/null +++ b/sources/shiboken2/libshiboken/sbkversion.h.in @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKVERSION_H +#define SBKVERSION_H + +#define SHIBOKEN_VERSION "@shiboken_MAJOR_VERSION@.@shiboken_MINOR_VERSION@.@shiboken_MICRO_VERSION@" +#define SHIBOKEN_MAJOR_VERSION @shiboken_MAJOR_VERSION@ +#define SHIBOKEN_MINOR_VERSION @shiboken_MINOR_VERSION@ +#define SHIBOKEN_MICRO_VERSION @shiboken_MICRO_VERSION@ +#define SHIBOKEN_RELEASE_LEVEL "final" +#define SHIBOKEN_SERIAL 0 + +#endif diff --git a/sources/shiboken2/libshiboken/shiboken.h b/sources/shiboken2/libshiboken/shiboken.h new file mode 100644 index 000000000..2738bf51f --- /dev/null +++ b/sources/shiboken2/libshiboken/shiboken.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIBOKEN_H +#define SHIBOKEN_H + +#include "sbkpython.h" +#include "autodecref.h" +#include "basewrapper.h" +#include "bindingmanager.h" +#include "conversions.h" +#include "gilstate.h" +#include "threadstatesaver.h" +#include "helper.h" +#include "sbkconverter.h" +#include "sbkenum.h" +#include "sbkmodule.h" +#include "sbkstring.h" +#include "shibokenmacros.h" +#include "typeresolver.h" +#include "shibokenbuffer.h" + +#endif // SHIBOKEN_H + diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.cpp b/sources/shiboken2/libshiboken/shibokenbuffer.cpp new file mode 100644 index 000000000..6cc617668 --- /dev/null +++ b/sources/shiboken2/libshiboken/shibokenbuffer.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "shibokenbuffer.h" +#include +#include + +bool Shiboken::Buffer::checkType(PyObject* pyObj) +{ + return PyObject_CheckReadBuffer(pyObj); +} + +void* Shiboken::Buffer::getPointer(PyObject* pyObj, Py_ssize_t* size) +{ + +#ifdef IS_PY3K + Py_buffer view; + if (PyObject_GetBuffer(pyObj, &view, PyBUF_ND) == 0) { + if (size) + *size = view.len; + return view.buf; + } else { + return 0; + } +#else + const void* buffer = 0; + Py_ssize_t bufferSize = 0; + + PyObject_AsReadBuffer(pyObj, &buffer, &bufferSize); + + if (size) + *size = bufferSize; + return const_cast(buffer); +#endif +} + +PyObject* Shiboken::Buffer::newObject(void* memory, Py_ssize_t size, Type type) +{ + if (size == 0) + Py_RETURN_NONE; +#ifdef IS_PY3K + Py_buffer view; + memset(&view, 0, sizeof(Py_buffer)); + view.buf = memory; + view.len = size; + view.readonly = type == Shiboken::Buffer::ReadOnly; + view.ndim = 1; + view.itemsize = sizeof(char); + Py_ssize_t shape[] = { size }; + view.shape = shape; + return PyMemoryView_FromBuffer(&view); +#else + return type == ReadOnly ? PyBuffer_FromMemory(memory, size) : PyBuffer_FromReadWriteMemory(memory, size); +#endif +} + +PyObject* Shiboken::Buffer::newObject(const void* memory, Py_ssize_t size) +{ + return newObject(const_cast(memory), size, ReadOnly); +} diff --git a/sources/shiboken2/libshiboken/shibokenbuffer.h b/sources/shiboken2/libshiboken/shibokenbuffer.h new file mode 100644 index 000000000..18d86c6e1 --- /dev/null +++ b/sources/shiboken2/libshiboken/shibokenbuffer.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIBOKEN_BUFFER_H +#define SHIBOKEN_BUFFER_H + +#include "sbkpython.h" +#include "shibokenmacros.h" + +namespace Shiboken +{ + +namespace Buffer +{ + enum Type { + ReadOnly, + WriteOnly, + ReadWrite + }; + + /** + * Creates a new Python buffer pointing to a contiguous memory block at + * \p memory of size \p size. + */ + LIBSHIBOKEN_API PyObject* newObject(void* memory, Py_ssize_t size, Type type); + + /** + * Creates a new read only Python buffer pointing to a contiguous memory block at + * \p memory of size \p size. + */ + LIBSHIBOKEN_API PyObject* newObject(const void* memory, Py_ssize_t size); + + /** + * Check if is ok to use \p pyObj as argument in all function under Shiboken::Buffer namespace. + */ + LIBSHIBOKEN_API bool checkType(PyObject* pyObj); + + /** + * Returns a pointer to the memory pointed by the buffer \p pyObj, \p size is filled with the buffer + * size if not null. + * + * If the \p pyObj is a non-contiguous buffer a Python error is set. + */ + LIBSHIBOKEN_API void* getPointer(PyObject* pyObj, Py_ssize_t* size = 0); + +} // namespace Buffer +} // namespace Shiboken + +#endif diff --git a/sources/shiboken2/libshiboken/shibokenmacros.h b/sources/shiboken2/libshiboken/shibokenmacros.h new file mode 100644 index 000000000..acd8f6ada --- /dev/null +++ b/sources/shiboken2/libshiboken/shibokenmacros.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SHIBOKENMACROS_H +#define SHIBOKENMACROS_H + +// LIBSHIBOKEN_API macro is used for the public API symbols. +#if defined _WIN32 + #if LIBSHIBOKEN_EXPORTS + #define LIBSHIBOKEN_API __declspec(dllexport) + #else + #ifdef _MSC_VER + #define LIBSHIBOKEN_API __declspec(dllimport) + #endif + #endif + #define SBK_DEPRECATED(func) __declspec(deprecated) func +#elif __GNUC__ >= 4 + #define LIBSHIBOKEN_API __attribute__ ((visibility("default"))) + #define SBK_DEPRECATED(func) func __attribute__ ((deprecated)) +#endif + +#ifndef LIBSHIBOKEN_API + #define LIBSHIBOKEN_API + #define SBK_DEPRECATED(func) func +#endif + +#endif diff --git a/sources/shiboken2/libshiboken/threadstatesaver.cpp b/sources/shiboken2/libshiboken/threadstatesaver.cpp new file mode 100644 index 000000000..3d3ba81ab --- /dev/null +++ b/sources/shiboken2/libshiboken/threadstatesaver.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "threadstatesaver.h" + +namespace Shiboken +{ + +ThreadStateSaver::ThreadStateSaver() + : m_threadState(0) + {} + +ThreadStateSaver::~ThreadStateSaver() +{ + restore(); +} + +void ThreadStateSaver::save() +{ + if (PyEval_ThreadsInitialized()) + m_threadState = PyEval_SaveThread(); +} + +void ThreadStateSaver::restore() +{ + if (m_threadState) { + PyEval_RestoreThread(m_threadState); + m_threadState = 0; + } +} + +} // namespace Shiboken + diff --git a/sources/shiboken2/libshiboken/threadstatesaver.h b/sources/shiboken2/libshiboken/threadstatesaver.h new file mode 100644 index 000000000..3fe595d95 --- /dev/null +++ b/sources/shiboken2/libshiboken/threadstatesaver.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef THREADSTATESAVER_H +#define THREADSTATESAVER_H + +#include "sbkpython.h" +#include + +namespace Shiboken +{ + +class LIBSHIBOKEN_API ThreadStateSaver +{ +public: + ThreadStateSaver(); + ~ThreadStateSaver(); + void save(); + void restore(); +private: + PyThreadState* m_threadState; + + ThreadStateSaver(const ThreadStateSaver&); + ThreadStateSaver& operator=(const ThreadStateSaver&); +}; + +} // namespace Shiboken + +#endif // THREADSTATESAVER_H + diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp new file mode 100644 index 000000000..c3e25014e --- /dev/null +++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkconverter.h" +#include "sbkconverter_p.h" +#include "basewrapper_p.h" + +#include "sbkdbg.h" + +namespace Shiboken { +namespace Conversions { + +static SbkConverter* createConverterObject(PyTypeObject* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc) +{ + SbkConverter* converter = new SbkConverter; + converter->pythonType = type; + + converter->pointerToPython = pointerToPythonFunc; + converter->copyToPython = copyToPythonFunc; + + converter->toCppPointerConversion = std::make_pair(toCppPointerCheckFunc, toCppPointerConvFunc); + converter->toCppConversions.clear(); + + return converter; +} + +SbkConverter* createConverter(SbkObjectType* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc) +{ + SbkConverter* converter = createConverterObject((PyTypeObject*)type, + toCppPointerConvFunc, toCppPointerCheckFunc, + pointerToPythonFunc, copyToPythonFunc); + type->d->converter = converter; + return converter; +} + +void deleteConverter(SbkConverter* converter) +{ + if (converter) { + converter->toCppConversions.clear(); + delete converter; + } +} + +void addPythonToCppValueConversion(SbkConverter* converter, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc) +{ + converter->toCppConversions.push_back(std::make_pair(isConvertibleToCppFunc, pythonToCppFunc)); +} +void addPythonToCppValueConversion(SbkObjectType* type, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc) +{ + addPythonToCppValueConversion(type->d->converter, pythonToCppFunc, isConvertibleToCppFunc); +} + +PyObject* pointerToPython(SbkObjectType* type, const void* cppIn) +{ + if (!cppIn) + Py_RETURN_NONE; + return type->d->converter->pointerToPython(cppIn); +} + +static inline PyObject* CopyCppToPython(SbkConverter* converter, const void* cppIn) +{ + assert(cppIn); + return converter->copyToPython(cppIn); +} +PyObject* copyToPython(SbkObjectType* type, const void* cppIn) +{ + return CopyCppToPython(type->d->converter, cppIn); +} +PyObject* toPython(SbkConverter* converter, const void* cppIn) +{ + return CopyCppToPython(converter, cppIn); +} + +PyObject* referenceToPython(SbkObjectType* type, const void* cppIn) +{ + assert(cppIn); + PyObject* pyOut = (PyObject*)BindingManager::instance().retrieveWrapper(cppIn); + if (pyOut) { + Py_INCREF(pyOut); + return pyOut; + } + // If it is Value Type, return a copy of the C++ object. + if (type->d->converter->copyToPython) + return type->d->converter->copyToPython(cppIn); + // If it is an Object Type, return a copy of the C++ object. + return type->d->converter->pointerToPython(cppIn); +} + +PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn) +{ + assert(pyIn); + return type->d->converter->toCppPointerConversion.first(pyIn); +} + +static inline PythonToCppFunc IsPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) +{ + assert(pyIn); + ToCppConversionList& convs = converter->toCppConversions; + for (ToCppConversionList::iterator conv = convs.begin(); conv != convs.end(); ++conv) { + PythonToCppFunc toCppFunc = 0; + if ((toCppFunc = (*conv).first(pyIn))) + return toCppFunc; + } + return 0; +} +PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn) +{ + return IsPythonToCppConvertible(type->d->converter, pyIn); +} +PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn) +{ + return IsPythonToCppConvertible(converter, pyIn); +} + +PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn) +{ + if (pyIn != Py_None) { + PythonToCppFunc toCpp = isPythonToCppPointerConvertible(type, pyIn); + if (toCpp) + return toCpp; + } + return isPythonToCppValueConvertible(type, pyIn); +} + +void nonePythonToCppNullPtr(PyObject*, void* cppOut) +{ + assert(cppOut); + *((void**)cppOut) = 0; +} + +void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut) +{ + assert(pyIn); + assert(cppOut); + SbkObjectType* inType = (SbkObjectType*)pyIn->ob_type; + if (ObjectType::hasCast(inType)) + *((void**)cppOut) = ObjectType::cast(inType, (SbkObject*)pyIn, (PyTypeObject*)type); + else + *((void**)cppOut) = Object::cppPointer((SbkObject*)pyIn, (PyTypeObject*)type); +} + +bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCppFunc) +{ + // This is the Object Type or Value Type conversion that only + // retrieves the C++ pointer held in the Python wrapper. + if (toCppFunc == type->d->converter->toCppPointerConversion.second) + return false; + + // Object Types doesn't have any kind of value conversion, + // only C++ pointer retrieval. + if (type->d->converter->toCppConversions.empty()) + return false; + + // The first conversion of the non-pointer conversion list is + // a Value Type's copy to C++ function, which is not an implicit + // conversion. + // Otherwise it must be one of the implicit conversions. + // Note that we don't check if the Python to C++ conversion is in + // the list of the type's conversions, for it is expected that the + // caller knows what he's doing. + ToCppConversionList::iterator conv = type->d->converter->toCppConversions.begin(); + return toCppFunc != (*conv).second; +} + +} } // namespace Shiboken::Conversions diff --git a/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h new file mode 100644 index 000000000..d4bbbca1d --- /dev/null +++ b/sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBK_CONVERTER_H +#define SBK_CONVERTER_H + +#include +#include +#include "shibokenmacros.h" +#include "basewrapper.h" + +extern "C" +{ + +/** + * SbkConverter is used to perform type conversions from C++ + * to Python and vice-versa;.and it is also used for type checking. + * SbkConverter is a private structure that must be accessed + * using the functions provided by the converter API. + */ +struct SbkConverter; + +/** + * Given a void pointer to a C++ object, this function must return + * the proper Python object. It may be either an existing wrapper + * for the C++ object, or a newly create one. Or even the Python + * equivalent of the C++ value passed in the argument. + * + * C++ -> Python + */ +typedef PyObject* (*CppToPythonFunc)(const void*); + +/** + * This function converts a Python object to a C++ value, it may be + * a pointer, value, class, container or primitive type, passed via + * a void pointer, that will be cast properly inside the function. + * This function is usually returned by an IsConvertibleToCppFunc + * function, or obtained knowing the type of the Python object input, + * thus it will not check the Python object type, and will expect + * the void pointer to be pointing to a proper variable. + * + * Python -> C++ + */ +typedef void (*PythonToCppFunc)(PyObject*,void*); + +/** + * Checks if the Python object passed in the argument is convertible to a + * C++ type defined inside the function, it returns the converter function + * that will transform a Python argument into a C++ value. + * It returns NULL if the Python object is not convertible to the C++ type + * that the function represents. + * + * Python -> C++ ? + */ +typedef PythonToCppFunc (*IsConvertibleToCppFunc)(PyObject*); + +} // extern "C" + + +namespace Shiboken { +namespace Conversions { + +/** + * Creates a converter for a wrapper type. + * \param type A Shiboken.ObjectType that will receive the new converter. + * \param toCppPointerConvFunc Function to retrieve the C++ pointer held by a Python wrapper. + * \param toCppPointerCheckFunc Check and return the retriever function of the C++ pointer held by a Python wrapper. + * \param pointerToPythonFunc Function to convert a C++ object to a Python \p type wrapper, keeping their identity. + * \param copyToPythonFunc Function to convert a C++ object to a Python \p type, copying the object. + * \returns The new converter referred by the wrapper \p type. + */ +LIBSHIBOKEN_API SbkConverter* createConverter(SbkObjectType* type, + PythonToCppFunc toCppPointerConvFunc, + IsConvertibleToCppFunc toCppPointerCheckFunc, + CppToPythonFunc pointerToPythonFunc, + CppToPythonFunc copyToPythonFunc = 0); + +LIBSHIBOKEN_API void deleteConverter(SbkConverter* converter); + +/** + * Adds a new conversion of a Python object to a C++ value. + * This is used in copy and implicit conversions. + */ +LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkConverter* converter, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc); +LIBSHIBOKEN_API void addPythonToCppValueConversion(SbkObjectType* type, + PythonToCppFunc pythonToCppFunc, + IsConvertibleToCppFunc isConvertibleToCppFunc); + +// C++ -> Python --------------------------------------------------------------------------- + +/** + * Retrieves the Python wrapper object for the given \p cppIn C++ pointer object. + * This function is used only for Value and Object Types. + * Example usage: + * TYPE* var; + * PyObject* pyVar = pointerToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* pointerToPython(SbkObjectType* type, const void* cppIn); + +/** + * Retrieves the Python wrapper object for the given C++ value pointed by \p cppIn. + * This function is used only for Value Types. + * Example usage: + * TYPE var; + * PyObject* pyVar = copyToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* copyToPython(SbkObjectType* type, const void* cppIn); + +// TODO:WRITEDOCSTRING - used only for Value Types - cppIn must point to a value +/** + * Retrieves the Python wrapper object for the given C++ reference pointed by \p cppIn. + * This function is used only for Value and Object Types. + * It differs from pointerToPython() for not checking for a NULL pointer. + * Example usage: + * TYPE& var = SOMETHING; + * PyObject* pyVar = copyToPython(SBKTYPE, &var); + */ +LIBSHIBOKEN_API PyObject* referenceToPython(SbkObjectType* type, const void* cppIn); + +// TODO:WRITEDOCSTRING - used only for Primitives and Containers (and Value Types) - cppIn must point to a primitive, container or value type +/// This is the same as copyToPython function. +LIBSHIBOKEN_API PyObject* toPython(SbkConverter* converter, const void* cppIn); + +// Python -> C++ convertibility checks ----------------------------------------------------- + +// TODO:WRITEDOCSTRING +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppPointerConvertible(SbkObjectType* type, PyObject* pyIn); + +// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppValueConvertible(SbkObjectType* type, PyObject* pyIn); + +// TODO:WRITEDOCSTRING- Returns a Python to C++ conversion function if true, or NULL if false. +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppReferenceConvertible(SbkObjectType* type, PyObject* pyIn); + +/// This is the same as isPythonToCppValueConvertible function. +LIBSHIBOKEN_API PythonToCppFunc isPythonToCppConvertible(SbkConverter* converter, PyObject* pyIn); + +// Python -> C++ --------------------------------------------------------------------------- + +// TODO:WRITEDOCSTRING - function used by the generated [TYPE]_PythonToCpp_[TYPE]_PTR +LIBSHIBOKEN_API void pythonToCppPointer(SbkObjectType* type, PyObject* pyIn, void* cppOut); + +// TODO:WRITEDOCSTRING - function used by the generated isConvertible when the PyObject is None, +// making a C++ NULL pointer the result of the toCpp function call. +// DRAFT: When the Python object is a Py_None, it's C++ conversion is always a NULL pointer. +LIBSHIBOKEN_API void nonePythonToCppNullPtr(PyObject*, void* cppOut); + +// TODO:WRITEDOCSTRING - tells if \p toCpp is an implicit conversion. +LIBSHIBOKEN_API bool isImplicitConversion(SbkObjectType* type, PythonToCppFunc toCpp); + +} } // namespace Shiboken::Conversions + +#endif // SBK_CONVERTER_H diff --git a/sources/shiboken2/libshiboken/typeresolver.cpp b/sources/shiboken2/libshiboken/typeresolver.cpp new file mode 100644 index 000000000..b23eb6371 --- /dev/null +++ b/sources/shiboken2/libshiboken/typeresolver.cpp @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "typeresolver.h" +#include "sbkdbg.h" +#include +#include +#include +#include "basewrapper_p.h" + +using namespace Shiboken; + +typedef std::unordered_map TypeResolverMap; +static TypeResolverMap typeResolverMap; + +struct TypeResolver::TypeResolverPrivate +{ + CppToPythonFunc cppToPython; + PythonToCppFunc pythonToCpp; + PyTypeObject* pyType; +}; + +static void deinitTypeResolver() +{ + for (TypeResolverMap::const_iterator it = typeResolverMap.begin(); it != typeResolverMap.end(); ++it) + delete it->second; + typeResolverMap.clear(); +} + +void Shiboken::initTypeResolver() +{ + assert(typeResolverMap.empty()); + std::atexit(deinitTypeResolver); +} + +TypeResolver::TypeResolver() : m_d(new TypeResolverPrivate) +{ +} + +TypeResolver* TypeResolver::createTypeResolver(const char* typeName, + CppToPythonFunc cppToPy, + PythonToCppFunc pyToCpp, + PyTypeObject* pyType) +{ + TypeResolver*& tr = typeResolverMap[typeName]; + if (!tr) { + tr = new TypeResolver; + tr->m_d->cppToPython = cppToPy; + tr->m_d->pythonToCpp = pyToCpp; + tr->m_d->pyType = pyType; + + /* + * Note: + * + * Value types are also registered as object types, but the generator *always* first register the value + * type version in the TypeResolver and it *must* always do it! otherwise this code wont work. + */ + if (pyType && PyType_IsSubtype(pyType, reinterpret_cast(&SbkObject_Type))) { + SbkObjectType* sbkType = reinterpret_cast(pyType); + // TODO-CONVERTERS: to be deprecated + if (!sbkType->d->type_behaviour) { + const size_t len = strlen(typeName); + sbkType->d->type_behaviour = typeName[len -1] == '*' ? BEHAVIOUR_OBJECTTYPE : BEHAVIOUR_VALUETYPE; + } + } + } + return tr; +} + +TypeResolver::~TypeResolver() +{ + delete m_d; +} + +TypeResolver* TypeResolver::get(const char* typeName) +{ + TypeResolverMap::const_iterator it = typeResolverMap.find(typeName); + if (it != typeResolverMap.end()) { + return it->second; + } else { + if (Py_VerboseFlag > 0) + SbkDbg() << "Can't find type resolver for " << typeName; + return 0; + } +} + +void TypeResolver::toCpp(PyObject* pyObj, void** place) +{ + m_d->pythonToCpp(pyObj, place); +} + +PyObject* TypeResolver::toPython(void* cppObj) +{ + return m_d->cppToPython(cppObj); +} + +PyTypeObject* TypeResolver::pythonType() +{ + return m_d->pyType; +} + +TypeResolver::Type TypeResolver::getType(const char* name) +{ + const size_t len = strlen(name); + bool isObjTypeName = name[len - 1] == '*'; + if (TypeResolver::get(name)) { + // great, we found the type in our first attempt! + return isObjTypeName ? ObjectType : ValueType; + } else { + // Type not found... let's copy the string. + std::string typeName(name); + if (isObjTypeName) + typeName.erase(len - 1, 1); + else + typeName += '*'; + isObjTypeName = !isObjTypeName; + + if (TypeResolver::get(typeName.c_str())) + return isObjTypeName ? ObjectType : ValueType; + else + return UnknownType; + } +} + diff --git a/sources/shiboken2/libshiboken/typeresolver.h b/sources/shiboken2/libshiboken/typeresolver.h new file mode 100644 index 000000000..bc56522fe --- /dev/null +++ b/sources/shiboken2/libshiboken/typeresolver.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPERESOLVER_H +#define TYPERESOLVER_H + +#include "shibokenmacros.h" +#include "conversions.h" + +namespace Shiboken +{ + +/* To C++ convertion functions. */ +template +inline void pythonToValueType(PyObject* pyobj, void** data) +{ + *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); +} + +template +inline void pythonToObjectType(PyObject* pyobj, void** data) +{ + *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); +} + +template +inline PyObject* objectTypeToPython(void* cptr) +{ + return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); +} + +template +inline PyObject* referenceTypeToPython(void* cptr) +{ + // cptr comes the same way it come when we have a value type, but + // we deliver a Python object of a reference + return Shiboken::Converter::toPython(*reinterpret_cast(cptr)); +} + +/** +* \internal This function is not part of the public API. +* Initialize the TypeResource internal cache. +*/ +void initTypeResolver(); + +class LIBSHIBOKEN_API TypeResolver +{ +public: + enum Type + { + ObjectType, + ValueType, + UnknownType + }; + + typedef PyObject* (*CppToPythonFunc)(void*); + typedef void (*PythonToCppFunc)(PyObject*, void**); + + ~TypeResolver(); + + template + static TypeResolver* createValueTypeResolver(const char* typeName) + { + return createTypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType()); + } + + template + static TypeResolver* createObjectTypeResolver(const char* typeName) + { + return createTypeResolver(typeName, &objectTypeToPython, &pythonToObjectType, SbkType()); + } + + /** + * This kind of type resolver is used only when we have a signal with a reference in their arguments + * like on QSqlTableModel::primeInsert. + */ + template + static TypeResolver* createReferenceTypeResolver(const char* typeName) + { + return createTypeResolver(typeName, &referenceTypeToPython, &pythonToValueType, SbkType()); + } + + static Type getType(const char* name); + static TypeResolver* get(const char* typeName); + + PyObject* toPython(void* cppObj); + void toCpp(PyObject* pyObj, void** place); + PyTypeObject* pythonType(); + +private: + struct TypeResolverPrivate; + TypeResolverPrivate* m_d; + + TypeResolver(); + // disable object copy + TypeResolver(const TypeResolver&); + TypeResolver& operator=(const TypeResolver&); + + static TypeResolver* createTypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType); +}; +} + +#endif diff --git a/sources/shiboken2/shibokenmodule/CMakeLists.txt b/sources/shiboken2/shibokenmodule/CMakeLists.txt new file mode 100644 index 000000000..7e90b51ab --- /dev/null +++ b/sources/shiboken2/shibokenmodule/CMakeLists.txt @@ -0,0 +1,40 @@ +project(shibokenmodule) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shibokenmodule.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt" @ONLY) + + +set(sample_SRC +${CMAKE_CURRENT_BINARY_DIR}/shiboken2/shiboken2_module_wrapper.cpp +) + +add_custom_command(OUTPUT ${sample_SRC} +# Note: shiboken2 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/shiboken2/pull/11 +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/shibokenmodule.txt ${GENERATOR_EXTRA_FLAGS} +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'shiboken2'..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libshiboken_SOURCE_DIR} + ${libshiboken_BINARY_DIR}) +add_library(shibokenmodule MODULE ${sample_SRC}) +set_property(TARGET shibokenmodule PROPERTY PREFIX "") +set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "shiboken2") +if(WIN32) + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set_property(TARGET shibokenmodule PROPERTY OUTPUT_NAME "shiboken2_d") + endif() + set_property(TARGET shibokenmodule PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(shibokenmodule + ${SBK_PYTHON_LIBRARIES} + libshiboken) + +add_dependencies(shibokenmodule shiboken2) + +install(TARGETS shibokenmodule DESTINATION ${PYTHON_SITE_PACKAGES}) \ No newline at end of file diff --git a/sources/shiboken2/shibokenmodule/nothing.h b/sources/shiboken2/shibokenmodule/nothing.h new file mode 100644 index 000000000..e69de29bb diff --git a/sources/shiboken2/shibokenmodule/shibokenmodule.txt.in b/sources/shiboken2/shibokenmodule/shibokenmodule.txt.in new file mode 100644 index 000000000..c5adc6091 --- /dev/null +++ b/sources/shiboken2/shibokenmodule/shibokenmodule.txt.in @@ -0,0 +1,16 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/nothing.h +typesystem-file = @CMAKE_CURRENT_SOURCE_DIR@/typesystem_shiboken.xml + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +# include-path = @libsample_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +avoid-protected-hack +#enable-parent-ctor-heuristic +#use-isnull-as-nb_nonzero diff --git a/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml new file mode 100644 index 000000000..18ab52e80 --- /dev/null +++ b/sources/shiboken2/shibokenmodule/typesystem_shiboken.xml @@ -0,0 +1,120 @@ + + + + + + + + + + bool isValid = Shiboken::Object::isValid(%1, false); + %PYARG_0 = %CONVERTTOPYTHON[bool](isValid); + + + + + + Shiboken::Object::invalidate(%1); + + + + + + if (Shiboken::ObjectType::checkType((PyTypeObject*)%2)) + %PYARG_0 = Shiboken::Object::newObject((SbkObjectType*)%2, (void*)%1, false, true); + else + PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); + + + + + + if (Shiboken::Object::checkType(%1)) { + std::vector<void*> ptrs = Shiboken::Object::cppPointers((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."); + } + + + + + + if (Shiboken::Object::checkType(%1)) { + Shiboken::Object::callCppDestructors((SbkObject*)%1); + } else { + PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); + } + + + + + + if (Shiboken::Object::checkType(%1)) { + bool hasOwnership = Shiboken::Object::hasOwnership((SbkObject*)%1); + %PYARG_0 = %CONVERTTOPYTHON[bool](hasOwnership); + } else { + PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); + } + + + + + + if (Shiboken::Object::checkType(%1)) { + bool wasCreatedByPython = Shiboken::Object::wasCreatedByPython((SbkObject*)%1); + %PYARG_0 = %CONVERTTOPYTHON[bool](wasCreatedByPython); + } else { + PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type."); + } + + + + + + if (!Shiboken::Object::checkType(%1)) { + %PYARG_0 = Shiboken::String::fromCString("Ordinary Python type."); + } else { + std::string str = Shiboken::Object::info((SbkObject*)%1); + %PYARG_0 = Shiboken::String::fromCString(str.c_str()); + } + + + + + + std::set<PyObject*> setAll = Shiboken::BindingManager::instance().getAllPyObjects(); + PyObject* listAll = PyList_New(0); + if (listAll == NULL) + return NULL; + + const std::set<PyObject*>::iterator end = setAll.end(); + for (std::set<PyObject*>::iterator iter = setAll.begin(); iter != end; ++iter) { + if (*iter != NULL) { + if (PyList_Append(listAll, *iter) != 0) { + Py_DECREF(listAll); + return NULL; + } + } + } + return listAll; + + + + + + + + // Add __version__ and __version_info__ attributes to the module + PyObject* version = PyTuple_New(5); + PyTuple_SET_ITEM(version, 0, PyInt_FromLong(SHIBOKEN_MAJOR_VERSION)); + PyTuple_SET_ITEM(version, 1, PyInt_FromLong(SHIBOKEN_MINOR_VERSION)); + PyTuple_SET_ITEM(version, 2, PyInt_FromLong(SHIBOKEN_MICRO_VERSION)); + PyTuple_SET_ITEM(version, 3, Shiboken::String::fromCString(SHIBOKEN_RELEASE_LEVEL)); + PyTuple_SET_ITEM(version, 4, PyInt_FromLong(SHIBOKEN_SERIAL)); + PyModule_AddObject(module, "__version_info__", version); + PyModule_AddStringConstant(module, "__version__", SHIBOKEN_VERSION); + + diff --git a/sources/shiboken2/tests/CMakeLists.txt b/sources/shiboken2/tests/CMakeLists.txt new file mode 100644 index 000000000..c06c56f6d --- /dev/null +++ b/sources/shiboken2/tests/CMakeLists.txt @@ -0,0 +1,102 @@ +find_package(Qt5 REQUIRED COMPONENTS Core) +include_directories(${Qt5Core_INCLUDE_DIRS}) + +add_subdirectory(libminimal) +if(NOT DEFINED MINIMAL_TESTS) + add_subdirectory(libsample) + add_subdirectory(libsmart) + add_subdirectory(libother) +endif() + +if(WIN32 OR DEFINED AVOID_PROTECTED_HACK) + message(STATUS "Tests will be generated avoiding the protected hack!") + set(GENERATOR_EXTRA_FLAGS --avoid-protected-hack) +else() + message(STATUS "Tests will be generated using the protected hack!") + set(GENERATOR_EXTRA_FLAGS ) +endif() + +add_subdirectory(minimalbinding) +if(NOT DEFINED MINIMAL_TESTS) + add_subdirectory(samplebinding) + add_subdirectory(smartbinding) + add_subdirectory(otherbinding) +endif() + +if(DEFINED MINIMAL_TESTS) + file(GLOB TEST_FILES minimalbinding/*_test.py) +else() + file(GLOB TEST_FILES minimalbinding/*_test.py + samplebinding/*_test.py + otherbinding/*_test.py + smartbinding/*_test.py + shibokenmodule/*_test.py) +endif() +list(SORT TEST_FILES) + +set(test_blacklist "") + +find_package(PythonInterp REQUIRED) +if(NOT CTEST_TESTING_TIMEOUT) + set(CTEST_TESTING_TIMEOUT 60) +endif() + +if(CMAKE_VERSION VERSION_LESS 2.8) + message("CMake version greater than 2.8 necessary to run tests") +else() + if(WIN32) + set(TEST_PYTHONPATH "${smart_BINARY_DIR};${minimal_BINARY_DIR};${sample_BINARY_DIR};${other_BINARY_DIR};${shibokenmodule_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}") + set(TEST_LIBRARY_PATH "$ENV{PATH};${libminimal_BINARY_DIR};${libsample_BINARY_DIR};${libother_BINARY_DIR};${libsmart_BINARY_DIR};${libshiboken_BINARY_DIR}") + set(LIBRARY_PATH_VAR "PATH") + string(REPLACE "\\" "/" TEST_PYTHONPATH "${TEST_PYTHONPATH}") + string(REPLACE "\\" "/" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") + string(REPLACE ";" "\\;" TEST_PYTHONPATH "${TEST_PYTHONPATH}") + string(REPLACE ";" "\\;" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") + else() + set(TEST_PYTHONPATH "${smart_BINARY_DIR}:${minimal_BINARY_DIR}:${sample_BINARY_DIR}:${other_BINARY_DIR}:${shibokenmodule_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}") + set(TEST_LIBRARY_PATH "$ENV{LD_LIBRARY_PATH}:${libminimal_BINARY_DIR}:${libsample_BINARY_DIR}:${libother_BINARY_DIR}:${libsmart_BINARY_DIR}:${libshiboken_BINARY_DIR}") + set(LIBRARY_PATH_VAR "LD_LIBRARY_PATH") + endif() + 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}) + set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH}") + set_tests_properties(${test_name} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT}) + if (${expect_fail} GREATER -1) + set_tests_properties(${test_name} PROPERTIES WILL_FAIL TRUE) + endif() + endforeach() +endif() + +add_subdirectory(dumpcodemodel) + +# FIXME Skipped until add an option to choose the generator +# add_subdirectory(test_generator) + +if (NOT APIEXTRACTOR_DOCSTRINGS_DISABLED) +# project(sphinxtabletest) +# +# # TODO +# set(sphinxtabletest_SRC sphinxtabletest.cpp) +# qt4_automoc(${sphinxtabletest_SRC}) +# +# include_directories(${QT_INCLUDE_DIR} +# ${QT_QTCORE_INCLUDE_DIR} +# ${CMAKE_CURRENT_BINARY_DIR} +# ${qtdoc_generator_SOURCE_DIR}) +# +# add_executable(sphinxtabletest ${sphinxtabletest_SRC}) +# +# target_link_libraries(sphinxtabletest +# ${QT_QTTEST_LIBRARY} +# ${APIEXTRACTOR_LIBRARY} +# qtdoc_generator +# genrunner) +# +# add_test("sphinxtable" sphinxtabletest) +# if (INSTALL_TESTS) +# install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/sphinxtabletest DESTINATION ${TEST_INSTALL_DIR}) +# endif() +endif() diff --git a/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt new file mode 100644 index 000000000..af18cb3c8 --- /dev/null +++ b/sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt @@ -0,0 +1,5 @@ +add_executable(dumpcodemodel main.cpp) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${apiextractor_SOURCE_DIR} ${Qt5Core_INCLUDE_DIRS}) + +target_link_libraries(dumpcodemodel apiextractor ${Qt5Core_LIBRARIES}) diff --git a/sources/shiboken2/tests/dumpcodemodel/main.cpp b/sources/shiboken2/tests/dumpcodemodel/main.cpp new file mode 100644 index 000000000..13dab6e8a --- /dev/null +++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + + QCommandLineParser parser; + parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); + parser.setApplicationDescription(QStringLiteral("Code model tester")); + parser.addHelpOption(); + parser.addVersionOption(); + QCommandLineOption verboseOption(QStringLiteral("d"), + QStringLiteral("Display verbose output about types")); + parser.addOption(verboseOption); + parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("C++ source file")); + + parser.process(app); + const QStringList &positionalArguments = parser.positionalArguments(); + if (positionalArguments.isEmpty()) + parser.showHelp(1); + + QByteArrayList arguments; + std::transform(positionalArguments.cbegin(), positionalArguments.cend(), + std::back_inserter(arguments), QFile::encodeName); + const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, 0); + if (dom.isNull()) { + QString message = QLatin1String("Unable to parse ") + positionalArguments.join(QLatin1Char(' ')); + std::cerr << qPrintable(message) << '\n'; + return -2; + } + + QString output; + { + QDebug debug(&output); + if (parser.isSet(verboseOption)) + debug.setVerbosity(3); + debug << dom.data(); + } + std::cout << qPrintable(output) << '\n'; + + return 0; +} diff --git a/sources/shiboken2/tests/libminimal/CMakeLists.txt b/sources/shiboken2/tests/libminimal/CMakeLists.txt new file mode 100644 index 000000000..a25892571 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/CMakeLists.txt @@ -0,0 +1,13 @@ +project(libminimal) + +set(libminimal_SRC +obj.cpp +listuser.cpp +typedef.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_definitions("-DLIBMINIMAL_BUILD") +add_library(libminimal SHARED ${libminimal_SRC}) +set_property(TARGET libminimal PROPERTY PREFIX "") + diff --git a/sources/shiboken2/tests/libminimal/libminimalmacros.h b/sources/shiboken2/tests/libminimal/libminimalmacros.h new file mode 100644 index 000000000..5c9e62e8a --- /dev/null +++ b/sources/shiboken2/tests/libminimal/libminimalmacros.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIBMINIMALMACROS_H +#define LIBMINIMALMACROS_H + +#if defined _WIN32 || defined __CYGWIN__ + #if LIBMINIMAL_BUILD + #define LIBMINIMAL_API __declspec(dllexport) + #else + #define LIBMINIMAL_API __declspec(dllimport) + #endif +#else +#if __GNUC__ >= 4 + #define LIBMINIMAL_API __attribute__ ((visibility("default"))) +#else + #define LIBMINIMAL_API +#endif +#endif + +#endif diff --git a/sources/shiboken2/tests/libminimal/listuser.cpp b/sources/shiboken2/tests/libminimal/listuser.cpp new file mode 100644 index 000000000..ec2eb3923 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/listuser.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "listuser.h" + +std::list +ListUser::createIntList(int num) +{ + std::list retval; + for (int i = 0; i < num; ++i) + retval.push_back(i); + return retval; +} + +int +ListUser::sumIntList(std::list intList) +{ + int total = 0; + for (std::list::iterator iter = intList.begin(); iter != intList.end(); iter++) + total += *iter; + return total; +} + +std::list +ListUser::createMinBoolList(MinBool mb1, MinBool mb2) +{ + std::list retval; + retval.push_back(mb1); + retval.push_back(mb2); + return retval; +} + +MinBool +ListUser::oredMinBoolList(std::list minBoolList) +{ + MinBool result(false); + for (std::list::iterator iter = minBoolList.begin(); iter != minBoolList.end(); iter++) + result |= *iter; + return result; +} + +std::list +ListUser::createValList(int num) +{ + std::list retval; + for (int i = 0; i < num; ++i) + retval.push_back(Val(i)); + return retval; +} + +int +ListUser::sumValList(std::list valList) +{ + int total = 0; + for (std::list::iterator iter = valList.begin(); iter != valList.end(); iter++) + total += iter->valId(); + return total; +} + +std::list +ListUser::createObjList(Obj* o1, Obj* o2) +{ + std::list retval; + retval.push_back(o1); + retval.push_back(o2); + return retval; +} + +int +ListUser::sumObjList(std::list objList) +{ + int total = 0; + for (std::list::iterator iter = objList.begin(); iter != objList.end(); iter++) + total += (*iter)->objId(); + return total; +} + +std::list > +ListUser::createListOfIntLists(int num) +{ + std::list > retval; + for (int i = 0; i < num; ++i) + retval.push_back(createIntList(num)); + return retval; +} + +int +ListUser::sumListOfIntLists(std::list > intListList) +{ + int total = 0; + for (std::list >::iterator it0 = intListList.begin(); it0 != intListList.end(); it0++) { + for (std::list::iterator it1 = (*it0).begin(); it1 != (*it0).end(); it1++) + total += *it1; + } + return total; +} + diff --git a/sources/shiboken2/tests/libminimal/listuser.h b/sources/shiboken2/tests/libminimal/listuser.h new file mode 100644 index 000000000..4138b9f3c --- /dev/null +++ b/sources/shiboken2/tests/libminimal/listuser.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LISTUSER_H +#define LISTUSER_H + +#include +#include "obj.h" +#include "val.h" +#include "minbool.h" + +#include "libminimalmacros.h" + +struct LIBMINIMAL_API ListUser +{ + virtual ~ListUser() {} + + // List of C++ primitive type items + virtual std::list createIntList(int num); + std::list callCreateIntList(int num) { return createIntList(num); } + virtual int sumIntList(std::list intList); + int callSumIntList(std::list intList) { return sumIntList(intList); } + + // List of C++ MinBool objects used as primitives in Python + virtual std::list createMinBoolList(MinBool mb1, MinBool mb2); + std::list callCreateMinBoolList(MinBool mb1, MinBool mb2) { return createMinBoolList(mb1, mb2); } + virtual MinBool oredMinBoolList(std::list minBoolList); + MinBool callOredMinBoolList(std::list minBoolList) { return oredMinBoolList(minBoolList); } + + // List of C++ value types + virtual std::list createValList(int num); + std::list callCreateValList(int num) { return createValList(num); } + virtual int sumValList(std::list valList); + int callSumValList(std::list valList) { return sumValList(valList); } + + // List of C++ object types + virtual std::list createObjList(Obj* o1, Obj* o2); + std::list callCreateObjList(Obj* o1, Obj* o2) { return createObjList(o1, o2); } + virtual int sumObjList(std::list objList); + int callSumObjList(std::list objList) { return sumObjList(objList); } + + // List of lists of C++ primitive type items + virtual std::list > createListOfIntLists(int num); + std::list > callCreateListOfIntLists(int num) { return createListOfIntLists(num); } + virtual int sumListOfIntLists(std::list > intListList); + int callSumListOfIntLists(std::list > intListList) { return sumListOfIntLists(intListList); } +}; + +#endif // LISTUSER_H + diff --git a/sources/shiboken2/tests/libminimal/minbool.h b/sources/shiboken2/tests/libminimal/minbool.h new file mode 100644 index 000000000..ebd2f71e2 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/minbool.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MINBOOL_H +#define MINBOOL_H + +#include "libminimalmacros.h" + +class LIBMINIMAL_API MinBool +{ +public: + inline explicit MinBool(bool b) : m_value(b) {} + 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; + return *this; + } +private: + bool m_value; +}; + +inline bool operator==(MinBool b1, bool b2) { return (!b1).value() == !b2; } +inline bool operator==(bool b1, MinBool b2) { return (!b1) == (!b2).value(); } +inline bool operator==(MinBool b1, MinBool b2) { return (!b1).value() == (!b2).value(); } +inline bool operator!=(MinBool b1, bool b2) { return (!b1).value() != !b2; } +inline bool operator!=(bool b1, MinBool b2) { return (!b1) != (!b2).value(); } +inline bool operator!=(MinBool b1, MinBool b2) { return (!b1).value() != (!b2).value(); } + +class LIBMINIMAL_API MinBoolUser +{ +public: + MinBoolUser() : m_minbool(MinBool(false)) {} + virtual ~MinBoolUser() {} + 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; +}; + +#endif diff --git a/sources/shiboken2/tests/libminimal/obj.cpp b/sources/shiboken2/tests/libminimal/obj.cpp new file mode 100644 index 000000000..a1d18d0e3 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/obj.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "obj.h" + +Obj::Obj(int objId) : m_objId(objId) +{ +} + +Obj::~Obj() +{ +} + +bool +Obj::virtualMethod(int val) +{ + return !bool(val%2); +} + diff --git a/sources/shiboken2/tests/libminimal/obj.h b/sources/shiboken2/tests/libminimal/obj.h new file mode 100644 index 000000000..16f838e19 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/obj.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJ_H +#define OBJ_H + +#include "libminimalmacros.h" + +class LIBMINIMAL_API Obj +{ +public: + explicit Obj(int objId); + virtual ~Obj(); + + int objId() { return m_objId; } + void setObjId(int objId) { m_objId = objId; } + + virtual bool virtualMethod(int val); + bool callVirtualMethod(int val) { return virtualMethod(val); } + + virtual Obj* passObjectType(Obj* obj) { return obj; } + Obj* callPassObjectType(Obj* obj) { return passObjectType(obj); } + + virtual Obj* passObjectTypeReference(Obj& obj) { return &obj; } + Obj* callPassObjectTypeReference(Obj& obj) { return passObjectTypeReference(obj); } + +private: + Obj(const Obj&); + Obj& operator=(const Obj&); + int m_objId; +}; + +#endif // OBJ_H + diff --git a/sources/shiboken2/tests/libminimal/typedef.cpp b/sources/shiboken2/tests/libminimal/typedef.cpp new file mode 100644 index 000000000..4948d9944 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/typedef.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "typedef.h" + +// +// Test wrapping of a typedef +// +bool arrayFuncInt(std::vector a) +{ + return a.empty(); +} + +bool arrayFuncIntTypedef(MyArray a) +{ + return arrayFuncInt(a); +} + +std::vector arrayFuncIntReturn(int size) +{ + return std::vector(size); +} + +MyArray arrayFuncIntReturnTypedef(int size) +{ + return arrayFuncIntReturn(size); +} + +// +// Test wrapping of a typedef of a typedef +// +bool arrayFunc(std::vector a) +{ + return a.empty(); +} + +bool arrayFuncTypedef(MyArray a) +{ + return arrayFunc(a); +} + +std::vector arrayFuncReturn(int size) +{ + return std::vector(size); +} + +MyArray arrayFuncReturnTypedef(int size) +{ + return arrayFuncReturn(size); +} diff --git a/sources/shiboken2/tests/libminimal/typedef.h b/sources/shiboken2/tests/libminimal/typedef.h new file mode 100644 index 000000000..f54a6ed18 --- /dev/null +++ b/sources/shiboken2/tests/libminimal/typedef.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TYPEDEF_H +#define TYPEDEF_H + +#include "libminimalmacros.h" + +#include + +// Test wrapping of a typedef +typedef std::vector MyArrayInt; + +LIBMINIMAL_API bool arrayFuncInt(std::vector a); +LIBMINIMAL_API bool arrayFuncIntTypedef(MyArrayInt a); + +LIBMINIMAL_API std::vector arrayFuncIntReturn(int size); +LIBMINIMAL_API MyArrayInt arrayFuncIntReturnTypedef(int size); + +// Test wrapping of a typedef of a typedef +typedef MyArrayInt MyArray; + +LIBMINIMAL_API bool arrayFunc(std::vector a); +LIBMINIMAL_API bool arrayFuncTypedef(MyArray a); + +LIBMINIMAL_API std::vector arrayFuncReturn(int size); +LIBMINIMAL_API MyArray arrayFuncReturnTypedef(int size); + +#endif diff --git a/sources/shiboken2/tests/libminimal/val.h b/sources/shiboken2/tests/libminimal/val.h new file mode 100644 index 000000000..5ba4b3aff --- /dev/null +++ b/sources/shiboken2/tests/libminimal/val.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VAL_H +#define VAL_H + +#include "libminimalmacros.h" + +class LIBMINIMAL_API Val +{ +public: + explicit Val(int valId) : m_valId(valId) {} + virtual ~Val() {} + + int valId() { return m_valId; } + void setValId(int valId) { m_valId = valId; } + + virtual Val passValueType(Val val) { return val; } + Val callPassValueType(Val val) { return passValueType(val); } + + virtual Val* passValueTypePointer(Val* val) { return val; } + Val* callPassValueTypePointer(Val* val) { return passValueTypePointer(val); } + + virtual Val* passValueTypeReference(Val& val) { return &val; } + Val* callPassValueTypeReference(Val& val) { return passValueTypeReference(val); } + + enum ValEnum { One, Other }; + ValEnum oneOrTheOtherEnumValue(ValEnum enumValue) { return enumValue == One ? Other : One; } +private: + int m_valId; +}; + +#endif // VAL_H + diff --git a/sources/shiboken2/tests/libother/CMakeLists.txt b/sources/shiboken2/tests/libother/CMakeLists.txt new file mode 100644 index 000000000..9b3cf5552 --- /dev/null +++ b/sources/shiboken2/tests/libother/CMakeLists.txt @@ -0,0 +1,18 @@ +project(libother) + +set(libother_SRC +number.cpp +otherderived.cpp +otherobjecttype.cpp +othermultiplederived.cpp +) + +add_definitions("-DLIBOTHER_BUILD") +add_library(libother SHARED ${libother_SRC}) +set_property(TARGET libother PROPERTY PREFIX "") + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${libsample_SOURCE_DIR} + ${libsample_SOURCE_DIR}/..) +target_link_libraries(libother libsample) + diff --git a/sources/shiboken2/tests/libother/extendsnoimplicitconversion.h b/sources/shiboken2/tests/libother/extendsnoimplicitconversion.h new file mode 100644 index 000000000..744bfdc0d --- /dev/null +++ b/sources/shiboken2/tests/libother/extendsnoimplicitconversion.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef EXTENDSNOIMPLICITCONVERSION_H +#define EXTENDSNOIMPLICITCONVERSION_H + +#include "libothermacros.h" +#include "noimplicitconversion.h" + +class ExtendsNoImplicitConversion +{ +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 + diff --git a/sources/shiboken2/tests/libother/libothermacros.h b/sources/shiboken2/tests/libother/libothermacros.h new file mode 100644 index 000000000..41a4fb13e --- /dev/null +++ b/sources/shiboken2/tests/libother/libothermacros.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIBOTHERMACROS_H +#define LIBOTHERMACROS_H + +#if defined _WIN32 || defined __CYGWIN__ + #if LIBOTHER_BUILD + #define LIBOTHER_API __declspec(dllexport) + #else + #define LIBOTHER_API __declspec(dllimport) + #endif +#else +#if __GNUC__ >= 4 + #define LIBOTHER_API __attribute__ ((visibility("default"))) +#else + #define LIBOTHER_API +#endif +#endif + +#endif diff --git a/sources/shiboken2/tests/libother/number.cpp b/sources/shiboken2/tests/libother/number.cpp new file mode 100644 index 000000000..4da254286 --- /dev/null +++ b/sources/shiboken2/tests/libother/number.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "number.h" +#include +#include + +using namespace std; + +Str +Number::toStr() const +{ + ostringstream in; + in << m_value; + return in.str().c_str(); +} + +Point +operator*(const Point& p, const Number& n) +{ + return Point(p.x() * n.value(), p.y() * n.value()); +} + +Complex +Number::toComplex() const +{ + return Complex(m_value); +} + +Number +Number::fromComplex(Complex cpx) +{ + return Number(cpx.real()); +} diff --git a/sources/shiboken2/tests/libother/number.h b/sources/shiboken2/tests/libother/number.h new file mode 100644 index 000000000..4286068d5 --- /dev/null +++ b/sources/shiboken2/tests/libother/number.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NUMBER_H +#define NUMBER_H + +#include "libothermacros.h" +#include "str.h" +#include "point.h" +#include "complex.h" + +class LIBOTHER_API Number +{ +public: + explicit Number(int value) : m_value(value) {}; + inline int value() const { return m_value; } + + Str toStr() const; + inline operator Str() const { return toStr(); } + + friend LIBOTHER_API Point operator*(const Point&, const Number&); + + Complex toComplex() const; + static Number fromComplex(Complex cpx); + +private: + int m_value; +}; + +LIBOTHER_API Point operator*(const Point&, const Number&); + +#endif // NUMBER_H diff --git a/sources/shiboken2/tests/libother/otherderived.cpp b/sources/shiboken2/tests/libother/otherderived.cpp new file mode 100644 index 000000000..4128d73ff --- /dev/null +++ b/sources/shiboken2/tests/libother/otherderived.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "otherderived.h" + +OtherDerived::OtherDerived(int id) : Abstract(id) +{ +} + +OtherDerived::~OtherDerived() +{ +} + +Abstract* +OtherDerived::createObject() +{ + static int id = 100; + return new OtherDerived(id++); +} + +void +OtherDerived::pureVirtual() +{ +} + +void* +OtherDerived::pureVirtualReturningVoidPtr() +{ + return 0; +} + +void +OtherDerived::unpureVirtual() +{ +} + diff --git a/sources/shiboken2/tests/libother/otherderived.h b/sources/shiboken2/tests/libother/otherderived.h new file mode 100644 index 000000000..792b7c408 --- /dev/null +++ b/sources/shiboken2/tests/libother/otherderived.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OTHERDERIVED_H +#define OTHERDERIVED_H + +#include "libothermacros.h" +#include "abstract.h" +#include "derived.h" +#include "objecttype.h" +#include "complex.h" + +class ObjectType; + +class LIBOTHER_API OtherDerived : public Abstract +{ +public: + OtherDerived(int id = -1); + virtual ~OtherDerived(); + virtual void pureVirtual(); + virtual void* pureVirtualReturningVoidPtr(); + virtual void unpureVirtual(); + virtual PrintFormat returnAnEnum() { return Short; } + + 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(); + + void hideFunction(HideType*) {} + +protected: + inline const char* getClassName() { return className(); } + virtual const char* className() { return "OtherDerived"; } +}; +#endif // OTHERDERIVED_H + diff --git a/sources/shiboken2/tests/libother/othermultiplederived.cpp b/sources/shiboken2/tests/libother/othermultiplederived.cpp new file mode 100644 index 000000000..77fa44b83 --- /dev/null +++ b/sources/shiboken2/tests/libother/othermultiplederived.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "othermultiplederived.h" + +VirtualMethods OtherMultipleDerived::returnUselessClass() +{ + return VirtualMethods(); +} + +Base1* OtherMultipleDerived::createObject(const std::string& objName) +{ + if (objName == "Base1") + return new Base1; + else if (objName == "MDerived1") + return new MDerived1; + else if (objName == "SonOfMDerived1") + return new SonOfMDerived1; + else if (objName == "MDerived3") + return new MDerived3; + else if (objName == "OtherMultipleDerived") + return new OtherMultipleDerived; + return 0; +} + diff --git a/sources/shiboken2/tests/libother/othermultiplederived.h b/sources/shiboken2/tests/libother/othermultiplederived.h new file mode 100644 index 000000000..e75504320 --- /dev/null +++ b/sources/shiboken2/tests/libother/othermultiplederived.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OTHERMULTIPLEDERIVED_H +#define OTHERMULTIPLEDERIVED_H + +#include "libothermacros.h" +#include "multiple_derived.h" +#include "virtualmethods.h" + +class ObjectType; + +class LIBOTHER_API OtherMultipleDerived : public MDerived1 +{ +public: + // this will use CppCopier from other module (bug#142) + VirtualMethods returnUselessClass(); + static Base1* createObject(const std::string& objName); +}; + +#endif diff --git a/sources/shiboken2/tests/libother/otherobjecttype.cpp b/sources/shiboken2/tests/libother/otherobjecttype.cpp new file mode 100644 index 000000000..266b2583e --- /dev/null +++ b/sources/shiboken2/tests/libother/otherobjecttype.cpp @@ -0,0 +1,36 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "otherobjecttype.h" + +Collector& +operator<<(Collector& collector, const OtherObjectType& obj) +{ + collector << obj.identifier()*2; + return collector; +} diff --git a/sources/shiboken2/tests/libother/otherobjecttype.h b/sources/shiboken2/tests/libother/otherobjecttype.h new file mode 100644 index 000000000..2bba912b6 --- /dev/null +++ b/sources/shiboken2/tests/libother/otherobjecttype.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OTHEROBJECTTYPE_H +#define OTHEROBJECTTYPE_H + +#include +#include "str.h" + +#include "libothermacros.h" +#include "objecttype.h" +#include "collector.h" + +class OtherObjectType : public ObjectType +{ +public: + +}; + + +LIBOTHER_API Collector& operator<<(Collector&, const OtherObjectType&); + +#endif // OTHEROBJECTTYPE_H + diff --git a/sources/shiboken2/tests/libsample/CMakeLists.txt b/sources/shiboken2/tests/libsample/CMakeLists.txt new file mode 100644 index 000000000..7bbc0c3dd --- /dev/null +++ b/sources/shiboken2/tests/libsample/CMakeLists.txt @@ -0,0 +1,57 @@ +project(libsample) + +set(libsample_SRC +abstract.cpp +blackbox.cpp +bytearray.cpp +bucket.cpp +collector.cpp +complex.cpp +onlycopy.cpp +derived.cpp +echo.cpp +functions.cpp +handle.cpp +implicitconv.cpp +injectcode.cpp +listuser.cpp +modifications.cpp +mapuser.cpp +modified_constructor.cpp +multiple_derived.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 +sample.cpp +samplenamespace.cpp +sbkdate.cpp +simplefile.cpp +size.cpp +sometime.cpp +str.cpp +strlist.cpp +templateptr.cpp +transform.cpp +virtualmethods.cpp +expression.cpp +filter.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_definitions("-DLIBSAMPLE_BUILD") +add_library(libsample SHARED ${libsample_SRC}) +set_property(TARGET libsample PROPERTY PREFIX "") + diff --git a/sources/shiboken2/tests/libsample/abstract.cpp b/sources/shiboken2/tests/libsample/abstract.cpp new file mode 100644 index 000000000..ab00a3bcc --- /dev/null +++ b/sources/shiboken2/tests/libsample/abstract.cpp @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "abstract.h" +#include "objecttype.h" + +using namespace std; + +const int Abstract::staticPrimitiveField = 0; + +Abstract::Abstract(int id) : m_id(id) +{ + primitiveField = 123; + valueTypeField = Point(12, 34); + objectTypeField = 0; + bitField = 0; +} + +Abstract::~Abstract() +{ +} + +void +Abstract::unpureVirtual() +{ +} + +void +Abstract::callUnpureVirtual() +{ + this->unpureVirtual(); +} + + +void +Abstract::callPureVirtual() +{ + this->pureVirtual(); +} + +void +Abstract::show(PrintFormat format) +{ + 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; + } + cout << '>'; +} + +void Abstract::callVirtualGettingEnum(PrintFormat p) +{ + virtualGettingAEnum(p); +} + +void Abstract::virtualGettingAEnum(Abstract::PrintFormat p) +{ +} + diff --git a/sources/shiboken2/tests/libsample/abstract.h b/sources/shiboken2/tests/libsample/abstract.h new file mode 100644 index 000000000..77a43f3d1 --- /dev/null +++ b/sources/shiboken2/tests/libsample/abstract.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ABSTRACT_H +#define ABSTRACT_H + +#include "libsamplemacros.h" +#include "point.h" +#include "complex.h" + +class ObjectType; + +// this class is not exported to python +class HideType +{ +}; + +class LIBSAMPLE_API Abstract +{ +private: + enum PrivateEnum { + PrivValue0, + PrivValue1, + PrivValue2 = PrivValue1 + 2 + }; +public: + enum PrintFormat { + Short, + Verbose, + OnlyId, + ClassNameAndId, + DummyItemToTestPrivateEnum1 = Abstract::PrivValue1, + DummyItemToTestPrivateEnum2 = PrivValue2, + }; + + enum Type { + TpAbstract, TpDerived + }; + + static const int staticPrimitiveField; + int primitiveField; + Complex userPrimitiveField; + Point valueTypeField; + ObjectType* objectTypeField; + + Abstract(int id = -1); + virtual ~Abstract(); + + inline int id() { return m_id; } + + // factory method + inline static Abstract* createObject() { return 0; } + + // method that receives an Object Type + inline static int getObjectId(Abstract* obj) { return obj->id(); } + + virtual void pureVirtual() = 0; + virtual void* pureVirtualReturningVoidPtr() = 0; + virtual void unpureVirtual(); + + virtual PrintFormat returnAnEnum() = 0; + void callVirtualGettingEnum(PrintFormat p); + virtual void virtualGettingAEnum(PrintFormat p); + + void callPureVirtual(); + void callUnpureVirtual(); + + void show(PrintFormat format = Verbose); + virtual Type type() const { return TpAbstract; } + + virtual void hideFunction(HideType* arg) = 0; + +protected: + virtual const char* className() { return "Abstract"; } + + // Protected bit-field structure member. + unsigned int bitField: 1; + +private: + int m_id; +}; +#endif // ABSTRACT_H diff --git a/sources/shiboken2/tests/libsample/blackbox.cpp b/sources/shiboken2/tests/libsample/blackbox.cpp new file mode 100644 index 000000000..9a10850f3 --- /dev/null +++ b/sources/shiboken2/tests/libsample/blackbox.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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()); + } +} + +int +BlackBox::keepObjectType(ObjectType* object) +{ + m_ticket++; + std::pair item(m_ticket, object); + m_objects.insert(item); + object->setParent(0); + + return m_ticket; +} + +ObjectType* +BlackBox::retrieveObjectType(int ticket) +{ + map::iterator it = m_objects.find(ticket); + if (it != m_objects.end()) { + ObjectType* second = it->second; + m_objects.erase(it); + return second; + } + return 0; +} + +void +BlackBox::disposeObjectType(int ticket) +{ + ObjectType* object = retrieveObjectType(ticket); + if (object) + delete object; +} + +int +BlackBox::keepPoint(Point* point) +{ + m_ticket++; + std::pair item(m_ticket, point); + m_points.insert(item); + + return m_ticket; +} + +Point* +BlackBox::retrievePoint(int ticket) +{ + map::iterator it = m_points.find(ticket); + if (it != m_points.end()) { + Point* second = it->second; + m_points.erase(it); + return second; + } + return 0; +} + +void +BlackBox::disposePoint(int ticket) +{ + Point* point = retrievePoint(ticket); + if (point) + delete point; +} + + +std::list +BlackBox::objects() +{ + std::list l; + map::iterator it; + + for ( it = m_objects.begin() ; it != m_objects.end(); it++ ) + l.push_back((*it).second); + + return l; +} + +std::list +BlackBox::points() +{ + std::list l; + map::iterator it; + + for ( it = m_points.begin() ; it != m_points.end(); it++ ) + l.push_back((*it).second); + + return l; +} + diff --git a/sources/shiboken2/tests/libsample/blackbox.h b/sources/shiboken2/tests/libsample/blackbox.h new file mode 100644 index 000000000..de776668c --- /dev/null +++ b/sources/shiboken2/tests/libsample/blackbox.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLACKBOX_H +#define BLACKBOX_H + +#include "libsamplemacros.h" +#include +#include "objecttype.h" +#include "point.h" + +class LIBSAMPLE_API BlackBox +{ +public: + typedef std::map ObjectTypeMap; + typedef std::map PointMap; + + BlackBox() { m_ticket = -1;} + ~BlackBox(); + + int keepObjectType(ObjectType* object); + ObjectType* retrieveObjectType(int ticket); + void disposeObjectType(int ticket); + + int keepPoint(Point* point); + Point* retrievePoint(int ticket); + void disposePoint(int ticket); + + std::list objects(); + std::list points(); + + inline void referenceToValuePointer(Point*&) {} + inline void referenceToObjectPointer(ObjectType*&) {} + +private: + ObjectTypeMap m_objects; + PointMap m_points; + int m_ticket; +}; + +#endif // BLACKBOX_H + diff --git a/sources/shiboken2/tests/libsample/bucket.cpp b/sources/shiboken2/tests/libsample/bucket.cpp new file mode 100644 index 000000000..50a1310e7 --- /dev/null +++ b/sources/shiboken2/tests/libsample/bucket.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "bucket.h" +#include + +#ifdef _WIN32 // _WIN32 is defined by all Windows 32 and 64 bit compilers, but not by others. +#include +#define SLEEP(x) Sleep(x) +#else +#include +#define SLEEP(x) usleep(x) +#endif + + +using namespace std; + +Bucket::Bucket() : m_locked(false) +{ +} + +void Bucket::push(int x) +{ + m_data.push_back(x); +} + +int Bucket::pop(void) +{ + int x = 0; + + if (m_data.size() > 0) { + x = m_data.front(); + m_data.pop_front(); + } + + return x; +} + +bool Bucket::empty() +{ + return m_data.empty(); +} + +void Bucket::lock() +{ + m_locked = true; + while (m_locked) { SLEEP(300); } +} + +void Bucket::unlock() +{ + m_locked = false; +} + +bool Bucket::virtualBlockerMethod() +{ + lock(); + // The return value was added just for diversity sake. + return true; +} + diff --git a/sources/shiboken2/tests/libsample/bucket.h b/sources/shiboken2/tests/libsample/bucket.h new file mode 100644 index 000000000..bd8648b6b --- /dev/null +++ b/sources/shiboken2/tests/libsample/bucket.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BUCKET_H +#define BUCKET_H + +#include "libsamplemacros.h" +#include "objecttype.h" +#include + +class ObjectType; + +class LIBSAMPLE_API Bucket : public ObjectType +{ +public: + Bucket(); + void push(int); + int pop(); + bool empty(); + void lock(); + inline bool locked() { return m_locked; } + void unlock(); + + virtual bool virtualBlockerMethod(); + inline bool callVirtualBlockerMethodButYouDontKnowThis() { return virtualBlockerMethod(); } + +private: + std::list m_data; + + volatile bool m_locked; +}; + +#endif // BUCKET_H + diff --git a/sources/shiboken2/tests/libsample/bytearray.cpp b/sources/shiboken2/tests/libsample/bytearray.cpp new file mode 100644 index 000000000..c86ada124 --- /dev/null +++ b/sources/shiboken2/tests/libsample/bytearray.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "bytearray.h" + +ByteArray::ByteArray() +{ + m_data = std::vector(1); + m_data[0] = '\0'; +} + +ByteArray::ByteArray(char c) +{ + m_data = std::vector(2); + m_data[0] = c; + m_data[1] = '\0'; +} + +ByteArray::ByteArray(const char* data) +{ + size_t len = strlen(data); + m_data = std::vector(len + 1); + memcpy(&m_data[0], data, len); + m_data[len] = '\0'; +} + +ByteArray::ByteArray(const char* data, int len) +{ + m_data = std::vector(len + 1); + memcpy(&m_data[0], data, len); + m_data[len] = '\0'; +} + +ByteArray::ByteArray(const ByteArray& other) +{ + m_data = std::vector(other.size() + 1); + memcpy(&m_data[0], &other.m_data[0], other.size()); + m_data[other.size()] = '\0'; +} + +int +ByteArray::size() const +{ + return m_data.size() - 1; +} + +char +ByteArray::at(int pos) const +{ + return m_data[pos]; +} + +const char* +ByteArray::data() const +{ + return &(m_data[0]); +} + +ByteArray& +ByteArray::append(char c) +{ + m_data.pop_back(); + m_data.push_back(c); + m_data.push_back('\0'); + return *this; +} + +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]); + m_data.push_back('\0'); + return *this; +} + +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]); + m_data.push_back('\0'); + return *this; +} + +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'); + return *this; +} + +static bool compare(const std::vector& mine, const char* other) +{ + for (int i = 0; i < (int)mine.size() - 1; ++i) { + if (mine[i] != other[i]) + return false; + } + return true; +} + +bool +ByteArray::operator==(const ByteArray& other) const +{ + return compare(m_data, &other.m_data[0]); +} +bool +operator==(const ByteArray& ba1, const char* ba2) +{ + return compare(ba1.m_data, ba2); +} +bool +operator==(const char* ba1, const ByteArray& ba2) +{ + return compare(ba2.m_data, ba1); +} + +bool +ByteArray::operator!=(const ByteArray& other) const +{ + return !(m_data == other.m_data); +} +bool +operator!=(const ByteArray& ba1, const char* ba2) +{ + return !(ba1 == ba2); +} +bool +operator!=(const char* ba1, const ByteArray& ba2) +{ + return !(ba1 == ba2); +} + +ByteArray& +ByteArray::operator+=(char c) +{ + return append(c); +} +ByteArray& +ByteArray::operator+=(const char* data) +{ + return append(data); +} +ByteArray& +ByteArray::operator+=(const ByteArray& other) +{ + return append(other); +} + +ByteArray +operator+(const ByteArray& ba1, const ByteArray& ba2) +{ + return ByteArray(ba1) += ba2; +} +ByteArray +operator+(const ByteArray& ba1, const char* ba2) +{ + return ByteArray(ba1) += ByteArray(ba2); +} +ByteArray +operator+(const char* ba1, const ByteArray& ba2) +{ + return ByteArray(ba1) += ba2; +} +ByteArray +operator+(const ByteArray& ba1, char ba2) +{ + return ByteArray(ba1) += ByteArray(ba2); +} +ByteArray +operator+(char ba1, const ByteArray& ba2) +{ + return ByteArray(ba1) += ba2; +} + +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]; + return result; +} diff --git a/sources/shiboken2/tests/libsample/bytearray.h b/sources/shiboken2/tests/libsample/bytearray.h new file mode 100644 index 000000000..d2219ee5d --- /dev/null +++ b/sources/shiboken2/tests/libsample/bytearray.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BYTEARRAY_H +#define BYTEARRAY_H + +#include "str.h" +#include "libsamplemacros.h" +#include + +class LIBSAMPLE_API ByteArray +{ +public: + ByteArray(); + ByteArray(char data); + ByteArray(const char* data); + ByteArray(const char* data, int len); + ByteArray(const ByteArray& other); + + int size() const; + char at(int i) const; + char operator[](int i) 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); + + 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); + + static unsigned int hash(const ByteArray& byteArray); +private: + std::vector 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 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 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/shiboken2/tests/libsample/collector.cpp b/sources/shiboken2/tests/libsample/collector.cpp new file mode 100644 index 000000000..e60ed3af3 --- /dev/null +++ b/sources/shiboken2/tests/libsample/collector.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "collector.h" + +void Collector::clear() +{ + m_items.clear(); +} + +Collector& Collector::operator<<(ObjectType::Identifier item) +{ + m_items.push_back(item); + return *this; +} + +Collector& Collector::operator<<(const ObjectType *obj) +{ + m_items.push_back(obj->identifier()); + return *this; +} + +std::list Collector::items() +{ + return m_items; +} + +int Collector::size() +{ + return (int) m_items.size(); +} + +Collector &operator<<(Collector &s, const IntWrapper &w) +{ + s << w.value; + return s; +} diff --git a/sources/shiboken2/tests/libsample/collector.h b/sources/shiboken2/tests/libsample/collector.h new file mode 100644 index 000000000..fe82909cb --- /dev/null +++ b/sources/shiboken2/tests/libsample/collector.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COLLECTOR_H +#define COLLECTOR_H + +#include +#include "libsamplemacros.h" + +#include "objecttype.h" + +class LIBSAMPLE_API Collector +{ +public: + Collector() {} + virtual ~Collector() {} + + void clear(); + + Collector& operator<<(ObjectType::Identifier item); + + Collector& operator<<(const ObjectType *); + + std::list items(); + int size(); + +private: + std::list m_items; + + Collector(const Collector&); + Collector& operator=(const Collector&); +}; + +/* Helper for testing external operators */ +class IntWrapper +{ +public: + IntWrapper(int x=0):value(x){} + + int value; +}; + +LIBSAMPLE_API Collector &operator<<(Collector&, const IntWrapper&); + +#endif // COLLECTOR_H + diff --git a/sources/shiboken2/tests/libsample/complex.cpp b/sources/shiboken2/tests/libsample/complex.cpp new file mode 100644 index 000000000..10e4b3f58 --- /dev/null +++ b/sources/shiboken2/tests/libsample/complex.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "complex.h" + +using namespace std; + +Complex::Complex(double real, double imag) + : m_real(real), m_imag(imag) +{ +} + +Complex +Complex::operator+(Complex& other) +{ + Complex result; + result.setReal(m_real + other.real()); + result.setImaginary(m_imag + other.imag()); + return result; +} + +void +Complex::show() +{ + cout << "(real: " << m_real << ", imag: " << m_imag << ")"; +} + + diff --git a/sources/shiboken2/tests/libsample/complex.h b/sources/shiboken2/tests/libsample/complex.h new file mode 100644 index 000000000..cb167bde9 --- /dev/null +++ b/sources/shiboken2/tests/libsample/complex.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef COMPLEX_H +#define COMPLEX_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Complex +{ +public: + Complex(double real = 0.0, double imag = 0.0); + ~Complex() {} + + 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); + + void show(); + +private: + double m_real; + double m_imag; +}; + +#endif // COMPLEX_H + diff --git a/sources/shiboken2/tests/libsample/ctorconvrule.h b/sources/shiboken2/tests/libsample/ctorconvrule.h new file mode 100644 index 000000000..776f4744c --- /dev/null +++ b/sources/shiboken2/tests/libsample/ctorconvrule.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CTORCONVRULE_H +#define CTORCONVRULE_H + +#include "libsamplemacros.h" + +class CtorConvRule +{ +public: + explicit CtorConvRule(long value) : m_value(value) {} + virtual ~CtorConvRule() {} + virtual void dummyVirtualMethod() {} + long value() { return m_value; } +private: + long m_value; +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/cvlist.h b/sources/shiboken2/tests/libsample/cvlist.h new file mode 100644 index 000000000..c74007945 --- /dev/null +++ b/sources/shiboken2/tests/libsample/cvlist.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CONSTVALUELIST_H +#define CONSTVALUELIST_H + +#include +#include "libsamplemacros.h" + +class CVValueType +{ + CVValueType(); +}; + +typedef std::list const_ptr_value_list; + +// 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 +// binding code (the container conversion in particular) is const-valid. + +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; } +}; + +#endif // LIST_H diff --git a/sources/shiboken2/tests/libsample/derived.cpp b/sources/shiboken2/tests/libsample/derived.cpp new file mode 100644 index 000000000..00ac8ebe5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/derived.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "derived.h" + +using namespace std; + +Derived::Derived(int id) : Abstract(id) +{ +} + +Derived::~Derived() +{ +} + +Abstract* +Derived::createObject() +{ + static int id = 100; + return new Derived(id++); +} + +void +Derived::pureVirtual() +{ +} + +void* +Derived::pureVirtualReturningVoidPtr() +{ + return 0; +} + +void +Derived::unpureVirtual() +{ +} + +bool +Derived::singleArgument(bool b) +{ + return !b; +} + +double +Derived::defaultValue(int n) +{ + return ((double) n) + 0.1; +} + +OverloadedFuncEnum +Derived::overloaded(int i, int d) +{ + return OverloadedFunc_ii; +} + +OverloadedFuncEnum +Derived::overloaded(double n) +{ + return OverloadedFunc_d; +} + +Derived::OtherOverloadedFuncEnum +Derived::otherOverloaded(int a, int b, bool c, double d) +{ + return OtherOverloadedFunc_iibd; +} + +Derived::OtherOverloadedFuncEnum +Derived::otherOverloaded(int a, double b) +{ + return OtherOverloadedFunc_id; +} + +struct SecretClass : public Abstract { + virtual void pureVirtual() {} + virtual void* pureVirtualReturningVoidPtr() { return 0; } + virtual PrintFormat returnAnEnum() { return Short; } + void hideFunction(HideType*){}; +}; + +Abstract* Derived::triggerImpossibleTypeDiscovery() +{ + return new SecretClass; +} + +struct AnotherSecretClass : public Derived { +}; + +Abstract* Derived::triggerAnotherImpossibleTypeDiscovery() +{ + return new AnotherSecretClass; +} diff --git a/sources/shiboken2/tests/libsample/derived.h b/sources/shiboken2/tests/libsample/derived.h new file mode 100644 index 000000000..5c57e4691 --- /dev/null +++ b/sources/shiboken2/tests/libsample/derived.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DERIVED_H +#define DERIVED_H + +#include "libsamplemacros.h" +#include "abstract.h" + +enum OverloadedFuncEnum { + OverloadedFunc_ii, + OverloadedFunc_d +}; + +class LIBSAMPLE_API Derived : public Abstract +{ +public: + enum OtherOverloadedFuncEnum { + OtherOverloadedFunc_iibd, + OtherOverloadedFunc_id + }; + + class SomeInnerClass { + public: + void uselessMethod() {} + SomeInnerClass operator+(const SomeInnerClass& other) { return other; } + bool operator==(const SomeInnerClass& other) { return true; } + }; + + Derived(int id = -1); + virtual ~Derived(); + virtual void pureVirtual(); + virtual void* pureVirtualReturningVoidPtr(); + virtual void unpureVirtual(); + + virtual PrintFormat returnAnEnum() { return Short; } + virtual Type type() const { return TpDerived; } + + // factory method + static Abstract* createObject(); + + // single argument + bool singleArgument(bool b); + + // method with default value + double defaultValue(int n = 0); + + // overloads + OverloadedFuncEnum overloaded(int i = 0, int d = 0); + OverloadedFuncEnum overloaded(double n); + + // more overloads + OtherOverloadedFuncEnum otherOverloaded(int a, int b, bool c, double d); + OtherOverloadedFuncEnum otherOverloaded(int a, double b); + + inline SomeInnerClass returnMyParameter(const SomeInnerClass& s) { return s; } + + static Abstract* triggerImpossibleTypeDiscovery(); + static Abstract* triggerAnotherImpossibleTypeDiscovery(); + + void hideFunction(HideType*) {} +protected: + const char* getClassName() { return className(); } + virtual const char* className() { return "Derived"; } +}; +#endif // DERIVED_H + diff --git a/sources/shiboken2/tests/libsample/echo.cpp b/sources/shiboken2/tests/libsample/echo.cpp new file mode 100644 index 000000000..00fec78b0 --- /dev/null +++ b/sources/shiboken2/tests/libsample/echo.cpp @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "echo.h" diff --git a/sources/shiboken2/tests/libsample/echo.h b/sources/shiboken2/tests/libsample/echo.h new file mode 100644 index 000000000..a976c9cbc --- /dev/null +++ b/sources/shiboken2/tests/libsample/echo.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ECHO_H +#define ECHO_H + +#include "libsamplemacros.h" +#include "str.h" + +class ObjectType; + +class Echo +{ +public: + Echo(){} + ~Echo(){} + + 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; } +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/expression.cpp b/sources/shiboken2/tests/libsample/expression.cpp new file mode 100644 index 000000000..ff87e2ed2 --- /dev/null +++ b/sources/shiboken2/tests/libsample/expression.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "expression.h" +#include + +Expression::Expression() : m_value(0), m_operation(None), m_operand1(0), m_operand2(0) +{ +} + +Expression::Expression(int number) : m_value(number), m_operation(None), m_operand1(0), m_operand2(0) +{ +} + +Expression::Expression(const Expression& other) +{ + m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; + m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; + m_value = other.m_value; + m_operation = other.m_operation; +} + +Expression& Expression::operator=(const Expression& other) +{ + delete m_operand1; + delete m_operand2; + m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; + m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; + m_operation = other.m_operation; + m_value = other.m_value; + return *this; +} + +Expression::~Expression() +{ + delete m_operand1; + delete m_operand2; +} + +Expression Expression::operator+(const Expression& other) +{ + Expression expr; + expr.m_operation = Add; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator-(const Expression& other) +{ + Expression expr; + expr.m_operation = Add; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator<(const Expression& other) +{ + Expression expr; + expr.m_operation = LessThan; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator>(const Expression& other) +{ + Expression expr; + expr.m_operation = GreaterThan; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +std::string Expression::toString() const +{ + if (m_operation == None) { + std::ostringstream s; + s << m_value; + return s.str(); + } + + std::string result; + result += '('; + result += m_operand1->toString(); + char op; + switch (m_operation) { + case Add: + op = '+'; + break; + case Sub: + op = '-'; + break; + case LessThan: + op = '<'; + break; + case GreaterThan: + op = '<'; + break; + case None: // just to avoid the compiler warning + default: + op = '?'; + break; + } + result += op; + result += m_operand2->toString(); + result += ')'; + return result; +} + diff --git a/sources/shiboken2/tests/libsample/expression.h b/sources/shiboken2/tests/libsample/expression.h new file mode 100644 index 000000000..c4bb1a1f5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/expression.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include "libsamplemacros.h" +#include + +class LIBSAMPLE_API Expression +{ +public: + enum Operation { + None, Add, Sub, LessThan, GreaterThan + }; + + Expression(int number); + Expression(const Expression& other); + Expression& operator=(const Expression& other); + + ~Expression(); + + 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; + + Expression(); +}; + +#endif // EXPRESSION_H diff --git a/sources/shiboken2/tests/libsample/filter.cpp b/sources/shiboken2/tests/libsample/filter.cpp new file mode 100644 index 000000000..dac5d5e96 --- /dev/null +++ b/sources/shiboken2/tests/libsample/filter.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "filter.h" +Data::Data(Field field, std::string value) + : m_field(field), m_value(value) +{ +} + +Union::Union(const Data& filter) +{ + m_filters.push_back(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) +{ + m_filters.push_back(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 filter; + filter.addFilter(a); + filter.addFilter(b); + + return filter; +} diff --git a/sources/shiboken2/tests/libsample/filter.h b/sources/shiboken2/tests/libsample/filter.h new file mode 100644 index 000000000..6ee2e6123 --- /dev/null +++ b/sources/shiboken2/tests/libsample/filter.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FILTER_H +#define FILTER_H + +#include +#include + +#include "libsamplemacros.h" + +class Intersection; + +class LIBSAMPLE_API Filter +{ +}; + +class LIBSAMPLE_API Data : public Filter +{ + +public: + enum Field { + Name, + Album, + Year + }; + + Data(Field field, std::string value); + + Field field() const { return m_field; } + std::string value() const { return m_value; } + +private: + Field m_field; + std::string m_value; +}; + +class LIBSAMPLE_API Union : public Filter +{ +public: + + Union(const Data&); + Union(const Intersection&); + Union() {}; + Union(const Union&); + + std::list filters() const { return m_filters; } + void addFilter(const Filter& data) { m_filters.push_back(data); } + +private: + std::list m_filters; +}; + +class LIBSAMPLE_API Intersection : public Filter +{ +public: + + Intersection(const Data&); + Intersection(const Union&); + Intersection() {}; + Intersection(const Intersection&); + + std::list filters() const { return m_filters; } + void addFilter(const Filter& data) { m_filters.push_back(data); } + +private: + std::list m_filters; +}; + +LIBSAMPLE_API Intersection operator&(const Intersection& a, const Intersection& b); + +#endif // FILTER_H + + diff --git a/sources/shiboken2/tests/libsample/functions.cpp b/sources/shiboken2/tests/libsample/functions.cpp new file mode 100644 index 000000000..4a15cdae8 --- /dev/null +++ b/sources/shiboken2/tests/libsample/functions.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "functions.h" +#include +#include + +using namespace std; + +void +printSomething() +{ + cout << __FUNCTION__ << endl; +} + +int +gimmeInt() +{ + static int val = 2; + val = val * 1.3; + return val; +} + +double +gimmeDouble() +{ + static double val = 7.77; + val = val * 1.3; + return val; +} + +std::list +gimmeComplexList() +{ + std::list lst; + lst.push_back(Complex()); + lst.push_back(Complex(1.1, 2.2)); + lst.push_back(Complex(1.3, 2.4)); + return lst; +} + +Complex +sumComplexPair(std::pair cpx_pair) +{ + return cpx_pair.first + cpx_pair.second; +} + +double +multiplyPair(std::pair pair) +{ + return pair.first * pair.second; +} + +int +countCharacters(const char* text) +{ + if (!text) + return -1; + int count; + for(count = 0; text[count] != '\0'; count++) + ; + return count; +} + +char* +makeCString() +{ + char* string = new char[strlen(__FUNCTION__) + 1]; + strcpy(string, __FUNCTION__); + return string; +} + +const char* +returnCString() +{ + return __FUNCTION__; +} + +GlobalOverloadFuncEnum +overloadedFunc(int val) +{ + return GlobalOverloadFunc_i; +} + +GlobalOverloadFuncEnum +overloadedFunc(double val) +{ + return GlobalOverloadFunc_d; +} + +char* +returnNullPrimitivePointer() +{ + return 0; +} + +ObjectType* +returnNullObjectTypePointer() +{ + return 0; +} + +Event* +returnNullValueTypePointer() +{ + return 0; +} + +unsigned int +doubleUnsignedInt(unsigned int value) +{ + return value * 2; +} + +long long +doubleLongLong(long long value) +{ + return value * 2; +} + +unsigned long long +doubleUnsignedLongLong(unsigned long long value) +{ + return value * 2; +} + +short +doubleShort(short value) +{ + return value * 2; +} + +int +acceptInt(int x) +{ + return x; +} + +unsigned int +acceptUInt(unsigned int x) +{ + return x; +} + +long +acceptLong(long x) +{ + return x; +} + +unsigned long +acceptULong(unsigned long x) +{ + return x; +} + +double +acceptDouble(double x) +{ + return x; +} + +int +acceptIntReference(int& x) +{ + return x; +} + +OddBool +acceptOddBoolReference(OddBool& x) +{ + return x; +} + +ClassWithFunctionPointer::ClassWithFunctionPointer() +{ + callFunctionPointer(0, &ClassWithFunctionPointer::doNothing); +} + +void ClassWithFunctionPointer::callFunctionPointer(int dummy, void (*fp)(void *)) +{ + size_t a = dummy; + fp(reinterpret_cast(a)); +} + +void ClassWithFunctionPointer::doNothing(void *operand) +{ + (void) operand; +} diff --git a/sources/shiboken2/tests/libsample/functions.h b/sources/shiboken2/tests/libsample/functions.h new file mode 100644 index 000000000..89a175bc4 --- /dev/null +++ b/sources/shiboken2/tests/libsample/functions.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FUNCTIONS_H +#define FUNCTIONS_H + +#include "libsamplemacros.h" +#include +#include +#include "oddbool.h" +#include "complex.h" +#include "objecttype.h" + +enum GlobalEnum { + NoThing, + FirstThing, + SecondThing, + ThirdThing +}; + +enum GlobalOverloadFuncEnum { + GlobalOverloadFunc_i, + GlobalOverloadFunc_d +}; + +LIBSAMPLE_API void printSomething(); +LIBSAMPLE_API int gimmeInt(); +LIBSAMPLE_API double gimmeDouble(); +LIBSAMPLE_API double multiplyPair(std::pair pair); +LIBSAMPLE_API std::list gimmeComplexList(); +LIBSAMPLE_API Complex sumComplexPair(std::pair cpx_pair); + +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(); + +// Tests overloading on functions (!methods) +LIBSAMPLE_API GlobalOverloadFuncEnum overloadedFunc(int val); +LIBSAMPLE_API GlobalOverloadFuncEnum overloadedFunc(double val); + +LIBSAMPLE_API unsigned int doubleUnsignedInt(unsigned int value); +LIBSAMPLE_API long long doubleLongLong(long long value); +LIBSAMPLE_API unsigned long long doubleUnsignedLongLong(unsigned long long value); +LIBSAMPLE_API short doubleShort(short value); + +LIBSAMPLE_API int acceptInt(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); + + +class LIBSAMPLE_API ClassWithFunctionPointer +{ +public: + explicit ClassWithFunctionPointer(); + void callFunctionPointer(int dummy, void (*fp)(void *)); + static void doNothing(void *operand); +}; + +#endif // FUNCTIONS_H diff --git a/sources/shiboken2/tests/libsample/handle.cpp b/sources/shiboken2/tests/libsample/handle.cpp new file mode 100644 index 000000000..e0b1d8d18 --- /dev/null +++ b/sources/shiboken2/tests/libsample/handle.cpp @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "handle.h" + +HANDLE HandleHolder::createHandle() +{ + return (HANDLE) new OBJ; +} + +bool HandleHolder::compare(HandleHolder* other) +{ + return other->m_handle == m_handle; +} + +bool HandleHolder::compare2(HandleHolder* other) +{ + return other->m_handle2 == m_handle2; +} diff --git a/sources/shiboken2/tests/libsample/handle.h b/sources/shiboken2/tests/libsample/handle.h new file mode 100644 index 000000000..d656f946b --- /dev/null +++ b/sources/shiboken2/tests/libsample/handle.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef HANDLE_H +#define HANDLE_H + +#include "libsamplemacros.h" + +/* See http://bugs.pyside.org/show_bug.cgi?id=1105. */ +namespace Foo { + typedef unsigned long HANDLE; +} + +class LIBSAMPLE_API OBJ +{ +}; + +typedef OBJ* HANDLE; + +class LIBSAMPLE_API HandleHolder +{ +public: + explicit HandleHolder(HANDLE ptr = 0) : m_handle(ptr) {} + explicit HandleHolder(Foo::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; } + + static HANDLE createHandle(); + bool compare(HandleHolder* other); + bool compare2(HandleHolder* other); + +private: + HANDLE m_handle; + Foo::HANDLE m_handle2; +}; + +struct LIBSAMPLE_API PrimitiveStruct {}; +typedef struct PrimitiveStruct* PrimitiveStructPtr; +struct LIBSAMPLE_API PrimitiveStructPointerHolder +{ + PrimitiveStructPtr primitiveStructPtr; +}; + +#endif // HANDLE_H diff --git a/sources/shiboken2/tests/libsample/implicitconv.cpp b/sources/shiboken2/tests/libsample/implicitconv.cpp new file mode 100644 index 000000000..df4af2537 --- /dev/null +++ b/sources/shiboken2/tests/libsample/implicitconv.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "implicitconv.h" + +ImplicitConv +ImplicitConv::implicitConvCommon(ImplicitConv implicit) +{ + return implicit; +} + +ImplicitConv +ImplicitConv::implicitConvDefault(ImplicitConv implicit) +{ + return implicit; +} + +ImplicitConv::ICOverloadedFuncEnum +ImplicitConv::implicitConvOverloading(ImplicitConv implicit, int dummyArg) +{ + return ImplicitConv::OverFunc_Ii; +} + +ImplicitConv::ICOverloadedFuncEnum +ImplicitConv::implicitConvOverloading(ImplicitConv implicit, bool dummyArg) +{ + return ImplicitConv::OverFunc_Ib; +} + +ImplicitConv::ICOverloadedFuncEnum +ImplicitConv::implicitConvOverloading(int dummyArg) +{ + return ImplicitConv::OverFunc_i; +} + +ImplicitConv::ICOverloadedFuncEnum +ImplicitConv::implicitConvOverloading(CtorEnum dummyArg) +{ + return ImplicitConv::OverFunc_C; +} + diff --git a/sources/shiboken2/tests/libsample/implicitconv.h b/sources/shiboken2/tests/libsample/implicitconv.h new file mode 100644 index 000000000..2a8ac66c2 --- /dev/null +++ b/sources/shiboken2/tests/libsample/implicitconv.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef IMPLICITCONV_H +#define IMPLICITCONV_H + +#include "libsamplemacros.h" +#include "null.h" + +class ObjectType; + +class LIBSAMPLE_API ImplicitConv +{ +public: + enum CtorEnum { + CtorNone, + CtorOne, + CtorTwo, + CtorThree, + CtorObjectTypeReference, + CtorPrimitiveType + }; + + enum ICOverloadedFuncEnum { + OverFunc_Ii, + OverFunc_Ib, + OverFunc_i, + 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(double value, bool=true) : m_ctorEnum(CtorNone), m_value(value) {} + ImplicitConv(const Null& null) : m_ctorEnum(CtorPrimitiveType) {} + ~ImplicitConv() {} + + inline CtorEnum ctorEnum() { return m_ctorEnum; } + inline int objId() { return m_objId; } + inline double value() { return m_value; } + + static ImplicitConv implicitConvCommon(ImplicitConv implicit); + + static ImplicitConv implicitConvDefault(ImplicitConv implicit = CtorTwo); + + static ICOverloadedFuncEnum implicitConvOverloading(ImplicitConv implicit, int dummyArg); + static ICOverloadedFuncEnum implicitConvOverloading(ImplicitConv implicit, bool dummyArg); + static ICOverloadedFuncEnum implicitConvOverloading(int dummyArg); + static ICOverloadedFuncEnum implicitConvOverloading(CtorEnum dummyArg); + +private: + CtorEnum m_ctorEnum; + int m_objId; + double m_value; +}; + +#endif // IMPLICITCONV_H diff --git a/sources/shiboken2/tests/libsample/injectcode.cpp b/sources/shiboken2/tests/libsample/injectcode.cpp new file mode 100644 index 000000000..4406cdc5c --- /dev/null +++ b/sources/shiboken2/tests/libsample/injectcode.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "injectcode.h" +#include + +using namespace std; + +InjectCode::InjectCode() +{ +} + +InjectCode::~InjectCode() +{ +} + +template +const char* InjectCode::toStr(const T& value) +{ + std::ostringstream s; + s << value; + m_valueHolder = s.str(); + return m_valueHolder.c_str(); +} + +const char* InjectCode::simpleMethod1(int arg0, int arg1) +{ + return toStr(arg0 + arg1); +} + +const char* InjectCode::simpleMethod2() +{ + return "_"; +} + +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) +{ + toStr(arg0); + m_valueHolder += arg1 ? "true" : "false"; + return m_valueHolder.c_str(); +} + +const char* InjectCode::overloadedMethod(int arg0, double arg1) +{ + return toStr(arg0 + arg1); +} + +const char* InjectCode::overloadedMethod(int argc, char** argv) +{ + return simpleMethod3(argc, argv); +} + +const char* InjectCode::virtualMethod(int arg) +{ + return toStr(arg); +} + +int InjectCode::arrayMethod(int count, int *values) const +{ + int ret = 0; + for (int i=0; i < count; i++) + ret += values[i]; + return ret; +} + +int InjectCode::sumArrayAndLength(int* values) const +{ + int sum = 0; + + while(*values) { + sum = sum + *values + 1; + values++; + } + + return sum; +} diff --git a/sources/shiboken2/tests/libsample/injectcode.h b/sources/shiboken2/tests/libsample/injectcode.h new file mode 100644 index 000000000..ba1bedb17 --- /dev/null +++ b/sources/shiboken2/tests/libsample/injectcode.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef INJECTCODE_H +#define INJECTCODE_H + +#include "libsamplemacros.h" +#include +#include + +class LIBSAMPLE_API InjectCode +{ +public: + InjectCode(); + virtual ~InjectCode(); + + 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); + + 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; +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 + // another method of this class. + std::string m_valueHolder; + + template + const char* toStr(const T& value); +}; + +#endif // INJECTCODE_H + diff --git a/sources/shiboken2/tests/libsample/libsamplemacros.h b/sources/shiboken2/tests/libsample/libsamplemacros.h new file mode 100644 index 000000000..6a1bba88d --- /dev/null +++ b/sources/shiboken2/tests/libsample/libsamplemacros.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIBSAMPLEMACROS_H +#define LIBSAMPLEMACROS_H + +#if defined _WIN32 || defined __CYGWIN__ + #if LIBSAMPLE_BUILD + #define LIBSAMPLE_API __declspec(dllexport) + #else + #define LIBSAMPLE_API __declspec(dllimport) + #endif +#else +#if __GNUC__ >= 4 + #define LIBSAMPLE_API __attribute__ ((visibility("default"))) +#else + #define LIBSAMPLE_API +#endif +#endif + +#endif diff --git a/sources/shiboken2/tests/libsample/list.h b/sources/shiboken2/tests/libsample/list.h new file mode 100644 index 000000000..f1183440c --- /dev/null +++ b/sources/shiboken2/tests/libsample/list.h @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIST_H +#define LIST_H + +#include +#include "libsamplemacros.h" +#include "point.h" + +class ObjectType; + +template +class List : public std::list +{ +}; + +class IntList : public List +{ +public: + enum CtorEnum { + NoParamsCtor, + IntCtor, + CopyCtor, + ListOfIntCtor + }; + + inline IntList() : m_ctorUsed(NoParamsCtor) {} + inline explicit IntList(int val) : m_ctorUsed(IntCtor) { push_back(val); } + inline IntList(const IntList& lst) : List(lst), m_ctorUsed(CopyCtor) {} + inline IntList(const List& lst) : List(lst), m_ctorUsed(ListOfIntCtor) {} + + inline void append(int v) { insert(end(), v); } + CtorEnum constructorUsed() { return m_ctorUsed; } +private: + CtorEnum m_ctorUsed; +}; + +class PointValueList : public List +{ +public: + enum CtorEnum { + NoParamsCtor, + PointCtor, + CopyCtor, + ListOfPointValuesCtor + }; + + inline PointValueList() : m_ctorUsed(NoParamsCtor) {} + inline explicit PointValueList(Point val) : m_ctorUsed(PointCtor) { push_back(val); } + inline PointValueList(const PointValueList& lst) : List(lst), m_ctorUsed(CopyCtor) {} + inline PointValueList(const List& lst) : List(lst), m_ctorUsed(ListOfPointValuesCtor) {} + + inline void append(Point v) { insert(end(), v); } + CtorEnum constructorUsed() { return m_ctorUsed; } +private: + CtorEnum m_ctorUsed; +}; + +class ObjectTypePtrList : public List +{ +public: + enum CtorEnum { + NoParamsCtor, + ObjectTypeCtor, + CopyCtor, + ListOfObjectTypePtrCtor + }; + + inline ObjectTypePtrList() : m_ctorUsed(NoParamsCtor) {} + inline explicit ObjectTypePtrList(ObjectType* val) : m_ctorUsed(ObjectTypeCtor) { push_back(val); } + inline ObjectTypePtrList(const ObjectTypePtrList& lst) : List(lst), m_ctorUsed(CopyCtor) {} + inline ObjectTypePtrList(const List& lst) : List(lst), m_ctorUsed(ListOfObjectTypePtrCtor) {} + + inline void append(ObjectType* v) { insert(end(), v); } + CtorEnum constructorUsed() { return m_ctorUsed; } +private: + CtorEnum m_ctorUsed; +}; + +#endif // LIST_H diff --git a/sources/shiboken2/tests/libsample/listuser.cpp b/sources/shiboken2/tests/libsample/listuser.cpp new file mode 100644 index 000000000..24389766e --- /dev/null +++ b/sources/shiboken2/tests/libsample/listuser.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "listuser.h" + +using namespace std; + +std::list +ListUser::callCreateList() +{ + return createList(); +} + +std::list +ListUser::createList() +{ + std::list retval; + for (int i = 0; i < 4; i++) + retval.push_front(rand()); + return retval; +} + +std::list +ListUser::createComplexList(Complex cpx0, Complex cpx1) +{ + std::list retval; + retval.push_back(cpx0); + retval.push_back(cpx1); + return retval; +} + +double +ListUser::sumList(std::list vallist) +{ + return std::accumulate(vallist.begin(), vallist.end(), 0.0); +} + +double +ListUser::sumList(std::list vallist) +{ + return std::accumulate(vallist.begin(), vallist.end(), 0.0); +} + +ListUser::ListOfSomething +ListUser::listOfPoints(const std::list& pointlist) +{ + return ListOfPoint; +} + +ListUser::ListOfSomething +ListUser::listOfPoints(const std::list& pointlist) +{ + return ListOfPointF; +} + +void +ListUser::multiplyPointList(PointList& points, double multiplier) +{ + for(PointList::iterator piter = points.begin(); piter != points.end(); piter++) { + (*piter)->setX((*piter)->x() * multiplier); + (*piter)->setY((*piter)->y() * multiplier); + } +} + diff --git a/sources/shiboken2/tests/libsample/listuser.h b/sources/shiboken2/tests/libsample/listuser.h new file mode 100644 index 000000000..8f49c80d3 --- /dev/null +++ b/sources/shiboken2/tests/libsample/listuser.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LISTUSER_H +#define LISTUSER_H + +#include +#include "complex.h" +#include "point.h" +#include "pointf.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API ListUser +{ +public: + typedef std::list PointList; + + enum ListOfSomething { + ListOfPoint, + ListOfPointF + }; + + ListUser() {} + ListUser(const ListUser& other) : m_lst(other.m_lst) {} + virtual ~ListUser() {} + + virtual std::list createList(); + std::list callCreateList(); + + static std::list createComplexList(Complex cpx0, Complex cpx1); + + double sumList(std::list vallist); + double sumList(std::list vallist); + + static ListOfSomething listOfPoints(const std::list& pointlist); + static ListOfSomething listOfPoints(const std::list& pointlist); + + static void multiplyPointList(PointList& points, double multiplier); + + inline void setList(std::list lst) { m_lst = lst; } + inline std::list getList() { return m_lst; } + +private: + std::list m_lst; +}; + +#endif // LISTUSER_H + diff --git a/sources/shiboken2/tests/libsample/main.cpp b/sources/shiboken2/tests/libsample/main.cpp new file mode 100644 index 000000000..b22d05a36 --- /dev/null +++ b/sources/shiboken2/tests/libsample/main.cpp @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include "abstract.h" +#include "derived.h" +#include "kindergarten.h" +#include "complex.h" +#include "point.h" +#include "size.h" +#include "listuser.h" +#include "samplenamespace.h" + +using namespace std; + +int +main(int argv, char **argc) +{ + cout << endl; + + Derived derived; + + cout << endl; + + derived.unpureVirtual(); + derived.pureVirtual(); + derived.callPureVirtual(); + + cout << endl; + Abstract* abs; + abs = Abstract::createObject(); + cout << "Abstract::createObject(): " << abs << endl << endl; + delete abs; + + abs = Derived::createObject(); + cout << "Derived::createObject() : "; + abs->show(); + cout << endl; + delete abs; + cout << endl; + + abs = Derived::createObject(); + cout << "Derived::createObject() : "; + abs->show(); + cout << endl; + delete abs; + cout << endl; + + cout << endl << "-----------------------------------------" << endl; + + KinderGarten kg; + Derived* d[] = { 0, 0, 0 }; + + for (int i = 0; i < 3; i++) { + d[i] = new Derived(i); + d[i]->show(); + cout << endl; + kg.addChild(d[i]); + } + + kg.show(); + cout << endl; + + cout << endl << "* kill child "; + d[2]->show(); + cout << " ----------------" << endl; + kg.killChild(d[2]); + kg.show(); + cout << endl; + + cout << endl << "* release child "; + d[1]->show(); + cout << " -------------" << endl; + Abstract* released = kg.releaseChild(d[1]); + cout << "released: "; + released->show(); + cout << endl; + kg.show(); + cout << endl; + + cout << endl << "* kill children ------------------------------------" << endl; + kg.killChildren(); + kg.show(); + cout << endl << endl; + + cout << "-----------------------------------------" << endl; + ListUser lu; + cout << "ListUser::createList()" << endl; + std::list intlist = lu.createList(); + for (std::list::iterator it = intlist.begin(); it != intlist.end(); it++) { + cout << "* " << *it << endl; + } + + cout << "ListUser::createComplexList" << endl; + std::list cpxlist = ListUser::createComplexList(Complex(1.1, 2.2), Complex(3.3, 4.4)); + for (std::list::iterator it = cpxlist.begin(); it != cpxlist.end(); it++) { + cout << "* "; + (*it).show(); + cout << 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; + double val_d = 1.3; + cout << "SampleNamespace::powerOfTwo(" << val_d << "): "; + cout << SampleNamespace::powerOfTwo(val_d) << endl; + int val_i = 7; + cout << "SampleNamespace::powerOfTwo(" << val_i << "): "; + cout << SampleNamespace::powerOfTwo(val_i) << endl; + cout << endl; + + cout << "-----------------------------------------" << endl; + cout << "Point" << endl; + + Point p1(1.1, 2.2); + cout << "p1: "; + p1.show(); + cout << endl; + + Point p2(3.4, 5.6); + cout << "p2: "; + p2.show(); + cout << endl; + + cout << "p1 + p2 == "; + (p1 + p2).show(); + cout << endl; + + cout << "p1 * 2.0 == "; + (p1 * 2.0).show(); + cout << endl; + + cout << "1.5 * p2 == "; + (1.5 * p2).show(); + cout << endl; + + cout << "p1: "; + p1.show(); + cout << endl << "p2: "; + p2.show(); + cout << endl << "p1 += p2" << endl; + p1 += p2; + cout << "p1: "; + p1.show(); + cout << 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; + + cout << "-----------------------------------------" << endl; + cout << "Size" << endl; + + Size s1(2, 2); + cout << "s1: "; + s1.show(); + cout << ", area: " << s1.calculateArea(); + cout << endl; + + Size s2(3, 5); + 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: "; + s1.show(); + cout << endl << "s2: "; + s2.show(); + cout << endl << "s1 += s2" << endl; + s1 += s2; + cout << "s1: "; + s1.show(); + cout << endl; + + cout << endl; + + cout << "s1: "; + s1.show(); + cout << endl << "s1 *= 2.0" << endl; + s1 *= 2.0; + cout << "s1: "; + s1.show(); + cout << endl; + + cout << endl; + + return 0; +} + diff --git a/sources/shiboken2/tests/libsample/mapuser.cpp b/sources/shiboken2/tests/libsample/mapuser.cpp new file mode 100644 index 000000000..666188512 --- /dev/null +++ b/sources/shiboken2/tests/libsample/mapuser.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "mapuser.h" + +using namespace std; + +std::map > +MapUser::callCreateMap() +{ + return createMap(); +} + + +std::map > +MapUser::createMap() +{ + std::map > retval; + + std::pair > + item0("zero", std::pair(Complex(1.2, 3.4), 2)); + retval.insert(item0); + + std::pair > + item1("one", std::pair(Complex(5.6, 7.8), 3)); + retval.insert(item1); + + std::pair > + item2("two", std::pair(Complex(9.1, 2.3), 5)); + retval.insert(item2); + + return retval; +} + +void +MapUser::showMap(std::map mapping) +{ + std::map::iterator it; + cout << __FUNCTION__ << endl; + for (it = mapping.begin() ; it != mapping.end(); it++) + cout << (*it).first << " => " << (*it).second << endl; +} + diff --git a/sources/shiboken2/tests/libsample/mapuser.h b/sources/shiboken2/tests/libsample/mapuser.h new file mode 100644 index 000000000..90d036945 --- /dev/null +++ b/sources/shiboken2/tests/libsample/mapuser.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAPUSER_H +#define MAPUSER_H + +#include +#include +#include +#include +#include "complex.h" +#include "bytearray.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API MapUser +{ +public: + MapUser() {} + virtual ~MapUser() {} + + virtual std::map > createMap(); + std::map > callCreateMap(); + + void showMap(std::map mapping); + + inline void setMap(std::map > map) { m_map = map; } + inline std::map > getMap() { return m_map; } + + // Compile test + static void pointerToMap(std::map* arg) {} + static void referenceToMap(std::map& arg) {} + + inline const std::map& passMapIntValueType(const std::map& arg) { return arg; } + +private: + std::map > m_map; +}; + +#endif // MAPUSER_H diff --git a/sources/shiboken2/tests/libsample/modelindex.h b/sources/shiboken2/tests/libsample/modelindex.h new file mode 100644 index 000000000..12cc97ce4 --- /dev/null +++ b/sources/shiboken2/tests/libsample/modelindex.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#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; } + inline void setValue(int value) { m_value = value; } + inline int value() const { return m_value; } + static int getValue(const ModelIndex& index) { return index.value(); } +private: + int m_value; +}; + +class ReferentModelIndex +{ +public: + ReferentModelIndex() {} + ReferentModelIndex(const ModelIndex& index) : m_index(index) {} + ReferentModelIndex(const ReferentModelIndex& other) { m_index = other.m_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; +}; + +class PersistentModelIndex +{ +public: + PersistentModelIndex() {} + PersistentModelIndex(const ModelIndex& index) : m_index(index) {} + PersistentModelIndex(const PersistentModelIndex& other) { m_index = other.m_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 diff --git a/sources/shiboken2/tests/libsample/modifications.cpp b/sources/shiboken2/tests/libsample/modifications.cpp new file mode 100644 index 000000000..4a60a8071 --- /dev/null +++ b/sources/shiboken2/tests/libsample/modifications.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "modifications.h" +#include "objecttype.h" + +using namespace std; + +Modifications::Modifications() +{ + m_object = new ObjectType(); + m_object->setObjectName("MyObject"); +} + +Modifications::~Modifications() +{ + delete m_object; +} + +std::pair +Modifications::pointToPair(Point pt, bool* ok) +{ + std::pair retval(pt.x(), pt.y()); + *ok = true; + return retval; +} + +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) +{ + return (2 * value) + plus; +} + +int +Modifications::power(int base, int exponent) +{ + if (exponent == 0) + return 1; + int retval = base; + for (int i = 1; i < exponent; i++) + retval = retval * base; + return retval; +} + +int +Modifications::timesTen(int number) +{ + return number * 10; +} + +int +Modifications::increment(int number) +{ + return ++number; +} + +void +Modifications::exclusiveCppStuff() +{ + cout << __FUNCTION__ << endl; +} + +int +Modifications::cppMultiply(int a, int b) +{ + return a * b; +} + +const char* +Modifications::className() +{ + return "Modifications"; +} + +Point +Modifications::sumPointArray(int arraySize, const Point pointArray[]) +{ + Point point; + for (int i = 0; i < arraySize; ++i) + point = point + pointArray[i]; + return point; +} + +int +Modifications::getSize(const void* data, int size) +{ + (void)data; + return size; +} + +int +Modifications::sumPointCoordinates(const Point* point) +{ + return point->x() + point->y(); +} + +double +Modifications::differenceOfPointCoordinates(const Point* pt, bool* ok) +{ + if (!pt) { + *ok = false; + return 0.0; + } + *ok = true; + double result = pt->x() - pt->y(); + if (result < 0) + result = result * -1.0; + return result; +} + +bool +Modifications::nonConversionRuleForArgumentWithDefaultValue(ObjectType** object) +{ + if (object) + *object = m_object; + return true; +} diff --git a/sources/shiboken2/tests/libsample/modifications.h b/sources/shiboken2/tests/libsample/modifications.h new file mode 100644 index 000000000..2978270b0 --- /dev/null +++ b/sources/shiboken2/tests/libsample/modifications.h @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MODIFICATIONS_H +#define MODIFICATIONS_H + +#include "libsamplemacros.h" +#include +#include "point.h" +#include "oddbool.h" + +class ObjectType; + +class LIBSAMPLE_API Modifications +{ +public: + Modifications(); + virtual ~Modifications(); + + enum OverloadedModFunc { + OverloadedNone, + Overloaded_ibid, + Overloaded_ibib, + Overloaded_ibiP, + Overloaded_ibii, + Overloaded_ibPP + }; + + // 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; } + + inline void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456) {} + inline 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) {} + + inline 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) {} + + inline 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) {} + + // '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 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); + + // completely remove 'plus' from the Python side + int doublePlus(int value, int plus = 0); + + // the default value for both arguments must be changed in Python + int power(int base = 1, int exponent = 0); + + // in Python set argument default value to 10 + int timesTen(int number); + + // in Python remove the argument default value + int increment(int number = 0); + + // don't export this method to Python + void exclusiveCppStuff(); + + // change the name of this regular method + int cppMultiply(int a, int b); + + // change the name of this virtual method + virtual const char* className(); + + Point sumPointArray(int arraySize, const Point pointArray[]); + + // Replace 'const void*' by 'ByteArray&'. + int getSize(const void* data, int size); + + // Mark the argument with a tag; + // the test implementation must expect point never to be null. + 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); } + + // Sets an ObjectType in the argument and returns true. + bool nonConversionRuleForArgumentWithDefaultValue(ObjectType** object = 0); + 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; } + +private: + ObjectType* m_object; +}; + +class LIBSAMPLE_API AbstractModifications : public Modifications +{ +public: + AbstractModifications() {} + virtual ~AbstractModifications() {} + + inline bool invert(bool value) { return !value; } + + // completely remove this method in Python + virtual void pointlessPureVirtualMethod() = 0; +}; + +#endif // MODIFICATIONS_H diff --git a/sources/shiboken2/tests/libsample/modified_constructor.cpp b/sources/shiboken2/tests/libsample/modified_constructor.cpp new file mode 100644 index 000000000..48224358f --- /dev/null +++ b/sources/shiboken2/tests/libsample/modified_constructor.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "modified_constructor.h" + +ModifiedConstructor::ModifiedConstructor(int first_arg) +{ + m_stored_value = first_arg; +} + +int +ModifiedConstructor::retrieveValue() +{ + return m_stored_value; +} + + diff --git a/sources/shiboken2/tests/libsample/modified_constructor.h b/sources/shiboken2/tests/libsample/modified_constructor.h new file mode 100644 index 000000000..9ac5497d7 --- /dev/null +++ b/sources/shiboken2/tests/libsample/modified_constructor.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MODIFIEDCONSTRUCTOR_H +#define MODIFIEDCONSTRUCTOR_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API ModifiedConstructor +{ +public: + + ModifiedConstructor(int first_arg); + int retrieveValue(); + +private: + int m_stored_value; +}; + +#endif // MODIFIEDCONSTRUCTOR_H + diff --git a/sources/shiboken2/tests/libsample/multiple_derived.cpp b/sources/shiboken2/tests/libsample/multiple_derived.cpp new file mode 100644 index 000000000..1d7a33cbe --- /dev/null +++ b/sources/shiboken2/tests/libsample/multiple_derived.cpp @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "multiple_derived.h" + +MDerived1::MDerived1() : m_value(100) +{ +} + +MDerived2::MDerived2() : m_value(200) +{ +} + +MDerived3::MDerived3() : m_value(3000) +{ +} + +MDerived4::MDerived4() +{ +} + +MDerived5::MDerived5() +{ +} + +MDerived1* +MDerived1::transformFromBase1(Base1* self) +{ + MDerived1* ptr = dynamic_cast(self); + return ptr; +} + +MDerived1* +MDerived1::transformFromBase2(Base2* self) +{ + MDerived1* ptr = dynamic_cast(self); + return ptr; +} + diff --git a/sources/shiboken2/tests/libsample/multiple_derived.h b/sources/shiboken2/tests/libsample/multiple_derived.h new file mode 100644 index 000000000..5825e59b4 --- /dev/null +++ b/sources/shiboken2/tests/libsample/multiple_derived.h @@ -0,0 +1,195 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MDERIVED_H +#define MDERIVED_H + +#include "libsamplemacros.h" +#include + +class Base1 +{ +public: + Base1() : m_value(1) {} + virtual ~Base1() {} + virtual int base1Method() { return m_value; } + + virtual void publicMethod() {}; +private: + int m_value; +}; + +class Base2 +{ +public: + Base2() : m_value(2) {} + virtual ~Base2() {} + virtual int base2Method() { return m_value; } +private: + int m_value; +}; + +class LIBSAMPLE_API MDerived1 : public Base1, public Base2 +{ +public: + MDerived1(); + virtual ~MDerived1() {} + + virtual int mderived1Method() { return m_value; } + virtual int base1Method() { return Base1::base1Method() * 10; } + virtual int base2Method() { return Base2::base2Method() * 10; } + + inline Base1* castToBase1() { return (Base1*) this; } + inline Base2* castToBase2() { return (Base2*) this; } + + static MDerived1* transformFromBase1(Base1 *self); + static MDerived1* transformFromBase2(Base2 *self); + +private: + virtual void publicMethod() {} + int m_value; +}; + +class SonOfMDerived1 : public MDerived1 +{ +public: + SonOfMDerived1() : m_value(0) {} + ~SonOfMDerived1() {} + + inline MDerived1* castToMDerived1() { return (MDerived1*) this; } + + int sonOfMDerived1Method() { return m_value; } +private: + int m_value; +}; + +class Base3 +{ +public: + explicit Base3(int val = 3) : m_value(val) {} + virtual ~Base3() {} + int base3Method() { return m_value; } +private: + int m_value; +}; + +class Base4 +{ +public: + Base4() : m_value(4) {} + virtual ~Base4() {} + int base4Method() { return m_value; } +private: + int m_value; +}; + +class Base5 +{ +public: + Base5() : m_value(5) {} + virtual ~Base5() {} + virtual int base5Method() { return m_value; } +private: + int m_value; +}; + +class Base6 +{ +public: + Base6() : m_value(6) {} + virtual ~Base6() {} + virtual int base6Method() { return m_value; } +private: + int m_value; +}; + + +class LIBSAMPLE_API MDerived2 : public Base3, public Base4, public Base5, public Base6 +{ +public: + MDerived2(); + virtual ~MDerived2() {} + + 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; } + +private: + int m_value; +}; + +class LIBSAMPLE_API MDerived3 : public MDerived1, public MDerived2 +{ +public: + MDerived3(); + virtual ~MDerived3() {} + + inline virtual int mderived3Method() { return m_value; } + + inline MDerived1* castToMDerived1() { return (MDerived1*) this; } + inline MDerived2* castToMDerived2() { return (MDerived2*) this; } + + inline Base3* castToBase3() { return (Base3*) this; } + +private: + int m_value; +}; + +class LIBSAMPLE_API MDerived4 : public Base3, public Base4 +{ +public: + MDerived4(); + ~MDerived4() {} + + inline int mderived4Method() { return 0; } + inline int justDummyMethod() { return m_value; } + + inline Base3* castToBase3() { return (Base3*) this; } + inline Base4* castToBase4() { return (Base4*) this; } +private: + int m_value; +}; + +class LIBSAMPLE_API MDerived5 : public Base3, public Base4 +{ +public: + MDerived5(); + virtual ~MDerived5() {} + + virtual int mderived5Method() { return 0; } + + inline Base3* castToBase3() { return (Base3*) this; } + inline Base4* castToBase4() { return (Base4*) this; } +}; + +#endif // MDERIVED_H + diff --git a/sources/shiboken2/tests/libsample/noimplicitconversion.h b/sources/shiboken2/tests/libsample/noimplicitconversion.h new file mode 100644 index 000000000..0a8882d3a --- /dev/null +++ b/sources/shiboken2/tests/libsample/noimplicitconversion.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NOIMPLICITCONVERSION_H +#define NOIMPLICITCONVERSION_H + +#include "libsamplemacros.h" + +// This class must not have implicit conversions AND +// no conversion operators should be defined in its own module. +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; } +private: + int m_objId; +}; + +#endif // NOIMPLICITCONVERSION_H + diff --git a/sources/shiboken2/tests/libsample/nondefaultctor.h b/sources/shiboken2/tests/libsample/nondefaultctor.h new file mode 100644 index 000000000..d2b186bd8 --- /dev/null +++ b/sources/shiboken2/tests/libsample/nondefaultctor.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NONDEFAULTCTOR_H +#define NONDEFAULTCTOR_H + +#include "libsamplemacros.h" + +class NonDefaultCtor +{ + int m_value; +public: + NonDefaultCtor(int value) : m_value(value) + { + } + + inline int value() + { + return m_value; + } + + inline NonDefaultCtor returnMyself() + { + return *this; + } + + inline NonDefaultCtor returnMyself(int) + { + return *this; + } + + inline NonDefaultCtor returnMyself(int, NonDefaultCtor) + { + return *this; + } + + virtual NonDefaultCtor returnMyselfVirtual() + { + return *this; + } + + inline NonDefaultCtor callReturnMyselfVirtual() + { + return returnMyselfVirtual(); + } + + virtual ~NonDefaultCtor() {} +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/null.h b/sources/shiboken2/tests/libsample/null.h new file mode 100644 index 000000000..634262a99 --- /dev/null +++ b/sources/shiboken2/tests/libsample/null.h @@ -0,0 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NULL_H +#define NULL_H + +class Null +{ +public: + Null(bool value) : m_isNull(value) {} + Null() : m_isNull(false) {} + void setIsNull(bool flag) { m_isNull = flag; } + +private: + bool m_isNull; +}; + +#endif // STR_H + diff --git a/sources/shiboken2/tests/libsample/objectmodel.cpp b/sources/shiboken2/tests/libsample/objectmodel.cpp new file mode 100644 index 000000000..370b58aa1 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objectmodel.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objectmodel.h" + +void +ObjectModel::setData(ObjectType* data) +{ + m_data = data; +} + +ObjectType* +ObjectModel::data() const +{ + return m_data; +} + diff --git a/sources/shiboken2/tests/libsample/objectmodel.h b/sources/shiboken2/tests/libsample/objectmodel.h new file mode 100644 index 000000000..aa4a64433 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objectmodel.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTMODEL_H +#define OBJECTMODEL_H + +#include "objecttype.h" +#include "libsamplemacros.h" + +class LIBSAMPLE_API ObjectModel : public ObjectType +{ +public: + explicit ObjectModel(ObjectType* parent = 0) + : ObjectType(parent), m_data(0) + {} + + 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; } + +private: + // The model holds only one piece of data. + // (This is just a test after all.) + ObjectType* m_data; +}; + +#endif // OBJECTMODEL_H + diff --git a/sources/shiboken2/tests/libsample/objecttype.cpp b/sources/shiboken2/tests/libsample/objecttype.cpp new file mode 100644 index 000000000..4f10b01df --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttype.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objecttype.h" +#include "objecttypelayout.h" +#include +#include +#include +#include + +using namespace std; + +ObjectType::ObjectType(ObjectType* parent) : m_parent(0), m_layout(0), m_call_id(-1) +{ + setParent(parent); +} + +ObjectType::~ObjectType() +{ + for (ObjectTypeList::iterator child_iter = m_children.begin(); + child_iter != m_children.end(); ++child_iter) + delete *child_iter; +} + +ObjectType* +ObjectType::createWithChild() +{ + ObjectType* parent = create(); + ObjectType* child = create(); + child->setObjectName("child"); + child->setParent(parent); + return parent; +} + +void +ObjectType::removeChild(ObjectType* child) +{ + if (!child) + return; + + ObjectTypeList::iterator child_iter = std::find(m_children.begin(), m_children.end(), child); + if (child_iter != m_children.end()) { + m_children.erase(child_iter); + child->m_parent = 0; + } +} + +ObjectType* +ObjectType::takeChild(ObjectType* child) +{ + if (!child) + return 0; + + ObjectTypeList::iterator child_iter = std::find(m_children.begin(), m_children.end(), child); + if (child_iter != m_children.end()) { + m_children.erase(child_iter); + child->m_parent = 0; + return child; + } + return 0; +} + +ObjectType* +ObjectType::takeChild(const Str& name) +{ + return takeChild(findChild(name)); + +} + +ObjectType* +ObjectType::findChild(const Str& name) +{ + for (ObjectTypeList::iterator child_iter = m_children.begin(); + child_iter != m_children.end(); ++child_iter) { + + if ((*child_iter)->objectName() == name) + return *child_iter; + } + return 0; +} + +void +ObjectType::killChild(const Str& name) +{ + for (ObjectTypeList::iterator child_iter = m_children.begin(); + child_iter != m_children.end(); ++child_iter) { + + if ((*child_iter)->objectName() == name) { + ObjectType* child = *child_iter; + removeChild(child); + delete child; + break; + } + } +} + +void +ObjectType::setParent(ObjectType* parent) +{ + if (m_parent == parent) + return; + + if (m_parent) + m_parent->removeChild(this); + + m_parent = parent; + if (m_parent) + m_parent->m_children.push_back(this); +} + +void +ObjectType::setObjectName(const Str& name) +{ + m_objectName = name; +} + +Str +ObjectType::objectName() const +{ + return m_objectName; +} + +bool +ObjectType::causeEvent(Event::EventType eventType) +{ + Event e(eventType); + return event(&e); +} + +bool +ObjectType::event(Event* event) +{ + return true; +} + +int +ObjectType::processEvent(ObjectTypeList objects, Event *event) +{ + int evaluated = 0; + + for (ObjectTypeList::iterator obj_iter = objects.begin(); + obj_iter != objects.end(); ++obj_iter) { + if((*obj_iter)->event(event)) + evaluated++; + } + + return evaluated; + +} + +void +ObjectType::callInvalidateEvent(Event* event) +{ + invalidateEvent(event); +} + +void +ObjectType::setLayout(ObjectTypeLayout* l) +{ + if (!l) { + cerr << "[WARNING] ObjectType::setLayout: Cannot set layout to 0." << endl; + 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; + } + return; + } + + 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; + return; + } else { + // Steal the layout from an ObjectType parent. + oldParent->takeLayout(); + } + } + + m_layout = l; + if (oldParent != this) { + l->setParent(this); + l->reparentChildren(this); + } +} + +ObjectTypeLayout* ObjectType::takeLayout() +{ + ObjectTypeLayout* l = layout(); + if (!l) + return 0; + m_layout = 0; + l->setParent(0); + return l; +} + +unsigned int +objectTypeHash(const ObjectType* objectType) +{ + return reinterpret_cast(objectType); +} + +unsigned char +ObjectType::callWithEnum(const Str& prefix, Event::EventType type, unsigned char value){ + return value*value; +} + +unsigned char +ObjectType::callWithEnum(const Str& prefix, unsigned char value) { + return value; +} + +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) +{ + std::string result(name.cstring(), size); + m_objectName = result.c_str(); +} + +void +ObjectType::setObjectNameWithSize(const Str& name, int size) +{ + setObjectNameWithSize("", size, name); +} + +void ObjectType::setObject(ObjectType *) +{ + m_call_id = 0; +} + +void ObjectType::setObject(const Null&) +{ + m_call_id = 1; +} + +int ObjectType::callId() const +{ + return m_call_id; +} + + +void ObjectType::callVirtualCreateChild() +{ + ObjectType* fake_parent = new ObjectType(); + ObjectType* fake_child = createChild(fake_parent); + assert(fake_child->isPython()); + delete fake_parent; +} + +ObjectType* ObjectType::createChild(ObjectType* parent) +{ + return new ObjectType(parent); +} + +std::size_t ObjectType::createObjectType() +{ + void* addr = new ObjectType(); + return (std::size_t) addr; +} + +OtherBase::~OtherBase() +{ +} + +ObjectTypeDerived::~ObjectTypeDerived() +{ +} + +bool +ObjectTypeDerived::event(Event* event) +{ + return true; +} diff --git a/sources/shiboken2/tests/libsample/objecttype.h b/sources/shiboken2/tests/libsample/objecttype.h new file mode 100644 index 000000000..eae95b3b1 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttype.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTTYPE_H +#define OBJECTTYPE_H + +#include +#include "str.h" +#include "null.h" + +#include "libsamplemacros.h" + +#include + +struct Event +{ + enum EventType { + NO_EVENT, + BASIC_EVENT, + SOME_EVENT, + ANY_EVENT + }; + Event(EventType eventType) : m_eventType(eventType) {} + EventType eventType() { return m_eventType; } +private: + EventType m_eventType; +}; + +class ObjectTypeLayout; +class ObjectType; +typedef std::list ObjectTypeList; + +class LIBSAMPLE_API ObjectType +{ +public: + // ### Fixme: Use uintptr_t in C++ 11 + typedef size_t Identifier; + + explicit ObjectType(ObjectType* parent = 0); + virtual ~ObjectType(); + + // factory method + 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); + + inline Identifier identifier() const { return reinterpret_cast(this); } + + bool causeEvent(Event::EventType eventType); + + // Returns true if the event is processed. + virtual bool event(Event* event); + static int processEvent(ObjectTypeList objects, 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; } + + // 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); + + //Functions used in test with named arguments + void setObjectSplittedName(const char*, const Str& prefix = Str("")); + void setObjectNameWithSize(const char*, int size=9, const Str& name = Str("")); + void setObjectNameWithSize(const Str& name = Str(""), int size=9); + + //Function used to confuse the generator when two values accept Null as arg + void setObject(ObjectType *); + 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); + static std::size_t createObjectType(); + + //return a parent from C++ + ObjectType* getCppParent() { + if (!m_parent) { + ObjectType* parent = new ObjectType(); + setParent(parent); + } + return m_parent; + } + + void destroyCppParent() { + delete m_parent; + m_parent = 0; + } + + //Deprecated test + bool deprecatedFunction() { return true; } + + // 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; } + +private: + ObjectType(const ObjectType&); + ObjectType& operator=(const ObjectType&); + + ObjectTypeLayout* takeLayout(); + + Str m_objectName; + ObjectType* m_parent; + ObjectTypeList m_children; + + ObjectTypeLayout* m_layout; + + + //used on overload null test + int m_call_id; +}; + +LIBSAMPLE_API unsigned int objectTypeHash(const ObjectType* objectType); + +class LIBSAMPLE_API OtherBase { +public: + OtherBase() {}; + virtual ~OtherBase(); +}; + +class LIBSAMPLE_API ObjectTypeDerived: public ObjectType, public OtherBase { +public: + ObjectTypeDerived(): ObjectType(), OtherBase() {}; + + virtual bool event(Event* event); + virtual ~ObjectTypeDerived(); +}; + +#endif // OBJECTTYPE_H + diff --git a/sources/shiboken2/tests/libsample/objecttypebyvalue.h b/sources/shiboken2/tests/libsample/objecttypebyvalue.h new file mode 100644 index 000000000..1b61ec4dc --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypebyvalue.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTTYPEBYVALUE_H +#define OBJECTTYPEBYVALUE_H +#include +#include "protected.h" + +class ObjectTypeByValue +{ +public: + ObjectTypeByValue returnSomeKindOfMe() { return ObjectTypeByValue(); } + void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe) {} + + void acceptListOfObjectTypeByValue(std::list listOfMe) {} + + // prop used to check for segfaults + ProtectedProperty prop; +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/objecttypeholder.cpp b/sources/shiboken2/tests/libsample/objecttypeholder.cpp new file mode 100644 index 000000000..dabeb2f86 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypeholder.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objecttypeholder.h" + +ObjectTypeHolder::ObjectTypeHolder(const char* objectName) +{ + m_objectType = new ObjectType(); + m_objectType->setObjectName(objectName); +} + +ObjectTypeHolder::~ObjectTypeHolder() +{ + delete m_objectType; +} + +Str +ObjectTypeHolder::passObjectTypeAsReference(const ObjectType& objectType) +{ + return objectType.objectName(); +} + +Str +ObjectTypeHolder::callPassObjectTypeAsReference() +{ + return passObjectTypeAsReference(*m_objectType); +} diff --git a/sources/shiboken2/tests/libsample/objecttypeholder.h b/sources/shiboken2/tests/libsample/objecttypeholder.h new file mode 100644 index 000000000..c2e7275d4 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypeholder.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTTYPEHOLDER_H +#define OBJECTTYPEHOLDER_H + +#include "libsamplemacros.h" +#include "objecttype.h" +#include "str.h" + +class LIBSAMPLE_API ObjectTypeHolder +{ +public: + explicit ObjectTypeHolder(const char* objectName); + virtual ~ObjectTypeHolder(); + + ObjectType* getObjecType() { return m_objectType; } + + virtual Str passObjectTypeAsReference(const ObjectType& objectType); + Str callPassObjectTypeAsReference(); + +private: + ObjectType* m_objectType; +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/objecttypelayout.cpp b/sources/shiboken2/tests/libsample/objecttypelayout.cpp new file mode 100644 index 000000000..d2a7d1bba --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypelayout.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objecttypelayout.h" +#include + +using namespace std; + +void ObjectTypeLayout::addObject(ObjectType* obj) +{ + if (obj->isLayoutType()) { + ObjectTypeLayout* l = reinterpret_cast(obj); + if (l->parent()) { + cerr << "[WARNING] ObjectTypeLayout::addObject: layout '" << l->objectName().cstring(); + cerr << "' already has a parent." << endl; + return; + } + + l->setParent(this); + + if (parent() && !parent()->isLayoutType()) + l->reparentChildren(parent()); + } + + m_objects.push_back(obj); +} + +std::list< ObjectType* > ObjectTypeLayout::objects() const +{ + return m_objects; +} + +void ObjectTypeLayout::reparentChildren(ObjectType* parent) +{ + std::list::const_iterator it = m_objects.begin(); + for (; it != m_objects.end(); ++it) { + if ((*it)->isLayoutType()) + reinterpret_cast(*it)->reparentChildren(parent); + else + (*it)->setParent(parent); + } +} + diff --git a/sources/shiboken2/tests/libsample/objecttypelayout.h b/sources/shiboken2/tests/libsample/objecttypelayout.h new file mode 100644 index 000000000..3fa8b9dbf --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypelayout.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTTYPELAYOUT_H +#define OBJECTTYPELAYOUT_H + +#include "libsamplemacros.h" +#include "objecttype.h" +#include + +class ObjectType; + +class LIBSAMPLE_API ObjectTypeLayout : public ObjectType +{ +public: + void addObject(ObjectType* obj); + std::list objects() const; + + virtual bool isLayoutType() { return true; } + inline static ObjectTypeLayout* create() { return new ObjectTypeLayout(); } + + virtual ObjectType* takeChild(const Str& name) { return ObjectType::takeChild(name); } +private: + std::list m_objects; + + void reparentChildren(ObjectType* parent); + friend LIBSAMPLE_API void ObjectType::setLayout(ObjectTypeLayout* l); +}; + +#endif // OBJECTTYPELAYOUT_H + diff --git a/sources/shiboken2/tests/libsample/objecttypeoperators.cpp b/sources/shiboken2/tests/libsample/objecttypeoperators.cpp new file mode 100644 index 000000000..1bdaded30 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypeoperators.cpp @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objecttypeoperators.h" + +ObjectTypeOperators::ObjectTypeOperators(const std::string key) : m_key(key) +{ +} + +bool ObjectTypeOperators::operator==(const ObjectTypeOperators& other) const +{ + return m_key == other.m_key; +} + +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) +{ + return obj->key() == str; +} + +bool operator==(const std::string& str, const ObjectTypeOperators* obj) +{ + return str == obj->key(); +} + +std::string operator+(const ObjectTypeOperators* obj, const std::string& str) +{ + return obj->key() + str; +} + +std::string operator+(const std::string& str, const ObjectTypeOperators* obj) +{ + return str + obj->key(); +} diff --git a/sources/shiboken2/tests/libsample/objecttypeoperators.h b/sources/shiboken2/tests/libsample/objecttypeoperators.h new file mode 100644 index 000000000..5795ac456 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objecttypeoperators.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTTYPEOPERATORS_H +#define OBJECTTYPEOPERATORS_H + +#include "libsamplemacros.h" +#include + +class LIBSAMPLE_API ObjectTypeOperators +{ +public: + explicit ObjectTypeOperators(const std::string key); + virtual ~ObjectTypeOperators() {} + + bool operator==(const ObjectTypeOperators& other) const; + const ObjectTypeOperators& operator<(const ObjectTypeOperators& other) const; + + // chaos! + 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); + +#endif // OBJECTTYPEOPERATORS_H diff --git a/sources/shiboken2/tests/libsample/objectview.cpp b/sources/shiboken2/tests/libsample/objectview.cpp new file mode 100644 index 000000000..08c5f45f6 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objectview.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "objectview.h" +#include "objectmodel.h" +#include "str.h" + +Str +ObjectView::displayModelData() +{ + if (!m_model) + return Str("(NULL)"); + return Str("Name: %VAR").arg(m_model->objectName()); +} + +void +ObjectView::modifyModelData(Str& data) +{ + if (m_model) + m_model->setObjectName(data); +} + + +ObjectType* +ObjectView::getRawModelData() +{ + return m_model->data(); +} + diff --git a/sources/shiboken2/tests/libsample/objectview.h b/sources/shiboken2/tests/libsample/objectview.h new file mode 100644 index 000000000..0bcc09a30 --- /dev/null +++ b/sources/shiboken2/tests/libsample/objectview.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OBJECTVIEW_H +#define OBJECTVIEW_H + +#include "objecttype.h" +#include "libsamplemacros.h" + +class Str; +class ObjectModel; + +class LIBSAMPLE_API ObjectView : public ObjectType +{ +public: + ObjectView(ObjectModel* model = 0, ObjectType* parent = 0) + : ObjectType(parent), m_model(model) + {} + + inline void setModel(ObjectModel* model) { m_model = model; } + inline ObjectModel* model() const { return m_model; } + + Str displayModelData(); + void modifyModelData(Str& data); + + ObjectType* getRawModelData(); + +private: + ObjectModel* m_model; +}; + +#endif // OBJECTVIEW_H + diff --git a/sources/shiboken2/tests/libsample/oddbool.h b/sources/shiboken2/tests/libsample/oddbool.h new file mode 100644 index 000000000..ee0f4fa03 --- /dev/null +++ b/sources/shiboken2/tests/libsample/oddbool.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ODDBOOL_H +#define ODDBOOL_H + +#include "libsamplemacros.h" + +class OddBool +{ + +public: + inline explicit OddBool(bool b) : m_value(b) {} + bool value() const { return m_value; } + + inline OddBool operator!() const { return OddBool(!m_value); } + +private: + bool m_value; +}; + +inline bool operator==(OddBool b1, bool b2) { return (!b1).value() == !b2; } +inline bool operator==(bool b1, OddBool b2) { return (!b1) == (!b2).value(); } +inline bool operator==(OddBool b1, OddBool b2) { return (!b1).value() == (!b2).value(); } +inline bool operator!=(OddBool b1, bool b2) { return (!b1).value() != !b2; } +inline bool operator!=(bool b1, OddBool b2) { return (!b1) != (!b2).value(); } +inline bool operator!=(OddBool b1, OddBool b2) { return (!b1).value() != (!b2).value(); } + +class OddBoolUser +{ +public: + OddBoolUser() : m_oddbool(OddBool(false)) {} + OddBoolUser(const OddBool& oddBool) : m_oddbool(oddBool) {} + virtual ~OddBoolUser() {} + + inline OddBool oddBool() { return m_oddbool; } + inline void setOddBool(OddBool oddBool) { m_oddbool = oddBool; } + + virtual OddBool invertedOddBool() + { + return !m_oddbool; + } + + inline OddBool callInvertedOddBool() + { + return invertedOddBool(); + } + + static inline OddBool getOddBool(const OddBoolUser& oddBoolUser) + { + return oddBoolUser.m_oddbool; + } + +private: + OddBool m_oddbool; +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/onlycopy.cpp b/sources/shiboken2/tests/libsample/onlycopy.cpp new file mode 100644 index 000000000..5407f9d33 --- /dev/null +++ b/sources/shiboken2/tests/libsample/onlycopy.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "onlycopy.h" + +OnlyCopy::OnlyCopy(const OnlyCopy& other) +{ + m_value = other.m_value; +} + +OnlyCopy& +OnlyCopy::operator=(const OnlyCopy& other) +{ + m_value = other.m_value; + return *this; +} + +OnlyCopy +FriendOfOnlyCopy::createOnlyCopy(int value) +{ + + return OnlyCopy(value); +} + +std::list +FriendOfOnlyCopy::createListOfOnlyCopy(int quantity) +{ + std::list list; + for (int i = 0; i < quantity; ++i) + list.push_back(createOnlyCopy(i)); + return list; +} diff --git a/sources/shiboken2/tests/libsample/onlycopy.h b/sources/shiboken2/tests/libsample/onlycopy.h new file mode 100644 index 000000000..6abad7382 --- /dev/null +++ b/sources/shiboken2/tests/libsample/onlycopy.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ONLYCOPYCLASS_H +#define ONLYCOPYCLASS_H + +#include "libsamplemacros.h" +#include + +// These classes simulate a situation found in +// QtWebKit's QWebDatabase and QWebSecurityOrigin. + +class LIBSAMPLE_API OnlyCopy +{ +public: + OnlyCopy(const OnlyCopy& other); + OnlyCopy& operator=(const OnlyCopy& other); + int value() const { return m_value; } + static int getValue(OnlyCopy onlyCopy) { return onlyCopy.m_value; } + static int getValueFromReference(const OnlyCopy& onlyCopy) { return onlyCopy.m_value; } +private: + int m_value; + OnlyCopy(int value) : m_value(value) {}; + friend class FriendOfOnlyCopy; +}; + +class LIBSAMPLE_API FriendOfOnlyCopy +{ +public: + static OnlyCopy createOnlyCopy(int value); + static std::list createListOfOnlyCopy(int quantity); +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/overload.cpp b/sources/shiboken2/tests/libsample/overload.cpp new file mode 100644 index 000000000..753407e35 --- /dev/null +++ b/sources/shiboken2/tests/libsample/overload.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "overload.h" + +Overload::FunctionEnum Overload::overloaded() +{ + return Function0; +} + +Overload::FunctionEnum Overload::overloaded(Size* size) +{ + return Function1; +} + +Overload::FunctionEnum Overload::overloaded(Point* point, ParamEnum param) +{ + return Function2; +} + +Overload::FunctionEnum Overload::overloaded(const Point& point) +{ + return Function3; +} + diff --git a/sources/shiboken2/tests/libsample/overload.h b/sources/shiboken2/tests/libsample/overload.h new file mode 100644 index 000000000..5005b4f8c --- /dev/null +++ b/sources/shiboken2/tests/libsample/overload.h @@ -0,0 +1,143 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OVERLOAD_H +#define OVERLOAD_H + +#include "echo.h" +#include "str.h" +#include "size.h" +#include "point.h" +#include "pointf.h" +#include "polygon.h" +#include "rect.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Overload +{ +public: + enum FunctionEnum { + Function0, + Function1, + Function2, + Function3, + Function4, + Function5, + Function6 + }; + + enum ParamEnum { + Param0, + Param1 + }; + + Overload() {} + virtual ~Overload() {} + + FunctionEnum overloaded(); + 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; } + + 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; } + + inline FunctionEnum intDoubleOverloads(int a0, int a1) const { return Function0; } + inline FunctionEnum intDoubleOverloads(double a0, double a1) const { return Function1; } + + 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; } + + // Similar to QImage constructor + FunctionEnum strBufferOverloads(const Str& arg0, const char* arg1 = 0, bool arg2 = true) { return Function0; } + FunctionEnum strBufferOverloads(unsigned char* arg0, int arg1) { return Function1; } + 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; } + + // 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; } + + // 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; } + + // 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 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; } + // The type must be changed to PySequence. + FunctionEnum acceptSequence(const char* const a0[]) { return Function4; } + FunctionEnum acceptSequence(void* a0) { return Function5; } +}; + +class LIBSAMPLE_API Overload2 : public Overload +{ +public: + // test bug#616, public and private method differ only by const + void doNothingInPublic() const {} + void doNothingInPublic(int) {} + virtual void doNothingInPublic3() const {} + void doNothingInPublic3(int) const {} +protected: + void doNothingInPublic2() const {} + void doNothingInPublic2(int) {} +private: + void doNothingInPublic() {} + void doNothingInPublic2() {} + void doNothingInPublic3() {} +}; + +#endif // OVERLOAD_H + diff --git a/sources/shiboken2/tests/libsample/overloadsort.cpp b/sources/shiboken2/tests/libsample/overloadsort.cpp new file mode 100644 index 000000000..f1bc9665b --- /dev/null +++ b/sources/shiboken2/tests/libsample/overloadsort.cpp @@ -0,0 +1,30 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "overloadsort.h" + diff --git a/sources/shiboken2/tests/libsample/overloadsort.h b/sources/shiboken2/tests/libsample/overloadsort.h new file mode 100644 index 000000000..9145504ae --- /dev/null +++ b/sources/shiboken2/tests/libsample/overloadsort.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef OVERLOADSORT_H +#define OVERLOADSORT_H + +#include "libsamplemacros.h" + +#include + +class ImplicitTarget +{ +public: + ImplicitTarget(){} +}; + +class ImplicitBase +{ +public: + ImplicitBase(){} + ImplicitBase(const ImplicitTarget &b){} +}; + +class SortedOverload +{ +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 &x) { + return "list(ImplicitBase)"; + } + + inline int implicit_overload(const ImplicitBase &x) { + return 1; + } + + inline const char *overloadDeep(int x, ImplicitBase &y) { + return "ImplicitBase"; + } + + + inline const char* pyObjOverload(int, int) { return "int,int"; } + inline const char* pyObjOverload(unsigned char*, int) { return "PyObject,int"; } + +}; + +#endif // OVERLOADSORT_H + diff --git a/sources/shiboken2/tests/libsample/pairuser.cpp b/sources/shiboken2/tests/libsample/pairuser.cpp new file mode 100644 index 000000000..b4b51b8cf --- /dev/null +++ b/sources/shiboken2/tests/libsample/pairuser.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "pairuser.h" + +using namespace std; + +std::pair +PairUser::callCreatePair() +{ + return createPair(); +} + +std::pair +PairUser::createPair() +{ + return std::pair(10, 20); +} + +std::pair +PairUser::createComplexPair(Complex cpx0, Complex cpx1) +{ + return std::pair(cpx0, cpx1); +} + +double +PairUser::sumPair(std::pair pair) +{ + return ((double) pair.first) + pair.second; +} + diff --git a/sources/shiboken2/tests/libsample/pairuser.h b/sources/shiboken2/tests/libsample/pairuser.h new file mode 100644 index 000000000..7b87ba65b --- /dev/null +++ b/sources/shiboken2/tests/libsample/pairuser.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PAIRUSER_H +#define PAIRUSER_H + +#include +#include "complex.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API PairUser +{ +public: + PairUser() {} + virtual ~PairUser() {} + + virtual std::pair createPair(); + std::pair callCreatePair(); + static std::pair createComplexPair(Complex cpx0, Complex cpx1); + double sumPair(std::pair pair); + + inline void setPair(std::pair pair) { m_pair = pair; } + inline std::pair getPair() { return m_pair; } + +private: + std::pair m_pair; +}; +#endif // PAIRUSER_H + diff --git a/sources/shiboken2/tests/libsample/pen.cpp b/sources/shiboken2/tests/libsample/pen.cpp new file mode 100644 index 000000000..509b47c76 --- /dev/null +++ b/sources/shiboken2/tests/libsample/pen.cpp @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "pen.h" + +Color::Color() : m_null(true) +{ +} + +Color::Color(SampleNamespace::InValue arg) : m_null(false) +{ +} + +Color::Color(unsigned int arg) : m_null(false) +{ +} + +bool Color::isNull() const +{ + return m_null; +} + +Pen::Pen() : m_ctor(EmptyCtor) +{ +} + +Pen::Pen(SampleNamespace::Option option) : m_ctor(EnumCtor) +{ +} + +Pen::Pen(const Color& color) : m_ctor(ColorCtor) +{ +} + +Pen::Pen(const Pen& pen) : m_ctor(CopyCtor) +{ +} + +int Pen::ctorType() +{ + return m_ctor; +} diff --git a/sources/shiboken2/tests/libsample/pen.h b/sources/shiboken2/tests/libsample/pen.h new file mode 100644 index 000000000..e1fb641d3 --- /dev/null +++ b/sources/shiboken2/tests/libsample/pen.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PEN_H +#define PEN_H + +#include "libsamplemacros.h" +#include "samplenamespace.h" + +class LIBSAMPLE_API Color +{ +public: + Color(); + Color(SampleNamespace::InValue arg); + Color(unsigned int arg); + + bool isNull() const; +private: + bool m_null; +}; + +class LIBSAMPLE_API Pen +{ +public: + enum { EmptyCtor, EnumCtor, ColorCtor, CopyCtor }; + + Pen(); + Pen(SampleNamespace::Option option); + Pen(const Color& color); + Pen(const Pen& pen); + + int ctorType(); +private: + int m_ctor; +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/photon.cpp b/sources/shiboken2/tests/libsample/photon.cpp new file mode 100644 index 000000000..debc9f116 --- /dev/null +++ b/sources/shiboken2/tests/libsample/photon.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "photon.h" + +namespace Photon +{ +const ClassType Base::staticType; +int callCalculateForValueDuplicatorPointer(ValueDuplicator* value) +{ + return value->calculate(); +} +int callCalculateForValueDuplicatorReference(ValueDuplicator& value) +{ + return value.calculate(); +} +int countValueIdentities(const std::list& values) +{ + return values.size(); +} +int countValueDuplicators(const std::list >& values) +{ + return values.size(); +} +} // namespace Photon diff --git a/sources/shiboken2/tests/libsample/photon.h b/sources/shiboken2/tests/libsample/photon.h new file mode 100644 index 000000000..d8b1be423 --- /dev/null +++ b/sources/shiboken2/tests/libsample/photon.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PHOTON_H +#define PHOTON_H + +#include +#include "libsamplemacros.h" + +// This namespace and classes simulate +// situations found in Qt's phonon module. + +namespace Photon +{ + +enum ClassType { + BaseType = 0, + IdentityType = 1, + DuplicatorType = 2 +}; + +class LIBSAMPLE_API Base +{ +public: + explicit Base(int value) : m_value(value) {} + virtual ~Base() {} + inline void setValue(int value) { m_value = value; } + inline int value() const { return m_value; } + + template bool isType() { return type() == T::staticType; } + bool isType(ClassType t) { return type() == t; } + + virtual ClassType type() const { return BaseType; }; + static const ClassType staticType = BaseType; + +protected: + int m_value; +}; + +template +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); } + static inline ClassType classType() { return CLASS_TYPE; } + + inline int sumValueUsingPointer(TemplateBase* other) const { return m_value + other->m_value; } + inline int sumValueUsingReference(TemplateBase& other) const { return m_value + other.m_value; } + + inline std::list > getListOfThisTemplateBase() + { + std::list > objs; + objs.push_back(*this); + objs.push_back(*this); + return objs; + } + + static inline TemplateBase* passPointerThrough(TemplateBase* obj) { return obj; } + + virtual ClassType type() const { return CLASS_TYPE; } + static const ClassType staticType = CLASS_TYPE; +}; + +#if defined _WIN32 || defined __CYGWIN__ +template class LIBSAMPLE_API TemplateBase; +template class LIBSAMPLE_API TemplateBase; +#endif + +typedef TemplateBase ValueIdentity; +typedef TemplateBase ValueDuplicator; + +LIBSAMPLE_API int callCalculateForValueDuplicatorPointer(ValueDuplicator* value); +LIBSAMPLE_API int callCalculateForValueDuplicatorReference(ValueDuplicator& value); +LIBSAMPLE_API int countValueIdentities(const std::list& values); +LIBSAMPLE_API int countValueDuplicators(const std::list >& 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 +class Pointer +{ +public: + Pointer() PHOTON_NOEXCEPT : px(0) {} + Pointer(int* p) : px(p) {} + + void reset() PHOTON_NOEXCEPT { Pointer().swap(*this); } + + int* get() const PHOTON_NOEXCEPT { return px; } + int& operator*() const { return *px; } + + void swap(Pointer& rhs) PHOTON_NOEXCEPT + { + int* tmp = px; + px = rhs.px; + rhs.px = tmp; + } + +private: + int* px; +}; + +} // namespace Photon + +#endif // PHOTON_H diff --git a/sources/shiboken2/tests/libsample/point.cpp b/sources/shiboken2/tests/libsample/point.cpp new file mode 100644 index 000000000..30275393b --- /dev/null +++ b/sources/shiboken2/tests/libsample/point.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "point.h" + +using namespace std; + +Point::Point(int x, int y) : m_x(x), m_y(y) +{ +} + +Point::Point(double x, double y) : m_x(x), m_y(y) +{ +} + +void +Point::midpoint(const Point& other, Point* midpoint) const +{ + if (!midpoint) + return; + midpoint->setX((m_x + other.m_x) / 2.0); + midpoint->setY((m_y + other.m_y) / 2.0); +} + +Point* +Point::copy() const +{ + Point* pt = new Point(); + pt->m_x = m_x; + pt->m_y = m_y; + return pt; +} + +void +Point::show() +{ + cout << "(x: " << m_x << ", y: " << m_y << ")"; +} + +bool +Point::operator==(const Point& other) +{ + return m_x == other.m_x && m_y == other.m_y; +} + +Point +Point::operator+(const Point& other) +{ + return Point(m_x + other.m_x, m_y + other.m_y); +} + +Point +Point::operator-(const Point& other) +{ + return Point(m_x - other.m_x, m_y - other.m_y); +} + +Point& +Point::operator+=(Point &other) +{ + m_x += other.m_x; + m_y += other.m_y; + return *this; +} + +Point& +Point::operator-=(Point &other) +{ + m_x -= other.m_x; + m_y -= other.m_y; + return *this; +} + +Point +operator*(const Point& pt, double mult) +{ + return Point(pt.m_x * mult, pt.m_y * mult); +} + +Point +operator*(const Point& pt, int mult) +{ + return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +Point +operator*(double mult, const Point& pt) +{ + return Point(pt.m_x * mult, pt.m_y * mult); +} + +Point +operator*(int mult, const Point& pt) +{ + return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +Point +operator-(const Point& pt) +{ + return Point(-pt.m_x, -pt.m_y); +} + +bool +operator!(const Point& pt) +{ + return (pt.m_x == 0.0 && pt.m_y == 0.0); +} + +Point +Point::operator/(int operand) +{ + return Point(m_x/operand, m_y/operand); +} + +Complex +transmutePointIntoComplex(const Point& point) +{ + Complex cpx(point.x(), point.y()); + return cpx; +} + +Point +transmuteComplexIntoPoint(const Complex& cpx) +{ + Point pt(cpx.real(), cpx.imag()); + return pt; +} + diff --git a/sources/shiboken2/tests/libsample/point.h b/sources/shiboken2/tests/libsample/point.h new file mode 100644 index 000000000..9416d6ddf --- /dev/null +++ b/sources/shiboken2/tests/libsample/point.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POINT_H +#define POINT_H + +#include "complex.h" +#include + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Point +{ +public: + Point(int x = 0, int y = 0); + Point(double x, double y); + ~Point() {} + + inline double x() const { return m_x; } + inline double y() const { return m_y; } + + inline void setX(double x) { m_x = x; } + inline void setY(double y) { m_y = y; } + inline void setXAsUint(unsigned int x) { m_x = x; } + inline void setYAsUint(unsigned int y) { m_y = y; } + + // 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; + + Point* copy() const; + + 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); + + 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); + + Point& operator+=(Point &other); + Point& operator-=(Point &other); + + void show(); + +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 Complex transmutePointIntoComplex(const Point& point); +LIBSAMPLE_API Point transmuteComplexIntoPoint(const Complex& cpx); + +LIBSAMPLE_API Point operator*(const Point& pt, double multiplier); + +#endif // POINT_H diff --git a/sources/shiboken2/tests/libsample/pointerholder.h b/sources/shiboken2/tests/libsample/pointerholder.h new file mode 100644 index 000000000..84e709d38 --- /dev/null +++ b/sources/shiboken2/tests/libsample/pointerholder.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POINTERHOLDER_H +#define POINTERHOLDER_H + +#include "libsamplemacros.h" + +class PointerHolder +{ +public: + explicit PointerHolder(void* ptr) : m_pointer(ptr) {} + ~PointerHolder() {} + inline void* pointer() const { return m_pointer; } +private: + void* m_pointer; +}; + +#endif // POINTERHOLDER_H + diff --git a/sources/shiboken2/tests/libsample/pointf.cpp b/sources/shiboken2/tests/libsample/pointf.cpp new file mode 100644 index 000000000..0719bdb87 --- /dev/null +++ b/sources/shiboken2/tests/libsample/pointf.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "pointf.h" + +using namespace std; + +PointF::PointF(const Point& point) : m_x(point.x()), m_y(point.y()) +{ +} + +PointF::PointF(double x, double y) : m_x(x), m_y(y) +{ +} + +void +PointF::midpoint(const PointF& other, PointF* midpoint) const +{ + if (!midpoint) + return; + midpoint->setX((m_x + other.m_x) / 2.0); + midpoint->setY((m_y + other.m_y) / 2.0); +} + +void +PointF::show() +{ + cout << "(x: " << m_x << ", y: " << m_y << ")"; +} + +bool +PointF::operator==(const PointF& other) +{ + return m_x == other.m_x && m_y == other.m_y; +} + +PointF +PointF::operator+(const PointF& other) +{ + return PointF(m_x + other.m_x, m_y + other.m_y); +} + +PointF +PointF::operator-(const PointF& other) +{ + return PointF(m_x - other.m_x, m_y - other.m_y); +} + +PointF& +PointF::operator+=(PointF &other) +{ + m_x += other.m_x; + m_y += other.m_y; + return *this; +} + +PointF& +PointF::operator-=(PointF &other) +{ + m_x -= other.m_x; + m_y -= other.m_y; + return *this; +} + +PointF +operator*(const PointF& pt, double mult) +{ + return PointF(pt.m_x * mult, pt.m_y * mult); +} + +PointF +operator*(const PointF& pt, int mult) +{ + return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +PointF +operator*(double mult, const PointF& pt) +{ + return PointF(pt.m_x * mult, pt.m_y * mult); +} + +PointF +operator*(int mult, const PointF& pt) +{ + return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +PointF +operator-(const PointF& pt) +{ + return PointF(-pt.m_x, -pt.m_y); +} + +bool +operator!(const PointF& pt) +{ + return (pt.m_x == 0.0 && pt.m_y == 0.0); +} + diff --git a/sources/shiboken2/tests/libsample/pointf.h b/sources/shiboken2/tests/libsample/pointf.h new file mode 100644 index 000000000..c80739fea --- /dev/null +++ b/sources/shiboken2/tests/libsample/pointf.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POINTF_H +#define POINTF_H + +#include "point.h" +#include + +#include "libsamplemacros.h" + +class LIBSAMPLE_API PointF +{ +public: + PointF(const Point& point); + PointF(double x = 0.0, double y = 0.0); + ~PointF() {} + + inline double x() const { return m_x; } + inline double y() const { return m_y; } + + inline void setX(double x) { m_x = x; } + inline void setY(double y) { m_y = y; } + + // 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; + + // 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); + + 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); + + PointF& operator+=(PointF &other); + PointF& operator-=(PointF &other); + + void show(); + +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 multiplier); + +#endif // POINTF_H diff --git a/sources/shiboken2/tests/libsample/polygon.cpp b/sources/shiboken2/tests/libsample/polygon.cpp new file mode 100644 index 000000000..cb553a75c --- /dev/null +++ b/sources/shiboken2/tests/libsample/polygon.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "polygon.h" + +using namespace std; + +Polygon::Polygon(double x, double y) +{ + m_points.push_back(Point(x, y)); +} + +Polygon::Polygon(Point point) +{ + m_points.push_back(point); +} + +Polygon::Polygon(PointList points) +{ + m_points = points; +} + +void +Polygon::addPoint(Point point) +{ + m_points.push_back(point); +} + +Polygon +Polygon::doublePolygonScale(Polygon polygon) +{ + Polygon result; + for(PointList::const_iterator piter = result.points().begin(); piter != result.points().end(); piter++) + result.addPoint((*piter) * 2.0); + return result; +} + +void +Polygon::stealOwnershipFromPython(Point* point) +{ + delete point; +} + +void +Polygon::stealOwnershipFromPython(Polygon* polygon) +{ + delete polygon; +} + diff --git a/sources/shiboken2/tests/libsample/polygon.h b/sources/shiboken2/tests/libsample/polygon.h new file mode 100644 index 000000000..5e0769e0f --- /dev/null +++ b/sources/shiboken2/tests/libsample/polygon.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef POLYGON_H +#define POLYGON_H + +#include +#include "point.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Polygon +{ +public: + typedef std::list PointList; + + Polygon() {} + Polygon(double x, double y); + Polygon(Point point); + Polygon(PointList points); + ~Polygon() {} + + void addPoint(Point point); + + 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); + + // This method invalidates the argument to be used in a call to doublePolygonScale(Polygon). + static void stealOwnershipFromPython(Polygon* polygon); + +private: + PointList m_points; +}; + +#endif // POLYGON_H + diff --git a/sources/shiboken2/tests/libsample/privatector.h b/sources/shiboken2/tests/libsample/privatector.h new file mode 100644 index 000000000..4f4699761 --- /dev/null +++ b/sources/shiboken2/tests/libsample/privatector.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PRIVATECTOR_H +#define PRIVATECTOR_H + +#include "libsamplemacros.h" + +class PrivateCtor +{ +public: + inline static PrivateCtor* instance() + { + static PrivateCtor self; + self.m_instanciations++; + return &self; + } + + inline int instanceCalls() + { + return m_instanciations; + } + +private: + int m_instanciations; + + PrivateCtor() : m_instanciations(0) {} +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/privatedtor.h b/sources/shiboken2/tests/libsample/privatedtor.h new file mode 100644 index 000000000..a0c4d4769 --- /dev/null +++ b/sources/shiboken2/tests/libsample/privatedtor.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PRIVATEDTOR_H +#define PRIVATEDTOR_H + +#include "libsamplemacros.h" + +class PrivateDtor +{ +public: + inline static PrivateDtor* instance() + { + static PrivateDtor self; + self.m_instanciations++; + return &self; + } + + inline int instanceCalls() + { + return m_instanciations; + } + +protected: + inline int protectedInstanceCalls() { return m_instanciations; } + +private: + int m_instanciations; + + PrivateDtor() : m_instanciations(0) {} + PrivateDtor(const PrivateDtor&) {} + ~PrivateDtor() {} +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/protected.cpp b/sources/shiboken2/tests/libsample/protected.cpp new file mode 100644 index 000000000..08c9fd065 --- /dev/null +++ b/sources/shiboken2/tests/libsample/protected.cpp @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "protected.h" + +int ProtectedVirtualDestructor::dtor_called = 0; + diff --git a/sources/shiboken2/tests/libsample/protected.h b/sources/shiboken2/tests/libsample/protected.h new file mode 100644 index 000000000..c33bdf4b2 --- /dev/null +++ b/sources/shiboken2/tests/libsample/protected.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef PROTECTED_H +#define PROTECTED_H + +#include "libsamplemacros.h" +#include "objecttype.h" +#include "point.h" +#include +#include + +class LIBSAMPLE_API ProtectedNonPolymorphic +{ +public: + explicit ProtectedNonPolymorphic(const char *name) : m_name(name) {} + ~ProtectedNonPolymorphic() {} + + inline const char* publicName() { return m_name.c_str(); } + + inline static ProtectedNonPolymorphic* create() { return new ProtectedNonPolymorphic("created"); } + +protected: + 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 = 0) const { return "pointer"; } + inline const char* dataTypeName(int data) const { return "integer"; } + +private: + std::string m_name; +}; + +class LIBSAMPLE_API ProtectedPolymorphic +{ +public: + explicit ProtectedPolymorphic(const char *name) : m_name(name) {} + virtual ~ProtectedPolymorphic() {} + + 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(); } + +private: + std::string m_name; +}; + +class LIBSAMPLE_API ProtectedPolymorphicDaughter : public ProtectedPolymorphic +{ +public: + 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"); } +}; + +class LIBSAMPLE_API ProtectedVirtualDestructor +{ +public: + ProtectedVirtualDestructor() {} + inline static ProtectedVirtualDestructor* create() { return new ProtectedVirtualDestructor(); } + inline static int dtorCalled() { return dtor_called; } + inline static void resetDtorCounter() { dtor_called = 0; } +protected: + virtual ~ProtectedVirtualDestructor() { dtor_called++; } +private: + static int dtor_called; +}; + +class LIBSAMPLE_API ProtectedEnumClass +{ +public: + ProtectedEnumClass() {} + virtual ~ProtectedEnumClass() {} + enum PublicEnum { + PublicItem0, + PublicItem1 + }; +protected: + enum ProtectedEnum { + ProtectedItem0, + ProtectedItem1 + }; + 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(0), + protectedObjectTypeProperty(0) + {} +protected: + // This is deliberately the first member to test wrapper registration + // for value type members sharing the same memory address. + Point protectedValueTypeProperty; + int protectedProperty; + std::list protectedContainerProperty; + Event::EventType protectedEnumProperty; + Point* protectedValueTypePointerProperty; + ObjectType* protectedObjectTypeProperty; +}; + +LIBSAMPLE_API inline ProtectedProperty* createProtectedProperty() { + return new ProtectedProperty; +} + +#endif // PROTECTED_H diff --git a/sources/shiboken2/tests/libsample/rect.h b/sources/shiboken2/tests/libsample/rect.h new file mode 100644 index 000000000..b7ce6e890 --- /dev/null +++ b/sources/shiboken2/tests/libsample/rect.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef RECT_H +#define RECT_H + +#include "libsamplemacros.h" + +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) + : m_left(left), m_top(top), m_right(right), m_bottom(bottom) { } + ~Rect() {} + 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; +}; + +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) + : 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() {} + 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; +}; + +#endif // RECT_H + diff --git a/sources/shiboken2/tests/libsample/reference.cpp b/sources/shiboken2/tests/libsample/reference.cpp new file mode 100644 index 000000000..31a11a8ae --- /dev/null +++ b/sources/shiboken2/tests/libsample/reference.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "reference.h" + +using namespace std; + +void +Reference::show() const +{ + cout << "Reference.objId: " << m_objId << ", address: " << this; +} + +int +Reference::usesReferenceVirtual(Reference& r, int inc) +{ + return r.m_objId + inc; +} + +int +Reference::usesConstReferenceVirtual(const Reference& r, int inc) +{ + return r.m_objId + inc; +} + +int +Reference::callUsesReferenceVirtual(Reference& r, int inc) +{ + return usesReferenceVirtual(r, inc); +} + +int +Reference::callUsesConstReferenceVirtual(const Reference& r, int inc) +{ + return usesConstReferenceVirtual(r, inc); +} + +void +Reference::alterReferenceIdVirtual(Reference& r) +{ + r.setObjId(r.objId() * Reference::multiplier()); +} + +void +Reference::callAlterReferenceIdVirtual(Reference& r) +{ + alterReferenceIdVirtual(r); +} + +ObjTypeReference::~ObjTypeReference() +{ +} diff --git a/sources/shiboken2/tests/libsample/reference.h b/sources/shiboken2/tests/libsample/reference.h new file mode 100644 index 000000000..4ec8ee7fd --- /dev/null +++ b/sources/shiboken2/tests/libsample/reference.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef REFERENCE_H +#define REFERENCE_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Reference +{ +public: + explicit Reference(int objId = -1) + : m_objId(objId) {} + virtual ~Reference() {} + + inline int objId() { 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; } + + 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); + + 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; } + + // nonsense operator to test if Shiboken is ignoring dereference operators. + int operator*() { return m_objId; } +private: + int m_objId; +}; + +class LIBSAMPLE_API ObjTypeReference +{ +public: + ObjTypeReference() {} + ObjTypeReference(const ObjTypeReference&) {} + virtual ~ObjTypeReference(); + virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; } + virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; } + virtual ObjTypeReference& justAPureVirtualFunc(ObjTypeReference& ref) = 0; +}; + +#endif // REFERENCE_H + diff --git a/sources/shiboken2/tests/libsample/removednamespaces.h b/sources/shiboken2/tests/libsample/removednamespaces.h new file mode 100644 index 000000000..4520b6a27 --- /dev/null +++ b/sources/shiboken2/tests/libsample/removednamespaces.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef REMOVEDNAMESPACE_H +#define REMOVEDNAMESPACE_H + +#include "libsamplemacros.h" + +namespace RemovedNamespace1 +{ + +enum RemovedNamespace1_Enum { + RemovedNamespace1_Enum_Value0 +}; + +enum { + RemovedNamespace1_AnonymousEnum_Value0 +}; + +namespace RemovedNamespace2 { + enum RemovedNamespace2_Enum { + RemovedNamespace2_Enum_Value0 + }; +} + +} + +namespace UnremovedNamespace +{ +namespace RemovedNamespace3 +{ + enum RemovedNamespace3_Enum { + RemovedNamespace3_Enum_Value0 + }; + + enum { + RemovedNamespace3_AnonymousEnum_Value0 + }; +} +} + +#endif // REMOVEDNAMESPACE_H + diff --git a/sources/shiboken2/tests/libsample/sample.cpp b/sources/shiboken2/tests/libsample/sample.cpp new file mode 100644 index 000000000..fa1e1fda3 --- /dev/null +++ b/sources/shiboken2/tests/libsample/sample.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sample.h" + +sample::sample::sample(int value) : m_value(value) +{ +} + +int sample::sample::value() const +{ + return m_value; +} + diff --git a/sources/shiboken2/tests/libsample/sample.h b/sources/shiboken2/tests/libsample/sample.h new file mode 100644 index 000000000..46e3d0d1a --- /dev/null +++ b/sources/shiboken2/tests/libsample/sample.h @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SAMPLE_H +#define SAMPLE_H + +#include "libsamplemacros.h" + +// namespace with the same name of the current package to try to mess up with the generator +namespace sample +{ + // to increase the mess we add a class with the same name of the package/namespace + class LIBSAMPLE_API sample + { + public: + sample(int value = 0); + int value() const; + private: + int m_value; + }; +} + +#endif diff --git a/sources/shiboken2/tests/libsample/samplenamespace.cpp b/sources/shiboken2/tests/libsample/samplenamespace.cpp new file mode 100644 index 000000000..1fc6dff40 --- /dev/null +++ b/sources/shiboken2/tests/libsample/samplenamespace.cpp @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "samplenamespace.h" + +using namespace std; + +namespace SampleNamespace +{ + +OutValue +enumInEnumOut(InValue in) +{ + OutValue retval; + switch(in) { + case ZeroIn: + retval = ZeroOut; + break; + case OneIn: + retval = OneOut; + break; + case TwoIn: + retval = TwoOut; + break; + default: + retval = (OutValue) -1; + } + return retval; +} + +Option +enumArgumentWithDefaultValue(Option opt) +{ + return opt; +} + +int +getNumber(Option opt) +{ + int retval; + switch(opt) { + case RandomNumber: + retval = rand() % 100; + break; + case UnixTime: + retval = (int) time(0); + break; + default: + retval = 0; + } + return retval; +} + +void +doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format) +{ + // 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) +{ + return value; +} + +void +forceDecisorSideA(ObjectType* object) +{ +} + +void +forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object) +{ +} + +void +forceDecisorSideB(int a, ObjectType* object) +{ +} + +void +forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object) +{ +} + +double +passReferenceToValueType(const Point& point, double multiplier) +{ + return (point.x() + point.y()) * multiplier; +} + +int +passReferenceToObjectType(const ObjectType& obj, int multiplier) +{ + return obj.objectName().size() * multiplier; +} + +} // namespace SampleNamespace diff --git a/sources/shiboken2/tests/libsample/samplenamespace.h b/sources/shiboken2/tests/libsample/samplenamespace.h new file mode 100644 index 000000000..3ce410941 --- /dev/null +++ b/sources/shiboken2/tests/libsample/samplenamespace.h @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SAMPLENAMESPACE_H +#define SAMPLENAMESPACE_H + +#include +#include "libsamplemacros.h" +#include "str.h" +#include "point.h" +#include "objecttype.h" + +// Anonymous global enum +enum { + AnonymousGlobalEnum_Value0, + AnonymousGlobalEnum_Value1 +}; + +// Invisible namespace +namespace Invisible +{ + +enum EnumOnNamespace { + Option1 = 1, + Option2 = 2, + Option3 = 3 +}; + +}; + +namespace SampleNamespace +{ + +enum Option { + None_, + RandomNumber, + UnixTime +}; + +enum InValue { + ZeroIn, + OneIn, + TwoIn +}; + +enum OutValue { + ZeroOut, + OneOut, + TwoOut +}; + +// Anonymous non-global enum. +// This counts as a class enum, since C++ namespaces +// are represented as classes in Python. +enum { + AnonymousClassEnum_Value0, + AnonymousClassEnum_Value1 +}; + +LIBSAMPLE_API OutValue enumInEnumOut(InValue in); + +LIBSAMPLE_API Option enumArgumentWithDefaultValue(Option opt = UnixTime); + +LIBSAMPLE_API int getNumber(Option opt); + +inline double powerOfTwo(double num) { + return num * num; +} + +LIBSAMPLE_API void doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format = 0); + +LIBSAMPLE_API int enumItemAsDefaultValueToIntArgument(int value = ZeroIn); + +class SomeClass +{ +public: + class SomeInnerClass + { + public: + class OkThisIsRecursiveEnough + { + public: + virtual ~OkThisIsRecursiveEnough() {} + enum NiceEnum { + NiceValue1, NiceValue2 + }; + + inline int someMethod(SomeInnerClass*) { return 0; } + virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } + }; + protected: + enum ProtectedEnum { + ProtectedItem0, + ProtectedItem1 + }; + }; + struct SomeOtherInnerClass { + std::list someInnerClasses; + }; +protected: + enum ProtectedEnum { + ProtectedItem0, + ProtectedItem1 + }; +}; + +class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough +{ +public: + // FIXME Uncomment this when the fix for MSVC is available + // only to cause namespace confusion +// enum SampleNamespace { +// }; + virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } + inline OkThisIsRecursiveEnough* methodReturningTypeFromParentScope() { return 0; } +}; + +// 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 = 0); +LIBSAMPLE_API void forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object = 0); + +// 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 = 0); +LIBSAMPLE_API void forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object = 0); + +// Add a new signature on type system with only a Point value as parameter. +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); + +} // namespace SampleNamespace + +#endif // SAMPLENAMESPACE_H + diff --git a/sources/shiboken2/tests/libsample/sbkdate.cpp b/sources/shiboken2/tests/libsample/sbkdate.cpp new file mode 100644 index 000000000..e823521ec --- /dev/null +++ b/sources/shiboken2/tests/libsample/sbkdate.cpp @@ -0,0 +1,48 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sbkdate.h" + +SbkDate::SbkDate(int d, int m, int y) : m_d(d), m_m(m), m_y(y) +{ +} + +int SbkDate::day() const +{ + return m_d; +} + +int SbkDate::month() const +{ + return m_m; +} + +int SbkDate::year() const +{ + return m_y; +} diff --git a/sources/shiboken2/tests/libsample/sbkdate.h b/sources/shiboken2/tests/libsample/sbkdate.h new file mode 100644 index 000000000..7d0893cbb --- /dev/null +++ b/sources/shiboken2/tests/libsample/sbkdate.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SBKDATE_H +#define SBKDATE_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API SbkDate +{ +public: + SbkDate(int d, int m, int y); + + int day() const; + int month() const; + int year() const; + +private: + int m_d; + int m_m; + int m_y; +}; + +#endif // SBKDATE_H + diff --git a/sources/shiboken2/tests/libsample/simplefile.cpp b/sources/shiboken2/tests/libsample/simplefile.cpp new file mode 100644 index 000000000..bdbd3d1f5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/simplefile.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include "simplefile.h" + +class SimpleFile_p +{ +public: + SimpleFile_p(const char* filename) : m_descriptor(0), m_size(0) + { + m_filename = strdup(filename); + } + + ~SimpleFile_p() + { + free(m_filename); + } + + char* m_filename; + FILE* m_descriptor; + long m_size; +}; + +SimpleFile::SimpleFile(const char* filename) +{ + p = new SimpleFile_p(filename); +} + +SimpleFile::~SimpleFile() +{ + close(); + delete p; +} + +const char* SimpleFile::filename() +{ + return p->m_filename; +} + +long SimpleFile::size() +{ + return p->m_size; +} + +bool +SimpleFile::open() +{ + if ((p->m_descriptor = fopen(p->m_filename, "rb")) == 0) + return false; + + fseek(p->m_descriptor, 0, SEEK_END); + p->m_size = ftell(p->m_descriptor); + rewind(p->m_descriptor); + + return true; +} + +void +SimpleFile::close() +{ + if (p->m_descriptor) { + fclose(p->m_descriptor); + p->m_descriptor = 0; + } +} + +bool +SimpleFile::exists() const +{ + std::ifstream ifile(p->m_filename); + return !ifile.fail(); +} + +bool +SimpleFile::exists(const char* filename) +{ + std::ifstream ifile(filename); + return !ifile.fail(); +} + diff --git a/sources/shiboken2/tests/libsample/simplefile.h b/sources/shiboken2/tests/libsample/simplefile.h new file mode 100644 index 000000000..bae3b9998 --- /dev/null +++ b/sources/shiboken2/tests/libsample/simplefile.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SIMPLEFILE_H +#define SIMPLEFILE_H + +#include "libsamplemacros.h" +#include + +class SimpleFile_p; + +class LIBSAMPLE_API SimpleFile +{ +public: + explicit SimpleFile(const char* filename); + ~SimpleFile(); + + const char* filename(); + long size(); + bool open(); + void close(); + + bool exists() const; + static bool exists(const char* filename); + +private: + SimpleFile_p *p; +}; + +#endif // SIMPLEFILE_H + diff --git a/sources/shiboken2/tests/libsample/size.cpp b/sources/shiboken2/tests/libsample/size.cpp new file mode 100644 index 000000000..1faf5dfb2 --- /dev/null +++ b/sources/shiboken2/tests/libsample/size.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "size.h" + +using namespace std; + +void +Size::show() const +{ + cout << "(width: " << m_width << ", height: " << m_height << ")"; +} + diff --git a/sources/shiboken2/tests/libsample/size.h b/sources/shiboken2/tests/libsample/size.h new file mode 100644 index 000000000..433aba770 --- /dev/null +++ b/sources/shiboken2/tests/libsample/size.h @@ -0,0 +1,206 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SIZE_H +#define SIZE_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Size +{ +public: + Size(double width = 0.0, double height = 0.0) : m_width(width), m_height(height) {} + ~Size() {} + + inline double width() { return m_width; } + inline void setWidth(double width) { m_width = width; } + inline double height() { 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) + { + return m_width == other.m_width && m_height == other.m_height; + } + + inline bool operator<(const Size& other) + { + return calculateArea() < other.calculateArea(); + } + + 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 + // simplify comparison expressions by putting partial results in + // variables. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c109 + // for details. + double a = calculateArea(); + double b = other.calculateArea(); + return a > b; + } + + inline bool operator<=(const Size& other) + { + // See comments for operator>() + double a = calculateArea(); + double b = other.calculateArea(); + return a <= b; + } + + inline bool operator>=(const Size& other) + { + return calculateArea() >= other.calculateArea(); + } + + inline bool operator<(double area) { return calculateArea() < area; } + inline bool operator>(double area) { return calculateArea() > area; } + inline bool operator<=(double area) { return calculateArea() <= area; } + inline bool operator>=(double area) { return calculateArea() >= area; } + + // Arithmetic Operators + inline Size& operator+=(const Size& s) + { + m_width += s.m_width; + m_height += s.m_height; + return *this; + } + + inline Size& operator-=(const Size& s) + { + m_width -= s.m_width; + m_height -= s.m_height; + return *this; + } + + inline Size& operator*=(double mult) + { + m_width *= mult; + m_height *= mult; + return *this; + } + + inline Size& operator/=(double div) + { + m_width /= div; + m_height /= div; + return *this; + } + + // TODO: add ++size, size++, --size, size-- + + // External operators + 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 bool operator<(double, const Size&); + friend inline bool operator>(double, const Size&); + friend inline bool operator<=(double, const Size&); + friend inline bool operator>=(double, const Size&); + + void show() const; + +private: + double m_width; + double m_height; +}; + +// Comparison Operators +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) +{ + return area < s.calculateArea(); +} + +inline bool operator>(double area, const Size& s) +{ + return area > s.calculateArea(); +} + +inline bool operator<=(double area, const Size& s) +{ + return area <= s.calculateArea(); +} + +inline bool operator>=(double area, const Size& s) +{ + return area >= s.calculateArea(); +} + +// Arithmetic Operators +inline const 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) +{ + return Size(s1.m_width - s2.m_width, s1.m_height - s2.m_height); +} + +inline const 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) +{ + return Size(s.m_width * mult, s.m_height * mult); +} + +inline const Size operator/(const Size& s, double div) +{ + return Size(s.m_width / div, s.m_height / div); +} + +typedef double real; +typedef unsigned short ushort; +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; } + static inline ushort passTypedefOfUnsignedShort(ushort value) { return value; } +private: + real m_width; + real m_height; +}; + +#endif // SIZE_H + diff --git a/sources/shiboken2/tests/libsample/sometime.cpp b/sources/shiboken2/tests/libsample/sometime.cpp new file mode 100644 index 000000000..3038e26ca --- /dev/null +++ b/sources/shiboken2/tests/libsample/sometime.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sometime.h" +#include + +void +Time::setTime() +{ + m_hour = 0; + m_minute = 0; + m_second = 0; + m_msec = 0; + m_is_null = true; +} + +void +Time::setTime(int h, int m, int s, int ms) +{ + m_hour = h; + m_minute = m; + m_second = s; + m_msec = ms; + m_is_null = false; +} + + +Time::NumArgs +Time::somethingCompletelyDifferent() +{ + return ZeroArgs; +} + +Time::NumArgs +Time::somethingCompletelyDifferent(int h, int m, ImplicitConv ic, ObjectType* type) +{ + if (type) + return FourArgs; + if (ic.ctorEnum() == ImplicitConv::CtorThree && ic.objId() == -1) + return TwoArgs; + return ThreeArgs; +} + +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); + return Str(buffer); +} + +bool +Time::operator==(const Time& other) const +{ + return m_hour == other.m_hour + && m_minute == other.m_minute + && m_second == other.m_second + && m_msec == other.m_msec + && m_is_null == other.m_is_null; +} + +bool +Time::operator!=(const Time& other) const +{ + return !operator==(other); +} + +Time::operator Str() const +{ + return Time::toString(); +} + diff --git a/sources/shiboken2/tests/libsample/sometime.h b/sources/shiboken2/tests/libsample/sometime.h new file mode 100644 index 000000000..5f2ccf88a --- /dev/null +++ b/sources/shiboken2/tests/libsample/sometime.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SOMETIME_H +#define SOMETIME_H + +#include "libsamplemacros.h" +#include "str.h" +#include "implicitconv.h" +#include "objecttype.h" + +class LIBSAMPLE_API Time +{ +public: + enum NumArgs { + ZeroArgs, + TwoArgs, + ThreeArgs, + 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() {} + + inline bool isNull() const { return m_is_null; } + + inline int hour() const { return m_hour; } + inline int minute() const { return m_minute; } + inline int second() const { return m_second; } + inline int msec() const { return m_msec; } + + void setTime(); + void setTime(int h, int m, int s = 0, int ms = 0); + + // This one is completely different from the other methods in this class, + // it was added to give the overload decisor a really hard time with + // an value-type with implicit conversion and a default argument, and also + // an object-type, just because I feel like it. + NumArgs somethingCompletelyDifferent(); + NumArgs somethingCompletelyDifferent(int h, int m, + ImplicitConv ic = ImplicitConv::CtorThree, + ObjectType* type = 0); + + Str toString() 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; + + bool m_is_null; +}; + +#endif // SOMETIME_H + diff --git a/sources/shiboken2/tests/libsample/str.cpp b/sources/shiboken2/tests/libsample/str.cpp new file mode 100644 index 000000000..f3be2591e --- /dev/null +++ b/sources/shiboken2/tests/libsample/str.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "str.h" +#include +#include +#include +#include + +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) +{ + init(cstr); +} + +void +Str::init(const char* cstr) +{ + if (cstr) + m_str = cstr; +} + +Str::~Str() +{ +} + +Str +Str::arg(const Str& s) const +{ + size_t idx = m_str.find_first_of("%VAR"); + if (idx == std::string::npos) { + return *this; + } else { + std::string result = m_str; + result.replace(idx, 4, s.m_str); + return result.c_str(); + } +} + +Str& +Str::append(const Str& s) +{ + m_str += s.m_str; + return *this; +} + +Str& +Str::prepend(const Str& s) +{ + m_str = s.m_str + m_str; + return *this; +} + +const char* +Str::cstring() const +{ + return m_str.c_str(); +} + +int +Str::toInt(bool* ok, int base) const +{ + bool my_ok; + int result = 0; + 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; + } + my_ok = istringstream::eofbit & conv.rdstate(); + if (!my_ok) + result = 0; + if (ok) + *ok = my_ok; + return result; +} + +void +Str::show() const +{ + printf("%s", cstring()); +} + +char +Str::get_char(int pos) const +{ + return m_str[pos]; +} + +bool +Str::set_char(int pos, char ch) +{ + m_str[pos] = ch; + return true; +} + +Str Str::operator+(int number) const +{ + ostringstream in; + in << m_str << number; + return in.str().c_str(); +} + +bool Str::operator==(const Str& other) const +{ + return m_str == other.m_str; +} + +Str operator+(int number, const Str& str) +{ + ostringstream in; + in << number << str.m_str; + return in.str().c_str(); +} + +bool Str::operator<(const Str& other) const +{ + return m_str < other.m_str; +} + +unsigned int strHash(const Str& str) +{ + unsigned int result = 0; + const std::string& cppStr = str.m_str; + std::string::const_iterator it = cppStr.begin(); + for (; it != cppStr.end(); ++it) + result = 5 * result + *it; + return result; +} + +void changePStr(PStr* pstr, const char* suffix) +{ + pstr->append(suffix); +} + +void duplicatePStr(PStr* pstr) +{ + if (!pstr) + return; + pstr->append(*pstr); +} diff --git a/sources/shiboken2/tests/libsample/str.h b/sources/shiboken2/tests/libsample/str.h new file mode 100644 index 000000000..9c1e8c0a8 --- /dev/null +++ b/sources/shiboken2/tests/libsample/str.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STR_H +#define STR_H +#include + +#include "libsamplemacros.h" + +class LIBSAMPLE_API Str +{ +public: + Str(const Str& s); + Str(char c); + Str(const char* cstr = ""); + ~Str(); + + Str arg(const Str& s) const; + + Str& append(const Str& s); + Str& prepend(const Str& s); + + const char* cstring() const; + char get_char(int pos) const; + bool set_char(int pos, char ch); + + int toInt(bool* ok = 0, int base = 10) const; + + void show() const; + + inline int size() const { return 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; + +private: + 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); +}; + +LIBSAMPLE_API Str operator+(int number, const Str& str); +LIBSAMPLE_API unsigned int strHash(const Str& str); + +typedef Str PStr; +LIBSAMPLE_API void changePStr(PStr* pstr, const char* suffix); +LIBSAMPLE_API void duplicatePStr(PStr* pstr = 0); + +#endif // STR_H diff --git a/sources/shiboken2/tests/libsample/strlist.cpp b/sources/shiboken2/tests/libsample/strlist.cpp new file mode 100644 index 000000000..8956110d8 --- /dev/null +++ b/sources/shiboken2/tests/libsample/strlist.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "strlist.h" + +bool +StrList::operator==(const std::list& other) const +{ + if (size() != other.size()) + return false; + StrList::const_iterator this_it = begin(); + StrList::const_iterator other_it = begin(); + while (this_it != end()) { + if (!((*this_it) == (*other_it))) + return false; + ++this_it; + ++other_it; + } + return true; +} + +Str +StrList::join(const Str& sep) const +{ + Str result; + for (StrList::const_iterator it = begin(); it != end(); ++it) { + if (it != begin()) + result.append(sep); + result.append(*it); + } + return result; +} diff --git a/sources/shiboken2/tests/libsample/strlist.h b/sources/shiboken2/tests/libsample/strlist.h new file mode 100644 index 000000000..be908d5d5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/strlist.h @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef STRLIST_H +#define STRLIST_H + +#include +#include "str.h" + +#include "libsamplemacros.h" + +class LIBSAMPLE_API StrList : public std::list +{ +public: + enum CtorEnum { + NoParamsCtor, + StrCtor, + CopyCtor, + 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(lst), m_ctorUsed(CopyCtor) {} + inline StrList(const std::list& lst) : std::list(lst), m_ctorUsed(ListOfStrCtor) {} + + inline void append(Str str) { push_back(str); } + Str join(const Str& sep) const; + + bool operator==(const std::list& other) const; + inline bool operator!=(const std::list& other) const { return !(*this == other); } + + CtorEnum constructorUsed() { return m_ctorUsed; } +private: + CtorEnum m_ctorUsed; +}; + +typedef StrList PStrList; + +#endif // STRLIST_H diff --git a/sources/shiboken2/tests/libsample/templateptr.cpp b/sources/shiboken2/tests/libsample/templateptr.cpp new file mode 100644 index 000000000..571184776 --- /dev/null +++ b/sources/shiboken2/tests/libsample/templateptr.cpp @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "templateptr.h" + +void TemplatePtr::dummy(std::list > & items) +{ +} \ No newline at end of file diff --git a/sources/shiboken2/tests/libsample/templateptr.h b/sources/shiboken2/tests/libsample/templateptr.h new file mode 100644 index 000000000..67e154b1c --- /dev/null +++ b/sources/shiboken2/tests/libsample/templateptr.h @@ -0,0 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TEMPLATEPTR_H +#define TEMPLATEPTR_H + +#include +#include +#include "libsamplemacros.h" +#include "blackbox.h" + +class LIBSAMPLE_API TemplatePtr +{ +public: + void dummy(std::list > & items); +}; + +#endif diff --git a/sources/shiboken2/tests/libsample/transform.cpp b/sources/shiboken2/tests/libsample/transform.cpp new file mode 100644 index 000000000..951e2ca5b --- /dev/null +++ b/sources/shiboken2/tests/libsample/transform.cpp @@ -0,0 +1,65 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2013 Kitware, Inc. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "transform.h" + +#ifdef _WIN32 +#include +#include +static inline bool isfinite(double a) { return _finite(a); } +#else +#include +#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) +{ + 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 (okay) + *okay = true; + return Point(x / w, y / w); + } + else + { + if (okay) + *okay = false; + return Point(); + } +} diff --git a/sources/shiboken2/tests/libsample/transform.h b/sources/shiboken2/tests/libsample/transform.h new file mode 100644 index 000000000..fda5b33c5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/transform.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2013 Kitware, Inc. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef TRANSFORM_H +#define TRANSFORM_H + +#include "point.h" + +#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); + +#endif // TRANSFORM_H diff --git a/sources/shiboken2/tests/libsample/valueandvirtual.h b/sources/shiboken2/tests/libsample/valueandvirtual.h new file mode 100644 index 000000000..54e8114b5 --- /dev/null +++ b/sources/shiboken2/tests/libsample/valueandvirtual.h @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VALUEANDVIRTUAL_H +#define VALUEANDVIRTUAL_H + +class ValueAndVirtual +{ +public: + ValueAndVirtual(int id) : m_id(id) {} + ValueAndVirtual(const ValueAndVirtual &other) { m_id = other.m_id; } + + bool operator()(int id, int id2) { return id == id2; } + + inline int id() { return m_id; } + virtual ~ValueAndVirtual() {}; +private: + int m_id; +}; + +#endif // VALUEANDVIRTUAL_H + diff --git a/sources/shiboken2/tests/libsample/virtualmethods.cpp b/sources/shiboken2/tests/libsample/virtualmethods.cpp new file mode 100644 index 000000000..05b854e08 --- /dev/null +++ b/sources/shiboken2/tests/libsample/virtualmethods.cpp @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "virtualmethods.h" + +int VirtualDtor::dtor_called = 0; + +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) +{ + if (!text) { + ret = 0; + return false; + } + + ret = new Str(text); + return true; +} + +void +VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const +{ + *left = m_left; + *top = m_top; + *right = m_right; + *bottom = m_bottom; +} + diff --git a/sources/shiboken2/tests/libsample/virtualmethods.h b/sources/shiboken2/tests/libsample/virtualmethods.h new file mode 100644 index 000000000..5754d0d5d --- /dev/null +++ b/sources/shiboken2/tests/libsample/virtualmethods.h @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VIRTUALMETHODS_H +#define VIRTUALMETHODS_H + +#include "point.h" +#include "complex.h" +#include "str.h" + +#include "libsamplemacros.h" +#include "strlist.h" + +class LIBSAMPLE_API VirtualMethods +{ +public: + VirtualMethods(Str name = "VirtualMethods") : m_name(name) + { + m_left = m_top = m_right = m_bottom = 0; + } + virtual ~VirtualMethods() {} + + virtual double virtualMethod0(Point pt, int val, Complex cpx, bool b); + double callVirtualMethod0(Point pt, int val, Complex cpx, bool b) + { + return virtualMethod0(pt, val, cpx, b); + } + + // Binding modification: rename. + virtual int sum0(int a0, int a1, int a2) { return a0 + a1 + a2; } + int callSum0(int a0, int a1, int a2) { return sum0(a0, a1, a2); } + + // Binding modification: set default value for the last argument. + virtual int sum1(int a0, int a1, int a2) { return a0 + a1 + a2; } + int callSum1(int a0, int a1, int a2) { return sum1(a0, a1, a2); } + + // Binding modification: remove the last argument and set a default value for it. + virtual int sum2(int a0, int a1, int a2) { return a0 + a1 + a2; } + int callSum2(int a0, int a1, int a2) { return sum2(a0, a1, a2); } + + // Binding modification: remove the second argument. + virtual int sum3(int a0, int a1, int a2) { return a0 + a1 + a2; } + int callSum3(int a0, int a1, int a2) { return sum3(a0, a1, a2); } + + // Binding modification: remove the second argument and set its default + // value, then inject code on the binding reimplementation of the virtual + // (with a native inject-code) to sum the value of the removed + // argument to the first argument before the method is called. + virtual int sum4(int a0, int a1, int a2) { return a0 + a1 + a2; } + int callSum4(int a0, int a1, int a2) { return sum4(a0, a1, a2); } + + // Binding modification: prepend a string to the results of a Python override. + virtual Str name() { return m_name; } + Str callName() { return name(); } + + // Binding modification: code injection that calls the Python override by itself. + virtual void callMe() {} + 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); } + + // Return a non-binded method + std::list callStrListToStdList(const StrList& strList) { return strListToStdList(strList); } + virtual std::list strListToStdList(const StrList& strList ) { return strList; } + + void setMargins(int left, int top, int right, int bottom) + { + m_left = left; + m_top = top; + 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 + { + getMargins(left, top, right, bottom); + } + + virtual int recursionOnModifiedVirtual(Str arg) const { return 0; } + int callRecursionOnModifiedVirtual(Str arg) const { return recursionOnModifiedVirtual(arg); } + +private: + Str m_name; + int m_left; + int m_top; + int m_right; + int m_bottom; +}; + +class LIBSAMPLE_API VirtualDaughter : public VirtualMethods +{ +public: + VirtualDaughter() : VirtualMethods() {} + VirtualDaughter(Str name) : VirtualMethods(name) {} +}; + +class LIBSAMPLE_API VirtualDtor +{ +public: + VirtualDtor() {} + virtual ~VirtualDtor() { dtor_called++; } + + static VirtualDtor* create() { return new VirtualDtor(); } + static int dtorCalled() { return dtor_called; } + static void resetDtorCounter() { dtor_called = 0; } + +private: + static int dtor_called; +}; + +#endif // VIRTUALMETHODS_H + diff --git a/sources/shiboken2/tests/libsample/voidholder.h b/sources/shiboken2/tests/libsample/voidholder.h new file mode 100644 index 000000000..228bbae3f --- /dev/null +++ b/sources/shiboken2/tests/libsample/voidholder.h @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef VOIDHOLDER_H +#define VOIDHOLDER_H + +#include "libsamplemacros.h" + +class VoidHolder +{ +public: + explicit VoidHolder(void* ptr = 0) : m_ptr(ptr) {} + ~VoidHolder() {} + inline void* voidPointer() { return m_ptr; } + inline static void* gimmeMeSomeVoidPointer() + { + static void* pointerToSomething = new VoidHolder(); + return pointerToSomething; + } +private: + void* m_ptr; +}; + +#endif // VOIDHOLDER_H + diff --git a/sources/shiboken2/tests/libsmart/CMakeLists.txt b/sources/shiboken2/tests/libsmart/CMakeLists.txt new file mode 100644 index 000000000..66c27cdae --- /dev/null +++ b/sources/shiboken2/tests/libsmart/CMakeLists.txt @@ -0,0 +1,11 @@ +project(libsmart) + +set(libsmart_SRC +smart.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +add_definitions("-DLIBSMART_BUILD") +add_library(libsmart SHARED ${libsmart_SRC}) +set_property(TARGET libsmart PROPERTY PREFIX "") + diff --git a/sources/shiboken2/tests/libsmart/libsmartmacros.h b/sources/shiboken2/tests/libsmart/libsmartmacros.h new file mode 100644 index 000000000..e4166caff --- /dev/null +++ b/sources/shiboken2/tests/libsmart/libsmartmacros.h @@ -0,0 +1,46 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef LIB_SMART_MACROS_H +#define LIB_SMART_MACROS_H + +#if defined _WIN32 || defined __CYGWIN__ + #if LIBSMART_BUILD + #define LIB_SMART_API __declspec(dllexport) + #else + #define LIB_SMART_API __declspec(dllimport) + #endif +#else +#if __GNUC__ >= 4 + #define LIB_SMART_API __attribute__ ((visibility("default"))) +#else + #define LIB_SMART_API +#endif +#endif + +#endif diff --git a/sources/shiboken2/tests/libsmart/smart.cpp b/sources/shiboken2/tests/libsmart/smart.cpp new file mode 100644 index 000000000..28c9cf055 --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart.cpp @@ -0,0 +1,174 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "smart.h" + +bool shouldPrint() { + return Registry::getInstance()->shouldPrint(); +} + +Obj::Obj() : m_integer(123), m_internalInteger(new Integer) +{ + Registry::getInstance()->add(this); + if (shouldPrint()) + std::cout << "Object constructor " << this << '\n'; +} + +Obj::~Obj() +{ + Registry::getInstance()->remove(this); + delete m_internalInteger; + if (shouldPrint()) + std::cout << "Object destructor " << this << '\n'; +} + + +void Obj::printObj() { + if (shouldPrint()) { + std::cout << "integer value: " << m_integer + << " internal integer value: " << m_internalInteger->m_int << '\n'; + } +} + + +SharedPtr Obj::giveSharedPtrToObj() +{ + SharedPtr o(new Obj); + return o; +} + +SharedPtr Obj::giveSharedPtrToInteger() +{ + SharedPtr o(new Integer); + return o; +} + +int Obj::takeSharedPtrToObj(SharedPtr pObj) +{ + pObj->printObj(); + return pObj->m_integer; +} + +int Obj::takeSharedPtrToInteger(SharedPtr pInt) +{ + pInt->printInteger(); + return pInt->m_int; +} + +Integer Obj::takeInteger(Integer val) +{ + return val; +} + +Integer::Integer() : m_int(456) +{ + Registry::getInstance()->add(this); + if (shouldPrint()) + std::cout << "Integer constructor " << this << '\n'; +} + +Integer::Integer(const Integer &other) +{ + Registry::getInstance()->add(this); + if (shouldPrint()) + std::cout << "Integer copy constructor " << this << '\n'; + m_int = other.m_int; +} + +Integer &Integer::operator=(const Integer &other) +{ + Registry::getInstance()->add(this); + if (shouldPrint()) + std::cout << "Integer operator= " << this << '\n'; + m_int = other.m_int; + return *this; +} + +Integer::~Integer() +{ + Registry::getInstance()->remove(this); + if (shouldPrint()) + std::cout << "Integer destructor " << this << '\n'; +} + +void Integer::printInteger() +{ + if (shouldPrint()) + std::cout << "Integer value for object " << this << " is " << m_int << '\n'; +} + +Registry *Registry::getInstance() +{ + static Registry registry; + return ®istry; +} + +Registry::Registry() : m_printStuff(false) +{ + +} + +void Registry::add(Obj *p) +{ + m_objects.push_back(p); +} + +void Registry::add(Integer *p) +{ + m_integers.push_back(p); +} + +void Registry::remove(Obj *p) +{ + m_objects.erase(std::remove(m_objects.begin(), m_objects.end(), p), m_objects.end()); +} + +void Registry::remove(Integer *p) +{ + m_integers.erase(std::remove(m_integers.begin(), m_integers.end(), p), m_integers.end()); +} + +int Registry::countObjects() const +{ + return static_cast(m_objects.size()); +} + +int Registry::countIntegers() const +{ + return static_cast(m_integers.size()); +} + +bool Registry::shouldPrint() const +{ + return m_printStuff; +} + +void Registry::setShouldPrint(bool flag) +{ + m_printStuff = flag; +} diff --git a/sources/shiboken2/tests/libsmart/smart.h b/sources/shiboken2/tests/libsmart/smart.h new file mode 100644 index 000000000..c6b0dbbca --- /dev/null +++ b/sources/shiboken2/tests/libsmart/smart.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SMART_H +#define SMART_H + +#include +#include +#include + +#include "libsmartmacros.h" + +// Forward declarations. +template +class SharedPtr; +class Integer; +class Obj; + +LIB_SMART_API bool shouldPrint(); + +// Used to track which C++ objects are alive. +class LIB_SMART_API Registry { +public: + static Registry *getInstance(); + + void add(Obj *p); + void add(Integer *p); + void remove(Obj *p); + void remove(Integer *p); + int countObjects() const; + int countIntegers() const; + bool shouldPrint() const; + void setShouldPrint(bool flag); + +protected: + Registry(); + +private: + bool m_printStuff; + std::vector m_objects; + std::vector m_integers; +}; + +template +class RefData { +public: + RefData(T *ptr) : m_refCount(1), m_heldPtr(ptr) {} + ~RefData() { delete m_heldPtr; } + int inc() { return ++m_refCount; } + int dec() { return --m_refCount; } + int useCount() { return m_refCount; } + int m_refCount; + T *m_heldPtr; +}; + +template +class SharedPtr { +public: + SharedPtr() : m_refData(0) { + if (shouldPrint()) + std::cout << "shared_ptr default constructor " << this << "\n"; + } + + SharedPtr(T *v) + { + if (shouldPrint()) + std::cout << "shared_ptr constructor " << this << " with pointer " << v << "\n"; + if (v) + m_refData = new RefData(v); + } + + SharedPtr(const SharedPtr &other) : m_refData(other.m_refData) + { + if (shouldPrint()) + std::cout << "shared_ptr copy constructor " << this << " with pointer " + << other.m_refData << "\n"; + if (m_refData) + m_refData->inc(); + } + + SharedPtr &operator=(const SharedPtr& other) + { + if (this != &other) { + if (shouldPrint()) + std::cout << "shared_ptr assignment operator " << this << " with pointer " + << other.m_refData << "\n"; + if (m_refData && m_refData->dec() == 0) + delete m_refData; + m_refData = other.m_refData; + if (m_refData) + m_refData->inc(); + } + return *this; + } + + T *data() const + { + if (m_refData) + return m_refData->m_heldPtr; + return 0; + } + + int useCount() const + { + if (m_refData) + return m_refData->useCount(); + return 0; + } + + void dummyMethod1() + { + + } + + T& operator*() const + { + // Crashes if smart pointer is empty (just like std::shared_ptr). + return *(m_refData->m_heldPtr); + } + + T *operator->() const + { + if (m_refData) + return m_refData->m_heldPtr; + return 0; + } + + bool operator!() const + { + return !m_refData || !m_refData->m_heldPtr; + } + + bool isNull() const + { + return !m_refData || !m_refData->m_heldPtr; + } + + operator bool() const + { + return m_refData && m_refData->m_heldPtr; + } + + ~SharedPtr() + { + if (m_refData) { + if (shouldPrint()) + std::cout << "shared_ptr destructor " << this << " remaining refcount " + << m_refData->useCount() - 1 << "\n"; + } + if (m_refData && m_refData->dec() == 0) + delete m_refData; + } + + RefData *m_refData; +}; + +class LIB_SMART_API Integer { +public: + Integer(); + Integer(const Integer &other); + Integer &operator=(const Integer &other); + ~Integer(); + void printInteger(); + int m_int; +}; + +// Couldn't name it Object because it caused some namespace clashes. +class LIB_SMART_API Obj { +public: + Obj(); + virtual ~Obj(); + + void printObj(); + Integer takeInteger(Integer val); + SharedPtr giveSharedPtrToObj(); + SharedPtr giveSharedPtrToInteger(); + int takeSharedPtrToObj(SharedPtr pObj); + int takeSharedPtrToInteger(SharedPtr pInt); + + int m_integer; + Integer *m_internalInteger; +}; + +#endif // SMART_H + diff --git a/sources/shiboken2/tests/minimalbinding/CMakeLists.txt b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt new file mode 100644 index 000000000..fb0b2cc74 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/CMakeLists.txt @@ -0,0 +1,38 @@ +project(minimal) + +set(minimal_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_minimal.xml +) + +set(minimal_SRC +${CMAKE_CURRENT_BINARY_DIR}/minimal/minimal_module_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/minbooluser_wrapper.cpp +) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/minimal-binding.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt" @ONLY) + +add_custom_command(OUTPUT ${minimal_SRC} +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'minimal' test binding..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libminimal_SOURCE_DIR} + ${libshiboken_SOURCE_DIR}) +add_library(minimal MODULE ${minimal_SRC}) +set_property(TARGET minimal PROPERTY PREFIX "") +if(WIN32) + set_property(TARGET minimal PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(minimal + libminimal + ${SBK_PYTHON_LIBRARIES} + libshiboken) diff --git a/sources/shiboken2/tests/minimalbinding/global.h b/sources/shiboken2/tests/minimalbinding/global.h new file mode 100644 index 000000000..93eb38ed5 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/global.h @@ -0,0 +1,33 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "obj.h" +#include "val.h" +#include "minbool.h" +#include "listuser.h" +#include "typedef.h" diff --git a/sources/shiboken2/tests/minimalbinding/listuser_test.py b/sources/shiboken2/tests/minimalbinding/listuser_test.py new file mode 100644 index 000000000..d3b7f01e7 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/listuser_test.py @@ -0,0 +1,323 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from minimal import ListUser, Val, Obj +from py3kcompat import IS_PY3K + +if IS_PY3K: + import functools + reduce = functools.reduce + + +class ExtListUser(ListUser): + def __init__(self): + ListUser.__init__(self) + + def createIntList(self, num): + return list(range(0, num * 2, 2)) + + def sumIntList(self, intList): + return sum(intList) * 2 + + def createMinBoolList(self, mb1, mb2): + return [not mb1, not mb2] + + def oredMinBoolList(self, 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)] + + def sumValList(self, valList): + return sum([val.valId() for val in valList]) * 2 + + def createObjList(self, o1, o2): + o1.setObjId(o1.objId() * 2) + o2.setObjId(o2.objId() * 2) + return [o1, o2] + + def sumObjList(self, objList): + return sum([obj.objId() for obj in objList]) * 2 + + def createListOfIntLists(self, num): + return [self.createIntList(num)] * 4 + + def sumListOfIntLists(self, intListList): + return sum([sum(line) for line in intListList]) * 2 + + +class IntListConversionTest(unittest.TestCase): + + def testCreateIntList(self): + num = 4 + lu = ListUser() + lst = lu.createIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(num))) + lst = lu.callCreateIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(num))) + + def testCreateIntListFromExtendedClass(self): + lu = ExtListUser() + num = 4 + lst = lu.createIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(0, num * 2, 2))) + lst = lu.callCreateIntList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), int) + self.assertEqual(lst, list(range(0, num * 2, 2))) + + def testSumIntList(self): + lu = ListUser() + lst = range(4) + self.assertEqual(lu.sumIntList(lst), sum(lst)) + self.assertEqual(lu.callSumIntList(lst), sum(lst)) + + def testSumIntListFromExtendedClass(self): + lu = ExtListUser() + lst = range(4) + self.assertEqual(lu.sumIntList(lst), sum(lst) * 2) + self.assertEqual(lu.callSumIntList(lst), sum(lst) * 2) + + +class MinBoolListConversionTest(unittest.TestCase): + + def testCreateMinBoolList(self): + lu = ListUser() + lst = lu.createMinBoolList(True, False) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [True, False]) + + lst = lu.callCreateMinBoolList(False, True) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [False, True]) + + def testCreateMinBoolListFromExtendedClass(self): + lu = ExtListUser() + lst = lu.createMinBoolList(True, False) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [False, True]) + + lst = lu.callCreateMinBoolList(False, True) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), bool) + self.assertEqual(lst, [True, False]) + + def testOredMinBoolList(self): + lu = ListUser() + lst = [False, False, True] + self.assertTrue(lu.oredMinBoolList(lst)) + self.assertTrue(lu.callOredMinBoolList(lst)) + lst = [False, False, False] + self.assertFalse(lu.oredMinBoolList(lst)) + self.assertFalse(lu.callOredMinBoolList(lst)) + + def testOredMinBoolListFromExtendedClass(self): + lu = ExtListUser() + lst = [False, False, True] + self.assertFalse(lu.oredMinBoolList(lst)) + self.assertFalse(lu.callOredMinBoolList(lst)) + lst = [False, False, False] + self.assertTrue(lu.oredMinBoolList(lst)) + self.assertTrue(lu.callOredMinBoolList(lst)) + + +class ValListConversionTest(unittest.TestCase): + + def testCreateValList(self): + num = 4 + lu = ListUser() + lst = lu.createValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(num))) + lst = lu.callCreateValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(num))) + + def testCreateValListFromExtendedClass(self): + lu = ExtListUser() + num = 4 + lst = lu.createValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) + lst = lu.callCreateValList(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), Val) + self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) + + def testSumValList(self): + lu = ListUser() + lst = [Val(i) for i in range(4)] + self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst])) + self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst])) + + def testSumValListFromExtendedClass(self): + lu = ExtListUser() + lst = [Val(i) for i in range(4)] + self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst]) * 2) + self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst]) * 2) + + +class ObjListConversionTest(unittest.TestCase): + + def testCreateObjList(self): + o1 = Obj(1) + o2 = Obj(2) + lu = ListUser() + lst = lu.createObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [1, 2]) + + lst = lu.callCreateObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [1, 2]) + + def testCreateObjListFromExtendedClass(self): + o1 = Obj(1) + o2 = Obj(2) + lu = ExtListUser() + lst = lu.createObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [2, 4]) + + lst = lu.callCreateObjList(o1, o2) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), 2) + for i in lst: + self.assertEqual(type(i), Obj) + self.assertEqual(lst, [o1, o2]) + self.assertEqual([obj.objId() for obj in lst], [4, 8]) + + def testSumObjList(self): + lu = ListUser() + lst = [Obj(i) for i in list(range(4))] + self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst])) + self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst])) + + def testSumObjListFromExtendedClass(self): + lu = ExtListUser() + lst = [Obj(i) for i in list(range(4))] + self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst]) * 2) + self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst]) * 2) + + +class ListOfIntListConversionTest(unittest.TestCase): + + def testCreateListOfIntLists(self): + num = 4 + lu = ListUser() + lst = lu.createListOfIntLists(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), list) + self.assertEqual(i, list(range(num))) + for j in i: + self.assertEqual(type(j), int) + self.assertEqual(lst, [list(range(num))] * 4) + + def testCreateListOfIntListsFromExtendedClass(self): + num = 4 + lu = ExtListUser() + lst = lu.createListOfIntLists(num) + self.assertEqual(type(lst), list) + self.assertEqual(len(lst), num) + for i in lst: + self.assertEqual(type(i), list) + self.assertEqual(i, list(range(0, num * 2, 2))) + for j in i: + self.assertEqual(type(j), int) + self.assertEqual(lst, [list(range(0, num * 2, 2))] * 4) + + def testSumListIntLists(self): + lu = ListUser() + lst = [range(4)] * 4 + self.assertEqual(lu.sumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) + self.assertEqual(lu.callSumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) + + 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) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/minimalbinding/minbool_test.py b/sources/shiboken2/tests/minimalbinding/minbool_test.py new file mode 100644 index 000000000..b7830a79b --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/minbool_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +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.assertEqual(mbuTrue.minBool() == True, True) + self.assertEqual(False == mbuFalse.minBool(), True) + self.assertEqual(mbuTrue.minBool() == mbuFalse.minBool(), False) + + self.assertEqual(mbuFalse.minBool() != True, True) + self.assertEqual(True != mbuFalse.minBool(), True) + self.assertEqual(mbuTrue.minBool() != mbuFalse.minBool(), True) + + def testVirtuals(self): + dmbu = DerivedMinBoolUser() + self.assertEqual(dmbu.invertedMinBool(), True) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/minimalbinding/minimal-binding.txt.in b/sources/shiboken2/tests/minimalbinding/minimal-binding.txt.in new file mode 100644 index 000000000..85b139676 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/minimal-binding.txt.in @@ -0,0 +1,15 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @minimal_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libminimal_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +enable-parent-ctor-heuristic +use-isnull-as-nb_nonzero diff --git a/sources/shiboken2/tests/minimalbinding/obj_test.py b/sources/shiboken2/tests/minimalbinding/obj_test.py new file mode 100644 index 000000000..bf00f1c92 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/obj_test.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from minimal import Obj + +class ExtObj(Obj): + def __init__(self, objId): + Obj.__init__(self, objId) + self.virtual_method_called = False + + def virtualMethod(self, val): + self.virtual_method_called = True + return not Obj.virtualMethod(self, val) + + def passObjectType(self, obj): + obj.setObjId(obj.objId() + 1) + return obj + + def passObjectTypeReference(self, obj): + obj.setObjId(obj.objId() + 1) + return obj + + +class ObjTest(unittest.TestCase): + + def testNormalMethod(self): + objId = 123 + obj = Obj(objId) + self.assertEqual(obj.objId(), objId) + + def testNormalMethodFromExtendedClass(self): + objId = 123 + obj = ExtObj(objId) + self.assertEqual(obj.objId(), objId) + + def testVirtualMethod(self): + obj = Obj(0) + even_number = 8 + self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) + + def testVirtualMethodFromExtendedClass(self): + obj = ExtObj(0) + even_number = 8 + self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) + self.assertTrue(obj.virtual_method_called) + + def testPassObjectType(self): + obj = Obj(0) + self.assertEqual(obj, obj.passObjectType(obj)) + self.assertEqual(obj, obj.callPassObjectType(obj)) + + def testPassObjectTypeNone(self): + obj = Obj(0) + self.assertEqual(None, obj.passObjectType(None)) + self.assertEqual(None, obj.callPassObjectType(None)) + + def testPassObjectTypeReference(self): + obj = Obj(0) + self.assertEqual(obj, obj.passObjectTypeReference(obj)) + self.assertEqual(obj, obj.callPassObjectTypeReference(obj)) + + def testPassObjectTypeFromExtendedClass(self): + obj = ExtObj(0) + self.assertEqual(obj.objId(), 0) + sameObj = obj.passObjectType(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 1) + sameObj = obj.callPassObjectType(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 2) + + def testPassObjectTypeReferenceFromExtendedClass(self): + obj = ExtObj(0) + self.assertEqual(obj.objId(), 0) + sameObj = obj.passObjectTypeReference(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 1) + sameObj = obj.callPassObjectTypeReference(obj) + self.assertEqual(obj, sameObj) + self.assertEqual(sameObj.objId(), 2) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/minimalbinding/typedef_test.py b/sources/shiboken2/tests/minimalbinding/typedef_test.py new file mode 100644 index 000000000..62df9cbea --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/typedef_test.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from minimal import * +from py3kcompat import IS_PY3K + +try: + import numpy as np +except ImportError as e: + print(e) + np = None + + +if IS_PY3K: + import functools + reduce = functools.reduce + + +class TypedefTest(unittest.TestCase): + + def setUp(self): + self.the_size = 8 + + def test_arrayFuncInt(self): + none = () + full = range(self.the_size) + 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") + + 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(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") + + 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") + + def test_arrayFunc(self): + none = () + full = range(self.the_size) + self.assertTrue(arrayFunc(none), "None is empty, arrayFunc should return true") + 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") + + 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(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") + + 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") + + +if __name__ == '__main__': + if np != None: + unittest.main() diff --git a/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml b/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml new file mode 100644 index 000000000..968b27c53 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml @@ -0,0 +1,93 @@ + + + + + + + + + + return PyBool_FromLong(%in.value()); + + + + %out = %OUTTYPE(%in == Py_True); + + + + + + + + + + PyObject* %out = PyList_New((int) %in.size()); + %INTYPE::const_iterator it = %in.begin(); + for (int idx = 0; it != %in.end(); ++it, ++idx) { + %INTYPE_0 cppItem(*it); + PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); + } + return %out; + + + + Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq.object()); i++) { + PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), i); + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + %out.push_back(cppItem); + } + + + + + + + + + + + + + + + + + %INTYPE::size_type vectorSize = %in.size(); + PyObject* %out = PyList_New((int) vectorSize); + for (%INTYPE::size_type idx = 0; idx < vectorSize; ++idx) { + %INTYPE_0 cppItem(%in[idx]); + PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); + } + return %out; + + + + Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); + int vectorSize = PySequence_Fast_GET_SIZE(seq.object()); + %out.reserve(vectorSize); + for (int idx = 0; idx < vectorSize; ++idx ) { + PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), idx); + %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); + %out.push_back(cppItem); + } + + + + + + + + + + + + + + + + + + + + diff --git a/sources/shiboken2/tests/minimalbinding/val_test.py b/sources/shiboken2/tests/minimalbinding/val_test.py new file mode 100644 index 000000000..97e4e4778 --- /dev/null +++ b/sources/shiboken2/tests/minimalbinding/val_test.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from minimal import Val + + +class ExtVal(Val): + def __init__(self, valId): + Val.__init__(self, valId) + + def passValueType(self, val): + return ExtVal(val.valId() + 1) + + def passValueTypePointer(self, val): + val.setValId(val.valId() + 1) + return val + + def passValueTypeReference(self, val): + val.setValId(val.valId() + 1) + return val + + +class ValTest(unittest.TestCase): + + def testNormalMethod(self): + valId = 123 + val = Val(valId) + self.assertEqual(val.valId(), valId) + + def testPassValueType(self): + val = Val(123) + val1 = val.passValueType(val) + self.assertNotEqual(val, val1) + self.assertEqual(val1.valId(), 123) + val2 = val.callPassValueType(val) + self.assertNotEqual(val, val2) + self.assertEqual(val2.valId(), 123) + + def testPassValueTypePointer(self): + val = Val(0) + self.assertEqual(val, val.passValueTypePointer(val)) + self.assertEqual(val, val.callPassValueTypePointer(val)) + + def testPassValueTypeReference(self): + val = Val(0) + self.assertEqual(val, val.passValueTypeReference(val)) + self.assertEqual(val, val.callPassValueTypeReference(val)) + + def testPassAndReceiveEnumValue(self): + val = Val(0) + self.assertEqual(val.oneOrTheOtherEnumValue(Val.One), Val.Other) + self.assertEqual(val.oneOrTheOtherEnumValue(Val.Other), Val.One) + + def testPassValueTypeFromExtendedClass(self): + val = ExtVal(0) + val1 = val.passValueType(val) + self.assertNotEqual(val, val1) + self.assertEqual(val1.valId(), val.valId() + 1) + val2 = val.callPassValueType(val) + self.assertNotEqual(val, val2) + self.assertEqual(val2.valId(), val.valId() + 1) + + def testPassValueTypePointerFromExtendedClass(self): + val = ExtVal(0) + self.assertEqual(val.valId(), 0) + sameVal = val.passValueTypePointer(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 1) + sameVal = val.callPassValueTypePointer(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 2) + + def testPassValueTypeReferenceFromExtendedClass(self): + val = ExtVal(0) + self.assertEqual(val.valId(), 0) + sameVal = val.passValueTypeReference(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 1) + sameVal = val.callPassValueTypeReference(val) + self.assertEqual(val, sameVal) + self.assertEqual(sameVal.valId(), 2) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/CMakeLists.txt b/sources/shiboken2/tests/otherbinding/CMakeLists.txt new file mode 100644 index 000000000..ac7178e5d --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/CMakeLists.txt @@ -0,0 +1,48 @@ +project(other) + +set(other_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_other.xml +) + +set(other_SRC +${CMAKE_CURRENT_BINARY_DIR}/other/extendsnoimplicitconversion_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/number_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/otherderived_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/othermultiplederived_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/otherobjecttype_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/other/other_module_wrapper.cpp +) + + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/other-binding.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt" @ONLY) + +add_custom_command(OUTPUT ${other_SRC} +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${other_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'other' test binding..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libother_SOURCE_DIR} + ${libsample_SOURCE_DIR} + ${libsample_SOURCE_DIR}/.. + ${sample_BINARY_DIR} + ${sample_BINARY_DIR}/sample + ${libshiboken_SOURCE_DIR}) +add_library(other MODULE ${other_SRC}) +set_property(TARGET other PROPERTY PREFIX "") +if(WIN32) + set_property(TARGET other PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(other + libother + libsample + ${SBK_PYTHON_LIBRARIES} + libshiboken) + +add_dependencies(other sample) + diff --git a/sources/shiboken2/tests/otherbinding/collector_external_operator_test.py b/sources/shiboken2/tests/otherbinding/collector_external_operator_test.py new file mode 100644 index 000000000..328aec837 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/collector_external_operator_test.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Collector shift operators defined in other modules.''' + +import unittest + +from sample import Collector, ObjectType +from other import OtherObjectType + +class CollectorOtherObjectType(unittest.TestCase): + '''Test cases for Collector << OtherObjectType''' + + def testLShiftWithExpectedType(self): + '''Collector << ObjectType # libsample << operator''' + collector = Collector() + obj = ObjectType() + collector << obj + self.assertEqual(collector.items()[0], obj.identifier()) + + def testOtherReversal(self): + '''Collector << OtherObjectType # libother << operator''' + collector = Collector() + obj = OtherObjectType() + collector << obj + self.assertEqual(collector.items()[0], obj.identifier() * 2) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py b/sources/shiboken2/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py new file mode 100755 index 000000000..5c3733dc2 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests calling NoImplicitConversion using a ExtendsNoImplicitConversion parameter, + being that the latter defines a new conversion operator for the former, and this one + has no implicit conversions.''' + +import unittest + +from sample import NoImplicitConversion +from other import ExtendsNoImplicitConversion + +class ConversionOperatorForClassWithoutImplicitConversionsTest(unittest.TestCase): + '''Tests calling NoImplicitConversion constructor using a ExtendsNoImplicitConversion parameter.''' + + def testNoImplicitConversion(self): + '''Basic test to see if the NoImplicitConversion is Ok.''' + obj = NoImplicitConversion(123) + # NoImplicitConversion.receivesNoImplicitConversionByValue(NoImplicitConversion) + self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByValue(obj)) + # NoImplicitConversion.receivesNoImplicitConversionByPointer(NoImplicitConversion*) + self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByPointer(obj)) + # NoImplicitConversion.receivesNoImplicitConversionByReference(NoImplicitConversion&) + self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByReference(obj)) + + def testPassingExtendsNoImplicitConversionAsNoImplicitConversionByValue(self): + '''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.''' + obj = ExtendsNoImplicitConversion(123) + 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.''' + obj = ExtendsNoImplicitConversion(123) + self.assertRaises(TypeError, NoImplicitConversion.receivesNoImplicitConversionByPointer, obj) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/extended_multiply_operator_test.py b/sources/shiboken2/tests/otherbinding/extended_multiply_operator_test.py new file mode 100755 index 000000000..4acc53024 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/extended_multiply_operator_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for libsample's Point multiply operator defined in libother module.''' + +import unittest + +from sample import Point +from other import Number + +class PointOperationsWithNumber(unittest.TestCase): + '''Test cases for libsample's Point multiply operator defined in libother module.''' + + def testPointTimesInt(self): + '''sample.Point * int''' + pt1 = Point(2, 7) + num = 3 + pt2 = Point(pt1.x() * num, pt1.y() * num) + self.assertEqual(pt1 * num, pt2) + + def testIntTimesPoint(self): + '''int * sample.Point''' + pt1 = Point(2, 7) + num = 3 + pt2 = Point(pt1.x() * num, pt1.y() * num) + self.assertEqual(num * pt1, pt2) + + def testPointTimesNumber(self): + '''sample.Point * other.Number''' + pt = Point(2, 7) + num = Number(11) + self.assertEqual(pt * num, pt * 11) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/global.h b/sources/shiboken2/tests/otherbinding/global.h new file mode 100644 index 000000000..cc6634ab4 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/global.h @@ -0,0 +1,35 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "../samplebinding/global.h" +#include "extendsnoimplicitconversion.h" +#include "number.h" +#include "otherderived.h" +#include "otherobjecttype.h" +#include "othermultiplederived.h" + diff --git a/sources/shiboken2/tests/otherbinding/module_reload_test.py b/sources/shiboken2/tests/otherbinding/module_reload_test.py new file mode 100644 index 000000000..0f601d1a3 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/module_reload_test.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import os +import sys +import shutil +import unittest + +from py3kcompat import IS_PY3K + +if IS_PY3K: + from imp import reload + +orig_path = os.path.join(os.path.dirname(__file__)) +workdir = os.getcwd() +src = os.path.join(orig_path, 'test_module_template.py') +dst = os.path.join(workdir, 'test_module.py') +shutil.copyfile(src, dst) +sys.path.append(workdir) + +class TestModuleReloading(unittest.TestCase): + + def testModuleReloading(self): + '''Test module reloading with on-the-fly modifications.''' + import test_module + for i in range(3): + oldObject = test_module.obj + self.assertTrue(oldObject is test_module.obj) + reload(test_module) + self.assertFalse(oldObject is test_module.obj) + +if __name__ == "__main__": + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/new_ctor_operator_test.py b/sources/shiboken2/tests/otherbinding/new_ctor_operator_test.py new file mode 100755 index 000000000..634106cea --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/new_ctor_operator_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests calling Str constructor using a Number parameter, being that number defines a cast operator to Str.''' + +import unittest + +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.''' + + def testNumber(self): + '''Basic test to see if the Number class is Ok.''' + value = 123 + num = Number(value) + self.assertEqual(num.value(), value) + + def testStrCtorWithNumberArgument(self): + '''Try to build a Str from 'sample' module with a Number argument from 'other' module.''' + value = 123 + num = Number(value) + string = Str(num) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/objtypehashes_test.py b/sources/shiboken2/tests/otherbinding/objtypehashes_test.py new file mode 100644 index 000000000..753aec1a1 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/objtypehashes_test.py @@ -0,0 +1,53 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import * +from other import * +import shiboken2 as shiboken + +class TestHashFuncs (unittest.TestCase): + + def testIt(self): + obj1 = HandleHolder() + obj2 = HandleHolder() + + hash1 = hash(obj1) + hash2 = hash(obj2) + self.assertNotEqual(hash1, hash2) + + # Now invalidate the object and test its hash. It shouldn't segfault. + shiboken.invalidate(obj1) + + hash1_2 = hash(obj1) + self.assertEqual(hash1_2, hash1) + + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/other-binding.txt.in b/sources/shiboken2/tests/otherbinding/other-binding.txt.in new file mode 100644 index 000000000..a17b70fc1 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/other-binding.txt.in @@ -0,0 +1,18 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @other_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libother_SOURCE_DIR@ +include-path = @libsample_SOURCE_DIR@ +include-path = @libsample_SOURCE_DIR@/.. + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ +typesystem-path = @sample_SOURCE_DIR@ + +enable-parent-ctor-heuristic + diff --git a/sources/shiboken2/tests/otherbinding/otherderived_test.py b/sources/shiboken2/tests/otherbinding/otherderived_test.py new file mode 100644 index 000000000..f6906c88a --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/otherderived_test.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for OtherDerived class''' + +import sys +import unittest + +from sample import Abstract, Derived +from other import OtherDerived, Number + +class Multiple(Derived, Number): + def __init__(self): + Derived.__init__(self, 42) + Number.__init__(self, 42) + + def testCall(self): + return True + +class OtherDeviant(OtherDerived): + def __init__(self): + OtherDerived.__init__(self) + self.pure_virtual_called = False + self.unpure_virtual_called = False + + def pureVirtual(self): + self.pure_virtual_called = True + + def unpureVirtual(self): + self.unpure_virtual_called = True + + def className(self): + return 'OtherDeviant' + +class MultipleTest(unittest.TestCase): + '''Test case for Multiple derived class''' + + def testConstructor(self): + o = Multiple() + self.assertTrue(isinstance(o, Multiple)) + self.assertTrue(isinstance(o, Number)) + self.assertTrue(isinstance(o, Derived)) + del o + + def testMethodCall(self): + o = Multiple() + self.assertTrue(o.id_(), 42) + self.assertTrue(o.value(), 42) + self.assertTrue(o.testCall()) + +class OtherDerivedTest(unittest.TestCase): + '''Test case for OtherDerived class''' + + def testParentClassMethodsAvailability(self): + '''Test if OtherDerived class really inherits its methods from parent.''' + inherited_methods = set(['callPureVirtual', 'callUnpureVirtual', + 'id_', 'pureVirtual', 'unpureVirtual']) + 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++.''' + 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++.''' + d = OtherDeviant() + d.callUnpureVirtual() + self.assertTrue(d.unpure_virtual_called) + + def testVirtualMethodCallString(self): + '''Test virtual method call returning string.''' + d = OtherDerived() + self.assertEqual(d.className(), 'OtherDerived') + self.assertEqual(d.getClassName(), 'OtherDerived') + + def testReimplementedVirtualMethodCallReturningString(self): + '''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') + + def testCallToMethodWithAbstractArgument(self): + '''Call to method that expects an Abstract argument.''' + objId = 123 + d = OtherDerived(objId) + self.assertEqual(Abstract.getObjectId(d), objId) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/otherbinding/test_module_template.py b/sources/shiboken2/tests/otherbinding/test_module_template.py new file mode 100644 index 000000000..ddde85c2e --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/test_module_template.py @@ -0,0 +1,40 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +from other import * +from sample import * + + +class MyObjectType(ObjectType): + pass + +class MyOtherObjectType(OtherObjectType): + value = 10 + + +obj = MyObjectType() diff --git a/sources/shiboken2/tests/otherbinding/typediscovery_test.py b/sources/shiboken2/tests/otherbinding/typediscovery_test.py new file mode 100644 index 000000000..507c5be94 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/typediscovery_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for type discovery''' + +import unittest + +from sample import Abstract, Base1, Derived, MDerived1, MDerived3, SonOfMDerived1 +from other import OtherMultipleDerived + +class TypeDiscoveryTest(unittest.TestCase): + + def testPureVirtualsOfImpossibleTypeDiscovery(self): + a = Derived.triggerImpossibleTypeDiscovery() + self.assertEqual(type(a), Abstract) + # call some pure virtual method + a.pureVirtual() + + def testAnotherImpossibleTypeDiscovery(self): + a = Derived.triggerAnotherImpossibleTypeDiscovery() + self.assertEqual(type(a), Derived) + + def testMultipleInheritance(self): + obj = OtherMultipleDerived.createObject("Base1"); + self.assertEqual(type(obj), Base1) + 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) + obj = OtherMultipleDerived.createObject("OtherMultipleDerived"); + self.assertEqual(type(obj), OtherMultipleDerived) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/typesystem_other.xml b/sources/shiboken2/tests/otherbinding/typesystem_other.xml new file mode 100644 index 000000000..63ccdd518 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/typesystem_other.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/sources/shiboken2/tests/otherbinding/usersprimitivefromothermodule_test.py b/sources/shiboken2/tests/otherbinding/usersprimitivefromothermodule_test.py new file mode 100755 index 000000000..06cfce371 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/usersprimitivefromothermodule_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests user defined primitive type from a required module.''' + +import unittest +from other import Number + +class UserDefinedPrimitiveTypeFromRequiredModuleTest(unittest.TestCase): + + def testUsersPrimitiveFromRequiredModuleAsArgument(self): + '''static Number Number::fromComplex(Complex)''' + cpx = complex(3.0, 1.2) + number = Number.fromComplex(cpx) + self.assertEqual(number.value(), int(cpx.real)) + + def testUsersPrimitiveFromRequiredModuleAsReturnValue(self): + '''Complex Number::toComplex()''' + number = Number(12) + cpx = number.toComplex() + self.assertEqual(number.value(), int(cpx.real)) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/otherbinding/wrongctor_test.py b/sources/shiboken2/tests/otherbinding/wrongctor_test.py new file mode 100644 index 000000000..61317fe66 --- /dev/null +++ b/sources/shiboken2/tests/otherbinding/wrongctor_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import * +from other import * + +class Foo(OtherDerived): + def __init__(self): + 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 + + +class WrongCtorTest(unittest.TestCase): + def testIt(self): + self.assertRaises(TypeError, Foo) + self.assertRaises(TypeError, Foo2) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/py3k.py b/sources/shiboken2/tests/py3k.py new file mode 100644 index 000000000..5f2961a6a --- /dev/null +++ b/sources/shiboken2/tests/py3k.py @@ -0,0 +1,2 @@ +def printToFile(f, str): + print(str, file=f) diff --git a/sources/shiboken2/tests/py3kcompat.py b/sources/shiboken2/tests/py3kcompat.py new file mode 100644 index 000000000..45550efb3 --- /dev/null +++ b/sources/shiboken2/tests/py3kcompat.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import sys + +IS_PY3K = sys.version_info[0] == 3 + +if IS_PY3K: + def unicode(s): + return s + + def b(s): + return bytes(s, "UTF8") + + def l(n): + return n + + long = int +else: + def b(s): + return s + + def l(n): + return long(n) + + unicode = unicode + long = long diff --git a/sources/shiboken2/tests/samplebinding/CMakeLists.txt b/sources/shiboken2/tests/samplebinding/CMakeLists.txt new file mode 100644 index 000000000..f897712f4 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/CMakeLists.txt @@ -0,0 +1,145 @@ +project(sample) + +set(sample_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml +) + +set(sample_SRC +${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base4_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base5_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/bytearray_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/classwithfunctionpointer_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/color_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/ctorconvrule_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/derived_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/event_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/expression_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/friendofonlycopy_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/handleholder_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/implicitconv_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/implicitbase_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/implicittarget_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/intlist_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/sortedoverload_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/intwrapper_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/injectcode_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/listuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mapuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mderived1_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mderived2_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mderived3_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mderived4_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/mderived5_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/modelindex_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/modifications_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/modifiedconstructor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/noimplicitconversion_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objectmodel_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypebyvalue_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeholder_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypederived_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypelayout_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeptrlist_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeoperators_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objectview_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objtypereference_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/onlycopy_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/otherbase_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/overload_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/overload2_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pairuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pen_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/persistentmodelindex_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/photon_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/photon_base_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/photon_valueidentity_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/photon_valueduplicator_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/point_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pointerholder_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pointf_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pointvaluelist_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/polygon_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/primitivestructpointerholder_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/privatector_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/privatedtor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedenumclass_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectednonpolymorphic_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphic_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphicdaughter_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphicgranddaughter_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedproperty_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/protectedvirtualdestructor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/rect_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/rectf_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/reference_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/referentmodelindex_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp +${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_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/simplefile_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/size_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/sizef_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/sonofmderived1_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/str_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/strlist_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/time_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/templateptr_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/unremovednamespace_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdaughter_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdtor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/virtualmethods_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/voidholder_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/valueandvirtual_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/filter_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/data_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/intersection_wrapper.cpp +${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) + +add_custom_command(OUTPUT ${sample_SRC} +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/sample-binding.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${sample_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'sample' test binding..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libsample_SOURCE_DIR} + ${libshiboken_SOURCE_DIR}) +add_library(sample MODULE ${sample_SRC}) +set_property(TARGET sample PROPERTY PREFIX "") +if(WIN32) + set_property(TARGET sample PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(sample + libsample + ${SBK_PYTHON_LIBRARIES} + libshiboken) diff --git a/sources/shiboken2/tests/samplebinding/__del___test.py b/sources/shiboken2/tests/samplebinding/__del___test.py new file mode 100644 index 000000000..fd787b5f0 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/__del___test.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +import sample + +delCalled = False + +class MyObject(sample.ObjectType): + def __del__(self): + global delCalled + delCalled = True + +class TestDel(unittest.TestCase): + def testIt(self): + a = MyObject() + del a + self.assertTrue(delCalled) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/abstract_test.py b/sources/shiboken2/tests/samplebinding/abstract_test.py new file mode 100644 index 000000000..46aad3260 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/abstract_test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Abstract class''' + +import sys +import unittest + +from sample import Abstract + +class Incomplete(Abstract): + def __init__(self): + Abstract.__init__(self) + +class Concrete(Abstract): + def __init__(self): + Abstract.__init__(self) + self.pure_virtual_called = False + self.unpure_virtual_called = False + + def pureVirtual(self): + self.pure_virtual_called = True + + def pureVirtualReturningVoidPtr(self): + return 42 + + def unpureVirtual(self): + self.unpure_virtual_called = True + + def virtualGettingAEnum(self, enum): + self.virtual_getting_enum = True + + +class AbstractTest(unittest.TestCase): + '''Test case for Abstract class''' + + def testAbstractPureVirtualMethodAvailability(self): + '''Test if Abstract class pure virtual method was properly wrapped.''' + self.assertTrue('pureVirtual' in dir(Abstract)) + + def testAbstractInstanciation(self): + '''Test if instanciation of an abstract class raises the correct exception.''' + self.assertRaises(NotImplementedError, Abstract) + + def testUnimplementedPureVirtualMethodCall(self): + '''Test if calling a pure virtual method raises the correct exception.''' + i = Incomplete() + self.assertRaises(NotImplementedError, i.pureVirtual) + + def testPureVirtualReturningVoidPtrReturnValue(self): + '''Test if a pure virtual method returning void ptr can be properly reimplemented''' + # Note that the semantics of reimplementing the pure virtual method in + # 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) + + def testReimplementedVirtualMethodCall(self): + '''Test if a Python override of a virtual method is correctly called from C++.''' + c = Concrete() + c.callUnpureVirtual() + self.assertTrue(c.unpure_virtual_called) + + def testImplementedPureVirtualMethodCall(self): + '''Test if a Python override of a pure virtual method is correctly called from C++.''' + c = Concrete() + c.callPureVirtual() + self.assertTrue(c.pure_virtual_called) + + def testEnumParameterOnVirtualMethodCall(self): + '''testEnumParameterOnVirtualMethodCall''' + c = Concrete() + c.callVirtualGettingEnum(Abstract.Short) + self.assertTrue(c.virtual_getting_enum) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/addedfunction_test.py b/sources/shiboken2/tests/samplebinding/addedfunction_test.py new file mode 100644 index 000000000..1620a5114 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/addedfunction_test.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for added functions.''' + +import unittest +from sample import SampleNamespace, ObjectType, Point + +class TestAddedFunctionsWithSimilarTypes(unittest.TestCase): + '''Adds new signatures very similar to already existing ones.''' + + def testValueTypeReferenceAndValue(self): + '''In C++ we have "function(const ValueType&, double)", + in Python we add "function(ValueType)".''' + point = Point(10, 20) + multiplier = 4.0 + control = (point.x() + point.y()) * multiplier + self.assertEqual(SampleNamespace.passReferenceToValueType(point, multiplier), control) + control = point.x() + point.y() + self.assertEqual(SampleNamespace.passReferenceToValueType(point), control) + + def testObjectTypeReferenceAndPointer(self): + '''In C++ we have "function(const ObjectType&, int)", + in Python we add "function(ValueType)".''' + obj = ObjectType() + obj.setObjectName('sbrubbles') + multiplier = 3.0 + control = len(obj.objectName()) * multiplier + self.assertEqual(SampleNamespace.passReferenceToObjectType(obj, multiplier), control) + control = len(obj.objectName()) + self.assertEqual(SampleNamespace.passReferenceToObjectType(obj), control) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/addedfunction_with_container_args_test.py b/sources/shiboken2/tests/samplebinding/addedfunction_with_container_args_test.py new file mode 100644 index 000000000..da2406698 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/addedfunction_with_container_args_test.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for added functions with nested and multi-argument container types.''' + +import unittest +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]] + self.assertEqual(sum2d(values), 21) + + def testMultiArgContainerType(self): + '''Test added function with a two-argument container.''' + values = [(1,2),(3,4),(5,6)] + self.assertEqual(sumproduct(values), 44) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/argumentmodifications_test.py b/sources/shiboken2/tests/samplebinding/argumentmodifications_test.py new file mode 100644 index 000000000..90db99f91 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/argumentmodifications_test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for method arguments modifications performed as described on typesystem.''' + +import sys +import unittest + +from sample import Modifications, Point + +class ArgumentModificationsTest(unittest.TestCase): + '''Test cases for method arguments modifications performed as described on typesystem.''' + + def setUp(self): + self.mods = Modifications() + + def tearDown(self): + del self.mods + + def testArgRemoval0(self): + '''Tests argument removal modifications on Modifications.argRemoval0.''' + # void [-> PyObject*] argRemoval0(int, bool, int = 123 [removed, new val = 321], int = 456) + # code-injection: returns tuple with received parameters plus removed ones + a0, a1, a2 = 1, True, 2 + self.assertEqual(self.mods.argRemoval0(a0, a1), (a0, a1, 321, 456)) + self.assertEqual(self.mods.argRemoval0(a0, a1, a2), (a0, a1, 321, a2)) + # the other wasn't modified + # void argRemoval0(int, bool, int, bool) + self.assertEqual(self.mods.argRemoval0(0, False, 0, False), None) + + 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) + # 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)) + self.assertEqual(self.mods.argRemoval1(a0, a1, a2), (a0, a1, Point(1, 2), Point(3, 4), a2)) + # the other wasn't modified + # void argRemoval1(int, bool, int, bool) + self.assertEqual(self.mods.argRemoval1(0, False, 0, False), None) + + 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) + # 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)) + self.assertEqual(self.mods.argRemoval2(a0, a1, a2), (a0, a1, Point(1, 2), Point(3, 4), a2)) + + 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) + # 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)) + self.assertEqual(self.mods.argRemoval3(a0, a1), (a0, Point(1, 2), a1, Point(3, 4), 333)) + self.assertEqual(self.mods.argRemoval3(a0, a1, a2), (a0, Point(1, 2), a1, Point(3, 4), a2)) + + 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) + # code-injection: returns tuple with received parameters plus removed ones + a0, a1, a2 = 1, True, 2 + self.assertRaises(TypeError, self.mods.argRemoval4, a0) + self.assertEqual(self.mods.argRemoval4(a0, a1), (a0, Point(6, 9), a1, Point(3, 4), 333)) + self.assertEqual(self.mods.argRemoval4(a0, a1, a2), (a0, Point(6, 9), a1, Point(3, 4), a2)) + + def testArgRemoval5(self): + '''Tests argument removal modifications on Modifications.argRemoval5.''' + # void [-> PyObject*] argRemoval5(int [removed, new val = 100], 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 = True, 2, True + self.assertEqual(self.mods.argRemoval5(a0), (100, a0, Point(1, 2), Point(3, 4), 333)) + self.assertEqual(self.mods.argRemoval5(a0, a1), (100, a0, Point(1, 2), Point(3, 4), a1)) + # void [-> PyObject*] argRemoval5(int [removed, new val = 200], bool, int, bool) + # 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/shiboken2/tests/samplebinding/bug_554_test.py b/sources/shiboken2/tests/samplebinding/bug_554_test.py new file mode 100644 index 000000000..0bcce92cf --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/bug_554_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Unit test for bug#554''' + +from sample import * + +class Bug554: + def crash(self): + class Crasher(ObjectType): + pass + +if __name__ == '__main__': + bug = Bug554() + bug.crash() + + diff --git a/sources/shiboken2/tests/samplebinding/bug_704_test.py b/sources/shiboken2/tests/samplebinding/bug_704_test.py new file mode 100644 index 000000000..6b393f3b1 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/bug_704_test.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from py3kcompat import IS_PY3K + +from sample import ObjectType + + +class NewStyle(object): + def name(self): + return "NewStyle" + +class OldStyle: + def name(self): + return "OldStyle" + +def defineNewStyle(): + class MyObjectNew(ObjectType, NewStyle): + pass + +def defineOldStyle(): + class MyObjectOld(ObjectType, OldStyle): + pass + +class ObjectTypeTest(unittest.TestCase): + '''Test cases to avoid declaring Shiboken classes with multiple inheritance from old style classes.''' + + def testObjectTypeNewStype(self): + defineNewStyle() + + def testObjectTypeOldStype(self): + # Py 3k doesn't have old style classes + if not IS_PY3K: + self.assertRaises(TypeError, defineOldStyle) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp b/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp new file mode 100644 index 000000000..39fb8d353 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#if PY_VERSION_HEX < 0x03000000 +// ByteArray buffer protocol functions +// See: http://www.python.org/dev/peps/pep-3118/ +extern "C" { +static Py_ssize_t SbkByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp) +{ + if (lenp) + *lenp = self->ob_type->tp_as_sequence->sq_length(self); + return 1; +} +static Py_ssize_t SbkByteArray_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr) +{ + if (segment || !Shiboken::Object::isValid(self)) + return -1; + + ByteArray* cppSelf = %CONVERTTOCPP[ByteArray*](self); + *ptrptr = reinterpret_cast(const_cast(cppSelf->data())); + return cppSelf->size(); +} +PyBufferProcs SbkByteArrayBufferProc = { + /*bf_getreadbuffer*/ &SbkByteArray_readbufferproc, + /*bf_getwritebuffer*/ (writebufferproc)&SbkByteArray_readbufferproc, + /*bf_getsegcount*/ &SbkByteArray_segcountproc, + /*bf_getcharbuffer*/ (charbufferproc)&SbkByteArray_readbufferproc +}; +} +#endif diff --git a/sources/shiboken2/tests/samplebinding/bytearray_test.py b/sources/shiboken2/tests/samplebinding/bytearray_test.py new file mode 100644 index 000000000..0e8039469 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/bytearray_test.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from os.path import isdir +from sample import ByteArray +from py3kcompat import b + + +class ByteArrayBufferProtocolTest(unittest.TestCase): + '''Tests ByteArray implementation of Python buffer protocol.''' + + def testByteArrayBufferProtocol(self): + # Tests ByteArray implementation of Python buffer protocol using the os.path.isdir + # function which an unicode object or other object implementing the Python buffer protocol. + isdir(str(ByteArray('/tmp'))) + + +class ByteArrayConcatenationOperatorTest(unittest.TestCase): + '''Test cases for ByteArray concatenation with '+' operator.''' + + def testConcatByteArrayAndPythonString(self): + # Test concatenation of a ByteArray with a Python string, in this order. + ba = ByteArray('foo') + result = ba + '\x00bar' + self.assertEqual(type(result), ByteArray) + self.assertEqual(result, 'foo\x00bar') + + def testConcatPythonStringAndByteArray(self): + # Test concatenation of a Python string with a ByteArray, in this order. + concat_python_string_add_qbytearray_worked = True + ba = ByteArray('foo') + result = 'bar\x00' + ba + self.assertEqual(type(result), ByteArray) + self.assertEqual(result, 'bar\x00foo') + + +class ByteArrayOperatorEqual(unittest.TestCase): + '''TestCase for operator ByteArray == ByteArray.''' + + def testDefault(self): + # ByteArray() == ByteArray() + obj1 = ByteArray() + obj2 = ByteArray() + self.assertEqual(obj1, obj2) + + def testSimple(self): + # ByteArray(some_string) == ByteArray(some_string) + string = 'egg snakes' + self.assertEqual(ByteArray(string), ByteArray(string)) + + def testPyString(self): + # ByteArray(string) == string + string = 'my test string' + self.assertEqual(ByteArray(string), string) + + def testQString(self): + # ByteArray(string) == string + string = 'another test string' + self.assertEqual(ByteArray(string), string) + + +class ByteArrayOperatorAt(unittest.TestCase): + '''TestCase for operator ByteArray[]''' + + def testInRange(self): + # ByteArray[x] where x is a valid index. + string = 'abcdefgh' + obj = ByteArray(string) + for i in range(len(string)): + self.assertEqual(obj[i], b(string[i])) + + def testInRangeReverse(self): + # ByteArray[x] where x is a valid index (reverse order). + string = 'abcdefgh' + obj = ByteArray(string) + for i in range(len(string)-1, 0, -1): + self.assertEqual(obj[i], b(string[i])) + + def testOutOfRange(self): + # ByteArray[x] where x is out of index. + string = '1234567' + obj = ByteArray(string) + self.assertRaises(IndexError, lambda :obj[len(string)]) + + def testNullStrings(self): + ba = ByteArray('\x00') + self.assertEqual(ba.at(0), '\x00') + self.assertEqual(ba[0], b('\x00')) + + +class ByteArrayOperatorLen(unittest.TestCase): + '''Test case for __len__ operator of ByteArray''' + + def testBasic(self): + '''ByteArray __len__''' + self.assertEqual(len(ByteArray()), 0) + self.assertEqual(len(ByteArray('')), 0) + self.assertEqual(len(ByteArray(' ')), 1) + self.assertEqual(len(ByteArray('yabadaba')), 8) + + +class ByteArrayAndPythonStr(unittest.TestCase): + '''Test case for __str__ operator of ByteArray''' + + def testStrOperator(self): + '''ByteArray __str__''' + self.assertEqual(ByteArray().__str__(), '') + self.assertEqual(ByteArray('').__str__(), '') + self.assertEqual(ByteArray('aaa').__str__(), 'aaa') + + def testPythonStrAndNull(self): + s1 = b('123\000321') + ba = ByteArray(s1) + s2 = ba.data() + self.assertEqual(s1, s2) + self.assertEqual(type(s1), type(s2)) + self.assertEqual(s1, ba) + self.assertNotEqual(type(s1), type(ba)) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/child_return_test.py b/sources/shiboken2/tests/samplebinding/child_return_test.py new file mode 100644 index 000000000..30859dc5a --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/child_return_test.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''The BlackBox class has cases of ownership transference between C++ and Python.''' + +import sys +import unittest + +from sample import * + +class ReturnOfChildTest(unittest.TestCase): + '''The BlackBox class has cases of ownership transference between C++ and Python.''' + + def testKillParentKeepingChild(self): + '''Ownership transference from Python to C++ and back again.''' + o1 = ObjectType.createWithChild() + child = o1.children()[0] + del o1 + self.assertRaises(RuntimeError, child.objectName) + + def testKillParentKeepingChild2(self): + '''Ownership transference from Python to C++ and back again.''' + o1 = ObjectType.createWithChild() + child = o1.findChild("child") + del o1 + self.assertRaises(RuntimeError, child.objectName) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/class_fields_test.py b/sources/shiboken2/tests/samplebinding/class_fields_test.py new file mode 100644 index 000000000..0a2491cf2 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/class_fields_test.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Simple test case for accessing the exposed C++ class fields.''' + +from sys import getrefcount +import unittest + +from sample import Derived, Point, ObjectType + +class TestAccessingCppFields(unittest.TestCase): + '''Simple test case for accessing the exposed C++ class fields.''' + + def testAccessingPrimitiveTypeField(self): + '''Reads and writes a primitive type (in this case an 'int') field.''' + d = Derived() + self.assertEqual(type(d.primitiveField), int) + + # attribution + old_value = d.primitiveField + new_value = 2255 + d.primitiveField = new_value + self.assertEqual(d.primitiveField, new_value) + self.assertNotEqual(d.primitiveField, old_value) + + # attribution with a convertible type + value = 1.2 + d.primitiveField = value + self.assertEqual(d.primitiveField, int(value)) + + # attribution with invalid type + self.assertRaises(TypeError, lambda : setattr(d, 'primitiveField', None)) + + def testAccessingUsersPrimitiveTypeField(self): + '''Reads and writes an user's primitive type (in this case an 'Complex') field.''' + d = Derived() + self.assertEqual(type(d.userPrimitiveField), complex) + + # attribution + old_value = d.userPrimitiveField + new_value = complex(1.1, 2.2) + d.userPrimitiveField = new_value + self.assertEqual(d.userPrimitiveField, new_value) + self.assertNotEqual(d.userPrimitiveField, old_value) + + # attribution with invalid type + self.assertRaises(TypeError, lambda : setattr(d, 'userPrimitiveField', None)) + + def testAccessingValueTypeField(self): + '''Reads and writes a value type (in this case a 'Point') field.''' + d = Derived() + self.assertEqual(type(d.valueTypeField), Point) + + # attribution + old_value = d.valueTypeField + new_value = Point(-10, 537) + d.valueTypeField = new_value + self.assertEqual(d.valueTypeField, new_value) + + #object modify + d.valueTypeField.setX(10) + d.valueTypeField.setY(20) + self.assertEqual(d.valueTypeField.x(), 10) + self.assertEqual(d.valueTypeField.y(), 20) + + # attribution with invalid type + self.assertRaises(TypeError, lambda : setattr(d, 'valueTypeField', 123)) + + def testAccessingObjectTypeField(self): + '''Reads and writes a object type (in this case an 'ObjectType') field.''' + d = Derived() + + # attribution + old_value = d.objectTypeField + new_value = ObjectType() + d.objectTypeField = new_value + self.assertEqual(d.objectTypeField, new_value) + self.assertNotEqual(d.objectTypeField, old_value) + + # attribution with a convertible type + value = None + d.objectTypeField = value + self.assertEqual(d.objectTypeField, value) + + # attribution with invalid type + self.assertRaises(TypeError, lambda : setattr(d, 'objectTypeField', 123)) + + def testRefCountingAccessingObjectTypeField(self): + '''Accessing a object type field should respect the reference counting rules.''' + d = Derived() + + # attributing object to instance's field should increase its reference count + o1 = ObjectType() + refcount1 = getrefcount(o1) + d.objectTypeField = o1 + self.assertEqual(d.objectTypeField, o1) + self.assertEqual(getrefcount(d.objectTypeField), refcount1 + 1) + + # attributing a new object to instance's field should decrease the previous object's reference count + o2 = ObjectType() + refcount2 = getrefcount(o2) + d.objectTypeField = o2 + self.assertEqual(d.objectTypeField, o2) + self.assertEqual(getrefcount(o1), refcount1) + self.assertEqual(getrefcount(d.objectTypeField), refcount2 + 1) + + def testRefCountingOfReferredObjectAfterDeletingReferrer(self): + '''Deleting the object referring to other object should decrease the reference count of the referee.''' + d = Derived() + o = ObjectType() + refcount = getrefcount(o) + d.objectTypeField = o + self.assertEqual(getrefcount(o), refcount + 1) + del d + self.assertEqual(getrefcount(o), refcount) + + def testStaticField(self): + self.assertEqual(Derived.staticPrimitiveField, 0) + + def testAccessingUnsignedIntBitField(self): + d = Derived() + + # attribution + old_value = d.bitField + new_value = 1 + d.bitField= new_value + self.assertEqual(d.bitField, new_value) + self.assertNotEqual(d.bitField, old_value) + + # attribution with a convertible type + value = 1.2 + d.bitField = value + self.assertEqual(d.bitField, int(value)) + + # attribution with invalid type + self.assertRaises(TypeError, lambda : setattr(d, 'bitField', None)) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/collector_test.py b/sources/shiboken2/tests/samplebinding/collector_test.py new file mode 100644 index 000000000..cbd6326e6 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/collector_test.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Collector class' shift operators.''' + +import sys +import unittest + +from sample import Collector, IntWrapper, ObjectType + + +class CollectorTest(unittest.TestCase): + '''Test cases for Collector class' shift operators.''' + + def testLShiftOperatorSingleUse(self): + '''Test case for using the Collector.__lshift__ operator just one time.''' + collector = Collector() + collector << 13 + self.assertEqual(collector.size(), 1) + self.assertEqual(collector.items(), [13]) + + def testLShiftOperatorMultipleUses(self): + '''Test case for using the Collector.__lshift__ operator many times in the same line.''' + collector = Collector() + collector << 2 << 3 << 5 << 7 << 11 + 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''' + + def testLShiftExternal(self): + '''Collector external operator''' + collector = Collector() + collector << IntWrapper(5) + self.assertEqual(collector.size(), 1) + self.assertEqual(collector.items(), [5]) + + +class CollectorObjectType(unittest.TestCase): + '''Test cases for Collector ObjectType''' + + def testBasic(self): + '''Collector << ObjectType # greedy collector''' + collector = Collector() + obj = ObjectType() + collector << obj + self.assertEqual(collector.items()[0], obj.identifier()) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/complex_test.py b/sources/shiboken2/tests/samplebinding/complex_test.py new file mode 100644 index 000000000..3a14f4d15 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/complex_test.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Complex class''' + +import sys +import unittest + +import sample +from sample import Point + +class ComplexTest(unittest.TestCase): + '''Test case for conversions between C++ Complex class to Python complex class''' + + def testFunctionReturningComplexObject(self): + '''Test function returning a C++ Complex object.''' + cpx = sample.transmutePointIntoComplex(Point(5.0, 2.3)) + self.assertEqual(cpx, complex(5.0, 2.3)) + + def testFunctionReceivingComplexObjectAsArgument(self): + '''Test function returning a C++ Complex object.''' + pt = sample.transmuteComplexIntoPoint(complex(1.2, 3.4)) + # these assertions intentionally avoids to test the == operator, + # it should have its own test cases. + self.assertEqual(pt.x(), 1.2) + self.assertEqual(pt.y(), 3.4) + + def testComplexList(self): + '''Test list of C++ Complex objects conversion to a list of Python complex objects.''' + # the global function gimmeComplexList() is expected to return a list + # containing the following Complex values: [0j, 1.1+2.2j, 1.3+2.4j] + cpxlist = sample.gimmeComplexList() + self.assertEqual(cpxlist, [complex(), complex(1.1, 2.2), complex(1.3, 2.4)]) + + def testSumComplexPair(self): + '''Test sum of a tuple containing two complex objects.''' + cpx1 = complex(1.2, 3.4) + cpx2 = complex(5.6, 7.8) + self.assertEqual(sample.sumComplexPair((cpx1, cpx2)), cpx1 + cpx2) + + 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)))) + cpx1, cpx2 = (1, 3), (5, 7) + 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)))) + cpx1, cpx2 = (1, 2, 3), (4, 5, 7) + self.assertRaises(TypeError, sample.sumComplexPair, (cpx1, cpx2)) + cpx1, cpx2 = ('1', '2'), ('4', '5') + self.assertRaises(TypeError, sample.sumComplexPair, (cpx1, cpx2)) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/conversion_operator_test.py b/sources/shiboken2/tests/samplebinding/conversion_operator_test.py new file mode 100644 index 000000000..01ac102e8 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/conversion_operator_test.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for implicit conversion generated by conversion operator.''' + +import unittest + +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.''' + t = Time(1, 2, 3) + t_str = t.toString() + sl = StrList() + + # StrList.append expects a Str object. + sl.append(t) + + self.assertEqual(len(sl), 1) + self.assertEqual(sl[0], t_str) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/copy_test.py b/sources/shiboken2/tests/samplebinding/copy_test.py new file mode 100644 index 000000000..09c8e4cbc --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/copy_test.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for deep copy of objects''' + +import copy +import unittest + +try: + import cPickle as pickle +except ImportError: + import pickle + + +from sample import Point + + +class SimpleCopy(unittest.TestCase): + '''Simple copy of objects''' + + def testCopy(self): + point = Point(0.1, 2.4) + new_point = copy.copy(point) + + self.assertTrue(point is not new_point) + self.assertEqual(point, new_point) + + +class DeepCopy(unittest.TestCase): + '''Deep copy with shiboken objects''' + + def testDeepCopy(self): + '''Deep copy of value types''' + point = Point(3.1, 4.2) + new_point = copy.deepcopy([point])[0] + + self.assertTrue(point is not new_point) + self.assertEqual(point, new_point) + + +class PicklingTest(unittest.TestCase): + '''Support pickling''' + + def testSimple(self): + '''Simple pickling and unpickling''' + + point = Point(10.2, 43.5) + + data = pickle.dumps(point) + new_point = pickle.loads(data) + + self.assertEqual(point, new_point) + self.assertTrue(point is not new_point) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ctorconvrule_test.py b/sources/shiboken2/tests/samplebinding/ctorconvrule_test.py new file mode 100644 index 000000000..d1ebdc9d3 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ctorconvrule_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for proper generation of constructor altered by conversion-rule tag.''' + +import unittest + +from sample import CtorConvRule + +class TestCtorConvRule(unittest.TestCase): + '''Simple test case for CtorConvRule''' + + def testCtorConvRule(self): + '''Test CtorConvRule argument modification through conversion-rule tag.''' + value = 123 + obj = CtorConvRule(value) + self.assertEqual(obj.value(), value + 1) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/cyclic_test.py b/sources/shiboken2/tests/samplebinding/cyclic_test.py new file mode 100644 index 000000000..e92b3605f --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/cyclic_test.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import ObjectType +from sample import ObjectView +from sample import ObjectModel + + + +class ObjTest(unittest.TestCase): + + def test_cyclic_dependency_withParent(self): + """Create 2 objects with a cyclic dependency, so that they can + only be removed by the garbage collector, and then invoke the + garbage collector in a different thread. + """ + import gc + + class CyclicChildObject(ObjectType): + def __init__(self, parent): + super(CyclicChildObject, self).__init__(parent) + self._parent = parent + + class CyclicObject(ObjectType): + def __init__(self): + super(CyclicObject, self).__init__() + CyclicChildObject(self) + + # 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() ) + + # + # first proof that the wizard is only destructed by the garbage + # collector + # + cycle = CyclicObject() + self.assertTrue(alive()) + del cycle + self.assertTrue(alive()) + gc.collect() + self.assertFalse(alive()) + + def test_cyclic_dependency_withKeepRef(self): + """Create 2 objects with a cyclic dependency, so that they can + only be removed by the garbage collector, and then invoke the + garbage collector in a different thread. + """ + import gc + + class CyclicChildObject(ObjectView): + def __init__(self, model): + super(CyclicChildObject, self).__init__(None) + self.setModel(model) + + class CyclicObject(ObjectModel): + def __init__(self): + super(CyclicObject, self).__init__() + self._view = CyclicChildObject(self) + + # 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() ) + + # + # first proof that the wizard is only destructed by the garbage + # collector + # + cycle = CyclicObject() + self.assertTrue(alive()) + del cycle + self.assertTrue(alive()) + gc.collect() + self.assertFalse(alive()) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/date_test.py b/sources/shiboken2/tests/samplebinding/date_test.py new file mode 100644 index 000000000..800774a57 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/date_test.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for python conversions types ''' + +import sys +import unittest +from datetime import date + +from sample import SbkDate + +class DateConversionTest(unittest.TestCase): + + def testConstructorWithDateObject(self): + pyDate = date(2010, 12, 12) + cDate = SbkDate(pyDate) + self.assertTrue(cDate.day(), pyDate.day) + self.assertTrue(cDate.month(), pyDate.month) + self.assertTrue(cDate.year(), pyDate.year) + + def testToPythonFunction(self): + cDate = SbkDate(2010, 12, 12) + pyDate = cDate.toPython() + self.assertTrue(cDate.day(), pyDate.day) + self.assertTrue(cDate.month(), pyDate.month) + self.assertTrue(cDate.year(), pyDate.year) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/decisor_test.py b/sources/shiboken2/tests/samplebinding/decisor_test.py new file mode 100644 index 000000000..33f41b9ff --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/decisor_test.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for the method overload decisor.''' + +import unittest + +from sample import SampleNamespace, Point, ObjectType, ObjectModel + +class DecisorTest(unittest.TestCase): + '''Test cases for the method overload decisor.''' + + def testCallWithInvalidParametersSideA(self): + '''Call a method missing with the last argument missing. + This can trigger the bug #262, which means using an argument + not provided by the user.''' + pt = Point() + self.assertRaises(TypeError, SampleNamespace.forceDecisorSideA, pt) + + def testCallWithInvalidParametersSideB(self): + '''Same as the previous test, but with an integer as first argument, + just to complicate things for the overload method decisor.''' + pt = Point() + self.assertRaises(TypeError, SampleNamespace.forceDecisorSideB, 1, pt) + + def testDecideCallWithInheritance(self): + '''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) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/delete_test.py b/sources/shiboken2/tests/samplebinding/delete_test.py new file mode 100644 index 000000000..bc20ea234 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/delete_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +import sample +import shiboken2 as shiboken + +class DeleteTest(unittest.TestCase): + def testNonCppWrapperClassDelete(self): + """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/shiboken2/tests/samplebinding/deprecated_test.py b/sources/shiboken2/tests/samplebinding/deprecated_test.py new file mode 100644 index 000000000..6c850cd10 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/deprecated_test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import warnings +import unittest + +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/shiboken2/tests/samplebinding/derived_test.py b/sources/shiboken2/tests/samplebinding/derived_test.py new file mode 100644 index 000000000..b19835fef --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/derived_test.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Derived class''' + +import sys +import unittest + +import sample +from sample import Abstract, Derived, OverloadedFuncEnum + +class Deviant(Derived): + def __init__(self): + Derived.__init__(self) + self.pure_virtual_called = False + self.unpure_virtual_called = False + + def pureVirtual(self): + self.pure_virtual_called = True + + def unpureVirtual(self): + self.unpure_virtual_called = True + + def className(self): + return 'Deviant' + +class DerivedTest(unittest.TestCase): + '''Test case for Derived class''' + + def testParentClassMethodsAvailability(self): + '''Test if Derived class really inherits its methods from parent.''' + inherited_methods = set(['callPureVirtual', 'callUnpureVirtual', + 'id_', 'pureVirtual', 'unpureVirtual']) + self.assertTrue(inherited_methods.issubset(dir(Derived))) + + 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) + + def testOtherOverloadedMethodCall(self): + '''Another test to check overloaded method calling, just to double check.''' + derived = Derived() + + result = derived.otherOverloaded(1, 2, True, 3.3) + self.assertEqual(type(result), Derived.OtherOverloadedFuncEnum) + self.assertEqual(result, sample.Derived.OtherOverloadedFunc_iibd) + + result = derived.otherOverloaded(1, 2.2) + self.assertEqual(type(result), Derived.OtherOverloadedFuncEnum) + self.assertEqual(result, Derived.OtherOverloadedFunc_id) + + 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.''' + 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++.''' + 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++.''' + d = Deviant() + d.callUnpureVirtual() + self.assertTrue(d.unpure_virtual_called) + + def testVirtualMethodCallString(self): + '''Test virtual method call returning string.''' + d = Derived() + self.assertEqual(d.className(), 'Derived') + self.assertEqual(d.getClassName(), 'Derived') + + def testReimplementedVirtualMethodCallReturningString(self): + '''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') + + def testSingleArgument(self): + '''Test singleArgument call.''' + d = Derived() + self.assertTrue(d.singleArgument(False)) + self.assertTrue(not d.singleArgument(True)) + + def testMethodCallWithDefaultValue(self): + '''Test method call with default value.''' + d = Derived() + self.assertEqual(d.defaultValue(3), 3.1) + self.assertEqual(d.defaultValue(), 0.1) + + def testCallToMethodWithAbstractArgument(self): + '''Call to method that expects an Abstract argument.''' + objId = 123 + d = Derived(objId) + 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.''' + obj = Derived.createObject() + self.assertEqual(type(obj), Derived) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/duck_punching_test.py b/sources/shiboken2/tests/samplebinding/duck_punching_test.py new file mode 100644 index 000000000..fd60a96af --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/duck_punching_test.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for virtual methods.''' + +import types +import unittest +from py3kcompat import IS_PY3K + +from sample import VirtualMethods, SimpleFile, Point + +def MethodTypeCompat(func, instance): + if IS_PY3K: + return types.MethodType(func, instance) + else: + return types.MethodType(func, instance, type(instance)) + +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").''' + + def setUp(self): + self.multiplier = 2.0 + self.duck_method_called = False + self.call_counter = 0 + + def testMonkeyPatchOnVirtualMethod(self): + '''Injects new 'virtualMethod0' on a VirtualMethods instance and makes C++ call it.''' + vm = VirtualMethods() + pt, val, cpx, b = Point(1.1, 2.2), 4, complex(3.3, 4.4), True + + result1 = vm.virtualMethod0(pt, val, cpx, b) + result2 = vm.callVirtualMethod0(pt, val, cpx, b) + self.assertEqual(result1, result2) + self.assertEqual(result1, VirtualMethods.virtualMethod0(vm, pt, val, cpx, b)) + + def myVirtualMethod0(obj, pt, val, cpx, b): + self.duck_method_called = True + return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) * self.multiplier + vm.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, vm) + + result1 = vm.callVirtualMethod0(pt, val, cpx, b) + self.assertTrue(self.duck_method_called) + + result2 = vm.virtualMethod0(pt, val, cpx, b) + self.assertEqual(result1, result2) + 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 + # BindingManager. This is useful when compiling Shiboken + # for debug, since the BindingManager destructor has an + # assert that checks if the wrapper mapper is empty. + vm.virtualMethod0 = None + + def testMonkeyPatchOnVirtualMethodWithInheritance(self): + '''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 + + result1 = duck.virtualMethod0(pt, val, cpx, b) + result2 = duck.callVirtualMethod0(pt, val, cpx, b) + self.assertEqual(result1, result2) + self.assertEqual(result1, VirtualMethods.virtualMethod0(duck, pt, val, cpx, b)) + + def myVirtualMethod0(obj, pt, val, cpx, b): + self.duck_method_called = True + return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) * self.multiplier + duck.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, duck) + + result1 = duck.callVirtualMethod0(pt, val, cpx, b) + self.assertTrue(self.duck_method_called) + + result2 = duck.virtualMethod0(pt, val, cpx, b) + self.assertEqual(result1, result2) + self.assertEqual(result1, VirtualMethods.virtualMethod0(duck, pt, val, cpx, b) * self.multiplier) + + duck.virtualMethod0 = None + + def testMonkeyPatchOnMethodWithStaticAndNonStaticOverloads(self): + '''Injects new 'exists' on a SimpleFile instance and makes C++ call it.''' + simplefile = SimpleFile('foobar') + + # Static 'exists' + simplefile.exists('sbrubbles') + self.assertFalse(self.duck_method_called) + # Non-static 'exists' + simplefile.exists() + self.assertFalse(self.duck_method_called) + + def myExists(obj): + self.duck_method_called = True + return False + simplefile.exists = MethodTypeCompat(myExists, simplefile) + + # Static 'exists' was overridden by the monkey patch, which accepts 0 arguments + self.assertRaises(TypeError, simplefile.exists, 'sbrubbles') + # Monkey patched exists + simplefile.exists() + self.assertTrue(self.duck_method_called) + + simplefile.exists = None + + def testMonkeyPatchOnMethodWithStaticAndNonStaticOverloadsWithInheritance(self): + '''Injects new 'exists' on an object that inherits from SimpleFile and makes C++ call it.''' + monkey = Monkey('foobar') + + # Static 'exists' + monkey.exists('sbrubbles') + self.assertFalse(self.duck_method_called) + # Non-static 'exists' + monkey.exists() + self.assertFalse(self.duck_method_called) + + def myExists(obj): + self.duck_method_called = True + return False + monkey.exists = MethodTypeCompat(myExists, monkey) + + # Static 'exists' was overridden by the monkey patch, which accepts 0 arguments + self.assertRaises(TypeError, monkey.exists, 'sbrubbles') + # Monkey patched exists + monkey.exists() + self.assertTrue(self.duck_method_called) + + monkey.exists = None + + def testForInfiniteRecursion(self): + def myVirtualMethod0(obj, pt, val, cpx, b): + self.call_counter += 1 + return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) + vm = VirtualMethods() + vm.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, vm) + pt, val, cpx, b = Point(1.1, 2.2), 4, complex(3.3, 4.4), True + vm.virtualMethod0(pt, val, cpx, b) + self.assertEqual(self.call_counter, 1) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/echo_test.py b/sources/shiboken2/tests/samplebinding/echo_test.py new file mode 100644 index 000000000..1b0b6a2cc --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/echo_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for with const char* as argument''' + +import unittest + +from sample import Echo + +class TestEcho(unittest.TestCase): + '''Simple test case for Echo.echo''' + + def testEcho(self): + '''Test function added with const char * as arg''' + x = 'Foobar' + y = Echo().echo(x) + self.assertEqual(x, y) + + def testCallOperator(self): + e = Echo() + self.assertEqual(e("Hello", 3), "Hello3"); +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/enum_test.py b/sources/shiboken2/tests/samplebinding/enum_test.py new file mode 100644 index 000000000..6468d3cc4 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/enum_test.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Python representation of C++ enums.''' + +import os +import sys +import unittest + +import sample +from sample import SampleNamespace, ObjectType, Event +from py3kcompat import IS_PY3K, b + +def createTempFile(): + if sys.version_info >= (2, 6): + import tempfile + return tempfile.SpooledTemporaryFile(mode='rw') + else: + return os.tmpfile() + +class EnumTest(unittest.TestCase): + '''Test case for Python representation of C++ enums.''' + + 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.values: + enum_item1 = getattr(SampleNamespace.Option, value_name) + enum_item2 = getattr(SampleNamespace, value_name) + self.assertEqual(enum_item1, enum_item2) + + def testPassingIntegerOnEnumArgument(self): + '''Tries to use an integer in place of an enum argument.''' + self.assertRaises(TypeError, SampleNamespace.getNumber, 1) + + def testBuildingEnumFromIntegerValue(self): + '''Tries to build the proper enum using an integer.''' + SampleNamespace.getNumber(SampleNamespace.Option(1)) + + def testBuildingEnumWithDefaultValue(self): + '''Enum constructor with default value''' + enum = SampleNamespace.Option() + self.assertEqual(enum, SampleNamespace.None_) + + def testEnumConversionToAndFromPython(self): + '''Conversion of enum objects from Python to C++ back again.''' + enumout = SampleNamespace.enumInEnumOut(SampleNamespace.TwoIn) + self.assertTrue(enumout, SampleNamespace.TwoOut) + self.assertEqual(repr(enumout), repr(SampleNamespace.TwoOut)) + + def testEnumConstructorWithTooManyParameters(self): + '''Calling the constructor of non-extensible enum with the wrong number of parameters.''' + self.assertRaises(TypeError, SampleNamespace.InValue, 13, 14) + + def testEnumConstructorWithNonNumberParameter(self): + '''Calling the constructor of non-extensible enum with a string.''' + self.assertRaises(TypeError, SampleNamespace.InValue, '1') + + 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(123), 123) + + def testAnonymousGlobalEnums(self): + '''Checks availability of anonymous global enum items.''' + self.assertEqual(sample.AnonymousGlobalEnum_Value0, 0) + self.assertEqual(sample.AnonymousGlobalEnum_Value1, 1) + + def testAnonymousClassEnums(self): + '''Checks availability of anonymous class enum items.''' + self.assertEqual(SampleNamespace.AnonymousClassEnum_Value0, 0) + self.assertEqual(SampleNamespace.AnonymousClassEnum_Value1, 1) + + def testEnumTpPrintImplementation(self): + '''Without SbkEnum.tp_print 'print' returns the enum represented as an int.''' + tmpfile = createTempFile() + if IS_PY3K: + from py3k import printToFile + printToFile(tmpfile, Event.ANY_EVENT) + else: + sys.stdout = tmpfile + print(Event.ANY_EVENT) + sys.stdout = sys.__stdout__ + tmpfile.seek(0) + text = tmpfile.read().strip() + tmpfile.close() + self.assertEqual(text, str(Event.ANY_EVENT)) + self.assertEqual(text, repr(Event.ANY_EVENT)) + + def testEnumArgumentWithDefaultValue(self): + '''Option enumArgumentWithDefaultValue(Option opt = UnixTime);''' + self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(), SampleNamespace.UnixTime) + self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(SampleNamespace.RandomNumber), SampleNamespace.RandomNumber) + + +class MyEvent(Event): + def __init__(self): + Event.__init__(self, Event.EventType(999)) + +class OutOfBoundsTest(unittest.TestCase): + def testValue(self): + e = MyEvent() + self.assertEqual(repr(e.eventType()), 'sample.Event.EventType(999)') + + def testNoneName(self): + e = MyEvent() + t = e.eventType() + self.assertEqual(t.name, None) + +class EnumOverloadTest(unittest.TestCase): + '''Test case for overloads involving enums''' + + def testWithInt(self): + '''Overload with Enums and ints with default value''' + o = ObjectType() + + self.assertEqual(o.callWithEnum('', Event.ANY_EVENT, 9), 81) + self.assertEqual(o.callWithEnum('', 9), 9) + +class EnumOperators(unittest.TestCase): + '''Test case for operations on enums''' + + def testInequalitySameObject(self): + self.assertFalse(Event.ANY_EVENT != Event.ANY_EVENT) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py new file mode 100644 index 000000000..820e21f7c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +import sample + +class TestEnumFromRemovedNamespace(unittest.TestCase): + def testEnumPromotedToGlobal(self): + sample.RemovedNamespace1_Enum + sample.RemovedNamespace1_Enum_Value0 + sample.RemovedNamespace1_AnonymousEnum_Value0 + sample.RemovedNamespace2_Enum + sample.RemovedNamespace2_Enum_Value0 + + def testEnumPromotedToUpperNamespace(self): + sample.UnremovedNamespace + sample.UnremovedNamespace.RemovedNamespace3_Enum + sample.UnremovedNamespace.RemovedNamespace3_Enum_Value0 + sample.UnremovedNamespace.RemovedNamespace3_AnonymousEnum_Value0 + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/event_loop_call_virtual_test.py b/sources/shiboken2/tests/samplebinding/event_loop_call_virtual_test.py new file mode 100644 index 000000000..d8ed028c4 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/event_loop_call_virtual_test.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Simple event loop dispatcher test.''' + +import time +import unittest +from random import random + +from sample import ObjectType, Event + + +class NoOverride(ObjectType): + + pass + + +class Override(ObjectType): + + def __init__(self): + ObjectType.__init__(self) + self.called = False + + def event(self, event): + self.called = True + return True + + +class TestEventLoop(unittest.TestCase): + + def testEventLoop(self): + '''Calling virtuals in a event loop''' + objs = [ObjectType(), NoOverride(), Override()] + + evaluated = ObjectType.processEvent(objs, + Event(Event.BASIC_EVENT)) + + self.assertEqual(evaluated, 3) + self.assertTrue(objs[2].called) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/event_loop_thread_test.py b/sources/shiboken2/tests/samplebinding/event_loop_thread_test.py new file mode 100644 index 000000000..8211ecd15 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/event_loop_thread_test.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import time +import threading +import unittest +from random import random + +from sample import ObjectType, Event + + +class Producer(ObjectType): + + def __init__(self): + ObjectType.__init__(self) + self.data = None + self.read = False + + def event(self, event): + self.data = random() + + while not self.read: + time.sleep(0.01) + + return True + + +class Collector(threading.Thread): + + def __init__(self, objects): + threading.Thread.__init__(self) + self.max_runs = len(objects) + self.objects = objects + self.data = [] + + def run(self): + i = 0 + while i < self.max_runs: + if self.objects[i].data is not None: + self.data.append(self.objects[i].data) + self.objects[i].read = True + i += 1 + time.sleep(0.01) + + +class TestEventLoopWithThread(unittest.TestCase): + '''Communication between a python thread and an simple + event loop in C++''' + + def testBasic(self): + '''Allowing threads and calling virtuals from C++''' + number = 10 + objs = [Producer() for x in range(number)] + thread = Collector(objs) + + thread.start() + + evaluated = ObjectType.processEvent(objs, + Event(Event.BASIC_EVENT)) + + thread.join() + + producer_data = [x.data for x in objs] + self.assertEqual(evaluated, number) + self.assertEqual(producer_data, thread.data) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/filter_test.py b/sources/shiboken2/tests/samplebinding/filter_test.py new file mode 100644 index 000000000..eb84a932c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/filter_test.py @@ -0,0 +1,45 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import Data, Intersection, Union + +class TestFilters(unittest.TestCase): + + def testAnd(self): + + f1 = Data(Data.Name, "joe") + f2 = Union() + + inter = f1 & f2 + + self.assertEqual(type(inter), Intersection) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/global.h b/sources/shiboken2/tests/samplebinding/global.h new file mode 100644 index 000000000..d273de961 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/global.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "abstract.h" +#include "blackbox.h" +#include "bytearray.h" +#include "bucket.h" +#include "collector.h" +#include "complex.h" +#include "ctorconvrule.h" +#include "cvlist.h" +#include "sbkdate.h" +#include "derived.h" +#include "echo.h" +#include "functions.h" +#include "implicitconv.h" +#include "overloadsort.h" +#include "handle.h" +#include "injectcode.h" +#include "list.h" +#include "listuser.h" +#include "mapuser.h" +#include "modelindex.h" +#include "modifications.h" +#include "modified_constructor.h" +#include "multiple_derived.h" +#include "noimplicitconversion.h" +#include "nondefaultctor.h" +#include "objectmodel.h" +#include "objecttype.h" +#include "objecttypebyvalue.h" +#include "objecttypeholder.h" +#include "objecttypelayout.h" +#include "objecttypeoperators.h" +#include "objectview.h" +#include "oddbool.h" +#include "onlycopy.h" +#include "overload.h" +#include "pairuser.h" +#include "pen.h" +#include "photon.h" +#include "point.h" +#include "pointf.h" +#include "pointerholder.h" +#include "polygon.h" +#include "privatector.h" +#include "privatedtor.h" +#include "protected.h" +#include "rect.h" +#include "reference.h" +#include "removednamespaces.h" +#include "sample.h" +#include "samplenamespace.h" +#include "simplefile.h" +#include "size.h" +#include "str.h" +#include "strlist.h" +#include "sometime.h" +#include "templateptr.h" +#include "transform.h" +#include "virtualmethods.h" +#include "voidholder.h" +#include "valueandvirtual.h" +#include "expression.h" +#include "filter.h" diff --git a/sources/shiboken2/tests/samplebinding/handleholder_test.py b/sources/shiboken2/tests/samplebinding/handleholder_test.py new file mode 100644 index 000000000..6d945e499 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/handleholder_test.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +''' Test case for a class that holds a unknown handle object. + Test case for BUG #1105. +''' + +import unittest + +from sample import HandleHolder + +class HandleHolderTest(unittest.TestCase): + def testCreation(self): + holder = HandleHolder(HandleHolder.createHandle()) + holder2 = HandleHolder(HandleHolder.createHandle()) + self.assertEqual(holder.compare(holder2), False) + + def testTransfer(self): + holder = HandleHolder() + holder2 = HandleHolder(holder.handle()) + self.assertTrue(holder.compare(holder2)) + + def testUseDefinedType(self): + holder = HandleHolder(8) + holder2 = HandleHolder(holder.handle2()) + self.assertTrue(holder.compare2(holder2)) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/hashabletype_test.py b/sources/shiboken2/tests/samplebinding/hashabletype_test.py new file mode 100644 index 000000000..069824ca7 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/hashabletype_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for __hash__''' + +import unittest + +from sample import * + +class HashableTest(unittest.TestCase): + + def testStrHash(self): + h = {} + s = Str("Hi") + h[s] = 2 + self.assertTrue(h.get(s), 2) + + def testObjectTypeHash(self): + h = {} + o = ObjectType() + h[o] = 2 + self.assertTrue(h.get(o), 2) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ignorederefop_test.py b/sources/shiboken2/tests/samplebinding/ignorederefop_test.py new file mode 100644 index 000000000..dc3fe8b13 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ignorederefop_test.py @@ -0,0 +1,38 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import * + +class TestLackOfDereferenceOperators (unittest.TestCase): + def testIf(self): + r = Reference() + self.assertFalse(hasattr(r, "__mul__")) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/implicitconv_numerical_test.py b/sources/shiboken2/tests/samplebinding/implicitconv_numerical_test.py new file mode 100644 index 000000000..3fe66e30c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/implicitconv_numerical_test.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for inplicit converting C++ numeric types.''' + +import unittest +import sys +import sample +from py3kcompat import IS_PY3K, l, long + +# Hardcode the limits of the underlying C-types depending on architecture and memory +# model (taking MSVC using LLP64 into account). +cIntMin = -2147483648 +cIntMax = 2147483647 +cLongMin = cIntMin +cLongMax = cIntMax +maxRepresentableInt = sys.maxsize if IS_PY3K else sys.maxint +is64bitArchitecture = maxRepresentableInt > 2**32 +if is64bitArchitecture and sys.platform != 'win32': + cLongMin = -9223372036854775808 + cLongMax = 9223372036854775807 + +class NumericTester(unittest.TestCase): + '''Helper class for numeric comparison testing''' + + def check_value(self, source, expected, callback, desired_type=None): + result = callback(source) + self.assertEqual(result, expected) + + if desired_type: + self.assertEqual(type(result), desired_type) + + +class FloatImplicitConvert(NumericTester): + '''Test case for implicit converting C++ numeric types.''' + + def testFloatAsInt(self): + '''Float as Int''' + self.check_value(3.14, 3, sample.acceptInt, int) + self.assertRaises(OverflowError, sample.acceptInt, cIntMax + 400) + + def testFloatAsLong(self): + '''Float as Long''' + #C++ longs are python ints for us + self.check_value(3.14, 3, sample.acceptLong, int) + self.assertRaises(OverflowError, sample.acceptLong, cLongMax + 400) + + def testFloatAsUInt(self): + '''Float as unsigned Int''' + self.check_value(3.14, 3, sample.acceptUInt, long) + self.assertRaises(OverflowError, sample.acceptUInt, -3.14) + + def testFloatAsULong(self): + '''Float as unsigned Long''' + #FIXME Breaking with SystemError "bad argument to internal function" + self.check_value(3.14, 3, sample.acceptULong, long) + self.assertRaises(OverflowError, sample.acceptULong, -3.14) + + def testFloatAsDouble(self): + '''Float as double''' + self.check_value(3.14, 3.14, sample.acceptDouble, float) + + +class IntImplicitConvert(NumericTester): + '''Test case for implicit converting C++ numeric types.''' + + def testIntAsInt(self): + '''Int as Int''' + self.check_value(3, 3, sample.acceptInt, int) + + def testIntAsLong(self): + '''Int as Long''' + self.check_value(3, 3, sample.acceptLong, int) + + # cLongMax goes here as CPython implements int as a C long + self.check_value(cLongMax, cLongMax, sample.acceptLong, int) + self.check_value(cLongMin, cLongMin, sample.acceptLong, int) + + def testIntAsUInt(self): + '''Int as unsigned Int''' + self.check_value(3, 3, sample.acceptUInt, long) + self.assertRaises(OverflowError, sample.acceptUInt, -3) + + def testIntAsULong(self): + '''Int as unsigned Long''' + self.check_value(3, 3, sample.acceptULong, long) + self.assertRaises(OverflowError, sample.acceptULong, -3) + + def testFloatAsDouble(self): + '''Float as double''' + self.check_value(3.14, 3.14, sample.acceptDouble, float) + + +class LongImplicitConvert(NumericTester): + '''Test case for implicit converting C++ numeric types.''' + + def testLongAsInt(self): + '''Long as Int''' + self.check_value(l(24224), 24224, sample.acceptInt, int) + self.assertRaises(OverflowError, sample.acceptInt, cIntMax + 20) + + def testLongAsLong(self): + '''Long as Long''' + self.check_value(l(2405), 2405, sample.acceptLong, int) + self.assertRaises(OverflowError, sample.acceptLong, cLongMax + 20) + + def testLongAsUInt(self): + '''Long as unsigned Int''' + self.check_value(l(260), 260, sample.acceptUInt, long) + self.assertRaises(OverflowError, sample.acceptUInt, -42) + + def testLongAsULong(self): + '''Long as unsigned Long''' + self.check_value(l(128), 128, sample.acceptULong, long) + self.assertRaises(OverflowError, sample.acceptULong, l(-334)) + + def testLongAsDouble(self): + '''Float as double''' + self.check_value(l(42), 42, sample.acceptDouble, float) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/implicitconv_test.py b/sources/shiboken2/tests/samplebinding/implicitconv_test.py new file mode 100644 index 000000000..a94151d80 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/implicitconv_test.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for implicit conversions''' + +import unittest + +from sample import ImplicitConv, ObjectType + +class ImplicitConvTest(unittest.TestCase): + '''Test case for implicit conversions''' + + def testImplicitConversions(self): + '''Test if overloaded function call decisor takes implicit conversions into account.''' + ic = ImplicitConv.implicitConvCommon(ImplicitConv()) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorNone) + + ic = ImplicitConv.implicitConvCommon(3) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorOne) + self.assertEqual(ic.objId(), 3) + + ic = ImplicitConv.implicitConvCommon(ImplicitConv.CtorThree) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorThree) + + obj = ObjectType() + ic = ImplicitConv.implicitConvCommon(obj) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorObjectTypeReference) + + ic = ImplicitConv.implicitConvCommon(42.42) + self.assertEqual(ic.value(), 42.42) + + ic = ImplicitConv(None) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorPrimitiveType) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/inheritanceandscope_test.py b/sources/shiboken2/tests/samplebinding/inheritanceandscope_test.py new file mode 100755 index 000000000..a8ede0548 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/inheritanceandscope_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for finding scope in cases involving inheritance.''' + +import unittest + +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') + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/injectcode_test.py b/sources/shiboken2/tests/samplebinding/injectcode_test.py new file mode 100644 index 000000000..99847f891 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/injectcode_test.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for std::list container conversions''' + +import unittest +from sample import InjectCode + +class MyInjectCode(InjectCode): + def __init__(self): + InjectCode.__init__(self) + self.multiplier = 2 + + def arrayMethod(self, values): + return self.multiplier * sum(values) + +class InjectCodeTest(unittest.TestCase): + + def testTypeNativeBeginning_TypeTargetBeginning(self): + ic = InjectCode() + self.assertEqual(str(ic), "Hi! I'm the inject code dummy class.") + + def testFunctionTargetBeginning_FunctionTargetEnd(self): + ic = InjectCode() + ret = ic.simpleMethod1(2, 1) + self.assertEqual(ret, "4end") + ret = ic.simpleMethod1(4, 2) + self.assertEqual(ret, "7end") + + def testFunctionTargetBeginning(self): + ic = InjectCode() + ret = ic.simpleMethod2() + self.assertEqual(ret, "_end") + + def testArgsModification(self): + ic = InjectCode() + ret = ic.overloadedMethod(["1", "2", "3", "4"]) + self.assertEqual(ret, "1234") + ret = ic.overloadedMethod(2, 0.5) + self.assertEqual(ret, "2.5") + ret = ic.overloadedMethod(6, True) + self.assertEqual(ret, "6true") + + def testArgsModification2(self): + ic = InjectCode() + ret = ic.simpleMethod3(["1", "2", "3", "4"]) + self.assertEqual(ret, "1234") + + def testArgumentRemovalAndArgumentTypeModification(self): + '''A method has its first argument removed and the second modified.''' + ic = InjectCode() + values = (1, 2, 3, 4, 5) + result = ic.arrayMethod(values) + self.assertEqual(result, sum(values)) + + def testCallVirtualMethodWithArgumentRemovalAndArgumentTypeModification(self): + '''A virtual method has its first argument removed and the second modified.''' + ic = InjectCode() + values = (1, 2, 3, 4, 5) + result = ic.callArrayMethod(values) + self.assertEqual(result, sum(values)) + + def testCallReimplementedVirtualMethodWithArgumentRemovalAndArgumentTypeModification(self): + '''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.''' + 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)) + + +class IntArrayTest(unittest.TestCase): + '''Test case for converting python sequence to int array''' + + def testBasic(self): + '''Shiboken::sequenceToIntArray - basic case''' + args = [1, 2, 3, 4] + ic = InjectCode() + self.assertEqual(sum(args) + len(args), ic.sumArrayAndLength(args)) + + def testEmpty(self): + '''Shiboken::sequenceToIntArray - empty sequence''' + args = [] + ic = InjectCode() + self.assertEqual(sum(args) + len(args), ic.sumArrayAndLength(args)) + + def testWithZero(self): + '''Shiboken::sequenceToIntArray - count only up to zero''' + args = [1, 2, 0, 3] + ic = InjectCode() + self.assertEqual(sum([1, 2]) + len([1, 2]), ic.sumArrayAndLength(args)) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/innerclass_test.py b/sources/shiboken2/tests/samplebinding/innerclass_test.py new file mode 100644 index 000000000..0df636857 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/innerclass_test.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import Derived + +class TestInnerClass(unittest.TestCase): + def testInstaciate(self): + d = Derived.SomeInnerClass() + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/intlist_test.py b/sources/shiboken2/tests/samplebinding/intlist_test.py new file mode 100644 index 000000000..6d21ef053 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/intlist_test.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import IntList + +class IntListTest(unittest.TestCase): + + def testAutoFunctionsToBaseList(self): + lst = IntList() + self.assertEqual(len(lst), 0) + lst.append(10) + self.assertEqual(lst[0], 10) + lst.append(20) + self.assertEqual(lst[1], 20) + lst.append(30) + self.assertEqual(lst[2], 30) + lst[1] = 25 + self.assertEqual(lst[0], 10) + self.assertEqual(lst[1], 25) + self.assertEqual(lst[2], 30) + self.assertEqual(len(lst), 3) + + def testIntListCtor_NoParams(self): + '''IntList constructor receives no parameter.''' + il = IntList() + self.assertEqual(len(il), 0) + self.assertEqual(il.constructorUsed(), IntList.NoParamsCtor) + + def testIntListCtor_int(self): + '''IntList constructor receives an integer.''' + value = 123 + il = IntList(value) + self.assertEqual(len(il), 1) + self.assertEqual(il[0], value) + self.assertEqual(il.constructorUsed(), IntList.IntCtor) + + def testIntListCtor_IntList(self): + '''IntList constructor receives an IntList object.''' + il1 = IntList(123) + il2 = IntList(il1) + self.assertEqual(len(il1), len(il2)) + for i in range(len(il1)): + self.assertEqual(il1[i], il2[i]) + self.assertEqual(il2.constructorUsed(), IntList.CopyCtor) + + def testIntListCtor_ListOfInts(self): + '''IntList constructor receives an integer list.''' + ints = [123, 456] + il = IntList(ints) + self.assertEqual(len(il), len(ints)) + for i in range(len(il)): + self.assertEqual(il[i], ints[i]) + self.assertEqual(il.constructorUsed(), IntList.ListOfIntCtor) + + def testIntListAttributeTypeCheck(self): + '''Attribute values to IntList.''' + il = IntList([0, 1, 2]) + self.assertEqual(len(il), 3) + il[0] = 123 + self.assertEqual(len(il), 3) + self.assertEqual(il[0], 123) + il[1] = 432.1 + self.assertEqual(len(il), 3) + self.assertEqual(il[1], int(432.1)) + self.assertRaises(TypeError, il.__setitem__, 2, '78') + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/invalid_virtual_return_test.py b/sources/shiboken2/tests/samplebinding/invalid_virtual_return_test.py new file mode 100644 index 000000000..f160f1e07 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/invalid_virtual_return_test.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for returning invalid types in a virtual function''' + +import unittest +from sample import ObjectModel, ObjectType, ObjectView + +import warnings + + +class MyObject(ObjectType): + pass + + +class ListModelWrong(ObjectModel): + + def __init__(self, parent=None): + ObjectModel.__init__(self, parent) + self.obj = 0 + + def data(self): + warnings.simplefilter('error') + # Shouldn't segfault. Must set TypeError + return self.obj + + +class ModelWrongReturnTest(unittest.TestCase): + + def testWrongTypeReturn(self): + model = ListModelWrong() + view = ObjectView(model) + self.assertRaises(RuntimeWarning, view.getRawModelData) # calls model.data() + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/keep_reference_test.py b/sources/shiboken2/tests/samplebinding/keep_reference_test.py new file mode 100644 index 000000000..a8f63f6df --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/keep_reference_test.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' + +import unittest +from sys import getrefcount + +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).''' + + def testReferenceCounting(self): + '''Tests reference count of model-like object referred by view-like objects.''' + model1 = ObjectModel() + refcount1 = getrefcount(model1) + view1 = ObjectView() + view1.setModel(model1) + self.assertEqual(getrefcount(view1.model()), refcount1 + 1) + + view2 = ObjectView() + view2.setModel(model1) + self.assertEqual(getrefcount(view2.model()), refcount1 + 2) + + model2 = ObjectModel() + view2.setModel(model2) + self.assertEqual(getrefcount(view1.model()), refcount1 + 1) + + def testReferenceCountingWhenDeletingReferrer(self): + '''Tests reference count of model-like object referred by deceased view-like object.''' + model = ObjectModel() + refcount1 = getrefcount(model) + view = ObjectView() + view.setModel(model) + self.assertEqual(getrefcount(view.model()), refcount1 + 1) + + del view + self.assertEqual(getrefcount(model), refcount1) + + def testReferreedObjectSurvivalAfterContextEnd(self): + '''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() + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/list_test.py b/sources/shiboken2/tests/samplebinding/list_test.py new file mode 100644 index 000000000..22cb4c04b --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/list_test.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for std::list container conversions''' + +import unittest + +from sample import ListUser, Point, PointF + +class ExtendedListUser(ListUser): + def __init__(self): + ListUser.__init__(self) + self.create_list_called = False + + def createList(self): + self.create_list_called = True + return [2, 3, 5, 7, 13] + +class ListConversionTest(unittest.TestCase): + '''Test case for std::list container conversions''' + + def testReimplementedVirtualMethodCall(self): + '''Test if a Python override of a virtual method is correctly called from C++.''' + lu = ExtendedListUser() + lst = lu.callCreateList() + self.assertTrue(lu.create_list_called) + self.assertEqual(type(lst), list) + for item in lst: + self.assertEqual(type(item), int) + + def testPrimitiveConversionInsideContainer(self): + '''Test primitive type conversion inside conversible std::list container.''' + cpx0 = complex(1.2, 3.4) + cpx1 = complex(5.6, 7.8) + lst = ListUser.createComplexList(cpx0, cpx1) + self.assertEqual(type(lst), list) + for item in lst: + self.assertEqual(type(item), complex) + self.assertEqual(lst, [cpx0, cpx1]) + + def testSumListIntegers(self): + '''Test method that sums a list of integer values.''' + lu = ListUser() + lst = [3, 5, 7] + result = lu.sumList(lst) + self.assertEqual(result, sum(lst)) + + def testSumListFloats(self): + '''Test method that sums a list of float values.''' + lu = ListUser() + lst = [3.3, 4.4, 5.5] + result = lu.sumList(lst) + self.assertEqual(result, sum(lst)) + + def testConversionInBothDirections(self): + '''Test converting a list from Python to C++ and back again.''' + lu = ListUser() + lst = [3, 5, 7] + lu.setList(lst) + result = lu.getList() + self.assertEqual(result, lst) + + def testConversionInBothDirectionsWithSimilarContainer(self): + '''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) + result = lu.getList() + self.assertNotEqual(result, lst) + self.assertEqual(result, list(lst)) + + def testConversionOfListOfObjectsPassedAsArgument(self): + '''Calls method with a Python list of wrapped objects to be converted to a C++ list.''' + mult = 3 + pts0 = (Point(1.0, 2.0), Point(3.3, 4.4), Point(5, 6)) + pts1 = (Point(1.0, 2.0), Point(3.3, 4.4), Point(5, 6)) + ListUser.multiplyPointList(pts1, mult) + for pt0, pt1 in zip(pts0, pts1): + self.assertEqual(pt0.x() * mult, pt1.x()) + self.assertEqual(pt0.y() * mult, pt1.y()) + + def testConversionOfInvalidLists(self): + mult = 3 + pts = (Point(1.0, 2.0), 3, Point(5, 6)) + self.assertRaises(TypeError, ListUser.multiplyPointList, pts, mult) + + def testOverloadMethodReceivingRelatedContainerTypes(self): + self.assertEqual(ListUser.ListOfPointF, ListUser.listOfPoints([PointF()])) + self.assertEqual(ListUser.ListOfPoint, ListUser.listOfPoints([Point()])) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/lock_test.py b/sources/shiboken2/tests/samplebinding/lock_test.py new file mode 100644 index 000000000..35bf5149d --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/lock_test.py @@ -0,0 +1,95 @@ +#!/usr/bin/env python + +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Simple test with a blocking C++ method that should allow python + threads to run.''' + +import unittest +import threading + +from sample import Bucket + + +class Unlocker(threading.Thread): + + def __init__(self, bucket): + threading.Thread.__init__(self) + self.bucket = bucket + + def run(self): + while not self.bucket.locked(): + pass + + self.bucket.unlock() + + +class MyBucket(Bucket): + + def __init__(self): + Bucket.__init__(self) + + def virtualBlockerMethod(self): + self.lock() + return True + + +class TestLockUnlock(unittest.TestCase): + + def testBasic(self): + '''Locking in C++ and releasing in a python thread''' + bucket = Bucket() + unlocker = Unlocker(bucket) + + unlocker.start() + bucket.lock() + unlocker.join() + + def testVirtualBlocker(self): + '''Same as the basic case but blocker method is a C++ virtual called from C++.''' + bucket = Bucket() + unlocker = Unlocker(bucket) + + unlocker.start() + result = bucket.callVirtualBlockerMethodButYouDontKnowThis() + unlocker.join() + 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++.''' + mybucket = MyBucket() + unlocker = Unlocker(mybucket) + + unlocker.start() + result = mybucket.callVirtualBlockerMethodButYouDontKnowThis() + unlocker.join() + self.assertTrue(result) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/map_test.py b/sources/shiboken2/tests/samplebinding/map_test.py new file mode 100644 index 000000000..18cefd857 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/map_test.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for std::map container conversions''' + +import unittest + +from sample import MapUser + +class ExtendedMapUser(MapUser): + def __init__(self): + MapUser.__init__(self) + self.create_map_called = False + + 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)} + +class MapConversionTest(unittest.TestCase): + '''Test case for std::map container conversions''' + + def testReimplementedVirtualMethodCall(self): + '''Test if a Python override of a virtual method is correctly called from C++.''' + mu = ExtendedMapUser() + map_ = mu.callCreateMap() + self.assertTrue(mu.create_map_called) + self.assertEqual(type(map_), dict) + for key, value in map_.items(): + self.assertEqual(type(key), str) + self.assertEqual(type(value[0]), complex) + self.assertEqual(type(value[1]), int) + + 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]} + mu.setMap(map_) + result = mu.getMap() + self.assertEqual(result, map_) + + def testConversionMapIntKeyValueTypeValue(self): + '''C++ signature: MapUser::passMapIntValueType(const std::map&)''' + mu = MapUser() + map_ = {0 : 'string'} + result = mu.passMapIntValueType(map_) + self.assertEqual(map_, result) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/metaclass_test.py b/sources/shiboken2/tests/samplebinding/metaclass_test.py new file mode 100644 index 000000000..972a2f17d --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/metaclass_test.py @@ -0,0 +1,61 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +from sample import * +import unittest + +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.setX(1) + w1.setY(2) + + w2 = D() # should work! + w2.setX(3) + w2.setY(4) + + w3 = w1 + w2 + self.assertEqual(w3.x(), 4) + self.assertEqual(w3.y(), 6) diff --git a/sources/shiboken2/tests/samplebinding/mi_virtual_methods_test.py b/sources/shiboken2/tests/samplebinding/mi_virtual_methods_test.py new file mode 100644 index 000000000..0905dead9 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/mi_virtual_methods_test.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for virtual methods in multiple inheritance scenarios''' + +import unittest + +from sample import VirtualMethods, ObjectType, Event + + +class ImplementsNone(ObjectType, VirtualMethods): + '''Implements no virtual methods''' + + def __init__(self): + ObjectType.__init__(self) + VirtualMethods.__init__(self) + + +class ImplementsBoth(ObjectType, VirtualMethods): + '''Implements ObjectType.event and VirtualMethods.sum1''' + + def __init__(self): + ObjectType.__init__(self) + VirtualMethods.__init__(self) + self.event_processed = False + + def event(self, event): + self.event_processed = True + return True + + def sum1(self, arg0, arg1, arg2): + return (arg0 + arg1 + arg2) * 2 + + +class CppVirtualTest(unittest.TestCase): + '''Virtual method defined in c++ called from C++''' + + def testCpp(self): + '''C++ calling C++ virtual method in multiple inheritance scenario''' + obj = ImplementsNone() + self.assertTrue(ObjectType.processEvent([obj], Event(Event.BASIC_EVENT))) + self.assertRaises(AttributeError, getattr, obj, 'event_processed') + + self.assertEqual(obj.callSum0(1, 2, 3), 6) + + +class PyVirtualTest(unittest.TestCase): + '''Virtual method reimplemented in python called from C++''' + + def testEvent(self): + '''C++ calling Python reimplementation of virtual in multiple inheritance''' + obj = ImplementsBoth() + self.assertTrue(ObjectType.processEvent([obj], Event(Event.BASIC_EVENT))) + self.assertTrue(obj.event_processed) + + self.assertEqual(obj.callSum1(1, 2, 3), 12) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/mixed_mi_test.py b/sources/shiboken2/tests/samplebinding/mixed_mi_test.py new file mode 100644 index 000000000..b6268cf2c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/mixed_mi_test.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for multiple inheritance in mixed Python/C++ scenarios''' + +import unittest + +from sample import ObjectType + + +class Base(object): + '''Base Python class''' + + def __init__(self): + self.name = '' + + def pythonName(self): + return self.name + + def setPythonName(self, name): + self.name = name + + +class Child(Base, ObjectType): + '''Dummy class with mixed parents''' + + def __init__(self): + Base.__init__(self) + ObjectType.__init__(self) + + +class MixedInheritanceTest(unittest.TestCase): + + def testMixed(self): + '''Mixed Python/C++ multiple inheritance''' + obj = Child() + + obj.setObjectName('aaa') + self.assertEqual(obj.objectName(), 'aaa') + + obj.setPythonName('python') + self.assertEqual(obj.pythonName(), 'python') + + +if __name__ == '__main__': + unittest.main() + + diff --git a/sources/shiboken2/tests/samplebinding/modelindex_test.py b/sources/shiboken2/tests/samplebinding/modelindex_test.py new file mode 100644 index 000000000..5dd7d3bc7 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/modelindex_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import ModelIndex, ReferentModelIndex, PersistentModelIndex + +class TestCastOperator(unittest.TestCase): + + def testCastOperatorReturningValue(self): + index = PersistentModelIndex() + index.setValue(123) + self.assertEqual(index.value(), 123) + self.assertEqual(index.value(), ModelIndex.getValue(index)) + + def testCastOperatorReturningReference(self): + index = ReferentModelIndex() + index.setValue(123) + self.assertEqual(index.value(), 123) + self.assertEqual(index.value(), ModelIndex.getValue(index)) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/modelview_test.py b/sources/shiboken2/tests/samplebinding/modelview_test.py new file mode 100644 index 000000000..081de303d --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/modelview_test.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' + +import unittest +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) + self.obj = MyObject() + self.obj.setObjectName(object_name) + + def data(self): + return self.obj + +class ListModelDoesntKeepsReference(ObjectModel): + def data(self): + obj = MyObject() + obj.setObjectName(object_name) + return obj + + +class ModelViewTest(unittest.TestCase): + + def testListModelDoesntKeepsReference(self): + model = ListModelDoesntKeepsReference() + view = ObjectView(model) + obj = view.getRawModelData() + self.assertEqual(type(obj), MyObject) + self.assertEqual(obj.objectName(), object_name) + + def testListModelKeepsReference(self): + model = ListModelKeepsReference() + view = ObjectView(model) + obj = view.getRawModelData() + self.assertEqual(type(obj), MyObject) + self.assertEqual(obj.objectName(), object_name) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/modifications_test.py b/sources/shiboken2/tests/samplebinding/modifications_test.py new file mode 100644 index 000000000..44748dc8c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/modifications_test.py @@ -0,0 +1,224 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for method modifications performed as described on type system. ''' + +import unittest + +from sample import Modifications, Point, ByteArray + +class ExtModifications(Modifications): + def __init__(self): + Modifications.__init__(self) + self.multiplier = 3.0 + self.increment = 10.0 + + def name(self): + return 'ExtModifications' + + def differenceOfPointCoordinates(self, point): + ok, res = Modifications.differenceOfPointCoordinates(self, point) + return ok, res * self.multiplier + self.increment + + +class ModificationsTest(unittest.TestCase): + '''Test cases for method modifications performed as described on type system. ''' + + def setUp(self): + self.mods = Modifications() + + def tearDown(self): + del self.mods + + 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'.''' + 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.''' + em = ExtModifications() + self.assertEqual(self.mods.name(), 'Modifications') + self.assertEqual(em.name(), 'ExtModifications') + + def testRegularMethodRenaming(self): + '''Test if Modifications::cppMultiply was correctly renamed to calculateArea.''' + self.assertTrue('cppMultiply' not in dir(Modifications)) + self.assertTrue('calculateArea' in dir(Modifications)) + self.assertEqual(self.mods.calculateArea(3, 6), 3 * 6) + + def testRegularMethodRemoval(self): + '''Test if 'Modifications::exclusiveCppStuff' was removed from Python bindings.''' + self.assertTrue('exclusiveCppStuff' not in dir(Modifications)) + + def testArgumentRemoval(self): + '''Test if second argument of Modifications::doublePlus(int, int) was removed.''' + self.assertRaises(TypeError, self.mods.doublePlus, 3, 7) + self.assertEqual(self.mods.doublePlus(7), 14) + + def testDefaultValueRemoval(self): + '''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.''' + # 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); + self.assertEqual(self.mods.power(), 2) + self.assertEqual(self.mods.power(3), 3) + 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).''' + 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).''' + result, ok = self.mods.pointToPair(Point(2, 5)) + self.assertEqual(type(ok), bool) + self.assertEqual(type(result), tuple) + self.assertEqual(len(result), 2) + self.assertEqual(type(result[0]), float) + self.assertEqual(type(result[1]), float) + self.assertEqual(result[0], 2.0) + self.assertEqual(result[1], 5.0) + + def testArgumentRemovalAndReturnTypeModificationWithTypesystemTemplates2(self): + '''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) + self.assertEqual(result, 14.1) + + def testOverloadedMethodModifications(self): + '''Tests modifications to an overloaded method''' + # overloaded(int, bool[removed], int, double) + self.assertEqual(self.mods.overloaded(1, 2, 3.1), Modifications.Overloaded_ibid) + # overloaded(int, bool, int[removed,default=321], int) + 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.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) + + def testPointArrayModification(self): + points = (Point(1, 1), Point(2, 2)) + summedPoint = Point(1, 1) + Point(2, 2) + self.assertEqual(self.mods.sumPointArray(points), summedPoint) + + def testTypeSystemVariableReplacementInFunctionModification(self): + ba = ByteArray('12345') + self.assertEqual(self.mods.getSize(ba), len(ba)) + self.assertEqual(self.mods.getSize(ba, 20), 20) + + def testNoNulPointerTag(self): + point = Point(12, 34) + self.assertEqual(self.mods.sumPointCoordinates(point), 12 + 34) + self.assertRaises(TypeError, self.mods.sumPointCoordinates, None) + + def testNonConversionRuleForArgumentWithDefaultValue(self): + status, obj = self.mods.nonConversionRuleForArgumentWithDefaultValue() + self.assertTrue(status) + self.assertEqual(obj, self.mods.getObject()) + self.assertEqual(obj.objectName(), 'MyObject') + + def testInjectCodeWithConversionVariableForUserPrimitive(self): + self.assertTrue(Modifications.invertBoolean(False)) + self.assertFalse(Modifications.invertBoolean(True)) + + def testConversionRuleForReturnType(self): + x, y = 11, 2 + diff = float(abs(x - y)) + point = Point(x, y) + + ok, res = self.mods.differenceOfPointCoordinates(point) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, diff) + + ok, res = self.mods.callDifferenceOfPointCoordinates(point) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, diff) + + ok, res = self.mods.differenceOfPointCoordinates(None) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, 0.0) + + ok, res = self.mods.callDifferenceOfPointCoordinates(None) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, 0.0) + + def testConversionRuleForReturnTypeOnExtendedClass(self): + x, y = 11, 2 + diff = float(abs(x - y)) + point = Point(x, y) + em = ExtModifications() + + ok, res = em.differenceOfPointCoordinates(point) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, diff * em.multiplier + em.increment) + + ok, res = em.callDifferenceOfPointCoordinates(point) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, diff * em.multiplier + em.increment) + + ok, res = em.differenceOfPointCoordinates(None) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, em.increment) + + ok, res = em.callDifferenceOfPointCoordinates(None) + self.assertTrue(isinstance(ok, bool)) + self.assertTrue(isinstance(res, float)) + self.assertEqual(res, em.increment) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/modified_constructor_test.py b/sources/shiboken2/tests/samplebinding/modified_constructor_test.py new file mode 100644 index 000000000..859f89452 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/modified_constructor_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests cases for ConstructorWithModifiedArgument class.''' + +import sys +import unittest + +from sample import * + + +class ConstructorWithModifiedArgumentTest(unittest.TestCase): + '''Test cases for ConstructorWithModifiedArgument class.''' + + def testConstructorWithModifiedArgument(self): + sampleClass = ModifiedConstructor("10") + self.assertTrue(sampleClass.retrieveValue(), 10) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/modifiedvirtualmethods_test.py b/sources/shiboken2/tests/samplebinding/modifiedvirtualmethods_test.py new file mode 100644 index 000000000..3121a9cc2 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/modifiedvirtualmethods_test.py @@ -0,0 +1,248 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for modified virtual methods.''' + +import unittest + +from sample import VirtualMethods, Str + +class ExtendedVirtualMethods(VirtualMethods): + def __init__(self): + VirtualMethods.__init__(self) + self.name_called = False + self.sum0_called = False + self.sum1_called = False + self.sum2_called = False + self.sum3_called = False + self.sum4_called = False + self.sumThree_called = False + self.callMe_called = 0 + self.multiplier = 12345 + + def sum0(self, a0, a1, a2): + self.sum0_called = True + return VirtualMethods.sumThree(self, a0, a1, a2) * self.multiplier + + def sumThree(self, a0, a1, a2): + self.sumThree_called = True + return VirtualMethods.sumThree(self, a0, a1, a2) * self.multiplier + + def sum1(self, a0, a1, a2): + self.sum1_called = True + return VirtualMethods.sum1(self, a0, a1, a2) * self.multiplier + + def sum2(self, a0, a1): + self.sum2_called = True + return VirtualMethods.sum2(self, a0, a1) * self.multiplier + + def sum3(self, a0, a1): + self.sum3_called = True + return VirtualMethods.sum3(self, a0, a1) * self.multiplier + + def sum4(self, a0, a1): + self.sum4_called = True + return VirtualMethods.sum4(self, a0, a1) * self.multiplier + + def name(self): + self.name_called = True + return Str('ExtendedVirtualMethods') + + def callMe(self): + self.callMe_called += 1 + + def getMargins(self): + return tuple([m*2 for m in VirtualMethods.getMargins(self)]) + + +class VirtualMethodsTest(unittest.TestCase): + '''Test case for modified virtual methods.''' + + def setUp(self): + self.vm = VirtualMethods() + self.evm = ExtendedVirtualMethods() + + def tearDown(self): + del self.vm + del self.evm + + def testModifiedVirtualMethod0(self): + '''Renamed virtual method.''' + a0, a1, a2 = 2, 3, 5 + result0 = self.vm.callSum0(a0, a1, a2) + result1 = self.vm.sumThree(a0, a1, a2) + self.assertEqual(result0, a0 + a1 + a2) + self.assertEqual(result0, result1) + self.assertRaises(AttributeError, getattr, self.vm, 'sum0') + + def testReimplementedModifiedVirtualMethod0(self): + '''Override of a renamed virtual method.''' + a0, a1, a2 = 2, 3, 5 + result0 = self.vm.callSum0(a0, a1, a2) + result1 = self.vm.sumThree(a0, a1, a2) + result2 = self.evm.callSum0(a0, a1, a2) + self.assertEqual(result0, result1) + self.assertEqual(result0 * self.evm.multiplier, result2) + self.assertTrue(self.evm.sumThree_called) + self.assertFalse(self.evm.sum0_called) + + def testModifiedVirtualMethod1(self): + '''Virtual method with three arguments and the last one + changed to have the default value set to 1000.''' + a0, a1, a2 = 2, 3, 5 + result0 = self.vm.sum1(a0, a1) + self.assertEqual(result0, a0 + a1 + 1000) + result1 = self.vm.sum1(a0, a1, a2) + result2 = self.vm.callSum1(a0, a1, a2) + self.assertEqual(result1, result2) + + def testReimplementedModifiedVirtualMethod1(self): + '''Override of the virtual method with three arguments and + the last one changed to have the default value set to 1000.''' + a0, a1 = 2, 3 + result0 = self.vm.sum1(a0, a1) + result1 = self.evm.callSum1(a0, a1, 1000) + self.assertEqual(result0 * self.evm.multiplier, result1) + self.assertTrue(self.evm.sum1_called) + + def testModifiedVirtualMethod2(self): + '''Virtual method originally with three arguments, the last + one was removed and the default value set to 2000.''' + a0, a1 = 1, 2 + result0 = self.vm.sum2(a0, a1) + self.assertEqual(result0, a0 + a1 + 2000) + result1 = self.vm.sum2(a0, a1) + result2 = self.vm.callSum2(a0, a1, 2000) + self.assertEqual(result1, result2) + self.assertRaises(TypeError, self.vm.sum2, 1, 2, 3) + + def testReimplementedModifiedVirtualMethod2(self): + '''Override of the virtual method originally with three arguments, + the last one was removed and the default value set to 2000.''' + a0, a1 = 1, 2 + ignored = 54321 + result0 = self.vm.sum2(a0, a1) + result1 = self.evm.callSum2(a0, a1, ignored) + self.assertEqual(result0 * self.evm.multiplier, result1) + self.assertTrue(self.evm.sum2_called) + + def testModifiedVirtualMethod3(self): + '''Virtual method originally with three arguments have the second + one removed and replaced by custom code that replaces it by the sum + of the first and the last arguments.''' + a0, a1 = 1, 2 + result0 = self.vm.sum3(a0, a1) + self.assertEqual(result0, a0 + (a0 + a1) + a1) + result1 = self.vm.callSum3(a0, 10, a1) + self.assertNotEqual(result0, result1) + result2 = self.vm.callSum3(a0, a0 + a1, a1) + self.assertEqual(result0, result2) + self.assertRaises(TypeError, self.vm.sum3, 1, 2, 3) + + def testReimplementedModifiedVirtualMethod3(self): + '''Override of the virtual method originally with three arguments + have the second one removed and replaced by custom code that + replaces it by the sum of the first and the last arguments.''' + a0, a1 = 1, 2 + ignored = 54321 + result0 = self.vm.sum3(a0, a1) + result1 = self.evm.callSum3(a0, ignored, a1) + self.assertEqual(result0 * self.evm.multiplier, result1) + self.assertTrue(self.evm.sum3_called) + + def testModifiedVirtualMethod4(self): + '''Virtual method originally with three arguments, the + last one was removed and the default value set to 3000.''' + a0, a1 = 1, 2 + default_value = 3000 + result0 = self.vm.sum4(a0, a1) + self.assertEqual(result0, a0 + default_value + a1) + removed_arg_value = 100 + result1 = self.vm.callSum4(a0, removed_arg_value, a1) + self.assertEqual(result1, a0 + removed_arg_value + a1) + self.assertRaises(TypeError, self.vm.sum4, 1, 2, 3) + + def testReimplementedModifiedVirtualMethod4(self): + '''Override of the virtual method originally with three arguments, + the last one was removed and the default value set to 3000. + The method was modified with code injection on the binding override + (the one that receives calls from C++ with the original signature + and forwards it to Python overrides) that subtracts the value of the + second argument (removed in Python) from the value of the first + before sending them to Python.''' + a0, a1 = 1, 2 + 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.assertTrue(self.evm.sum4_called) + + def testOverridenMethodResultModification(self): + '''Injected code modifies the result of a call to a virtual + method overridden in Python.''' + orig_name = self.vm.callName() + self.assertEqual(orig_name, 'VirtualMethods') + name = self.evm.callName() + self.assertEqual(name, 'PimpedExtendedVirtualMethods') + self.assertEqual(name, Str('PimpedExtendedVirtualMethods')) + self.assertTrue(self.evm.name_called) + + def testInjectCodeCallsPythonVirtualMethodOverride(self): + '''When injected code calls the Python override by itself + no code for the method call should be generated.''' + self.evm.callCallMe() + self.assertEqual(self.evm.callMe_called, 1) + + def testAllArgumentsRemoved(self): + values = (10, 20, 30, 40) + self.vm.setMargins(*values) + self.assertEqual(self.vm.getMargins(), values) + + def testAllArgumentsRemovedCallVirtual(self): + values = (10, 20, 30, 40) + self.vm.setMargins(*values) + self.assertEqual(self.vm.callGetMargins(), values) + + def testExtendedAllArgumentsRemoved(self): + values = (10, 20, 30, 40) + self.evm.setMargins(*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]) + self.assertEqual(self.evm.callGetMargins(), double) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/multi_cpp_inheritance_test.py b/sources/shiboken2/tests/samplebinding/multi_cpp_inheritance_test.py new file mode 100644 index 000000000..6546c3ac6 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/multi_cpp_inheritance_test.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for multiple inheritance''' + +import sys +import unittest + +from sample import * + +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): + s = SimpleUseCase("Hi") + self.assertEqual(s, "Hi") + s.setObjectName(s) + self.assertEqual(s.objectName(), "Hi") + + def testInstanciation2(self): + s = SimpleUseCase2("Hi") + self.assertEqual(s, "Hi") + s.setObjectName(s) + self.assertEqual(s.objectName(), "Hi") + + def testComplexInstanciation(self): + c = ComplexUseCase("Hi") + self.assertEqual(c, "Hi") + c.setObjectName(c) + self.assertEqual(c.objectName(), "Hi") + c.setX(2); + self.assertEqual(c.x(), 2) + +class MultipleCppDerivedReverseTest(unittest.TestCase): + def testInstanciation(self): + s = SimpleUseCaseReverse("Hi") + self.assertEqual(s, "Hi") + s.setObjectName(s) + self.assertEqual(s.objectName(), "Hi") + + def testInstanciation2(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)) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/multiple_derived_test.py b/sources/shiboken2/tests/samplebinding/multiple_derived_test.py new file mode 100644 index 000000000..e84cc76fd --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/multiple_derived_test.py @@ -0,0 +1,221 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for multiple inheritance''' + +import sys +import unittest + +from sample import Base1, Base2, Base3, Base4, Base5, Base6 +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''' + + def testIsInstance(self): + '''MDerived1 is instance of its parents Base1 and Base2.''' + a = MDerived1() + self.assertTrue(isinstance(a, MDerived1)) + self.assertTrue(isinstance(a, Base1)) + self.assertTrue(isinstance(a, Base2)) + + def testIsSubclass(self): + '''MDerived1 is subclass of its parents Base1 and Base2.''' + self.assertTrue(issubclass(MDerived1, Base1)) + 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.''' + 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.''' + 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.''' + a = ExtMDerived1() + self.assertTrue(isinstance(a, ExtMDerived1)) + self.assertTrue(isinstance(a, MDerived1)) + self.assertTrue(isinstance(a, Base1)) + self.assertTrue(isinstance(a, Base2)) + + def testPythonClassIsSubclass(self): + '''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)) + + def testCastFromMDerived1ToBases(self): + '''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() + b2 = a.castToBase2() + self.assertTrue(isinstance(b1, MDerived1)) + self.assertTrue(isinstance(b2, MDerived1)) + self.assertEqual(a, b1) + self.assertEqual(a, b2) + self.assertEqual(sys.getrefcount(a), refcnt + 2) + + def testCastFromExtMDerived1ToMDerived1Bases(self): + '''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() + self.assertTrue(isinstance(b1, MDerived1)) + self.assertTrue(isinstance(b1, ExtMDerived1)) + b2 = a.castToBase2() + self.assertTrue(isinstance(b2, MDerived1)) + self.assertTrue(isinstance(b2, ExtMDerived1)) + self.assertEqual(a, b1) + self.assertEqual(a, b2) + self.assertEqual(sys.getrefcount(a), refcnt + 2) + + def testCastFromSonOfMDerived1ToBases(self): + '''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() + b1 = a.castToBase1() + b2 = a.castToBase2() + self.assertTrue(isinstance(md1, SonOfMDerived1)) + self.assertTrue(isinstance(b2, SonOfMDerived1)) + self.assertTrue(isinstance(b2, SonOfMDerived1)) + self.assertEqual(a, md1) + self.assertEqual(a, b1) + self.assertEqual(a, b2) + self.assertEqual(sys.getrefcount(a), refcnt + 3) + + def testReimplementedBase2VirtualMethodOnClassInheritingFromMDerived1(self): + a = ExtMDerived1() + value = a.base2Method() + self.assertTrue(value, Base2.base2Method(a) * a.multiplier) + + def testCastFromMDerived2ToBases(self): + '''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() + b4 = a.castToBase4() + b5 = a.castToBase5() + b6 = a.castToBase6() + self.assertTrue(isinstance(b3, MDerived2)) + self.assertTrue(isinstance(b4, MDerived2)) + self.assertTrue(isinstance(b5, MDerived2)) + self.assertTrue(isinstance(b6, MDerived2)) + self.assertEqual(a, b3) + self.assertEqual(a, b4) + self.assertEqual(a, b5) + self.assertEqual(a, b6) + self.assertEqual(sys.getrefcount(a), refcnt + 4) + + def testCastFromMDerived3ToBases(self): + '''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() + md2 = a.castToMDerived2() + b1 = a.castToBase1() + b2 = a.castToBase2() + b3 = a.castToBase3() + b4 = a.castToBase4() + b5 = a.castToBase5() + b6 = a.castToBase6() + self.assertTrue(isinstance(md1, MDerived3)) + self.assertTrue(isinstance(md2, MDerived3)) + self.assertTrue(isinstance(b1, MDerived3)) + self.assertTrue(isinstance(b2, MDerived3)) + self.assertTrue(isinstance(b3, MDerived3)) + self.assertTrue(isinstance(b4, MDerived3)) + self.assertTrue(isinstance(b5, MDerived3)) + self.assertTrue(isinstance(b6, MDerived3)) + self.assertEqual(a, md1) + self.assertEqual(a, md2) + self.assertEqual(a, b1) + self.assertEqual(a, b2) + self.assertEqual(a, b3) + self.assertEqual(a, b4) + self.assertEqual(a, b5) + self.assertEqual(a, b6) + self.assertEqual(sys.getrefcount(a), refcnt + 8) + + def testCastFromMDerived4ToBases(self): + '''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() + b4 = a.castToBase4() + self.assertTrue(isinstance(b3, MDerived4)) + self.assertTrue(isinstance(b4, MDerived4)) + self.assertEqual(a, b3) + self.assertEqual(a, b4) + self.assertEqual(sys.getrefcount(a), refcnt + 2) + + def testCastFromMDerived5ToBases(self): + '''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() + b4 = a.castToBase4() + self.assertTrue(isinstance(b3, MDerived5)) + self.assertTrue(isinstance(b4, MDerived5)) + self.assertEqual(a, b3) + self.assertEqual(a, b4) + self.assertEqual(sys.getrefcount(a), refcnt + 2) + + def testCastFromMDerived3ToBase3(self): + '''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() + b3_inherited = MDerived2.castToBase3(a) + self.assertTrue(isinstance(b3_reimplemented, MDerived3)) + self.assertTrue(isinstance(b3_inherited, MDerived3)) + self.assertEqual(a, b3_reimplemented) + self.assertEqual(a, b3_inherited) + self.assertEqual(sys.getrefcount(a), refcnt + 2) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/namespace_test.py b/sources/shiboken2/tests/samplebinding/namespace_test.py new file mode 100644 index 000000000..653b9081b --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/namespace_test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for std::map container conversions''' + +import unittest +from sample import * +from py3kcompat import IS_PY3K + +if IS_PY3K: + TYPE_STR = "class" +else: + TYPE_STR = "type" + +class TestEnumUnderNamespace(unittest.TestCase): + def testInvisibleNamespace(self): + o1 = EnumOnNamespace.Option1 + self.assertEqual(o1, 1) + +class TestClassesUnderNamespace(unittest.TestCase): + def testIt(self): + 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() + + def testFunctionAddedOnNamespace(self): + res = SampleNamespace.ImInsideANamespace(2, 2) + self.assertEqual(res, 4) + + def testTpNames(self): + self.assertEqual(str(SampleNamespace.SomeClass), "<%s 'sample.SampleNamespace.SomeClass'>"%TYPE_STR) + self.assertEqual(str(SampleNamespace.SomeClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.ProtectedEnum'>"%TYPE_STR) + self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum'>"%TYPE_STR) + self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>"%TYPE_STR) + self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>"%TYPE_STR) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/newdivision_test.py b/sources/shiboken2/tests/samplebinding/newdivision_test.py new file mode 100644 index 000000000..d1a2eda75 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/newdivision_test.py @@ -0,0 +1,42 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +from __future__ import division +from sample import * +import unittest + +class TestNewDivision(unittest.TestCase): + + def testIt(self): + p = Point(4, 4) + p2 = p/2 + self.assertEqual(p2, Point(2, 2)) + +if __name__ == "__main__": + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/nondefaultctor_test.py b/sources/shiboken2/tests/samplebinding/nondefaultctor_test.py new file mode 100644 index 000000000..e38dc9455 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/nondefaultctor_test.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for ...''' + +import sys +import unittest + +from sample import NonDefaultCtor + +class DerivedNonDefaultCtor (NonDefaultCtor): + def returnMyselfVirtual(self): + return NonDefaultCtor(self.value()+1) + +class AnotherDerivedNonDefaultCtor (NonDefaultCtor): + def __init__(self, some_string): + pass + +class NonDefaultCtorTest(unittest.TestCase): + + def testNonDefaultCtor(self): + c = NonDefaultCtor(2) + # these functions returns NonDefaultCtor by value, so a PyObjecy is created every time + self.assertNotEqual(c.returnMyself(), c) + self.assertEqual(c.returnMyself().value(), 2) + self.assertNotEqual(c.returnMyself(3), c) + self.assertEqual(c.returnMyself(3).value(), 2) + self.assertNotEqual(c.returnMyself(4, c), c) + self.assertEqual(c.returnMyself(4, c).value(), 2) + + def testVirtuals(self): + c = DerivedNonDefaultCtor(3) + # these functions returns NonDefaultCtor by value, so a PyObjecy is created every time + self.assertNotEqual(c.returnMyselfVirtual(), c) + self.assertEqual(c.returnMyselfVirtual().value(), 4) + self.assertEqual(c.callReturnMyselfVirtual().value(), 4) + + def testCtorOverload(self): + c = AnotherDerivedNonDefaultCtor("testing") + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/nonzero_test.py b/sources/shiboken2/tests/samplebinding/nonzero_test.py new file mode 100644 index 000000000..7020d30a8 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/nonzero_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import * + +class TestNonZeroOperator(unittest.TestCase): + def testIt(self): + c = Color() + self.assertFalse(c) + c = Color(2) + self.assertTrue(c) + +if __name__ == "__main__": + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/numericaltypedef_test.py b/sources/shiboken2/tests/samplebinding/numericaltypedef_test.py new file mode 100644 index 000000000..774b7f1d1 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/numericaltypedef_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import SizeF + +class NumericalTypedefTest(unittest.TestCase): + + def testNumericalTypedefExact(self): + width, height = (1.1, 2.2) + size = SizeF(width, height) + self.assertEqual(size.width(), width) + self.assertEqual(size.height(), height) + + def testNumericalTypedefConvertible(self): + width, height = (1, 2) + size = SizeF(width, height) + self.assertEqual(size.width(), float(width)) + self.assertEqual(size.height(), float(height)) + + def testNumericalTypedefOfUnsignedShort(self): + self.assertEqual(SizeF.passTypedefOfUnsignedShort(123), 123) + self.assertEqual(SizeF.passTypedefOfUnsignedShort(321), 321) + self.assertNotEqual(SizeF.passTypedefOfUnsignedShort(123), 0) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/numpy_test.py b/sources/shiboken2/tests/samplebinding/numpy_test.py new file mode 100644 index 000000000..65861e864 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/numpy_test.py @@ -0,0 +1,58 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import sys + +try: + from distutils import sysconfig + if bool(sysconfig.get_config_var('Py_DEBUG')): + sys.exit(0) + import numpy +except: + sys.exit(0) + +import unittest +from sample import PointF + +class TestNumpyTypes(unittest.TestCase): + + def testNumpyConverted(self): + x, y = (0.1, 0.2) + p = PointF(float(numpy.float32(x)), float(numpy.float32(y))) + self.assertAlmostEqual(p.x(), x) + self.assertAlmostEqual(p.y(), y) + + def testNumpyAsIs(self): + x, y = (0.1, 0.2) + p = PointF(numpy.float32(x), numpy.float32(y)) + self.assertAlmostEqual(p.x(), x) + self.assertAlmostEqual(p.y(), y) + +if __name__ == "__main__": + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/objecttype_test.py b/sources/shiboken2/tests/samplebinding/objecttype_test.py new file mode 100644 index 000000000..1a06e7e08 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/objecttype_test.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests ObjectType class of object-type with privates copy constructor and = operator.''' + +import unittest +import sys + +from sample import ObjectType, Str +import shiboken2 as shiboken + + +class ObjectTypeTest(unittest.TestCase): + '''Test cases ObjectType class of object-type with privates copy constructor and = operator.''' + + def testObjectTypeSetObjectNameWithStrVariable(self): + '''ObjectType.setObjectName with Str variable as argument.''' + s = Str('object name') + o = ObjectType() + o.setObjectName(s) + self.assertEqual(str(o.objectName()), str(s)) + + def testObjectTypeSetObjectNameWithStrInstantiation(self): + '''ObjectType.setObjectName with Str instantiation as argument.''' + s = 'object name' + o = ObjectType() + o.setObjectName(Str(s)) + self.assertEqual(str(o.objectName()), s) + + def testObjectTypeSetObjectNameWithPythonString(self): + '''ObjectType.setObjectName with Python string as argument.''' + o = ObjectType() + o.setObjectName('object name') + self.assertEqual(str(o.objectName()), 'object name') + + def testNullOverload(self): + o = ObjectType() + o.setObject(None) + self.assertEqual(o.callId(), 0) + o.setNullObject(None) + self.assertEqual(o.callId(), 1) + + def testParentFromCpp(self): + o = ObjectType() + self.assertEqual(sys.getrefcount(o), 2) + o.getCppParent().setObjectName('parent') + self.assertEqual(sys.getrefcount(o), 3) + o.getCppParent().setObjectName('parent') + self.assertEqual(sys.getrefcount(o), 3) + o.getCppParent().setObjectName('parent') + self.assertEqual(sys.getrefcount(o), 3) + o.getCppParent().setObjectName('parent') + self.assertEqual(sys.getrefcount(o), 3) + o.getCppParent().setObjectName('parent') + self.assertEqual(sys.getrefcount(o), 3) + o.destroyCppParent() + self.assertEqual(sys.getrefcount(o), 2) + + def testNextInFocusChainCycle(self): + parent = ObjectType() + child = ObjectType(parent) + next_focus = child.nextInFocusChain() + + shiboken.invalidate(parent) + + def testNextInFocusChainCycleList(self): + '''As above but in for a list of objects''' + parents = [] + children = [] + focus_chains = [] + for i in range(10): + parent = ObjectType() + child = ObjectType(parent) + next_focus = child.nextInFocusChain() + parents.append(parent) + children.append(child) + focus_chains.append(next_focus) + + shiboken.invalidate(parents) + + def testClassDecref(self): + # Bug was that class PyTypeObject wasn't decrefed when instance died + before = sys.getrefcount(ObjectType) + + for i in range(1000): + obj = ObjectType() + shiboken.delete(obj) + + after = sys.getrefcount(ObjectType) + + self.assertLess(abs(before - after), 5) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/objecttype_with_named_args_test.py b/sources/shiboken2/tests/samplebinding/objecttype_with_named_args_test.py new file mode 100755 index 000000000..533b5a5d1 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/objecttype_with_named_args_test.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import ObjectType + +class NamedArgsTest(unittest.TestCase): + + def testOneArgument(self): + p = ObjectType() + o = ObjectType(parent=p) + self.assertEqual(o.parent(), p) + + def testMoreArguments(self): + o = ObjectType() + + o.setObjectSplittedName("", prefix="pys", suffix="ide") + self.assertEqual(o.objectName(), "pyside") + + o.setObjectSplittedName("", suffix="ide", prefix="pys") + self.assertEqual(o.objectName(), "pyside") + + o.setObjectNameWithSize(name="pyside", size=6) + self.assertEqual(o.objectName(), "pyside") + + o.setObjectNameWithSize(size=6, name="pyside") + self.assertEqual(o.objectName(), "pyside") + + + def testUseDefaultValues(self): + o = ObjectType() + + o.setObjectNameWithSize(size=3) + self.assertEqual(o.objectName(), "") # user prefix=' b) + self.assertEqual(a.key(), "aoperator>") + + def testPointerOpeators(self): + a = ObjectTypeOperators("a") + b = ObjectTypeOperators("b") + self.assertEqual(a + "bc", "abc") + self.assertEqual("bc" + a, "bca") + self.assertEqual("a", a) + self.assertEqual(a, "a") + + def testOperatorInjection(self): + a = ObjectTypeOperators("a") + self.assertNotEqual(a, "b") + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py b/sources/shiboken2/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py new file mode 100644 index 000000000..3f09df200 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import ObjectTypeHolder + +class TestObjectTypeReferenceAsVirtualMethodArgument(unittest.TestCase): + + def testBasic(self): + holder = ObjectTypeHolder('TheObjectFromC++') + self.assertEqual(holder.callPassObjectTypeAsReference(), 'TheObjectFromC++') + + def testExtended(self): + class Holder(ObjectTypeHolder): + def passObjectTypeAsReference(self, objectType): + return objectType.objectName().prepend(('ThisIs')) + holder = Holder('TheObjectFromC++') + self.assertEqual(holder.callPassObjectTypeAsReference(), 'ThisIsTheObjectFromC++') + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/oddbool_test.py b/sources/shiboken2/tests/samplebinding/oddbool_test.py new file mode 100644 index 000000000..3424d9dc0 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/oddbool_test.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for OddBool user's primitive type conversion.''' + +import unittest + +from sample import OddBoolUser + +class DerivedOddBoolUser (OddBoolUser): + def returnMyselfVirtual(self): + return OddBoolUser() + pass + +class OddBoolTest(unittest.TestCase): + + def testOddBoolUser(self): + obuTrue = OddBoolUser() + obuFalse = OddBoolUser() + obuTrue.setOddBool(True) + self.assertEqual(obuFalse.oddBool(), False) + 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.assertEqual(obuFalse.oddBool() != True, True) + self.assertEqual(True != obuFalse.oddBool(), True) + self.assertEqual(obuTrue.oddBool() != obuFalse.oddBool(), True) + + def testVirtuals(self): + dobu = DerivedOddBoolUser() + self.assertEqual(dobu.invertedOddBool(), True) + + def testImplicitConversionWithUsersPrimitiveType(self): + obu = OddBoolUser(True) + self.assertTrue(obu.oddBool()) + obu = OddBoolUser(False) + self.assertFalse(obu.oddBool()) + cpx = complex(1.0, 0.0) + obu = OddBoolUser(cpx) + self.assertTrue(obu.oddBool()) + cpx = complex(0.0, 0.0) + obu = OddBoolUser(cpx) + self.assertFalse(obu.oddBool()) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/oldstyleclass_as_number_test.py b/sources/shiboken2/tests/samplebinding/oldstyleclass_as_number_test.py new file mode 100644 index 000000000..a4f52e1fe --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/oldstyleclass_as_number_test.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +import sample +from py3kcompat import IS_PY3K + +class OldStyle: + pass + +class NewStyle(object): + pass + +class OldStyleNumber: + def __init__(self, value): + self.value = value + def __trunc__(self): + return self.value + +class NewStyleNumber(object): + def __init__(self, value): + self.value = value + def __int__(self): + return int(self.value) + def __trunc__(self): + return self.value + +class TestOldStyleClassAsNumber(unittest.TestCase): + + def testBasic(self): + '''For the sake of calibration...''' + self.assertEqual(sample.acceptInt(123), 123) + + def testOldStyleClassPassedAsInteger(self): + '''Old-style classes aren't numbers and shouldn't be accepted.''' + obj = OldStyle() + self.assertRaises(TypeError, sample.acceptInt, obj) + + def testNewStyleClassPassedAsInteger(self): + '''New-style classes aren't numbers and shouldn't be accepted.''' + obj = NewStyle() + self.assertRaises(TypeError, sample.acceptInt, obj) + + def testOldStyleClassWithNumberProtocol(self): + obj = OldStyleNumber(123) + self.assertEqual(sample.acceptInt(obj), obj.value) + + def testNewStyleClassWithNumberProtocol(self): + obj = NewStyleNumber(123) + self.assertEqual(sample.acceptInt(obj), obj.value) + +if __name__ == "__main__" and not IS_PY3K: + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/onlycopyclass_test.py b/sources/shiboken2/tests/samplebinding/onlycopyclass_test.py new file mode 100644 index 000000000..647d2cdd7 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/onlycopyclass_test.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import OnlyCopy, FriendOfOnlyCopy + +class ClassWithOnlyCopyCtorTest(unittest.TestCase): + def testGetOne(self): + obj = FriendOfOnlyCopy.createOnlyCopy(123) + self.assertEqual(type(obj), OnlyCopy) + self.assertEqual(obj.value(), 123) + + def testGetMany(self): + objs = FriendOfOnlyCopy.createListOfOnlyCopy(3) + self.assertEqual(type(objs), list) + self.assertEqual(len(objs), 3) + for value, obj in enumerate(objs): + self.assertEqual(obj.value(), value) + + def testPassAsValue(self): + obj = FriendOfOnlyCopy.createOnlyCopy(123) + self.assertEqual(obj.value(), OnlyCopy.getValue(obj)) + + def testPassAsReference(self): + obj = FriendOfOnlyCopy.createOnlyCopy(123) + self.assertEqual(obj.value(), OnlyCopy.getValueFromReference(obj)) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/overflow_test.py b/sources/shiboken2/tests/samplebinding/overflow_test.py new file mode 100644 index 000000000..8a0fff45d --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/overflow_test.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for overflowing C++ numeric types.''' + +import sys +import unittest + +from sample import * +from py3kcompat import IS_PY3K, long + +class OverflowTest(unittest.TestCase): + '''Test case for overflowing C++ numeric types.''' + + def testUnsignedInt(self): + '''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.''' + val = 100 + self.assertEqual(doubleLongLong(val), 2 * val) + val = long(100) + self.assertEqual(doubleLongLong(val), 2 * val) + val = (2 << 64) + 1 + self.assertRaises(OverflowError, doubleLongLong, val) + + def testUnsignedLongLong(self): + '''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 = long(100) + self.assertEqual(doubleUnsignedLongLong(val), 2 * val) + val = -100 + self.assertRaises(OverflowError, doubleUnsignedLongLong, val) + val = long(-200) + self.assertRaises(OverflowError, doubleUnsignedLongLong, val) + + def testOverflow(self): + '''Calls function with unsigned int parameter using an overflowing value.''' + self.assertRaises(OverflowError, doubleUnsignedInt, 42415335332353253) + doubleUnsignedInt(0xdeadbeef) + + 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) + + 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/shiboken2/tests/samplebinding/overload_sorting_test.py b/sources/shiboken2/tests/samplebinding/overload_sorting_test.py new file mode 100644 index 000000000..30e1ad955 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/overload_sorting_test.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for overload sorting''' + +import unittest + +from sample import * + +class Dummy(object): + pass + +class SimpleOverloadSorting(unittest.TestCase): + + def setUp(self): + self.obj = SortedOverload() + + def testIntDouble(self): + '''Overloads with int and double''' + self.assertEqual(self.obj.overload(3), "int") + self.assertEqual(self.obj.overload(3.14), "double") + + def testImplicitConvert(self): + '''Overloads with implicit convertible types''' + self.assertEqual(self.obj.overload(ImplicitTarget()), "ImplicitTarget") + self.assertEqual(self.obj.overload(ImplicitBase()), "ImplicitBase") + + def testContainer(self): + '''Overloads with containers arguments''' + self.assertEqual(self.obj.overload([ImplicitBase()]), "list(ImplicitBase)") + + def testPyObject(self): + '''Overloads with PyObject args''' + self.assertEqual(self.obj.overload(Dummy()), "PyObject") + + def testImplicitOnly(self): + '''Passing an implicit convertible object to an overload''' + self.assertTrue(self.obj.implicit_overload(ImplicitTarget())) + + def testPyObjectSort(self): + self.assertEqual(self.obj.pyObjOverload(1, 2), "int,int") + self.assertEqual(self.obj.pyObjOverload(object(), 2), "PyObject,int") + + +class DeepOverloadSorting(unittest.TestCase): + + def setUp(self): + self.obj = SortedOverload() + + def testPyObject(self): + '''Deep Overload - (int, PyObject *)''' + self.assertEqual(self.obj.overloadDeep(1, Dummy()), "PyObject") + + def testImplicit(self): + '''Deep Overload - (int, ImplicitBase *)''' + self.assertEqual(self.obj.overloadDeep(1, ImplicitBase()), "ImplicitBase") + +class EnumOverIntSorting(unittest.TestCase): + def testEnumOverInt(self): + ic = ImplicitConv(ImplicitConv.CtorTwo) + self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorTwo) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/overload_test.py b/sources/shiboken2/tests/samplebinding/overload_test.py new file mode 100644 index 000000000..efcd3bed8 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/overload_test.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Overload class''' + +import unittest +from sample import Echo, Overload, Point, PointF, Polygon, Rect, RectF, Size, Str + + +def raisesWithErrorMessage(func, arguments, errorType, errorMsg): + '''NOTE: Using 'try' because assertRaisesRegexp is not available + to check the error message.''' + try: + func(*arguments) + return False + except Exception as err: + if type(err) != TypeError: + return False + if not errorMsg in str(err): + return False + return True + + +class OverloadTest(unittest.TestCase): + '''Test case for Overload class''' + + def testOverloadMethod0(self): + '''Check overloaded method call for signature "overloaded()".''' + overload = Overload() + self.assertEqual(overload.overloaded(), Overload.Function0) + + def testOverloadMethod1(self): + '''Check overloaded method call for signature "overloaded(Size*)".''' + overload = Overload() + size = Size() + self.assertEqual(overload.overloaded(size), Overload.Function1) + + def testOverloadMethod2(self): + '''Check overloaded method call for signature "overloaded(Point*, ParamEnum)".''' + overload = Overload() + point = Point() + self.assertEqual(overload.overloaded(point, Overload.Param1), Overload.Function2) + + def testOverloadMethod3(self): + '''Check overloaded method call for signature "overloaded(const Point&)".''' + overload = Overload() + point = Point() + self.assertEqual(overload.overloaded(point), Overload.Function3) + + def testDifferentReturnTypes(self): + '''Check method calls for overloads with different return types.''' + overload = Overload() + self.assertEqual(overload.differentReturnTypes(), None) + self.assertEqual(overload.differentReturnTypes(Overload.Param1), None) + self.assertEqual(overload.differentReturnTypes(Overload.Param0, 13), 13) + + def testIntOverloads(self): + overload = Overload() + self.assertEqual(overload.intOverloads(2, 3), 2) + self.assertEqual(overload.intOverloads(2, 4.5), 3) + self.assertEqual(overload.intOverloads(Point(0, 0), 3), 1) + + def testIntDoubleOverloads(self): + overload = Overload() + self.assertEqual(overload.intDoubleOverloads(1, 2), Overload.Function0) + self.assertEqual(overload.intDoubleOverloads(1, 2.0), Overload.Function0) + self.assertEqual(overload.intDoubleOverloads(1.0, 2), Overload.Function1) + self.assertEqual(overload.intDoubleOverloads(1.0, 2.0), Overload.Function1) + + def testWrapperIntIntOverloads(self): + overload = Overload() + self.assertEqual(overload.wrapperIntIntOverloads(Point(), 1, 2), Overload.Function0) + self.assertEqual(overload.wrapperIntIntOverloads(Polygon(), 1, 2), Overload.Function1) + + def testDrawTextPointAndStr(self): + overload = Overload() + self.assertEqual(overload.drawText(Point(), Str()), Overload.Function0) + self.assertEqual(overload.drawText(Point(), ''), Overload.Function0) + self.assertEqual(overload.drawText(PointF(), Str()), Overload.Function1) + self.assertEqual(overload.drawText(PointF(), ''), Overload.Function1) + + def testDrawTextRectIntStr(self): + overload = Overload() + self.assertEqual(overload.drawText(Rect(), 1, Str()), Overload.Function2) + self.assertEqual(overload.drawText(Rect(), 1, ''), Overload.Function2) + self.assertEqual(overload.drawText(RectF(), 1, Str()), Overload.Function3) + self.assertEqual(overload.drawText(RectF(), 1, ''), Overload.Function3) + + def testDrawTextRectFStrEcho(self): + overload = Overload() + self.assertEqual(overload.drawText(RectF(), Str()), Overload.Function4) + self.assertEqual(overload.drawText(RectF(), ''), Overload.Function4) + self.assertEqual(overload.drawText(RectF(), Str(), Echo()), Overload.Function4) + self.assertEqual(overload.drawText(RectF(), '', Echo()), Overload.Function4) + self.assertEqual(overload.drawText(Rect(), Str()), Overload.Function4) + self.assertEqual(overload.drawText(Rect(), ''), Overload.Function4) + self.assertEqual(overload.drawText(Rect(), Str(), Echo()), Overload.Function4) + self.assertEqual(overload.drawText(Rect(), '', Echo()), Overload.Function4) + + def testDrawTextIntIntStr(self): + overload = Overload() + self.assertEqual(overload.drawText(1, 2, Str()), Overload.Function5) + self.assertEqual(overload.drawText(1, 2, ''), Overload.Function5) + + def testDrawTextIntIntIntIntStr(self): + overload = Overload() + self.assertEqual(overload.drawText(1, 2, 3, 4, 5, Str()), Overload.Function6) + self.assertEqual(overload.drawText(1, 2, 3, 4, 5, ''), Overload.Function6) + + def testDrawText2IntIntIntIntStr(self): + overload = Overload() + self.assertEqual(overload.drawText2(1, 2, 3, 4, 5, Str()), Overload.Function6) + self.assertEqual(overload.drawText2(1, 2, 3, 4, 5, ''), Overload.Function6) + self.assertEqual(overload.drawText2(1, 2, 3, 4, 5), Overload.Function6) + self.assertEqual(overload.drawText2(1, 2, 3, 4), Overload.Function6) + self.assertEqual(overload.drawText2(1, 2, 3), Overload.Function6) + + def testDrawText3(self): + overload = Overload() + self.assertEqual(overload.drawText3(Str(), Str(), Str()), Overload.Function0) + self.assertEqual(overload.drawText3('', '', ''), Overload.Function0) + self.assertEqual(overload.drawText3(1, 2, 3, 4, 5), Overload.Function1) + self.assertEqual(overload.drawText3(1, 2, 3, 4, 5), Overload.Function1) + + def testDrawText3Exception(self): + overload = Overload() + args = (Str(), Str(), Str(), 4, 5) + result = raisesWithErrorMessage(overload.drawText3, args, + TypeError, 'called with wrong argument types:') + self.assertTrue(result) + + def testDrawText4(self): + overload = Overload() + self.assertEqual(overload.drawText4(1, 2, 3), Overload.Function0) + self.assertEqual(overload.drawText4(1, 2, 3, 4, 5), Overload.Function1) + + def testAcceptSequence(self): + # Overload.acceptSequence() + overload = Overload() + self.assertEqual(overload.acceptSequence(), Overload.Function0) + + def testAcceptSequenceIntInt(self): + # Overload.acceptSequence(int,int) + overload = Overload() + self.assertEqual(overload.acceptSequence(1, 2), Overload.Function1) + + def testAcceptSequenceStrParamEnum(self): + # Overload.acceptSequence(Str,Overload::ParamEnum) + overload = Overload() + self.assertEqual(overload.acceptSequence(''), Overload.Function2) + self.assertEqual(overload.acceptSequence('', Overload.Param0), Overload.Function2) + self.assertEqual(overload.acceptSequence(Str('')), Overload.Function2) + self.assertEqual(overload.acceptSequence(Str(''), Overload.Param0), Overload.Function2) + + def testAcceptSequenceSize(self): + # Overload.acceptSequence(Size) + overload = Overload() + self.assertEqual(overload.acceptSequence(Size()), Overload.Function3) + + def testAcceptSequenceStringList(self): + # Overload.acceptSequence(const char**) + overload = Overload() + strings = ['line 1', 'line 2'] + self.assertEqual(overload.acceptSequence(strings), Overload.Function4) + args = (['line 1', 2], ) + result = raisesWithErrorMessage(overload.acceptSequence, args, + TypeError, 'The argument must be a sequence of strings.') + self.assertTrue(result) + + 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/shiboken2/tests/samplebinding/overloadwithdefault_test.py b/sources/shiboken2/tests/samplebinding/overloadwithdefault_test.py new file mode 100644 index 000000000..9f243a573 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/overloadwithdefault_test.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import Overload, Str +from py3kcompat import b + +class OverloadTest(unittest.TestCase): + + def testNoArgument(self): + overload = Overload() + self.assertEqual(overload.strBufferOverloads(), Overload.Function2) + + def testStrArgument(self): + overload = Overload() + self.assertEqual(overload.strBufferOverloads(Str('')), Overload.Function0) + self.assertEqual(overload.strBufferOverloads(Str(''), ''), Overload.Function0) + self.assertEqual(overload.strBufferOverloads(Str(''), '', False), Overload.Function0) + + def testStringArgumentAsStr(self): + overload = Overload() + self.assertEqual(overload.strBufferOverloads('', ''), Overload.Function0) + self.assertEqual(overload.strBufferOverloads('', '', False), Overload.Function0) + + def testStringArgumentAsBuffer(self): + overload = Overload() + self.assertEqual(overload.strBufferOverloads(b'', 0), Overload.Function1) + + def testBufferArgument(self): + overload = Overload() + self.assertEqual(overload.strBufferOverloads(b(''), 0), Overload.Function1) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_argument_invalidation_test.py b/sources/shiboken2/tests/samplebinding/ownership_argument_invalidation_test.py new file mode 100644 index 000000000..5c6f31395 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_argument_invalidation_test.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Wrapper validity tests for arguments.''' + +import sys +import unittest + +from sample import Polygon, Point + +class WrapperValidityOfArgumentsTest(unittest.TestCase): + '''Wrapper validity tests for arguments.''' + + def testInvalidArgumentToMethod(self): + '''Call to method using invalidated Python wrapper as argument should raise RuntimeError.''' + poly = Polygon() + Polygon.stealOwnershipFromPython(poly) + self.assertRaises(RuntimeError, Polygon.doublePolygonScale, poly) + + def testInvalidArgumentToConstructor(self): + '''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.''' + pt = Point(1, 2) + Polygon.stealOwnershipFromPython(pt) + self.assertRaises(RuntimeError, Polygon.doublePolygonScale, pt) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_cpp_test.py b/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_cpp_test.py new file mode 100644 index 000000000..829cabd81 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_cpp_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for destroy a child object in C++''' + +import unittest + +from sample import ObjectType + + +class DeleteChildInCpp(unittest.TestCase): + '''Test case for destroying a child in c++''' + + def testDeleteChild(self): + '''Delete child in C++ should invalidate child - using C++ wrapper''' + parent = ObjectType() + parent.setObjectName('parent') + child = ObjectType(parent) + child.setObjectName('child') + + parent.killChild('child') + self.assertRaises(RuntimeError, child.objectName) + self.assertEqual(parent.objectName(), 'parent') + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_python_test.py b/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_python_test.py new file mode 100644 index 000000000..32312af7f --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_delete_child_in_python_test.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for deleting a child object in python''' + +import unittest +import random +import string + +from sample import ObjectType +from py3kcompat import IS_PY3K + +if IS_PY3K: + string.letters = string.ascii_letters + + +class DeleteChildInPython(unittest.TestCase): + '''Test case for deleting (unref) a child in python''' + + def testDeleteChild(self): + '''Delete child in python should not invalidate child''' + parent = ObjectType() + child = ObjectType(parent) + name = ''.join(random.sample(string.letters, 5)) + child.setObjectName(name) + + del child + new_child = parent.children()[0] + self.assertEqual(new_child.objectName(), name) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/ownership_delete_parent_test.py b/sources/shiboken2/tests/samplebinding/ownership_delete_parent_test.py new file mode 100644 index 000000000..1c135a4aa --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_delete_parent_test.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for destroying the parent''' + +import sys +import unittest + +from sample import ObjectType + + +class DeleteParentTest(unittest.TestCase): + '''Test case for deleting a parent object''' + + def testParentDestructor(self): + '''Delete parent object should invalidate child''' + parent = ObjectType() + child = ObjectType() + child.setParent(parent) + + refcount_before = sys.getrefcount(child) + + del parent + self.assertRaises(RuntimeError, child.objectName) + self.assertEqual(sys.getrefcount(child), refcount_before-1) + + def testParentDestructorMultipleChildren(self): + '''Delete parent object should invalidate all children''' + parent = ObjectType() + children = [ObjectType() for _ in range(10)] + + for child in children: + child.setParent(parent) + + del parent + for i, child in enumerate(children): + self.assertRaises(RuntimeError, child.objectName) + self.assertEqual(sys.getrefcount(child), 4) + + def testRecursiveParentDelete(self): + '''Delete parent should invalidate grandchildren''' + parent = ObjectType() + child = ObjectType(parent) + grandchild = ObjectType(child) + + del parent + self.assertRaises(RuntimeError, child.objectName) + self.assertEqual(sys.getrefcount(child), 2) + self.assertRaises(RuntimeError, grandchild.objectName) + self.assertEqual(sys.getrefcount(grandchild), 2) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/ownership_invalidate_after_use_test.py b/sources/shiboken2/tests/samplebinding/ownership_invalidate_after_use_test.py new file mode 100644 index 000000000..8b3e84738 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_invalidate_after_use_test.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Ownership tests for cases of invalidation of Python wrapper after use.''' + +import sys +import unittest + +from sample import ObjectType, ObjectTypeDerived, Event + + +class ExtObjectType(ObjectType): + def __init__(self): + 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__() + self.fail = False + + def event(self, ev): + self.callInvalidateEvent(ev) + try: + ev.eventType() + except: + self.fail = True + raise + return True + + 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.''' + eot = ExtObjectType() + eot.causeEvent(Event.SOME_EVENT) + self.assertEqual(eot.type_of_last_event, Event.SOME_EVENT) + self.assertRaises(RuntimeError, eot.last_event.eventType) + + def testObjectInvalidatedAfterUseAsParameter(self): + '''Tries to use wrapper invalidated after use as a parameter to another method.''' + eot = ExtObjectType() + ot = ObjectType() + eot.causeEvent(Event.ANY_EVENT) + self.assertEqual(eot.type_of_last_event, Event.ANY_EVENT) + self.assertRaises(RuntimeError, ot.event, eot.last_event) + + def testit(self): + obj = MyObjectType() + obj.causeEvent(Event.BASIC_EVENT) + self.assertFalse(obj.fail) + + def testInvalidateAfterUseInDerived(self): + '''Invalidate was failing in a derived C++ class that also inherited + other base classes''' + eot = ExtObjectTypeDerived() + eot.causeEvent(Event.SOME_EVENT) + 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/shiboken2/tests/samplebinding/ownership_invalidate_child_test.py b/sources/shiboken2/tests/samplebinding/ownership_invalidate_child_test.py new file mode 100644 index 000000000..e92fa39f5 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_invalidate_child_test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for invalidating a C++ created child that was already on the care of a parent.''' + +import unittest + +from sample import ObjectType, BlackBox + + +class InvalidateChildTest(unittest.TestCase): + '''Tests for invalidating a C++ created child that was already on the care of a parent.''' + + def testInvalidateChild(self): + '''Invalidating method call should remove child from the care of a parent if it has one.''' + parent = ObjectType() + child1 = ObjectType(parent) + child1.setObjectName('child1') + child2 = ObjectType.create() + child2.setParent(parent) + child2.setObjectName('child2') + + self.assertEqual(parent.children(), [child1, child2]) + + bbox = BlackBox() + + # This method steals ownership from Python to C++. + bbox.keepObjectType(child1) + self.assertEqual(parent.children(), [child2]) + + bbox.keepObjectType(child2) + self.assertEqual(parent.children(), []) + + del parent + + self.assertEqual(child1.objectName(), 'child1') + self.assertRaises(RuntimeError, child2.objectName) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py b/sources/shiboken2/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py new file mode 100644 index 000000000..69527974c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''The BlackBox class has cases of ownership transference between Python and C++.''' + +import sys +import unittest + +from sample import Point, BlackBox + +class OwnershipInvalidateNonPolymorphicTest(unittest.TestCase): + '''The BlackBox class has cases of ownership transference between Python and C++.''' + + def testOwnershipTransference(self): + '''Ownership transference from Python to C++ and back again.''' + p1 = Point(10, 20) + bb = BlackBox() + p1_ticket = bb.keepPoint(p1) + self.assertRaises(RuntimeError, p1.x) + p1_ret = bb.retrievePoint(p1_ticket) + self.assertEqual(p1_ret, Point(10, 20)) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_invalidate_parent_test.py b/sources/shiboken2/tests/samplebinding/ownership_invalidate_parent_test.py new file mode 100644 index 000000000..848c982ce --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_invalidate_parent_test.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for invalidating a parent of other objects.''' + +import unittest + +from sample import ObjectType, BlackBox + + +class InvalidateParentTest(unittest.TestCase): + '''Tests for invalidating a parent of other objects.''' + + def testInvalidateParent(self): + '''Invalidate parent should invalidate children''' + parent = ObjectType.create() + child1 = ObjectType(parent) + child1.setObjectName("child1") + child2 = ObjectType.create() + child2.setObjectName("child2") + child2.setParent(parent) + grandchild1 = ObjectType(child1) + grandchild1.setObjectName("grandchild1") + grandchild2 = ObjectType.create() + grandchild2.setObjectName("grandchild2") + grandchild2.setParent(child2) + bbox = BlackBox() + + bbox.keepObjectType(parent) # Should invalidate the parent + + self.assertRaises(RuntimeError, parent.objectName) + # some children still valid they are wrapper classes + self.assertEqual(child1.objectName(), "child1") + self.assertRaises(RuntimeError, child2.objectName) + self.assertEqual(grandchild1.objectName(), "grandchild1") + self.assertRaises(RuntimeError, grandchild2.objectName) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_reparenting_test.py b/sources/shiboken2/tests/samplebinding/ownership_reparenting_test.py new file mode 100644 index 000000000..20e6aca03 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_reparenting_test.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests for object reparenting.''' + +import unittest +import sys + +from sample import ObjectType + +class ExtObjectType(ObjectType): + def __init__(self): + ObjectType.__init__(self) + + +class ReparentingTest(unittest.TestCase): + '''Tests for object reparenting.''' + + def testReparentedObjectTypeIdentity(self): + '''Reparent children from one parent to another.''' + object_list = [] + old_parent = ObjectType() + new_parent = ObjectType() + for i in range(3): + obj = ObjectType() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for child in new_parent.children(): + self.assertTrue(child in object_list) + + def testReparentWithTheSameParent(self): + '''Set the same parent twice to check if the ref continue the same''' + obj = ObjectType() + parent = ObjectType() + self.assertEqual(sys.getrefcount(obj), 2) + obj.setParent(parent) + self.assertEqual(sys.getrefcount(obj), 3) + obj.setParent(parent) + self.assertEqual(sys.getrefcount(obj), 3) + + def testReparentedExtObjectType(self): + '''Reparent children from one extended parent to another.''' + object_list = [] + old_parent = ExtObjectType() + new_parent = ExtObjectType() + for i in range(3): + obj = ExtObjectType() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for orig, child in zip(object_list, new_parent.children()): + self.assertEqual(type(orig), type(child)) + + def testReparentedObjectTypeIdentityWithParentsCreatedInCpp(self): + '''Reparent children from one parent to another, both created in C++.''' + object_list = [] + old_parent = ObjectType.create() + new_parent = ObjectType.create() + for i in range(3): + obj = ObjectType() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for child in new_parent.children(): + self.assertTrue(child in object_list) + + def testReparentedObjectTypeIdentityWithChildrenCreatedInCpp(self): + '''Reparent children created in C++ from one parent to another.''' + object_list = [] + old_parent = ObjectType() + new_parent = ObjectType() + for i in range(3): + obj = ObjectType.create() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for child in new_parent.children(): + self.assertTrue(child in object_list) + + def testReparentedObjectTypeIdentityWithParentsAndChildrenCreatedInCpp(self): + '''Reparent children from one parent to another. Parents and children are created in C++.''' + object_list = [] + old_parent = ObjectType.create() + new_parent = ObjectType.create() + for i in range(3): + obj = ObjectType.create() + object_list.append(obj) + obj.setParent(old_parent) + for obj in object_list: + obj.setParent(new_parent) + for child in new_parent.children(): + self.assertTrue(child in object_list) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/ownership_transference_test.py b/sources/shiboken2/tests/samplebinding/ownership_transference_test.py new file mode 100644 index 000000000..0df2a09ba --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/ownership_transference_test.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''The BlackBox class has cases of ownership transference between C++ and Python.''' + +import sys +import unittest + +from sample import ObjectType, BlackBox + +class BlackBoxTest(unittest.TestCase): + '''The BlackBox class has cases of ownership transference between C++ and Python.''' + + def testOwnershipTransference(self): + '''Ownership transference from Python to C++ and back again.''' + o1 = ObjectType() + o1.setObjectName('object1') + o1_refcnt = sys.getrefcount(o1) + o2 = ObjectType() + o2.setObjectName('object2') + o2_refcnt = sys.getrefcount(o2) + bb = BlackBox() + o1_ticket = bb.keepObjectType(o1) + 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 + self.assertEqual(sys.getrefcount(o2), o2_refcnt + 1) + o2 = bb.retrieveObjectType(o2_ticket) + self.assertEqual(sys.getrefcount(o2), o2_refcnt) + del bb + self.assertRaises(RuntimeError, o1.objectName) + self.assertEqual(str(o2.objectName()), 'object2') + self.assertEqual(sys.getrefcount(o2), o2_refcnt) + + def testBlackBoxReleasingUnknownObjectType(self): + '''Asks BlackBox to release an unknown ObjectType.''' + o1 = ObjectType() + o2 = ObjectType() + bb = BlackBox() + o1_ticket = bb.keepObjectType(o1) + o3 = bb.retrieveObjectType(-5) + self.assertEqual(o3, None) + + def testOwnershipTransferenceCppCreated(self): + '''Ownership transference using a C++ created object.''' + o1 = ObjectType.create() + o1.setObjectName('object1') + o1_refcnt = sys.getrefcount(o1) + bb = BlackBox() + o1_ticket = bb.keepObjectType(o1) + self.assertRaises(RuntimeError, o1.objectName) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/pair_test.py b/sources/shiboken2/tests/samplebinding/pair_test.py new file mode 100644 index 000000000..4786213c5 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pair_test.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for std::pair container conversions''' + +import sys +import unittest + +from sample import PairUser + +class ExtendedPairUser(PairUser): + def __init__(self): + PairUser.__init__(self) + self.create_pair_called = False + + def createPair(self): + self.create_pair_called = True + return (7, 13) + +class PairConversionTest(unittest.TestCase): + '''Test case for std::pair container conversions''' + + def testReimplementedVirtualMethodCall(self): + '''Test if a Python override of a virtual method is correctly called from C++.''' + pu = ExtendedPairUser() + pair = pu.callCreatePair() + self.assertTrue(pu.create_pair_called) + self.assertEqual(type(pair), tuple) + self.assertEqual(type(pair[0]), int) + self.assertEqual(type(pair[1]), int) + self.assertEqual(pair, (7, 13)) + + def testPrimitiveConversionInsideContainer(self): + '''Test primitive type conversion inside conversible std::pair container.''' + cpx0 = complex(1.2, 3.4) + cpx1 = complex(5.6, 7.8) + cp = PairUser.createComplexPair(cpx0, cpx1) + self.assertEqual(type(cp), tuple) + self.assertEqual(type(cp[0]), complex) + self.assertEqual(type(cp[1]), complex) + 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)''' + 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)''' + pu = PairUser() + pair = (3.3, 7) + result = pu.sumPair(pair) + self.assertNotEqual(result, sum(pair)) + self.assertEqual(result, int(pair[0]) + pair[1]) + + def testConversionInBothDirections(self): + '''Test converting a pair from Python to C++ and the other way around.''' + pu = PairUser() + pair = (3, 5) + pu.setPair(pair) + result = pu.getPair() + 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.''' + pu = PairUser() + pair = [3, 5] + pu.setPair(pair) + result = pu.getPair() + self.assertNotEqual(result, pair) + self.assertEqual(result, tuple(pair)) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/pen_test.py b/sources/shiboken2/tests/samplebinding/pen_test.py new file mode 100644 index 000000000..54c96b9c8 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pen_test.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for with const char* as argument''' + +import unittest + +from sample import Color, Pen, SampleNamespace + +class TestPen(unittest.TestCase): + '''Simple test case for Pen.''' + + def testPenWithEmptyConstructor(self): + pen = Pen() + self.assertEqual(pen.ctorType(), Pen.EmptyCtor) + + def testPenWithEnumConstructor(self): + pen = Pen(SampleNamespace.RandomNumber) + self.assertEqual(pen.ctorType(), Pen.EnumCtor) + + def testPenWithColorConstructor(self): + pen = Pen(Color()) + self.assertEqual(pen.ctorType(), Pen.ColorCtor) + + def testPenWithCopyConstructor(self): + pen = Pen(Pen()) + self.assertEqual(pen.ctorType(), Pen.CopyCtor) + + def testPenWithIntConvertedToColor(self): + pen = Pen(1) + self.assertEqual(pen.ctorType(), Pen.ColorCtor) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/point_test.py b/sources/shiboken2/tests/samplebinding/point_test.py new file mode 100644 index 000000000..6f84ac999 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/point_test.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for Point class''' + +import sys +import unittest + +from sample import Point +from py3kcompat import unicode + +class PointTest(unittest.TestCase): + '''Test case for Point class, including operator overloads.''' + + def testConstructor(self): + '''Test Point class constructor.''' + pt = Point(5.0, 2.3) + self.assertEqual(pt.x(), 5.0) + self.assertEqual(pt.y(), 2.3) + + def testPlusOperator(self): + '''Test Point class + operator.''' + pt1 = Point(5.0, 2.3) + pt2 = Point(0.5, 3.2) + self.assertEqual(pt1 + pt2, Point(5.0 + 0.5, 2.3 + 3.2)) + + def testEqualOperator(self): + '''Test Point class == operator.''' + pt1 = Point(5.0, 2.3) + pt2 = Point(5.0, 2.3) + pt3 = Point(0.5, 3.2) + self.assertTrue(pt1 == pt1) + self.assertTrue(pt1 == pt2) + self.assertFalse(pt1 == pt3) + self.assertFalse(pt1 == object()) + + def testNotEqualOperator(self): + '''Test Point class != operator.''' + pt1 = Point(5.0, 2.3) + pt2 = Point(5.0, 2.3) + self.assertRaises(NotImplementedError, pt1.__ne__, pt2) + + def testReturnNewCopy(self): + '''Point returns a copy of itself.''' + pt1 = Point(1.1, 2.3) + pt2 = pt1.copy() + self.assertEqual(pt1, pt2) + pt2 += pt1 + self.assertFalse(pt1 == pt2) + + def testReturnConstPointer(self): + '''Point returns a const pointer for itself.''' + pt1 = Point(5.0, 2.3) + refcount1 = sys.getrefcount(pt1) + pt2 = pt1.getSelf() + self.assertEqual(pt1, pt2) + self.assertEqual(sys.getrefcount(pt1), refcount1 + 1) + self.assertEqual(sys.getrefcount(pt1), sys.getrefcount(pt2)) + + def testUintOverflow(self): + pt1 = Point(0.0, 0.0) + self.assertRaises(OverflowError, pt1.setXAsUint, 840835495615213080) + self.assertEqual(pt1.x(), 0.0) + + def testAddedOperator(self): + p = Point(0.0, 0.0) + r = p - unicode('Hi') + self.assertEqual(r, unicode('Hi')) + + # now the reverse op. + r = unicode('Hi') - p + self.assertEqual(r, unicode('Hi')) + + def testModifiedMethod(self): + pt1 = Point(0.0, 0.0) + pt2 = Point(10.0, 10.0) + 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/shiboken2/tests/samplebinding/pointerholder_test.py b/sources/shiboken2/tests/samplebinding/pointerholder_test.py new file mode 100644 index 000000000..32ef99d5c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pointerholder_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for a class that holds an arbitraty pointer and is modified to hold an PyObject.''' + +import sys +import unittest + +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.''' + + def testStoringAndRetrievingPointer(self): + ph = PointerHolder('Hello') + self.assertEqual(ph.pointer(), 'Hello') + a = (1, 2, 3) + ph = PointerHolder(a) + self.assertEqual(ph.pointer(), a) + + def testReferenceCounting(self): + '''Test reference counting when retrieving data with PointerHolder.pointer().''' + a = (1, 2, 3) + refcnt = sys.getrefcount(a) + ph = PointerHolder(a) + ptr = ph.pointer() + self.assertEqual(sys.getrefcount(a), refcnt + 1) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/pointf_test.py b/sources/shiboken2/tests/samplebinding/pointf_test.py new file mode 100644 index 000000000..9318dca24 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pointf_test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for PointF class''' + +import unittest + +from sample import PointF + +class PointFTest(unittest.TestCase): + '''Test case for PointF class, including operator overloads.''' + + def testConstructor(self): + '''Test PointF class constructor.''' + pt = PointF(5.0, 2.3) + self.assertEqual(pt.x(), 5.0) + self.assertEqual(pt.y(), 2.3) + + def testPlusOperator(self): + '''Test PointF class + operator.''' + pt1 = PointF(5.0, 2.3) + pt2 = PointF(0.5, 3.2) + self.assertEqual(pt1 + pt2, PointF(5.0 + 0.5, 2.3 + 3.2)) + + def testEqualOperator(self): + '''Test PointF class == operator.''' + pt1 = PointF(5.0, 2.3) + pt2 = PointF(5.0, 2.3) + pt3 = PointF(0.5, 3.2) + self.assertTrue(pt1 == pt1) + self.assertTrue(pt1 == pt2) + self.assertFalse(pt1 == pt3) + + def testModifiedMethod(self): + pt1 = PointF(0.0, 0.0) + pt2 = PointF(10.0, 10.0) + 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/shiboken2/tests/samplebinding/primitivereferenceargument_test.py b/sources/shiboken2/tests/samplebinding/primitivereferenceargument_test.py new file mode 100644 index 000000000..e973c0d78 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/primitivereferenceargument_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +import sample + +class PrimitiveReferenceArgumentTest(unittest.TestCase): + + def testIntReferenceArgument(self): + '''C++ signature: int acceptIntReference(int&)''' + self.assertEqual(sample.acceptIntReference(123), 123) + + def testOddBoolReferenceArgument(self): + '''C++ signature: OddBool acceptOddBoolReference(OddBool&)''' + self.assertEqual(sample.acceptOddBoolReference(True), True) + self.assertEqual(sample.acceptOddBoolReference(False), False) + self.assertNotEqual(sample.acceptOddBoolReference(True), False) + self.assertNotEqual(sample.acceptOddBoolReference(False), True) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/privatector_test.py b/sources/shiboken2/tests/samplebinding/privatector_test.py new file mode 100644 index 000000000..471f735cb --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/privatector_test.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for a class with only a private constructor.''' + +import gc +import sys +import unittest + +from sample import PrivateCtor + + +class PrivateCtorTest(unittest.TestCase): + '''Test case for PrivateCtor class''' + + def testPrivateCtorInstanciation(self): + '''Test if instanciation of class with a private constructor raises an exception.''' + self.assertRaises(TypeError, PrivateCtor) + + def testPrivateCtorInheritance(self): + '''Test if inheriting from PrivateCtor raises an exception.''' + def inherit(): + class Foo(PrivateCtor): + pass + self.assertRaises(TypeError, inherit) + + def testPrivateCtorInstanceMethod(self): + '''Test if PrivateCtor.instance() method return the proper singleton.''' + pd1 = PrivateCtor.instance() + calls = pd1.instanceCalls() + self.assertEqual(type(pd1), PrivateCtor) + pd2 = PrivateCtor.instance() + self.assertEqual(pd2, pd1) + self.assertEqual(pd2.instanceCalls(), calls + 1) + + def testPrivateCtorRefCounting(self): + '''Test refcounting of the singleton returned by PrivateCtor.instance().''' + pd1 = PrivateCtor.instance() + calls = pd1.instanceCalls() + refcnt = sys.getrefcount(pd1) + pd2 = PrivateCtor.instance() + self.assertEqual(pd2.instanceCalls(), calls + 1) + self.assertEqual(sys.getrefcount(pd2), sys.getrefcount(pd1)) + self.assertEqual(sys.getrefcount(pd2), refcnt + 1) + del pd1 + self.assertEqual(sys.getrefcount(pd2), refcnt) + del pd2 + gc.collect() + pd3 = PrivateCtor.instance() + self.assertEqual(type(pd3), PrivateCtor) + self.assertEqual(pd3.instanceCalls(), calls + 2) + self.assertEqual(sys.getrefcount(pd3), refcnt) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/privatedtor_test.py b/sources/shiboken2/tests/samplebinding/privatedtor_test.py new file mode 100644 index 000000000..3048a9848 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/privatedtor_test.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for a class with a private destructor.''' + +import gc +import sys +import unittest + +import shiboken2 as shiboken +from sample import PrivateDtor + + +class PrivateDtorTest(unittest.TestCase): + '''Test case for PrivateDtor class''' + + def testPrivateDtorInstanciation(self): + '''Test if instanciation of class with a private destructor raises an exception.''' + self.assertRaises(TypeError, PrivateDtor) + + def testPrivateDtorInheritance(self): + '''Test if inheriting from PrivateDtor raises an exception.''' + def inherit(): + class Foo(PrivateDtor): + pass + self.assertRaises(TypeError, inherit) + + def testPrivateDtorInstanceMethod(self): + '''Test if PrivateDtor.instance() method return the proper singleton.''' + pd1 = PrivateDtor.instance() + calls = pd1.instanceCalls() + self.assertEqual(type(pd1), PrivateDtor) + pd2 = PrivateDtor.instance() + self.assertEqual(pd2, pd1) + self.assertEqual(pd2.instanceCalls(), calls + 1) + + def testPrivateDtorRefCounting(self): + '''Test refcounting of the singleton returned by PrivateDtor.instance().''' + pd1 = PrivateDtor.instance() + calls = pd1.instanceCalls() + refcnt = sys.getrefcount(pd1) + pd2 = PrivateDtor.instance() + self.assertEqual(pd2.instanceCalls(), calls + 1) + self.assertEqual(sys.getrefcount(pd2), sys.getrefcount(pd1)) + self.assertEqual(sys.getrefcount(pd2), refcnt + 1) + del pd1 + self.assertEqual(sys.getrefcount(pd2), refcnt) + del pd2 + gc.collect() + pd3 = PrivateDtor.instance() + self.assertEqual(type(pd3), PrivateDtor) + self.assertEqual(pd3.instanceCalls(), calls + 2) + self.assertEqual(sys.getrefcount(pd3), refcnt) + + def testClassDecref(self): + # Bug was that class PyTypeObject wasn't decrefed when instance + # was invalidated + + before = sys.getrefcount(PrivateDtor) + + for i in range(1000): + obj = PrivateDtor.instance() + shiboken.invalidate(obj) + + after = sys.getrefcount(PrivateDtor) + + self.assertLess(abs(before - after), 5) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/protected_test.py b/sources/shiboken2/tests/samplebinding/protected_test.py new file mode 100644 index 000000000..9201a63cf --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/protected_test.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for protected methods.''' + +import unittest + +from sample import cacheSize +from sample import ProtectedNonPolymorphic, ProtectedVirtualDestructor +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.''' + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testProtectedCall(self): + '''Calls a non-virtual protected method.''' + p = ProtectedNonPolymorphic('NonPoly') + self.assertEqual(p.publicName(), p.protectedName()) + a0, a1 = 1, 2 + self.assertEqual(p.protectedSum(a0, a1), a0 + a1) + + def testProtectedCallWithInstanceCreatedOnCpp(self): + '''Calls a non-virtual protected method on an instance created in C++.''' + p = ProtectedNonPolymorphic.create() + self.assertEqual(p.publicName(), p.protectedName()) + a0, a1 = 1, 2 + self.assertEqual(p.protectedSum(a0, a1), a0 + a1) + + def testModifiedProtectedCall(self): + '''Calls a non-virtual protected method modified with code injection.''' + p = ProtectedNonPolymorphic('NonPoly') + self.assertEqual(p.dataTypeName(), 'integer') + 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.''' + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testProtectedCall(self): + '''Calls a virtual protected method.''' + p = ProtectedNonPolymorphic('Poly') + self.assertEqual(p.publicName(), p.protectedName()) + a0, a1 = 1, 2 + self.assertEqual(p.protectedSum(a0, a1), a0 + a1) + + def testProtectedCallWithInstanceCreatedOnCpp(self): + '''Calls a virtual protected method on an instance created in C++.''' + p = ProtectedPolymorphic.create() + self.assertEqual(p.publicName(), p.protectedName()) + self.assertEqual(p.callProtectedName(), p.protectedName()) + + def testReimplementedProtectedCall(self): + '''Calls a reimplemented virtual protected method.''' + original_name = 'Poly' + p = ExtendedProtectedPolymorphic(original_name) + name = p.callProtectedName() + 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.''' + + def testProtectedCallWithInstanceCreatedOnCpp(self): + '''Calls a virtual protected method from parent class on an instance created in C++.''' + p = ProtectedPolymorphicDaughter.create() + self.assertEqual(p.publicName(), p.protectedName()) + self.assertEqual(p.callProtectedName(), p.protectedName()) + + def testReimplementedProtectedCall(self): + '''Calls a reimplemented virtual protected method from parent class.''' + original_name = 'Poly' + p = ExtendedProtectedPolymorphicDaughter(original_name) + name = p.callProtectedName() + self.assertTrue(p.protectedName_called) + self.assertEqual(p.protectedName(), name) + self.assertEqual(ProtectedPolymorphicDaughter.protectedName(p), original_name) + + +class ProtectedPolymorphicGrandDaugherTest(unittest.TestCase): + '''Test cases for protected method in a class inheriting for a class that inherits from + another with protected virtual methods.''' + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testProtectedCallWithInstanceCreatedOnCpp(self): + '''Calls a virtual protected method from parent class on an instance created in C++.''' + p = ProtectedPolymorphicGrandDaughter.create() + self.assertEqual(p.publicName(), p.protectedName()) + self.assertEqual(p.callProtectedName(), p.protectedName()) + + def testReimplementedProtectedCall(self): + '''Calls a reimplemented virtual protected method from parent class.''' + original_name = 'Poly' + p = ExtendedProtectedPolymorphicGrandDaughter(original_name) + name = p.callProtectedName() + self.assertTrue(p.protectedName_called) + self.assertEqual(p.protectedName(), name) + self.assertEqual(ProtectedPolymorphicGrandDaughter.protectedName(p), original_name) + +class ProtectedVirtualDtorTest(unittest.TestCase): + '''Test cases for protected virtual destructor.''' + + def setUp(self): + ProtectedVirtualDestructor.resetDtorCounter() + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testVirtualProtectedDtor(self): + '''Original protected virtual destructor is being called.''' + dtor_called = ProtectedVirtualDestructor.dtorCalled() + for i in range(1, 10): + pvd = ProtectedVirtualDestructor() + del pvd + self.assertEqual(ProtectedVirtualDestructor.dtorCalled(), dtor_called + i) + + def testVirtualProtectedDtorOnCppCreatedObject(self): + '''Original protected virtual destructor is being called for a C++ created object.''' + dtor_called = ProtectedVirtualDestructor.dtorCalled() + for i in range(1, 10): + pvd = ProtectedVirtualDestructor.create() + del pvd + self.assertEqual(ProtectedVirtualDestructor.dtorCalled(), dtor_called + i) + + def testProtectedDtorOnDerivedClass(self): + '''Original protected virtual destructor is being called for a derived class.''' + dtor_called = ExtendedProtectedVirtualDestructor.dtorCalled() + for i in range(1, 10): + pvd = ExtendedProtectedVirtualDestructor() + del pvd + self.assertEqual(ExtendedProtectedVirtualDestructor.dtorCalled(), dtor_called + i) + + +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.''' + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testProtectedMethodWithProtectedEnumArgument(self): + '''Calls protected method with protected enum argument.''' + obj = ProtectedEnumClass() + + 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) + + 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.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(ProtectedEnumClass.protectedEnumMethod(obj, ProtectedEnumClass.ProtectedItem0), 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) + + 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(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) + + +class ProtectedPropertyTest(unittest.TestCase): + '''Test cases for a class with a protected property (or field in C++).''' + + def setUp(self): + self.obj = ProtectedProperty() + + def tearDown(self): + del self.obj + self.assertEqual(cacheSize(), 0) + + def testProtectedProperty(self): + '''Writes and reads a protected integer property.''' + self.obj.protectedProperty = 3 + self.assertEqual(self.obj.protectedProperty, 3) + + def testProtectedContainerProperty(self): + '''Writes and reads a protected list of integers property.''' + lst = [1, 2, 3, 4] + self.obj.protectedContainerProperty = lst + self.assertEqual(self.obj.protectedContainerProperty, lst) + + def testProtectedEnumProperty(self): + '''Writes and reads a protected enum property.''' + self.obj.protectedEnumProperty = Event.SOME_EVENT + self.assertEqual(self.obj.protectedEnumProperty, Event.SOME_EVENT) + + def testProtectedValueTypeProperty(self): + '''Writes and reads a protected value type property.''' + point = Point(12, 34) + self.obj.protectedValueTypeProperty = point + self.assertEqual(self.obj.protectedValueTypeProperty, point) + self.assertFalse(self.obj.protectedValueTypeProperty is point) + pointProperty = self.obj.protectedValueTypeProperty + self.assertTrue(self.obj.protectedValueTypeProperty is pointProperty) + + def testProtectedValueTypePropertyWrapperRegistration(self): + '''Access colocated protected value type property.''' + cache_size = cacheSize() + point = Point(12, 34) + obj = createProtectedProperty() + obj.protectedValueTypeProperty + self.assertEqual(obj.protectedValueTypeProperty.copy(), + obj.protectedValueTypeProperty) + obj.protectedValueTypeProperty = point + self.assertEqual(obj.protectedValueTypeProperty, point) + self.assertFalse(obj.protectedValueTypeProperty is point) + pointProperty = obj.protectedValueTypeProperty + self.assertTrue(obj.protectedValueTypeProperty is pointProperty) + del obj, point, pointProperty + self.assertEqual(cacheSize(), cache_size) + + def testProtectedValueTypePointerProperty(self): + '''Writes and reads a protected value type pointer property.''' + pt1 = Point(12, 34) + pt2 = Point(12, 34) + self.obj.protectedValueTypePointerProperty = pt1 + self.assertEqual(self.obj.protectedValueTypePointerProperty, pt1) + self.assertEqual(self.obj.protectedValueTypePointerProperty, pt2) + self.assertTrue(self.obj.protectedValueTypePointerProperty is pt1) + self.assertFalse(self.obj.protectedValueTypePointerProperty is pt2) + + def testProtectedObjectTypeProperty(self): + '''Writes and reads a protected object type property.''' + obj = ObjectType() + self.obj.protectedObjectTypeProperty = obj + self.assertEqual(self.obj.protectedObjectTypeProperty, obj) + + +class PrivateDtorProtectedMethodTest(unittest.TestCase): + '''Test cases for classes with private destructors and protected methods.''' + + def tearDown(self): + self.assertEqual(cacheSize(), 0) + + def testProtectedMethod(self): + '''Calls protected method of a class with a private destructor.''' + obj = PrivateDtor.instance() + + self.assertEqual(type(obj), PrivateDtor) + self.assertEqual(obj.instanceCalls(), 1) + self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) + obj = PrivateDtor.instance() + self.assertEqual(obj.instanceCalls(), 2) + self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/pstrlist_test.py b/sources/shiboken2/tests/samplebinding/pstrlist_test.py new file mode 100644 index 000000000..47e89bacb --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pstrlist_test.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +import sample + +class PStrListTest(unittest.TestCase): + + def testPStrList(self): + a = 'str0' + b = 'str1' + lst = sample.createPStrList(a, b) + self.assertEqual(lst, [a, b]) + + def testListOfPStr(self): + a = 'str0' + b = 'str1' + lst = sample.createListOfPStr(a, b) + self.assertEqual(lst, [a, b]) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/pystr_test.py b/sources/shiboken2/tests/samplebinding/pystr_test.py new file mode 100644 index 000000000..9056e96b7 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/pystr_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for definition of __str__ method.''' + +import sys +import unittest + +from sample import Point + +class PyStrTest(unittest.TestCase): + '''Test case for definition of __str__ method.''' + + def testPyStr(self): + '''Test case for defined __str__ method.''' + pt = Point(5, 2) + self.assertEqual(str(pt), 'Point(5.0, 2.0)') + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/python_thread_test.py b/sources/shiboken2/tests/samplebinding/python_thread_test.py new file mode 100644 index 000000000..dcd59ee1f --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/python_thread_test.py @@ -0,0 +1,116 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +#!/usr/bin/env python + +'''Tests for using Shiboken-based bindings with python threads''' + +import unittest +import threading +import sample +import time + +import logging + +#logging.basicConfig(level=logging.DEBUG) + +from random import random + +class Producer(threading.Thread): + '''Producer thread''' + + def __init__(self, bucket, max_runs, *args): + #Constructor. Receives the bucket + super(Producer, self).__init__(*args) + self.runs = 0 + self.bucket = bucket + self.max_runs = max_runs + self.production_list = [] + + def run(self): + while self.runs < self.max_runs: + value = int(random()*10) % 10 + self.bucket.push(value) + self.production_list.append(value) + logging.debug('PRODUCER - pushed %d' % value) + self.runs += 1 + #self.msleep(5) + time.sleep(0.01) + + +class Consumer(threading.Thread): + '''Consumer thread''' + def __init__(self, bucket, max_runs, *args): + #Constructor. Receives the bucket + super(Consumer, self).__init__(*args) + self.runs = 0 + self.bucket = bucket + self.max_runs = max_runs + self.consumption_list = [] + + def run(self): + while self.runs < self.max_runs: + if not self.bucket.empty(): + value = self.bucket.pop() + self.consumption_list.append(value) + logging.debug('CONSUMER - got %d' % value) + self.runs += 1 + else: + logging.debug('CONSUMER - empty bucket') + time.sleep(0.01) + +class ProducerConsumer(unittest.TestCase): + '''Basic test case for producer-consumer QThread''' + + def finishCb(self): + #Quits the application + self.app.exit(0) + + def testProdCon(self): + #QThread producer-consumer example + bucket = sample.Bucket() + prod = Producer(bucket, 10) + cons = Consumer(bucket, 10) + + prod.start() + cons.start() + + #QObject.connect(prod, SIGNAL('finished()'), self.finishCb) + #QObject.connect(cons, SIGNAL('finished()'), self.finishCb) + + prod.join() + cons.join() + + self.assertEqual(prod.production_list, cons.consumption_list) + + + + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/receive_null_cstring_test.py b/sources/shiboken2/tests/samplebinding/receive_null_cstring_test.py new file mode 100644 index 000000000..12cc67142 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/receive_null_cstring_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for a function that could receive a NULL pointer in a '[const] char*' parameter.''' + +import unittest + +from sample import countCharacters + +class ReceiveNullCStringTest(unittest.TestCase): + '''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.''' + a = '' + b = 'abc' + self.assertEqual(countCharacters(a), len(a)) + self.assertEqual(countCharacters(b), len(b)) + + def testReceiveNull(self): + '''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/shiboken2/tests/samplebinding/reference_test.py b/sources/shiboken2/tests/samplebinding/reference_test.py new file mode 100644 index 000000000..aaf809451 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/reference_test.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for methods that receive references to objects.''' + +import sys +import unittest + +from sample import * + +class ExtendedReference(Reference): + def __init__(self): + Reference.__init__(self) + self.uses_reference_virtual_called = False + self.uses_const_reference_virtual_called = False + self.reference_inc = 1 + self.const_reference_inc = 2 + self.multiplier = 333 + + def usesReferenceVirtual(self, ref, inc): + self.uses_reference_virtual_called = True + return ref.objId() + inc + self.reference_inc + + def usesConstReferenceVirtual(self, ref, inc): + self.uses_const_reference_virtual_called = True + return ref.objId() + inc + self.const_reference_inc + + def alterReferenceIdVirtual(self, ref): + ref.setObjId(ref.objId() * self.multiplier) + + +class ReferenceTest(unittest.TestCase): + '''Test case for methods that receive references to objects.''' + + def testMethodThatReceivesReference(self): + '''Test a method that receives a reference to an object as argument.''' + objId = 123 + r = Reference(objId) + self.assertEqual(Reference.usesReference(r), objId) + + def testCantSegFaultWhenReceiveNone(self): + '''do not segfault when receiving None as argument.''' + s = Str() + self.assertTrue(None == s) + + def testMethodThatReceivesConstReference(self): + '''Test a method that receives a const reference to an object as argument.''' + objId = 123 + r = Reference(objId) + 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++.''' + 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.''' + 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.''' + objId = 123 + r = Reference(objId) + er = ExtendedReference() + result = er.callAlterReferenceIdVirtual(r) + 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++.''' + inc = 9 + objId = 123 + r = Reference(objId) + er = ExtendedReference() + result = er.callUsesReferenceVirtual(r, inc) + 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++.''' + inc = 9 + objId = 123 + r = Reference(objId) + er = ExtendedReference() + result = er.callUsesConstReferenceVirtual(r, inc) + self.assertEqual(result, objId + inc + er.const_reference_inc) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/referencetopointer_test.py b/sources/shiboken2/tests/samplebinding/referencetopointer_test.py new file mode 100644 index 000000000..8d85032a0 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/referencetopointer_test.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for a reference to pointer argument type.''' + +import unittest + +from sample import VirtualMethods, Str + +class ExtendedVirtualMethods(VirtualMethods): + def __init__(self): + VirtualMethods.__init__(self) + self.prefix = 'Ext' + + def createStr(self, text): + ext_text = text + if text is not None: + ext_text = self.prefix + text + return VirtualMethods.createStr(self, ext_text) + + +class ReferenceToPointerTest(unittest.TestCase): + '''Test cases for a reference to pointer argument type.''' + + def testSimpleCallWithNone(self): + '''Simple call to createStr method with a None argument.''' + obj = VirtualMethods() + ok, string = obj.createStr(None) + self.assertFalse(ok) + self.assertEqual(string, None) + + def testSimpleCallWithString(self): + '''Simple call to createStr method with a Python string argument.''' + obj = VirtualMethods() + ok, string = obj.createStr('foo') + self.assertTrue(ok) + self.assertEqual(string, Str('foo')) + + def testCallNonReimplementedMethodWithNone(self): + '''Calls createStr method from C++ with a None argument.''' + obj = VirtualMethods() + ok, string = obj.callCreateStr(None) + self.assertFalse(ok) + self.assertEqual(string, None) + + def testCallNonReimplementedMethodWithString(self): + '''Calls createStr method from C++ with a Python string argument.''' + obj = VirtualMethods() + ok, string = obj.callCreateStr('foo') + self.assertTrue(ok) + self.assertEqual(string, Str('foo')) + + def testCallReimplementedMethodWithNone(self): + '''Calls reimplemented createStr method from C++ with a None argument.''' + obj = ExtendedVirtualMethods() + ok, string = obj.callCreateStr(None) + self.assertFalse(ok) + self.assertEqual(string, None) + + def testCallReimplementedMethodWithString(self): + '''Calls reimplemented createStr method from C++ with a Python string argument.''' + obj = ExtendedVirtualMethods() + ok, string = obj.callCreateStr('foo') + self.assertTrue(ok) + self.assertEqual(string, Str(obj.prefix + 'foo')) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/return_null_test.py b/sources/shiboken2/tests/samplebinding/return_null_test.py new file mode 100644 index 000000000..377624482 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/return_null_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for functions that could return a NULL pointer.''' + +import sys +import unittest + +from sample import returnNullPrimitivePointer, returnNullValueTypePointer, returnNullObjectTypePointer + +class ReturnNullTest(unittest.TestCase): + '''Test case for functions that could return a NULL pointer.''' + + def testReturnNull(self): + '''Function returns a NULL pointer to a primitive type.''' + o = returnNullPrimitivePointer() + self.assertEqual(o, None) + + def testReturnNullObjectType(self): + '''Function returns a NULL pointer to an object-type.''' + o = returnNullObjectTypePointer() + self.assertEqual(o, None) + + def testReturnNullValueType(self): + '''Function returns a NULL pointer to a value-type.''' + o = returnNullValueTypePointer() + self.assertEqual(o, None) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/richcompare_test.py b/sources/shiboken2/tests/samplebinding/richcompare_test.py new file mode 100644 index 000000000..8c5eea694 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/richcompare_test.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import * + +class TestRichCompare(unittest.TestCase): + + def testIt(self): + a = Expression(2) + b = Expression(3) + c = a + b + d = a + c < b + a + self.assertEqual(d.toString(), "((2+(2+3))<(3+2))") + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/sample-binding.txt.in b/sources/shiboken2/tests/samplebinding/sample-binding.txt.in new file mode 100644 index 000000000..317f76f09 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/sample-binding.txt.in @@ -0,0 +1,15 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @sample_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libsample_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +enable-parent-ctor-heuristic +use-isnull-as-nb_nonzero diff --git a/sources/shiboken2/tests/samplebinding/sample_test.py b/sources/shiboken2/tests/samplebinding/sample_test.py new file mode 100644 index 000000000..65d1d2871 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/sample_test.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for libsample bindings module''' + +import unittest + +import sample + +class ModuleTest(unittest.TestCase): + '''Test case for module and global functions''' + + 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))) + + 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))) + + 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' + self.assertEqual(sample.multiplyString(str1, 3), str1 * 3) + self.assertEqual(sample.multiplyString(str1, 0), str1 * 0) + + def testAddedFunctionWithVarargs(self): + '''Calls function that receives varargs added to module from type system description.''' + self.assertEqual(sample.countVarargs(1), 0) + self.assertEqual(sample.countVarargs(1, 2), 1) + self.assertEqual(sample.countVarargs(1, 2, 3, 'a', 'b', 4, (5, 6)), 6) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/simplefile_glue.cpp b/sources/shiboken2/tests/samplebinding/simplefile_glue.cpp new file mode 100644 index 000000000..a7f05eb99 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/simplefile_glue.cpp @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +if (!%CPPSELF.%FUNCTION_NAME()) { + PyObject* error_msg = PyBytes_FromFormat( + "Could not open file: \"%s\"", %CPPSELF->filename()); + PyErr_SetObject(PyExc_IOError, error_msg); + return 0; +} diff --git a/sources/shiboken2/tests/samplebinding/simplefile_test.py b/sources/shiboken2/tests/samplebinding/simplefile_test.py new file mode 100644 index 000000000..c2a1afe59 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/simplefile_test.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for SimpleFile class''' + +import os +import unittest + +from sample import SimpleFile + +class SimpleFileTest(unittest.TestCase): + '''Test cases for SimpleFile class.''' + + def setUp(self): + filename = 'simplefile%d.txt' % os.getpid() + self.existing_filename = os.path.join(os.path.curdir, filename) + self.delete_file = False + if not os.path.exists(self.existing_filename): + f = open(self.existing_filename, 'w') + for line in range(10): + f.write('sbrubbles\n') + f.close() + self.delete_file = True + + self.non_existing_filename = os.path.join(os.path.curdir, 'inexistingfile.txt') + i = 0 + while os.path.exists(self.non_existing_filename): + i += 1 + filename = 'inexistingfile-%d.txt' % i + self.non_existing_filename = os.path.join(os.path.curdir, filename) + + def tearDown(self): + if self.delete_file: + os.remove(self.existing_filename) + + def testExistingFile(self): + '''Test SimpleFile class with existing file.''' + f = SimpleFile(self.existing_filename) + self.assertEqual(f.filename(), self.existing_filename) + f.open() + self.assertNotEqual(f.size(), 0) + f.close() + + def testNonExistingFile(self): + '''Test SimpleFile class with non-existing file.''' + f = SimpleFile(self.non_existing_filename) + self.assertEqual(f.filename(), self.non_existing_filename) + self.assertRaises(IOError, f.open) + self.assertEqual(f.size(), 0) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/size_test.py b/sources/shiboken2/tests/samplebinding/size_test.py new file mode 100644 index 000000000..502539689 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/size_test.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for operator overloads on Size class''' + +import unittest + +from sample import Size + +class PointTest(unittest.TestCase): + '''Test case for Size class, including operator overloads.''' + + def testConstructor(self): + '''Test Size class constructor.''' + width, height = (5.0, 2.3) + size = Size(width, height) + self.assertEqual(size.width(), width) + self.assertEqual(size.height(), height) + self.assertEqual(size.calculateArea(), width * height) + + def testCopyConstructor(self): + '''Test Size class copy constructor.''' + width, height = (5.0, 2.3) + s1 = Size(width, height) + s2 = Size(s1) + self.assertFalse(s1 is s2) + self.assertEqual(s1, s2) + + def testPlusOperator(self): + '''Test Size class + operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(0.5, 3.2) + self.assertEqual(s1 + s2, Size(5.0 + 0.5, 2.3 + 3.2)) + + def testEqualOperator(self): + '''Test Size class == operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(5.0, 2.3) + s3 = Size(0.5, 3.2) + self.assertTrue(s1 == s1) + self.assertTrue(s1 == s2) + self.assertFalse(s1 == s3) + + def testNotEqualOperator(self): + '''Test Size class != operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(5.0, 2.3) + s3 = Size(0.5, 3.2) + self.assertFalse(s1 != s1) + self.assertFalse(s1 != s2) + self.assertTrue(s1 != s3) + + def testMinorEqualOperator(self): + '''Test Size class <= operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(5.0, 2.3) + s3 = Size(0.5, 3.2) + self.assertTrue(s1 <= s1) + self.assertTrue(s1 <= s2) + self.assertTrue(s3 <= s1) + self.assertFalse(s1 <= s3) + + def testMinorOperator(self): + '''Test Size class < operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(0.5, 3.2) + self.assertFalse(s1 < s1) + self.assertFalse(s1 < s2) + self.assertTrue(s2 < s1) + + def testMajorEqualOperator(self): + '''Test Size class >= operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(5.0, 2.3) + s3 = Size(0.5, 3.2) + self.assertTrue(s1 >= s1) + self.assertTrue(s1 >= s2) + self.assertTrue(s1 >= s3) + self.assertFalse(s3 >= s1) + + def testMajorOperator(self): + '''Test Size class > operator.''' + s1 = Size(5.0, 2.3) + s2 = Size(0.5, 3.2) + self.assertFalse(s1 > s1) + self.assertTrue(s1 > s2) + self.assertFalse(s2 > s1) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/static_nonstatic_methods_test.py b/sources/shiboken2/tests/samplebinding/static_nonstatic_methods_test.py new file mode 100644 index 000000000..6451c4440 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/static_nonstatic_methods_test.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for overloads involving static and non-static versions of a method.''' + +import os +import unittest + +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.''' + + def setUp(self): + filename = 'simplefile%d.txt' % os.getpid() + self.existing_filename = os.path.join(os.path.curdir, filename) + self.delete_file = False + if not os.path.exists(self.existing_filename): + f = open(self.existing_filename, 'w') + for line in range(10): + f.write('sbrubbles\n') + f.close() + self.delete_file = True + + self.non_existing_filename = os.path.join(os.path.curdir, 'inexistingfile.txt') + i = 0 + while os.path.exists(self.non_existing_filename): + i += 1 + filename = 'inexistingfile-%d.txt' % i + self.non_existing_filename = os.path.join(os.path.curdir, filename) + + def tearDown(self): + if self.delete_file: + os.remove(self.existing_filename) + + def testCallingStaticMethodWithClass(self): + '''Call static method using class.''' + self.assertTrue(SimpleFile.exists(self.existing_filename)) + self.assertFalse(SimpleFile.exists(self.non_existing_filename)) + + def testCallingStaticMethodWithInstance(self): + '''Call static method using instance of class.''' + f = SimpleFile(self.non_existing_filename) + self.assertTrue(f.exists(self.existing_filename)) + self.assertFalse(f.exists(self.non_existing_filename)) + + def testCallingInstanceMethod(self): + '''Call instance method.''' + f1 = SimpleFile(self.non_existing_filename) + self.assertFalse(f1.exists()) + f2 = SimpleFile(self.existing_filename) + self.assertTrue(f2.exists()) + + def testOverridingStaticNonStaticMethod(self): + f = SimpleFile2(self.existing_filename) + self.assertEqual(f.exists(), "Mooo") + + f = SimpleFile3(self.existing_filename) + self.assertTrue(f.exists()) + + f = SimpleFile4(self.existing_filename) + self.assertEqual(f.exists, 5) + + def testDuckPunchingStaticNonStaticMethod(self): + f = SimpleFile(self.existing_filename) + f.exists = lambda : "Meee" + self.assertEqual(f.exists(), "Meee") + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/str_test.py b/sources/shiboken2/tests/samplebinding/str_test.py new file mode 100644 index 000000000..dca7e1f44 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/str_test.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for a method that receives a reference to class that is implicitly convertible from a Python native type.''' + +import unittest + +from sample import Str + +class StrTest(unittest.TestCase): + '''Test cases for thr Str class.''' + + def test__str__Method(self): + '''Test if the binding correcly implements the Python __str__ method.''' + s1 = 'original string' + s2 = Str(s1) + self.assertEqual(s1, s2) + self.assertEqual(s1, str(s2)) + + def testPassExactClassAsReferenceToArgument(self): + '''Test passing the expected class as an argument to a method that expects a reference.''' + s1 = Str('This is %VAR!').arg(Str('Sparta')) + 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.''' + 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); + + # 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.assertRaises(TypeError, s1.__getitem__, 6) + + # setitem + s1[0] = 'A' + 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") + + def testToIntError(self): + self.assertEqual(Str('Z').toInt(), (0, False)) + + def testToIntWithDecimal(self): + decimal = Str('37') + val, ok = decimal.toInt() + self.assertEqual(type(val), int) + self.assertEqual(type(ok), bool) + self.assertEqual(val, int(str(decimal))) + + def testToIntWithOctal(self): + octal = Str('52') + val, ok = octal.toInt(8) + self.assertEqual(type(val), int) + self.assertEqual(type(ok), bool) + self.assertEqual(val, int(str(octal), 8)) + + def testToIntWithHexadecimal(self): + hexa = Str('2A') + val, ok = hexa.toInt(16) + self.assertEqual(type(val), int) + self.assertEqual(type(ok), bool) + self.assertEqual(val, int(str(hexa), 16)) + self.assertEqual(hexa.toInt(), (0, False)) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/strlist_test.py b/sources/shiboken2/tests/samplebinding/strlist_test.py new file mode 100644 index 000000000..341fcfa32 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/strlist_test.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for StrList class that inherits from std::list.''' + +import unittest + +from sample import Str, StrList + +class StrListTest(unittest.TestCase): + '''Test cases for StrList class that inherits from std::list.''' + + def testStrListCtor_NoParams(self): + '''StrList constructor receives no parameter.''' + sl = StrList() + self.assertEqual(len(sl), 0) + self.assertEqual(sl.constructorUsed(), StrList.NoParamsCtor) + + def testStrListCtor_Str(self): + '''StrList constructor receives a Str object.''' + s = Str('Foo') + sl = StrList(s) + self.assertEqual(len(sl), 1) + self.assertEqual(sl[0], s) + self.assertEqual(sl.constructorUsed(), StrList.StrCtor) + + def testStrListCtor_PythonString(self): + '''StrList constructor receives a Python string.''' + s = 'Foo' + sl = StrList(s) + self.assertEqual(len(sl), 1) + self.assertEqual(sl[0], s) + self.assertEqual(sl.constructorUsed(), StrList.StrCtor) + + def testStrListCtor_StrList(self): + '''StrList constructor receives a StrList object.''' + sl1 = StrList(Str('Foo')) + sl2 = StrList(sl1) + #self.assertEqual(len(sl1), len(sl2)) + #self.assertEqual(sl1, sl2) + self.assertEqual(sl2.constructorUsed(), StrList.CopyCtor) + + def testStrListCtor_ListOfStrs(self): + '''StrList constructor receives a Python list of Str objects.''' + strs = [Str('Foo'), Str('Bar')] + sl = StrList(strs) + self.assertEqual(len(sl), len(strs)) + self.assertEqual(sl, strs) + self.assertEqual(sl.constructorUsed(), StrList.ListOfStrCtor) + + def testStrListCtor_MixedListOfStrsAndPythonStrings(self): + '''StrList constructor receives a Python list of mixed Str objects and Python strings.''' + strs = [Str('Foo'), 'Bar'] + sl = StrList(strs) + self.assertEqual(len(sl), len(strs)) + self.assertEqual(sl, strs) + self.assertEqual(sl.constructorUsed(), StrList.ListOfStrCtor) + + def testCompareStrListWithTupleOfStrs(self): + '''Compares StrList with a Python tuple of Str objects.''' + sl = StrList() + sl.append(Str('Foo')) + sl.append(Str('Bar')) + self.assertEqual(len(sl), 2) + self.assertEqual(sl, (Str('Foo'), Str('Bar'))) + + def testCompareStrListWithTupleOfPythonStrings(self): + '''Compares StrList with a Python tuple of Python strings.''' + sl = StrList() + sl.append(Str('Foo')) + sl.append(Str('Bar')) + self.assertEqual(len(sl), 2) + self.assertEqual(sl, ('Foo', 'Bar')) + + def testCompareStrListWithTupleOfStrAndPythonString(self): + '''Compares StrList with a Python tuple of mixed Str objects and Python strings.''' + sl = StrList() + sl.append(Str('Foo')) + sl.append(Str('Bar')) + self.assertEqual(len(sl), 2) + self.assertEqual(sl, (Str('Foo'), 'Bar')) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/templateinheritingclass_test.py b/sources/shiboken2/tests/samplebinding/templateinheritingclass_test.py new file mode 100644 index 000000000..7acb6a597 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/templateinheritingclass_test.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import Photon + +'''This tests classes that inherit from template classes, +simulating a situation found in Qt's phonon module.''' + +class TemplateInheritingClassTest(unittest.TestCase): + def testClassBasics(self): + self.assertEqual(Photon.ValueIdentity.classType(), Photon.IdentityType) + self.assertEqual(Photon.ValueDuplicator.classType(), Photon.DuplicatorType) + + def testInstanceBasics(self): + value = 123 + samer = Photon.ValueIdentity(value) + self.assertEqual(samer.multiplicator(), 1) + doubler = Photon.ValueDuplicator(value) + self.assertEqual(doubler.multiplicator(), 2) + self.assertEqual(samer.value(), doubler.value()) + self.assertEqual(samer.calculate() * 2, doubler.calculate()) + + def testPassToFunctionAsPointer(self): + obj = Photon.ValueDuplicator(123) + self.assertEqual(Photon.callCalculateForValueDuplicatorPointer(obj), obj.calculate()) + + def testPassToFunctionAsReference(self): + obj = Photon.ValueDuplicator(321) + self.assertEqual(Photon.callCalculateForValueDuplicatorReference(obj), obj.calculate()) + + def testPassToMethodAsValue(self): + value1, value2 = 123, 321 + one = Photon.ValueIdentity(value1) + other = Photon.ValueIdentity(value2) + self.assertEqual(one.sumValueUsingPointer(other), value1 + value2) + + def testPassToMethodAsReference(self): + value1, value2 = 123, 321 + one = Photon.ValueDuplicator(value1) + other = Photon.ValueDuplicator(value2) + self.assertEqual(one.sumValueUsingReference(other), value1 + value2) + + def testPassPointerThrough(self): + obj1 = Photon.ValueIdentity(123) + self.assertEqual(obj1, obj1.passPointerThrough(obj1)) + obj2 = Photon.ValueDuplicator(321) + self.assertEqual(obj2, obj2.passPointerThrough(obj2)) + self.assertRaises(TypeError, obj1.passPointerThrough, obj2) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/time_test.py b/sources/shiboken2/tests/samplebinding/time_test.py new file mode 100644 index 000000000..db8818fd3 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/time_test.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for constructor and method signature decisor on Time class.''' + +import sys +import unittest +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 + CTORMETHOD(int h, int m, int s = 0, int ms = 0); there another method + with a more complex signature METH(int, int, ImplicitConv=DEFVALUE, ObjectType=0), + to produce an even worse scenario. + ''' + + def testConstructorWithoutParamers(self): + '''Constructor without parameters: Time()''' + time = Time() + self.assertTrue(time.isNull()) + + def testConstructorWithAllParamers(self): + '''Constructor with all parameters: Time(int h, int m, int s = 0, int ms = 0)''' + time = Time(1, 2, 3, 4) + self.assertTrue(time.toString(), '01:02:03.004') + + def testConstructorWithThreeParamers(self): + '''Constructor with 3 parameters: Time(int h, int m, int s = 0, int ms = 0)''' + time = Time(1, 2, 3) + self.assertTrue(time.toString(), '01:02:03.000') + + def testConstructorWithTwoParamers(self): + '''Constructor with 2 parameters: Time(int h, int m, int s = 0, int ms = 0)''' + time = Time(1, 2) + self.assertTrue(time.toString(), '01:02:00.000') + + def testSimpleMethodWithoutParamers(self): + '''Constructor without parameters: Time.setTime()''' + time = Time(1, 2, 3, 4) + time.setTime() + self.assertTrue(time.isNull()) + + def testSimpleMethodWithAllParamers(self): + '''Simple method with all parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' + time = Time() + time.setTime(1, 2, 3, 4) + self.assertTrue(time.toString(), '01:02:03.004') + + def testSimpleMethodWithThreeParamers(self): + '''Simple method with 3 parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' + time = Time() + time.setTime(1, 2, 3) + self.assertTrue(time.toString(), '01:02:03.000') + + def testSimpleMethodWithTwoParamers(self): + '''Simple method with 2 parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' + time = Time() + time.setTime(1, 2) + self.assertTrue(time.toString(), '01:02:00.000') + + def testMethodWithoutParamers(self): + '''Method without parameters: Time.somethingCompletelyDifferent()''' + time = Time() + result = time.somethingCompletelyDifferent() + self.assertEqual(result, Time.ZeroArgs) + + def testMethodWithAllParamers(self): + '''Method with all parameters: + Time.somethingCompletelyDifferent( + int h, int m, ImplicitConv ic = ImplicitConv::CtorThree, ObjectType* type = 0 + ); + ''' + time = Time() + obj = ObjectType() + result = time.somethingCompletelyDifferent(1, 2, ImplicitConv(2), obj) + self.assertEqual(result, Time.FourArgs) + + def testMethodWithThreeParamers(self): + '''Method with 3 parameters: Time.somethingCompletelyDifferent(...)''' + time = Time() + result = time.somethingCompletelyDifferent(1, 2, ImplicitConv(ImplicitConv.CtorOne)) + self.assertEqual(result, Time.ThreeArgs) + + def testMethodWithTwoParamers(self): + '''Method with 2 parameters: Time.somethingCompletelyDifferent(...)''' + time = Time() + result = time.somethingCompletelyDifferent(1, 2) + self.assertEqual(result, Time.TwoArgs) + + def testMethodWithThreeParamersAndImplicitConversion(self): + '''Method with 3 parameters, the last one triggers an implicit conversion.''' + time = Time() + result = time.somethingCompletelyDifferent(1, 2, ImplicitConv.CtorOne) + self.assertEqual(result, Time.ThreeArgs) + + def testCompareWithPythonTime(self): + time = Time(12, 32, 5) + py = datetime.time(12, 32, 5) + self.assertEqual(time, py) + + def testNotEqual(self): + time = Time(12, 32, 6) + py = datetime.time(12, 32, 5) + self.assertNotEqual(time, py) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/transform_test.py b/sources/shiboken2/tests/samplebinding/transform_test.py new file mode 100644 index 000000000..f490945b8 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/transform_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for argument modification with more than nine arguments.''' + +import unittest + +from sample import Point, applyHomogeneousTransform + +class TransformTest(unittest.TestCase): + '''Test cases for modifying a function with > 9 arguments.''' + + def testTransform_ValidMatrix(self): + '''Transform applies successfully.''' + p = Point(3, 4) + r = applyHomogeneousTransform(p, 0, 1, 0, -1, 0, 0, 0, 0, 1) + self.assertTrue(type(r) is Point) + self.assertEqual(r.x(), 4) + self.assertEqual(r.y(), -3) + + def testTransform_InvalidMatrix(self): + '''Transform does not apply successfully.''' + p = Point(3, 4) + 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/shiboken2/tests/samplebinding/typeconverters_test.py b/sources/shiboken2/tests/samplebinding/typeconverters_test.py new file mode 100644 index 000000000..b3b469c56 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/typeconverters_test.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Tests various usages of the type converters.''' + +import unittest +import sample + +class GetPythonTypeByNameTest(unittest.TestCase): + + '''Uses an added function with inject code that uses the libshiboken + function "Shiboken::Conversions::getPythonTypeObject(typeName)".''' + + def testGetObjectType(self): + pyType1 = sample.getPythonType('ObjectType') + self.assertEqual(pyType1, sample.ObjectType) + pyType2 = sample.getPythonType('ObjectType*') + self.assertEqual(pyType2, sample.ObjectType) + self.assertEqual(pyType1, pyType2) + + def testGetValueType(self): + pyType1 = sample.getPythonType('Point') + self.assertEqual(pyType1, sample.Point) + pyType2 = sample.getPythonType('Point*') + self.assertEqual(pyType2, sample.Point) + self.assertEqual(pyType1, pyType2) + + def testGetUsersPrimitiveType(self): + pyType = sample.getPythonType('OddBool') + self.assertEqual(pyType, bool) + + def testGetUsersPrimitiveTypeWithoutTargetLangApiName(self): + '''If the primitive type attribute "target-lang-api-name" is not set + there'll be no Python type associated with the C++ type.''' + pyType = sample.getPythonType('PStr') + self.assertEqual(pyType, None) + + def testPrimitiveTypeAndTypedef(self): + pyType = sample.getPythonType('double') + self.assertEqual(pyType, float) + pyTypedef = sample.getPythonType('real') + self.assertEqual(pyType, pyTypedef) + + def testPairContainerType(self): + pyType = sample.getPythonType('std::pair') + self.assertEqual(pyType, list) + + def testListContainerType(self): + pyType = sample.getPythonType('std::list') + self.assertEqual(pyType, list) + + def testMapContainerType(self): + pyType = sample.getPythonType('std::map') + self.assertEqual(pyType, dict) + + def testGlobalEnumType(self): + pyType = sample.getPythonType('GlobalEnum') + self.assertEqual(pyType, sample.GlobalEnum) + + def testScopedEnumType(self): + pyType = sample.getPythonType('Abstract::Type') + self.assertEqual(pyType, sample.Abstract.Type) + + +class CheckValueAndObjectTypeByNameTest(unittest.TestCase): + + '''Uses an added function with inject code that uses the libshiboken + functions that check if a type is Object or Value, based on its converter.''' + + def testErrors(self): + '''not existent type''' + self.assertRaises(ValueError, sample.cppTypeIsValueType, 'NotExistentType') + self.assertRaises(ValueError, sample.cppTypeIsObjectType, 'NotExistentType') + + def testObjectType1(self): + self.assertTrue(sample.cppTypeIsObjectType('ObjectType')) + self.assertFalse(sample.cppTypeIsValueType('ObjectType')) + + def testObjectType2(self): + self.assertTrue(sample.cppTypeIsObjectType('ObjectType*')) + self.assertFalse(sample.cppTypeIsValueType('ObjectType*')) + + def testValueType1(self): + self.assertTrue(sample.cppTypeIsValueType('Point')) + self.assertFalse(sample.cppTypeIsObjectType('Point')) + + def testValueType2(self): + self.assertTrue(sample.cppTypeIsValueType('Point*')) + self.assertFalse(sample.cppTypeIsObjectType('Point*')) + + def testUsersPrimitiveType(self): + self.assertFalse(sample.cppTypeIsValueType('Complex')) + self.assertFalse(sample.cppTypeIsObjectType('Complex')) + + def testContainerType(self): + self.assertFalse(sample.cppTypeIsValueType('std::list')) + self.assertFalse(sample.cppTypeIsObjectType('std::list')) + + +class SpecificConverterTest(unittest.TestCase): + + '''Uses an added function with inject code that uses the libshiboken + adapter class "Shiboken::Conversions::SpecificConverter".''' + + def testNotExistentType(self): + conversion = sample.getConversionTypeString('NotExistentType') + self.assertEqual(conversion, 'Invalid conversion') + + def testObjectType(self): + conversion = sample.getConversionTypeString('ObjectType') + self.assertEqual(conversion, 'Pointer conversion') + conversion = sample.getConversionTypeString('ObjectType*') + self.assertEqual(conversion, 'Pointer conversion') + conversion = sample.getConversionTypeString('ObjectType&') + self.assertEqual(conversion, 'Reference conversion') + + def testValueType(self): + conversion = sample.getConversionTypeString('Point') + self.assertEqual(conversion, 'Copy conversion') + conversion = sample.getConversionTypeString('Point*') + self.assertEqual(conversion, 'Pointer conversion') + conversion = sample.getConversionTypeString('Point&') + self.assertEqual(conversion, 'Reference conversion') + + +class StringBasedConversionTest(unittest.TestCase): + + def testValueType(self): + pts = (sample.Point(1, 1), sample.Point(2, 2), sample.Point(3, 3)) + result = sample.convertValueTypeToCppAndThenToPython(pts[0], pts[1], pts[2]) + for orig, new in zip(pts, result): + self.assertEqual(orig, new) + self.assertFalse(pts[0] is result[0]) + self.assertTrue(pts[1] is result[1]) + self.assertTrue(pts[2] is result[2]) + + def testObjectType(self): + objs = (sample.ObjectType(), sample.ObjectType()) + objs[0].setObjectName('obj0') + objs[1].setObjectName('obj1') + result = sample.convertObjectTypeToCppAndThenToPython(objs[0], objs[1]) + for orig, new in zip(objs, result): + self.assertEqual(orig, new) + self.assertEqual(orig.objectName(), new.objectName()) + self.assertTrue(orig is new) + + def testContainerType(self): + lst = range(4) + result = sample.convertListOfIntegersToCppAndThenToPython(lst) + self.assertTrue(len(result), 1) + self.assertTrue(lst, result[0]) + + def testCppPrimitiveType(self): + integers = (12, 34) + result = sample.convertIntegersToCppAndThenToPython(integers[0], integers[1]) + for orig, new in zip(integers, result): + self.assertEqual(orig, new) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/typedealloc_test.py b/sources/shiboken2/tests/samplebinding/typedealloc_test.py new file mode 100644 index 000000000..b0fe763e0 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/typedealloc_test.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test deallocation of type extended in Python.''' + +import gc +import weakref +import unittest + +from sample import Point + + +class TypeDeallocTest(unittest.TestCase): + + def setUp(self): + self.called = False + + def tearDown(self): + del self.called + + def callback(self, *args): + self.called = True + + def testScopeEnd(self): + ref = None + def scope(): + class Ext(Point): + pass + o = Ext() + global ref + ref = weakref.ref(Ext, self.callback) + scope() + gc.collect() + self.assertTrue(self.called) + + def testDeleteType(self): + class Ext(Point): + pass + ref = weakref.ref(Ext, self.callback) + del Ext + gc.collect() + self.assertTrue(self.called) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/typedtordoublefree_test.py b/sources/shiboken2/tests/samplebinding/typedtordoublefree_test.py new file mode 100644 index 000000000..1106c8761 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/typedtordoublefree_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import ObjectType + +class TestTypeDestructorDoubleFree(unittest.TestCase): + def testTypeDestructorDoubleFree(self): + '''Causes the type destructors of two derived classes to be called.''' + def scope(): + class ExtObj1(ObjectType): + def __init__(self): + ObjectType.__init__(self) + 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/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml new file mode 100644 index 000000000..089f835fc --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -0,0 +1,2426 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + return PyLong_FromSize_t(%in); + + + + %out = %OUTTYPE(PyLong_AsSsize_t(%in)); + + + + + + + static bool Check2TupleOfNumbers(PyObject* pyIn) { + if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) + return false; + Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); + if (!SbkNumber_Check(pyReal)) + return false; + Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); + if (!SbkNumber_Check(pyImag)) + return false; + return true; + } + + + + + + return PyComplex_FromDoubles(%in.real(), %in.imag()); + + + + + double real = PyComplex_RealAsDouble(%in); + double imag = PyComplex_ImagAsDouble(%in); + %out = %OUTTYPE(real, imag); + + + 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); + + + + + + + + + + SBK_UNUSED(%in); + Py_RETURN_NONE; + + + + %out = %OUTTYPE(%in == 0); + + + + + + + + + + if (!%in) + Py_RETURN_NONE; + #ifdef IS_PY3K + return PyCapsule_New(%in, 0, 0); + #else + return PyCObject_FromVoidPtr(%in, 0); + #endif + + + + %out = 0; + + + void* ptr; + #ifdef IS_PY3K + ptr = PyCapsule_GetPointer(%in, 0); + #else + ptr = PyCObject_AsVoidPtr(%in); + #endif + %out = (%OUTTYPE)ptr; + + + + + + + static bool checkPyCapsuleOrPyCObject(PyObject* pyObj) + { + #ifdef IS_PY3K + return PyCapsule_CheckExact(pyObj); + #else + return PyCObject_Check(pyObj); + #endif + } + + + + + + + #ifdef IS_PY3K + return PyCapsule_New(&%in, 0, 0); + #else + return PyCObject_FromVoidPtr(&%in, 0); + #endif + + + + void* ptr; + #ifdef IS_PY3K + ptr = PyCapsule_GetPointer(%in, 0); + #else + ptr = PyCObject_AsVoidPtr(%in); + #endif + %out = *((%OUTTYPE*)ptr); + + + + + + + + + + + return PyBool_FromLong(%in.value()); + + + + // Tests CONVERTTOCPP macro with C++ primitive type. + bool b = %CONVERTTOCPP[bool](%in); + %out = %OUTTYPE(b); + + + // Tests CONVERTTOCPP macro with user's primitive type. + Complex cpx = %CONVERTTOCPP[Complex](%in); + %out = %OUTTYPE(cpx.real() != 0.0 || cpx.imag() != 0.0); + + + + + + + + + + return Shiboken::String::fromCString(%in.cstring(), %in.size()); + + + + const char* str = %CONVERTTOCPP[const char*](%in); + %out = %OUTTYPE(str); + + + %out = %OUTTYPE(); + + + + + + + + + + + + + + + + %FUNCTION_NAME(&%1, %2); + %PYARG_0 = %CONVERTTOPYTHON[PStr](%1); + + + + + + + + + + + + + + + + %FUNCTION_NAME(&%1); + %PYARG_0 = %CONVERTTOPYTHON[PStr](%1); + + + + + + + + + PyObject* %out = PyList_New((int) %in.size()); + PStrList::const_iterator it = %in.begin(); + for (int idx = 0; it != %in.end(); ++it, ++idx) { + PStr cppItem(*it); + PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[PStr](cppItem)); + } + return %out; + + + + %OUTTYPE& list = %out; + Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); + for (int i = 0; i < PySequence_Fast_GET_SIZE(seq.object()); i++) { + PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), i); + PStr cppItem = %CONVERTTOCPP[PStr](pyItem); + list.push_back(cppItem); + } + + + + + + + + PStrList %0; + %0.push_back(%1); + %0.push_back(%2); + %PYARG_0 = %CONVERTTOPYTHON[PStrList](%0); + + + + + std::list<PStr> %0; + %0.push_back(%1); + %0.push_back(%2); + %PYARG_0 = %CONVERTTOPYTHON[std::list<PStr>](%0); + + + + + + %PYARG_0 = (PyObject*) Shiboken::Conversions::getPythonTypeObject(%1); + if (!%PYARG_0) + %PYARG_0 = Py_None; + Py_INCREF(%PYARG_0); + + + + + + + + + + + + + + + + + + + + + + Shiboken::Conversions::SpecificConverter converter(%1); + const char* %0 = 0; + switch (converter.conversionType()) { + case Shiboken::Conversions::SpecificConverter::CopyConversion: + %0 = "Copy conversion"; + break; + case Shiboken::Conversions::SpecificConverter::PointerConversion: + %0 = "Pointer conversion"; + break; + case Shiboken::Conversions::SpecificConverter::ReferenceConversion: + %0 = "Reference conversion"; + break; + default: + %0 = "Invalid conversion"; + } + %PYARG_0 = %CONVERTTOPYTHON[const char*](%0); + + + + + static PyObject* __convertCppValuesToPython(const char** typeName, void** values, int size) + { + PyObject* result = PyTuple_New(size); + for (int i = 0; i < size; ++i) { + Shiboken::Conversions::SpecificConverter converter(typeName[i]); + PyTuple_SET_ITEM(result, i, converter.toPython(values[i])); + } + return result; + } + + + + const char* typeNames[] = { "Point", "Point*", "Point&" }; + void* values[] = { &%1, &%2, &(%3) }; + %PYARG_0 = __convertCppValuesToPython(typeNames, values, 3); + + + + + const char* typeNames[] = { "ObjectType*", "ObjectType&" }; + void* values[] = { &%1, &(%2) }; + %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2); + + + + + const char* typeNames[] = { "std::list<int>" }; + void* values[] = { &%1 }; + %PYARG_0 = __convertCppValuesToPython(typeNames, values, 1); + + + + + const char* typeNames[] = { "int", "int" }; + void* values[] = { &%1, &%2 }; + %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2); + + + + + + + + PyObject* %out = PyTuple_New(2); + PyTuple_SET_ITEM(%out, 0, %CONVERTTOPYTHON[%INTYPE_0](%in.first)); + PyTuple_SET_ITEM(%out, 1, %CONVERTTOPYTHON[%INTYPE_1](%in.second)); + return %out; + + + + %out.first = %CONVERTTOCPP[%OUTTYPE_0](PySequence_Fast_GET_ITEM(%in, 0)); + %out.second = %CONVERTTOCPP[%OUTTYPE_1](PySequence_Fast_GET_ITEM(%in, 1)); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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; + + + + PyObject* key; + PyObject* value; + Py_ssize_t pos = 0; + while (PyDict_Next(%in, &pos, &key, &value)) { + %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); + %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); + %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); + } + + + + + + + + %RETURN_TYPE %0 = Shiboken::BindingManager::instance().getAllPyObjects().size(); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + const unsigned char* %out = reinterpret_cast<const unsigned char*>(Shiboken::String::toCString(%PYARG_1)); + + + + + + unsigned int %out = static_cast<unsigned int>(Shiboken::String::len(%PYARG_1)); + + + + + + %RETURN_TYPE %0 = %1 + %2; + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + %RETURN_TYPE %0 = %1.x() + %1.y(); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + // The dot in "%1." must be replaced with a "->" by the generator. + %RETURN_TYPE %0 = %1.objectName().size(); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + const char* tmpArg = %CONVERTTOCPP[const char*](%PYARG_1); + %0 = new %FUNCTION_NAME(atoi(tmpArg)); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + static void reparent_layout_items(PyObject* parent, PyObject* layout) + { + // CHECKTYPE and ISCONVERTIBLE are used here for test purposes, don't change them. + if (!%CHECKTYPE[ObjectTypeLayout*](layout) && !%ISCONVERTIBLE[ObjectTypeLayout*](layout)) + return; + // %CHECKTYPE[ObjectTypeLayout*](layout) + // %ISCONVERTIBLE[ObjectTypeLayout*](layout) + ObjectTypeLayout* var; + var = %CONVERTTOCPP[ObjectTypeLayout*](layout); + // TODO-CONVERTER: erase this + /* + ObjectTypeLayout* var2 = %CONVERTTOCPP[ObjectTypeLayout*](layout); + */ + const ObjectTypeList& objChildren = var->objects(); + ObjectTypeList::const_iterator it = objChildren.begin(); + for (; it != objChildren.end(); ++it) { + if ((*it)->isLayoutType()) { + ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(*it); + reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); + Shiboken::Object::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); + } else { + Shiboken::Object::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); + } + } + } + + + + + + + if (%PYARG_1 != Py_None) + reparent_layout_items(%PYSELF, %PYARG_1); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %2) * 10; + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%PYARG_1); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, true, %3, %4); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + int %out = PySequence_Size(%PYARG_1); + + + + + + Shiboken::AutoArrayPointer<Point> %out(%1); + for (int i = 0; i < %1; ++i) + %out[i] = %CONVERTTOCPP[Point](PySequence_Fast_GET_ITEM(%PYARG_1, i)); + + + + + + + + + + + + int size = (%2 < 0) ? %1.size() : %2; + %BEGIN_ALLOW_THREADS + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME((const void*) %1.data(), size); + %END_ALLOW_THREADS + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); + Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); + *%2 = %CONVERTTOCPP[bool](_py_ok_); + %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ret_); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ObjectType* tmpObject = 0; + %BEGIN_ALLOW_THREADS + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(&tmpObject); + %END_ALLOW_THREADS + %PYARG_0 = PyTuple_New(2); + PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](%0)); + PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[ObjectType*](tmpObject)); + + + + + %RETURN_TYPE %0 = !%CPPSELF.%FUNCTION_NAME(%1); + %PYARG_0 = %CONVERTTOPYTHON[OddBool](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %1+%3, %3); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + PyObject* new_arg0 = PyInt_FromLong(PyInt_AS_LONG(%PYARG_1) - %2); + Py_DECREF(%PYARG_1); + %PYARG_1 = new_arg0; + + + + + %0.prepend(Str("Pimped")); + + + + + PyObject_Call(%PYTHON_METHOD_OVERRIDE, %PYTHON_ARGUMENTS, NULL); + + + + + + + + + + Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); + Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); + %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ok_); + %2 = %CONVERTTOCPP[Str*](_py_ret_); + + + + Str* _str_arg_ = 0; + %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, _str_arg_); + + + %PYARG_0 = PyTuple_New(2); + PyObject* _item_ = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + PyTuple_SET_ITEM(%PYARG_0, 0, _item_); + _item_ = %CONVERTTOPYTHON[Str*](_str_arg_); + PyTuple_SET_ITEM(%PYARG_0, 1, _item_); + + + + + + + + + + + Str* _str_arg_ = 0; + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, _str_arg_); + + + %PYARG_0 = PyTuple_New(2); + PyObject* _item_ = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + PyTuple_SET_ITEM(%PYARG_0, 0, _item_); + _item_ = %CONVERTTOPYTHON[Str*](_str_arg_); + PyTuple_SET_ITEM(%PYARG_0, 1, _item_); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %BEGIN_ALLOW_THREADS + // It's important for test purposes to use a constructor with parenthesis as argument. + %RETURN_TYPE %0 = %RETURN_TYPE(%CPPSELF.%FUNCTION_NAME(Str(%1))); + %END_ALLOW_THREADS + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + %0 = new %TYPE(%PYARG_1); + + + + + %PYARG_0 = reinterpret_cast<PyObject*>(%CPPSELF.%FUNCTION_NAME()); + if (!%PYARG_0) + %PYARG_0 = Py_None; + Py_INCREF(%PYARG_0); + + + + + + + + + + + + bool ok_; + %RETURN_TYPE retval_ = + %FUNCTION_NAME(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, &ok_); + if (!ok_) + %PYARG_0 = Py_None; + else + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](retval_); + + + + + + + + typedef std::list<int> Inner; + typedef std::list<Inner> Outer; + + int result = 0; + + Outer::const_iterator oiter, oend = %1.end(); + for (oiter = %1.begin(); oiter != oend; ++oiter) { + const Inner& inner = *oiter; + Inner::const_iterator iiter, iend = inner.end(); + for (iiter = inner.begin(); iiter != iend; ++iiter) + result += *iiter; + } + + %PYARG_0 = %CONVERTTOPYTHON[int](result); + + + + + + + typedef std::pair<int, int> Pair; + typedef std::list<Pair> List; + + int result = 0; + + List::const_iterator iter, end = %1.end(); + for (iter = %1.begin(); iter != end; ++iter) + result += iter->first * iter->second; + + %PYARG_0 = %CONVERTTOPYTHON[int](result); + + + + + + + + + + + + + int* array = NULL; + bool errorOccurred = false; + + if (PySequence_Check(%PYARG_1)) { + if((array = Shiboken::sequenceToIntArray(%PYARG_1, true)) == NULL && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "Should be a sequence of ints"); + errorOccurred = true; + } + } else { + PyErr_SetString(PyExc_TypeError, "Should be a sequence of ints"); + errorOccurred = true; + } + + if (!errorOccurred) { + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(array); + if (array) + delete[] array; + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + } + + + + + + + + int %out = PySequence_Size(%PYARG_1); + + + + + + int numItems = PySequence_Size(%PYARG_1); + Shiboken::AutoArrayPointer<int> %out(numItems); + for (int i = 0; i < numItems; ++i) { + if (%CHECKTYPE[int](PySequence_Fast_GET_ITEM(%PYARG_1, i))) + %out[i] = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(%PYARG_1, i)); + else if (%ISCONVERTIBLE[int](PySequence_Fast_GET_ITEM(%PYARG_1, i))) + %out[i] = -1; + else + %out[i] = -2; + } + + + PyObject* %out = PyList_New(count); + for (int i = 0; i < count; ++i) + PyList_SET_ITEM(%out, i, %CONVERTTOPYTHON[int](%in[i])); + + + + + + + + + + + + + int numItems = PySequence_Size(%PYARG_1); + int *cppItems = new int[numItems]; + for (int i = 0; i < numItems; i++) + cppItems[i] = %CONVERTTOCPP[int](PySequence_GetItem(%PYARG_1, i)); + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(numItems, cppItems); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + delete[] cppItems; + + + + + + PyObject* InjectCode_tpstr(PyObject*) { return Shiboken::String::fromCString("Hi! I'm the inject code dummy class."); } + + + + %PYTHONTYPEOBJECT.tp_str = InjectCode_tpstr; + + + + + + %1 += 1; + + + PyObject* tmp = Shiboken::String::fromCString("end"); + Shiboken::String::concat(&%PYARG_0, tmp); + Py_DECREF(tmp); + + + + + + + PyObject* tmp = Shiboken::String::fromCString("end"); + Shiboken::String::concat(&%PYARG_0, tmp); + Py_DECREF(tmp); + + + + + + + + + + + + + int argc; + char** argv; + if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + PyErr_SetString(PyExc_TypeError, "error"); + return 0; + } + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argc, argv); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + for (int i = 0; i < argc; ++i) + free(argv[i]); + delete[] argv; + + + + + + + + + + + + + int argc; + char** argv; + if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + PyErr_SetString(PyExc_TypeError, "error"); + return 0; + } + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argc, argv); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + for (int i = 0; i < argc; ++i) + free(argv[i]); + delete[] argv; + + + + + + + + + return Shiboken::String::fromCString("PyObject"); + + + + + + return Shiboken::String::fromCString("PyObject"); + + + + + + + unsigned char* %out = 0; + + + + + + + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 100)) - (x1 * 100); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 100)) - (y1 * 100); + %PYARG_0 = Shiboken::String::fromFormat("Point(%d.%d, %d.%d)", x1, x2, y1, y2); + + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 10)) - (x1 * 10); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 10)) - (y1 * 10); + %PYARG_0 = Shiboken::String::fromFormat("<Point object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); + + + + + + PyObject* type = PyObject_Type(%PYSELF); + PyObject* args = NULL; + + args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); + + %PYARG_0 = Py_BuildValue("(OO)", type, args); + + + + + + + + + + + + Point _midpoint; + // The test consists in *NOT* using the ARGUMENT_NAMES type system variable. + %CPPSELF.%FUNCTION_NAME(%1, &_midpoint); + %PYARG_0 = %CONVERTTOPYTHON[Point](_midpoint); + + + + + + + + + + + + + + + + + + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 100)) - (x1 * 100); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 100)) - (y1 * 100); + %PYARG_0 = Shiboken::String::fromFormat("PointF(%d.%d, %d.%d)", x1, x2, y1, y2); + + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 10)) - (x1 * 10); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 10)) - (y1 * 10); + %PYARG_0 = Shiboken::String::fromFormat("<PointF object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); + + + + + + PyObject *type = PyObject_Type(%PYSELF); + PyObject *args = NULL; + + args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); + + %PYARG_0 = Py_BuildValue("(OO)", type, args); + + + + + + + + + + + + PointF _midpoint; + // The test consists in using the ARGUMENT_NAMES type system variable. + %CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, &_midpoint); + %PYARG_0 = %CONVERTTOPYTHON[PointF](_midpoint); + + + + + + + + + + + + + + + + + + + + + + + + + + + + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + if (PyTime_Check(%1)) { + int pyH = PyDateTime_TIME_GET_HOUR(%1); + int pyM = PyDateTime_TIME_GET_MINUTE(%1); + int pyS = PyDateTime_TIME_GET_SECOND(%1); + if ((pyH == %CPPSELF.hour()) && + (pyM == %CPPSELF.minute()) && + (pyS == %CPPSELF.second())) + %PYARG_0 = Py_False; + else + %PYARG_0 = Py_True; + } + + + + + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + if (PyTime_Check(%1)) { + int pyH = PyDateTime_TIME_GET_HOUR(%1); + int pyM = PyDateTime_TIME_GET_MINUTE(%1); + int pyS = PyDateTime_TIME_GET_SECOND(%1); + if ((pyH == %CPPSELF.hour()) && + (pyM == %CPPSELF.minute()) && + (pyS == %CPPSELF.second())) + %PYARG_0 = Py_True; + else + %PYARG_0 = Py_False; + } + + + + + + + + %0 = new %TYPE(); + + + Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF, const_cast<char*>("setHeight"), const_cast<char*>("i"), 2)); + + + + + + + + + + + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, 2, %3); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + { + Shiboken::AutoDecRef strList(PySequence_Fast(%PYARG_1, "The argument must be a sequence.")); + int lineCount = PySequence_Fast_GET_SIZE(strList.object()); + for (int line = 0; line < lineCount; ++line) { + if (!Shiboken::String::check(PySequence_Fast_GET_ITEM(strList.object(), line))) { + PyErr_SetString(PyExc_TypeError, "The argument must be a sequence of strings."); + break; + } + } + } + const char** %out = 0; + + + + + + + + void* %out = 0; + + + + + + + + + + + + + + + + + + + + + %BEGIN_ALLOW_THREADS + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argOut, %2); + %END_ALLOW_THREADS + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + %PYARG_0 = Shiboken::String::fromCString(%CPPSELF.cstring()); + + + + + return %CPPSELF.size(); + + + + + if (_i < 0 || _i >= %CPPSELF.size()) { + PyErr_BadArgument(); + return 0; + } else { + char res[2]; + res[0] = %CPPSELF.get_char(_i); + res[1] = 0; + return Shiboken::String::fromCString(res); + } + + + + + PyObject* args = Py_BuildValue("(iO)", _i, _value); + PyObject* result = Sbk_StrFunc_set_char(self, args); + Py_DECREF(args); + int ok = result == Py_True; + if (result) { + Py_DECREF(result); + } + return !ok ? -1 : 0; + + + + + + + + + + + + + + + + + + + + + + + %out = %OUTTYPE(); + + + Py_ssize_t len; + const char* str = Shiboken::String::toCString(%in, &len); + %out = %OUTTYPE(str, len); + + + + + + + + + + + + PyObject* data = 0; + if (PyUnicode_CheckExact(%PYARG_1)) { + data = PyUnicode_AsASCIIString(%PYARG_1); + } else { + data = %PYARG_1; + Py_INCREF(data); + } + + %0 = new %TYPE(PyBytes_AsString(data), PyBytes_GET_SIZE(data)); + Py_DECREF(data); + + + + + + + #if PY_VERSION_HEX < 0x03000000 + Shiboken::SbkType<ByteArray>()->tp_as_buffer = &SbkByteArrayBufferProc; + Shiboken::SbkType<ByteArray>()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; + #endif + + + + + %PYARG_0 = PyBytes_FromStringAndSize(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.size()); + + + + + + + + + + + + + + + + + + + Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); + if (!data.isNull()) { + ByteArray ba(*%CPPSELF); + ba.append(PyBytes_AsString(data.object()), PyBytes_GET_SIZE(data.object())); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + } + + + + + Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); + if (!data.isNull()) { + ByteArray ba(PyBytes_AsString(data.object()), PyBytes_GET_SIZE(data.object())); + ba.append(*%CPPSELF); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + } + + + + + ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1)); + ba = ba + *%CPPSELF; + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + + + + + ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1)); + ba.append(*%CPPSELF); + %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); + + + + + ByteArray b(((PyObject*)%PYSELF)->ob_type->tp_name); + PyObject* aux = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); + if (PyUnicode_CheckExact(aux)) { + PyObject* tmp = PyUnicode_AsASCIIString(aux); + Py_DECREF(aux); + aux = tmp; + } + b += "('"; + b += ByteArray(PyBytes_AS_STRING(aux), PyBytes_GET_SIZE(aux)); + b += "')"; + %PYARG_0 = Shiboken::String::fromStringAndSize(b.data(), b.size()); + + + + + + %PYARG_0 = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); + + + + + + return %CPPSELF.size(); + + + + + if (_i < 0 || _i >= %CPPSELF.size()) { + PyErr_SetString(PyExc_IndexError, "index out of bounds"); + return 0; + } else { + char res[2]; + res[0] = %CPPSELF.at(_i); + res[1] = 0; + return PyBytes_FromStringAndSize(res, 1); + } + + + + + + + + + return %CPPSELF.size(); + + + + + if (_i < 0 || _i >= static_cast<Py_ssize_t>(%CPPSELF.size())) { + PyErr_BadArgument(); + return 0; + } else { + %TYPE::const_iterator it = %CPPSELF.begin(); + for (Py_ssize_t i = 1; i <= _i; i++) + ++it; + return %CONVERTTOPYTHON[Str](*it); + } + + + + + + + + + + + + + + + + + + + + %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); + %PYARG_0 = Shiboken::Object::newObject(&SbkObject_Type, %0, false, false); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %PYARG_0 = Shiboken::String::fromCString(%1); + + + + + // This should test if code injections works inside rich comparison operators + Py_INCREF(Py_True); + %PYARG_0 = Py_True; + + + + + + + + + + + + + + + // Does nothing really, just test the code generation + // of constructors whose arguments where + long %out = PyInt_AS_LONG(%PYARG_1) + 1; + + + + + + + + %PYARG_0 = Shiboken::String::fromCString(""); + for (unsigned int i = 0; i < %2; ++i) + Shiboken::String::concat(&%PYARG_0, %PYARG_1); + + + + + + %RETURN_TYPE %0 = PyTuple_GET_SIZE(%PYARG_2); + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + static bool PyDate_ImportAndCheck(PyObject* pyIn) { + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + return PyDate_Check(pyIn); + } + + + + + int day = PyDateTime_GET_DAY(%in); + int month = PyDateTime_GET_MONTH(%in); + int year = PyDateTime_GET_YEAR(%in); + %out = %OUTTYPE(day, month, year); + + + + + + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + %PYARG_0 = PyDate_FromDate(%CPPSELF.day(), %CPPSELF.month(), %CPPSELF.year()); + + + + + + + + + + + %RETURN_TYPE %0 = %CPPSELF.key() != %1; + %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + %RETURN_TYPE %0 = *%CPPSELF & %1; + return %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + %RETURN_TYPE %0 = *%CPPSELF & %1; + return %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sources/shiboken2/tests/samplebinding/unsafe_parent_test.py b/sources/shiboken2/tests/samplebinding/unsafe_parent_test.py new file mode 100644 index 000000000..18da16458 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/unsafe_parent_test.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for ...''' + +import sys +import unittest + +from sample import ObjectType + +class DerivedObjectType(ObjectType): + def isPython(self): + return True + + 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/shiboken2/tests/samplebinding/useraddedctor_test.py b/sources/shiboken2/tests/samplebinding/useraddedctor_test.py new file mode 100644 index 000000000..ea9d1f878 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/useraddedctor_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for user added constructors''' + +import unittest +from sample import * + +class PointTest(unittest.TestCase): + def testUsingSelfOnCtor(self): + # This is a user added ctor and no errors should happen! + s = Size("oi") + self.assertEqual(s.height(), 2) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/virtualdtor_test.py b/sources/shiboken2/tests/samplebinding/virtualdtor_test.py new file mode 100644 index 000000000..46f29179c --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/virtualdtor_test.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for virtual destructor.''' + +import sys +import unittest + +from sample import VirtualDtor + +class ExtendedVirtualDtor(VirtualDtor): + def __init__(self): + VirtualDtor.__init__(self) + +class VirtualDtorTest(unittest.TestCase): + '''Test case for virtual destructor.''' + + def setUp(self): + VirtualDtor.resetDtorCounter() + + def testVirtualDtor(self): + '''Original virtual destructor is being called.''' + dtor_called = VirtualDtor.dtorCalled() + for i in range(1, 10): + vd = VirtualDtor() + del vd + self.assertEqual(VirtualDtor.dtorCalled(), dtor_called + i) + + def testVirtualDtorOnCppCreatedObject(self): + '''Original virtual destructor is being called for a C++ created object.''' + dtor_called = VirtualDtor.dtorCalled() + for i in range(1, 10): + vd = VirtualDtor.create() + del vd + self.assertEqual(VirtualDtor.dtorCalled(), dtor_called + i) + + def testDtorOnDerivedClass(self): + '''Original virtual destructor is being called for a derived class.''' + dtor_called = ExtendedVirtualDtor.dtorCalled() + for i in range(1, 10): + evd = ExtendedVirtualDtor() + del evd + self.assertEqual(ExtendedVirtualDtor.dtorCalled(), dtor_called + i) + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/virtualmethods_test.py b/sources/shiboken2/tests/samplebinding/virtualmethods_test.py new file mode 100644 index 000000000..8a361c9f9 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/virtualmethods_test.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test cases for virtual methods.''' + +import sys +import unittest + +from sample import * + +import warnings + +class ExtendedVirtualMethods(VirtualMethods): + def __init__(self): + VirtualMethods.__init__(self) + self.virtual_method0_called = False + + def virtualMethod0(self, pt, val, cpx, b): + self.virtual_method0_called = True + return VirtualMethods.virtualMethod0(self, pt, val, cpx, b) * -1.0 + + def strListToStdList(self, arg): + warnings.simplefilter('error') + # returning wrong type for test purposes. + return True + + def recursionOnModifiedVirtual(self, arg): + # 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) + self.grand_daughter_name_called = False + + def name(self): + self.grand_daughter_name_called = True + return VirtualDaughter.name(self).prepend('Extended') + +class ExtendedExtendedVirtualDaughter(ExtendedVirtualDaughter): + def __init__(self, name): + ExtendedVirtualDaughter.__init__(self, name) + self.grand_grand_daughter_name_called = False + + def name(self): + self.grand_grand_daughter_name_called = True + return ExtendedVirtualDaughter.name(self).prepend('Extended') + +class VirtualMethodsTest(unittest.TestCase): + '''Test case for virtual methods''' + + def setUp(self): + self.prefix_from_codeinjection = Str('Pimped') + + def tearDown(self): + del self.prefix_from_codeinjection + + def testReimplementedVirtualMethod0(self): + '''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) + val = 4 + cpx = complex(3.3, 4.4) + b = True + result0 = vm.callVirtualMethod0(pt, val, cpx, b) + result1 = evm.callVirtualMethod0(pt, val, cpx, b) + self.assertEqual(result0 * -1.0, result1) + + def testRecursionOnModifiedVirtual(self): + evm = ExtendedVirtualMethods() + self.assertEqual(evm.recursionOnModifiedVirtual(''), 10) + self.assertEqual(evm.callRecursionOnModifiedVirtual(''), 10) + + def testReimplementedVirtualMethodInheritedFromGrandParent(self): + '''Test Python override of a virtual method inherited from a grand parent.''' + original_name = 'Foo' + evd = ExtendedVirtualDaughter(original_name) + + self.assertEqual(VirtualDaughter.name(evd), original_name) + self.assertEqual(VirtualMethods.name(evd), original_name) + self.assertFalse(evd.grand_daughter_name_called) + + name = evd.callName() + self.assertTrue(evd.grand_daughter_name_called) + self.assertEqual(evd.name().prepend(self.prefix_from_codeinjection), name) + + def testReimplementedVirtualMethodInheritedFromGrandGrandParent(self): + '''Test Python override of a virtual method inherited from a grand grand parent.''' + original_name = 'Foo' + eevd = ExtendedExtendedVirtualDaughter(original_name) + + self.assertEqual(VirtualDaughter.name(eevd), original_name) + self.assertEqual(VirtualMethods.name(eevd), original_name) + self.assertFalse(eevd.grand_daughter_name_called) + self.assertFalse(eevd.grand_grand_daughter_name_called) + + name = eevd.callName() + self.assertTrue(eevd.grand_daughter_name_called) + self.assertTrue(eevd.grand_grand_daughter_name_called) + self.assertEqual(eevd.name().prepend(self.prefix_from_codeinjection), name) + +class PrettyErrorMessageTest(unittest.TestCase): + def testIt(self): + obj = ExtendedVirtualMethods() + self.assertRaises(RuntimeWarning, obj.callStrListToStdList, StrList()) + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/visibilitychange_test.py b/sources/shiboken2/tests/samplebinding/visibilitychange_test.py new file mode 100644 index 000000000..b89036a94 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/visibilitychange_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest + +from sample import * + +class VisibilityChangeTest(unittest.TestCase): + + def testVisibilityChange(self): + b1 = Base1() + b1.publicMethod() # ok... + d1 = MDerived1() + self.assertRaises(TypeError, d1.publicMethod); + +if __name__ == '__main__': + unittest.main() + + diff --git a/sources/shiboken2/tests/samplebinding/voidholder_test.py b/sources/shiboken2/tests/samplebinding/voidholder_test.py new file mode 100644 index 000000000..cb5cab6e5 --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/voidholder_test.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test case for a class that holds a void pointer.''' + +import unittest + +from sample import VoidHolder, Point + +class VoidHolderTest(unittest.TestCase): + '''Test case for void pointer manipulation.''' + + def testGetVoidPointerFromCppAndPutsOnVoidHolder(self): + '''Passes a void pointer created in C++ and to kept by VoidHolder.''' + voidptr = VoidHolder.gimmeMeSomeVoidPointer() + voidholder = VoidHolder(voidptr) + self.assertEqual(voidptr, voidholder.voidPointer()) + + def testPutRandomObjectInsideVoidHolder(self): + '''Passes a C++ pointer for an object created in Python to be kept by VoidHolder.''' + obj = Point(1, 2) + voidholder = VoidHolder(obj) + self.assertEqual(obj, voidholder.voidPointer()) + + def testGetNoneObjectFromVoidHolder(self): + '''A VoidHolder created without parameters returns a NULL pointer + that should be converted to a Python None.''' + voidholder = VoidHolder() + self.assertEqual(voidholder.voidPointer(), None) + + def testPutPythonObjectInsideVoidHolder(self): + '''Passes a native Python object to be kept by VoidHolder.''' + obj = 'Foo' + voidholder = VoidHolder(obj) + self.assertEqual(obj, voidholder.voidPointer()) + + + +if __name__ == '__main__': + unittest.main() + diff --git a/sources/shiboken2/tests/samplebinding/weakref_test.py b/sources/shiboken2/tests/samplebinding/weakref_test.py new file mode 100644 index 000000000..77be7ec9f --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/weakref_test.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +'''Test weakref support''' + +import weakref +import unittest + +from sample import ObjectType, PrivateDtor + + +class WeakrefBasicTest(unittest.TestCase): + '''Simple test case of using a weakref''' + + def setUp(self): + self.called = False + + def cb(self, *args): + self.called = True + + def testBasic(self): + '''ObjectType weakref''' + obj = ObjectType() + ref = weakref.ref(obj, self.cb) + del obj + self.assertTrue(self.called) + + def testPrivateDtor(self): + '''PrivateDtor weakref''' + obj = PrivateDtor.instance() + ref = weakref.ref(obj, self.cb) + del obj + self.assertTrue(self.called) + + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/writableclassdict_test.py b/sources/shiboken2/tests/samplebinding/writableclassdict_test.py new file mode 100644 index 000000000..828ac686a --- /dev/null +++ b/sources/shiboken2/tests/samplebinding/writableclassdict_test.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from sample import Point + +class ExtPoint(Point): pass + +class TestWritableClassDict(unittest.TestCase): + def testSetattrOnClass(self): + setattr(Point, 'foo', 123) + self.assertEqual(Point.foo, 123) + pt = Point() + self.assertEqual(pt.foo, 123) + + def testSetattrOnInheritingClass(self): + setattr(Point, 'bar', 321) + self.assertEqual(Point.bar, 321) + self.assertEqual(ExtPoint.bar, 321) + pt = ExtPoint() + self.assertEqual(pt.bar, 321) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/shibokenmodule/module_test.py b/sources/shiboken2/tests/shibokenmodule/module_test.py new file mode 100644 index 000000000..bc2931251 --- /dev/null +++ b/sources/shiboken2/tests/shibokenmodule/module_test.py @@ -0,0 +1,116 @@ +############################################################################# +## +## Copyright (C) 2016 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import shiboken2 as shiboken +import unittest +from sample import * + +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())) + self.assertTrue(shiboken.isValid(None)) + + bb = BlackBox() + item = ObjectType() + ticket = bb.keepObjectType(item) + bb.disposeObjectType(ticket) + self.assertFalse(shiboken.isValid(item)) + + def testWrapInstance(self): + addr = ObjectType.createObjectType() + obj = shiboken.wrapInstance(addr, ObjectType) + self.assertFalse(shiboken.createdByPython(obj)) + obj.setObjectName("obj") + self.assertEqual(obj.objectName(), "obj") + self.assertEqual(addr, obj.identifier()) + self.assertFalse(shiboken.createdByPython(obj)) + + # avoid mem leak =] + bb = BlackBox() + self.assertTrue(shiboken.createdByPython(bb)) + bb.disposeObjectType(bb.keepObjectType(obj)) + + def testIsOwnedByPython(self): + obj = ObjectType() + self.assertTrue(shiboken.ownedByPython(obj)) + p = ObjectType() + obj.setParent(p) + self.assertFalse(shiboken.ownedByPython(obj)) + + def testDump(self): + """Just check if dump doesn't crash on certain use cases""" + p = ObjectType() + obj = ObjectType(p) + obj2 = ObjectType(obj) + obj3 = ObjectType(obj) + self.assertEqual(shiboken.dump(None), "Ordinary Python type.") + shiboken.dump(obj) + + model = ObjectModel(p) + v = ObjectView(model, p) + shiboken.dump(v) + + m = MultipleInherited() + shiboken.dump(m) + self.assertEqual(len(shiboken.getCppPointer(m)), 2) + + # 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 + + def testDelete(self): + obj = ObjectType() + child = ObjectType(obj) + self.assertTrue(shiboken.isValid(obj)) + self.assertTrue(shiboken.isValid(child)) + # Note: this test doesn't assure that the object dtor was really called + shiboken.delete(obj) + self.assertFalse(shiboken.isValid(obj)) + self.assertFalse(shiboken.isValid(child)) + + def testVersionAttr(self): + self.assertEqual(type(shiboken.__version__), str) + self.assertTrue(len(shiboken.__version__) >= 5) + self.assertEqual(type(shiboken.__version_info__), tuple) + self.assertEqual(len(shiboken.__version_info__), 5) + + def testAllWrappers(self): + obj = ObjectType() + self.assertTrue(obj in shiboken.getAllValidWrappers()) + shiboken.delete(obj) + self.assertFalse(obj in shiboken.getAllValidWrappers()) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/smartbinding/CMakeLists.txt b/sources/shiboken2/tests/smartbinding/CMakeLists.txt new file mode 100644 index 000000000..e9c52d447 --- /dev/null +++ b/sources/shiboken2/tests/smartbinding/CMakeLists.txt @@ -0,0 +1,39 @@ +project(smart) + +set(smart_TYPESYSTEM +${CMAKE_CURRENT_SOURCE_DIR}/typesystem_smart.xml +) + +set(smart_SRC +${CMAKE_CURRENT_BINARY_DIR}/smart/smart_module_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/obj_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/integer_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/sharedptr_obj_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/sharedptr_integer_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/smart/registry_wrapper.cpp +) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/smart-binding.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt" @ONLY) + +add_custom_command(OUTPUT ${smart_SRC} +COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt ${GENERATOR_EXTRA_FLAGS} +DEPENDS ${smart_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +COMMENT "Running generator for 'smart' test binding..." +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_SOURCE_DIR} + ${SBK_PYTHON_INCLUDE_DIR} + ${libsmart_SOURCE_DIR} + ${libshiboken_SOURCE_DIR}) +add_library(smart MODULE ${smart_SRC}) +set_property(TARGET smart PROPERTY PREFIX "") +if(WIN32) + set_property(TARGET smart PROPERTY SUFFIX ".pyd") +endif() +target_link_libraries(smart + libsmart + ${SBK_PYTHON_LIBRARIES} + libshiboken) diff --git a/sources/shiboken2/tests/smartbinding/global.h b/sources/shiboken2/tests/smartbinding/global.h new file mode 100644 index 000000000..a72cd21a5 --- /dev/null +++ b/sources/shiboken2/tests/smartbinding/global.h @@ -0,0 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "smart.h" diff --git a/sources/shiboken2/tests/smartbinding/smart-binding.txt.in b/sources/shiboken2/tests/smartbinding/smart-binding.txt.in new file mode 100644 index 000000000..699f0bfe6 --- /dev/null +++ b/sources/shiboken2/tests/smartbinding/smart-binding.txt.in @@ -0,0 +1,15 @@ +[generator-project] + +generator-set = shiboken + +header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h +typesystem-file = @smart_TYPESYSTEM@ + +output-directory = @CMAKE_CURRENT_BINARY_DIR@ + +include-path = @libsmart_SOURCE_DIR@ + +typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ + +enable-parent-ctor-heuristic +use-isnull-as-nb_nonzero diff --git a/sources/shiboken2/tests/smartbinding/smart_pointer_test.py b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py new file mode 100644 index 000000000..c8eb1b2c5 --- /dev/null +++ b/sources/shiboken2/tests/smartbinding/smart_pointer_test.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +############################################################################# +## +## Copyright (C) 2017 The Qt Company Ltd. +## Contact: https://www.qt.io/licensing/ +## +## This file is part of the test suite of PySide2. +## +## $QT_BEGIN_LICENSE:GPL-EXCEPT$ +## Commercial License Usage +## Licensees holding valid commercial Qt licenses may use this file in +## accordance with the commercial license agreement provided with the +## Software or, alternatively, in accordance with the terms contained in +## a written agreement between you and The Qt Company. For licensing terms +## and conditions see https://www.qt.io/terms-conditions. For further +## information use the contact form at https://www.qt.io/contact-us. +## +## GNU General Public License Usage +## Alternatively, this file may be used under the terms of the GNU +## General Public License version 3 as published by the Free Software +## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +## included in the packaging of this file. Please review the following +## information to ensure the GNU General Public License requirements will +## be met: https://www.gnu.org/licenses/gpl-3.0.html. +## +## $QT_END_LICENSE$ +## +############################################################################# + +import unittest +from copy import copy +from smart import Obj, Registry, Integer + +def objCount(): + return Registry.getInstance().countObjects() + +def integerCount(): + return Registry.getInstance().countIntegers() + +class SmartPointerTests(unittest.TestCase): + def testObjSmartPointer(self): + # Uncomment to see more debug info about creation of objects and ref counts. + # Registry.getInstance().setShouldPrint(True) + + # Create Obj. + o = Obj() + self.assertEqual(objCount(), 1) + + # Create a shared pointer to an Obj together with an Obj. + ptrToObj = o.giveSharedPtrToObj() + self.assertEqual(objCount(), 2) + + # Delete the old Obj. + o = None + self.assertEqual(objCount(), 1) + + # Get a wrapper to the Obj inside of the shared pointer, object count should not change. + obj = ptrToObj.data() + self.assertEqual(objCount(), 1) + obj.m_integer = 50 + self.assertEqual(obj.m_integer, 50) + + # Set and get a member value via shared pointer (like operator->). + ptrToObj.m_integer = 100 + self.assertEqual(ptrToObj.m_integer, 100) + + # Get inner PyObject via shared pointer (like operator->) and set value in it. + ptrToObj.m_internalInteger.m_int = 200 + self.assertEqual(ptrToObj.m_internalInteger.m_int, 200) + + # Pass smart pointer as argument to a method, return value is the value of m_integer of + # passed Obj inside the smart pointer. + result = ptrToObj.takeSharedPtrToObj(ptrToObj) + self.assertEqual(result, 100) + + # Pass an Integer as an argument that returns itself. + result = ptrToObj.takeInteger(ptrToObj.m_internalInteger) + self.assertEqual(integerCount(), 2) + result = None + self.assertEqual(integerCount(), 1) + + # Make a copy of the shared pointer, object count should not change. + ptrToObj2 = copy(ptrToObj) + self.assertEqual(objCount(), 1) + + # Delete the first shared pointer, object count should not change because the second + # one still has a reference. + del ptrToObj + self.assertEqual(objCount(), 1) + + # Delete the second smart pointer, object should be deleted. + del ptrToObj2 + self.assertEqual(objCount(), 0) + self.assertEqual(integerCount(), 0) + + def testIntegerSmartPointer(self): + # Uncomment to see more debug info about creation of objects and ref counts. + # Registry.getInstance().setShouldPrint(True) + + # Create Obj. + o = Obj() + self.assertEqual(objCount(), 1) + + # Create a shared pointer to an Integer together with an Integer. + ptrToInteger = o.giveSharedPtrToInteger() + self.assertEqual(objCount(), 1) + self.assertEqual(integerCount(), 2) + + # Get a wrapper to the Integer inside of the shared pointer, integer count should not + # change. + integer = ptrToInteger.data() + self.assertEqual(integerCount(), 2) + integer.m_int = 50 + self.assertEqual(integer.m_int, 50) + + # Set and get a member value via shared pointer (like operator->). + ptrToInteger.m_int = 100 + self.assertEqual(ptrToInteger.m_int, 100) + + # Pass smart pointer as argument to a method, return value is the value of m_int of + # passed Integer inside the smart pointer. + result = o.takeSharedPtrToInteger(ptrToInteger) + self.assertEqual(result, 100) + + # Make a copy of the shared pointer, integer count should not change. + ptrToInteger2 = copy(ptrToInteger) + self.assertEqual(integerCount(), 2) + + # Delete the first shared pointer, integer count should not change because the second + # one still has a reference. + del ptrToInteger + self.assertEqual(integerCount(), 2) + + # Delete the second smart pointer, integer should be deleted. + del ptrToInteger2 + self.assertEqual(objCount(), 1) + self.assertEqual(integerCount(), 1) + + # Delete the original object which was used to create the integer. + del o + self.assertEqual(objCount(), 0) + self.assertEqual(integerCount(), 0) + +if __name__ == '__main__': + unittest.main() diff --git a/sources/shiboken2/tests/smartbinding/typesystem_smart.xml b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml new file mode 100644 index 000000000..a2654730d --- /dev/null +++ b/sources/shiboken2/tests/smartbinding/typesystem_smart.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + diff --git a/sources/shiboken2/tests/sphinxtabletest.cpp b/sources/shiboken2/tests/sphinxtabletest.cpp new file mode 100644 index 000000000..6a8ac7703 --- /dev/null +++ b/sources/shiboken2/tests/sphinxtabletest.cpp @@ -0,0 +1,332 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "sphinxtabletest.h" +#include "qtdocgenerator.h" +#include +#include + +QString SphinxTableTest::transformXml(const char* xml) +{ + return QtXmlToSphinx(m_generator, xml).result(); +} + +void SphinxTableTest::setUp() +{ + m_generator = new QtDocGenerator; +} + +void SphinxTableTest::tearDown() +{ + delete m_generator; +} + +void SphinxTableTest::testEmptyString() +{ + const char* xml = ""; + QCOMPARE(transformXml(xml), QString()); +} + +void SphinxTableTest::testSimpleTable() +{ + const char* xml = "\ +\ +
\ + \ + Header 1\ + \ + \ + Header 2\ + \ +
\ + \ + \ + 1 1\ + \ + \ + 1 2\ + \ + \ + \ + \ + 2 1\ + \ + \ + 2 2\ + \ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +--------+--------+\n\ + |Header 1|Header 2|\n\ + +--------+--------+\n\ + |1 1 |1 2 |\n\ + +--------+--------+\n\ + |2 1 |2 2 |\n\ + +--------+--------+\n\ +\n")); +} + +void SphinxTableTest::testColSpan() +{ + const char* xml = "\ +\ +
\ + \ + Header 1\ + \ + \ + Header 2\ + \ +
\ + \ + \ + I'm a big text!\ + \ + \ + \ + \ + 2 1\ + \ + \ + 2 2\ + \ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +---------------+--------+\n\ + |Header 1 |Header 2|\n\ + +---------------+--------+\n\ + |I'm a big text! |\n\ + +---------------+--------+\n\ + |2 1 |2 2 |\n\ + +---------------+--------+\n\ +\n")); +} + + +void SphinxTableTest::testRowSpan() +{ + const char* xml = "\ +\ +
\ + \ + Header 1\ + \ + \ + Header 2\ + \ +
\ + \ + \ + 1.1\ + \ + \ + 1.2\ + \ + \ + \ + \ + 2 2\ + \ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +--------+--------+\n\ + |Header 1|Header 2|\n\ + +--------+--------+\n\ + |1.1 |1.2 |\n\ + + +--------+\n\ + | |2 2 |\n\ + +--------+--------+\n\ +\n")); +} + + +void SphinxTableTest::testComplexTable() +{ + const char* xml = "\ +\ +
\ + \ + Header 1\ + \ + \ + Header 2\ + \ + \ + Header 3\ + \ +
\ + \ + \ + 1.1\ + \ + \ + 1.2\ + \ + \ + \ + \ + 2 2\ + \ + \ + 2 3\ + \ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +--------+--------+--------+\n\ + |Header 1|Header 2|Header 3|\n\ + +--------+--------+--------+\n\ + |1.1 |1.2 |\n\ + + +--------+--------+\n\ + | |2 2 |2 3 |\n\ + +--------+--------+--------+\n\ +\n")); +} + +void SphinxTableTest::testRowSpan2() +{ + const char* xml = "\ +\ +
\ + h1\ + h2\ + h3\ + h4\ +
\ + \ + A\ + B\ + C\ + D\ + \ + \ + E\ + F\ + \ + \ + E\ + F\ + \ + \ + E\ + F\ + \ + \ + E\ + F\ + \ + \ + E\ + F\ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +--+--+--+--+\n\ + |h1|h2|h3|h4|\n\ + +--+--+--+--+\n\ + |A |B |C |D |\n\ + + + +--+--+\n\ + | | |E |F |\n\ + + + +--+--+\n\ + | | |E |F |\n\ + + + +--+--+\n\ + | | |E |F |\n\ + + + +--+--+\n\ + | | |E |F |\n\ + + + +--+--+\n\ + | | |E |F |\n\ + +--+--+--+--+\n\ +\n")); +} + +void SphinxTableTest::testBrokenTable() +{ + const char* xml = "\ +\ +
\ + \ + Header 1\ + \ + \ + Header 2\ + \ +
\ + \ + \ + 1.1\ + \ + \ + 1.2\ + \ + \ + \ + \ + 2 2\ + \ + \ + 2 3\ + \ + \ + 2 4\ + \ + \ + 2 5\ + \ + \ + \ + \ + 3 1\ + \ + \ + 3 2\ + \ + \ + 3 3\ + \ + \ +
"; + QCOMPARE(transformXml(xml), QString("\ + +--------+------------+\n\ + |Header 1|Header 2 |\n\ + +--------+------------+\n\ + |1.1 |1.2 |\n\ + +--------+------------+\n\ + |2 2 2 3 2 4 2 5|\n\ + +--------+------------+\n\ + |3 1 |3 2 3 3 |\n\ + +--------+------------+\n\ +\n")); +} + + +QTEST_APPLESS_MAIN( SphinxTableTest ) + +#include "sphinxtabletest.moc" diff --git a/sources/shiboken2/tests/sphinxtabletest.h b/sources/shiboken2/tests/sphinxtabletest.h new file mode 100644 index 000000000..4779b75cd --- /dev/null +++ b/sources/shiboken2/tests/sphinxtabletest.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SPHINXTABLETEST_H +#define SPHINXTABLETEST_H + +#include + +class QtDocGenerator; +class SphinxTableTest : public QObject { + Q_OBJECT + +private slots: + void setUp(); + void tearDown(); + void testEmptyString(); + void testSimpleTable(); + void testRowSpan(); + void testColSpan(); + void testComplexTable(); + void testRowSpan2(); + void testBrokenTable(); +private: + QtDocGenerator* m_generator; + + QString transformXml(const char* xml); +}; + +#endif diff --git a/sources/shiboken2/tests/test_generator/CMakeLists.txt b/sources/shiboken2/tests/test_generator/CMakeLists.txt new file mode 100644 index 000000000..5f5099897 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/CMakeLists.txt @@ -0,0 +1,68 @@ +project(test_generator) + +set(dummy_generator_SRC dummygenerator.cpp) +add_library(dummy_generator SHARED ${dummy_generator_SRC}) +target_link_libraries(dummy_generator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} genrunner) +set_property(TARGET dummy_generator PROPERTY PREFIX "") + +add_executable(dummygenerator main.cpp) +set(DUMMYGENERATOR_EXECUTABLE dummygenerator${generator_SUFFIX}) +set_target_properties(dummygenerator PROPERTIES OUTPUT_NAME ${DUMMYGENERATOR_EXECUTABLE}) +target_link_libraries(dummygenerator ${Qt5Core_LIBRARIES}) + +configure_file(dummygentestconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/dummygentestconfig.h" @ONLY) + +get_filename_component(APIEXTRACTOR_LIBRARY_DIRS ${APIEXTRACTOR_LIBRARY} PATH) +if(WIN32) + set(PATH_SEP ";") + find_program(APIEXTRACTOR_BINARY apiextractor.dll HINTS ${APIEXTRACTOR_LIBRARY_DIRS}) + get_filename_component(APIEXTRACTOR_BINARY_DIR ${APIEXTRACTOR_BINARY} PATH) + set(APIEXTRACTOR_LIBRARY_DIRS "${APIEXTRACTOR_LIBRARY_DIRS}${PATH_SEP}${APIEXTRACTOR_BINARY_DIR}") +else() + set(PATH_SEP ":") +endif() + +set(ENV_PATH "${generatorrunner_BINARY_DIR}${PATH_SEP}${CMAKE_CURRENT_BINARY_DIR}${PATH_SEP}$ENV{PATH}${PATH_SEP}${APIEXTRACTOR_LIBRARY_DIRS}") +set(ENV_QT_PLUGIN_PATH "${CMAKE_CURRENT_BINARY_DIR}${PATH_SEP}$ENV{QT_PLUGIN_PATH}") +if(WIN32) + string(REPLACE "\\;" ";" ENV_PATH "${ENV_PATH}") + string(REPLACE ";" "\\;" ENV_PATH "${ENV_PATH}") + string(REPLACE "\\;" ";" ENV_QT_PLUGIN_PATH "${ENV_QT_PLUGIN_PATH}") + string(REPLACE ";" "\\;" ENV_QT_PLUGIN_PATH "${ENV_QT_PLUGIN_PATH}") +endif() + +macro(m_add_test testname) + if(CMAKE_VERSION VERSION_LESS 2.8) + add_test(${testname} ${CMAKE_COMMAND} -DTEST=${testname} + -DWORKDIR=${CMAKE_CURRENT_BINARY_DIR} + -DENV_PATH=${ENV_PATH} -DENV_QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH} + -P ${CMAKE_CURRENT_SOURCE_DIR}/run_test.cmake) + else() + add_test(${testname} ${testname}) + set_property(TEST ${testname} PROPERTY ENVIRONMENT "PATH=${ENV_PATH}" "QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH}") + endif() +endmacro() + +macro(declare_test testname) + qt4_automoc("${testname}.cpp") + add_executable(${testname} "${testname}.cpp") + include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + target_link_libraries(${testname} + ${QT_QTTEST_LIBRARY} + ${QT_QTCORE_LIBRARY} + ${Qt5Test_LIBRARIES} + ${Qt5Core_LIBRARIES} + ) + m_add_test(${testname}) +endmacro(declare_test testname) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/test_global.h" + "${CMAKE_CURRENT_BINARY_DIR}/test_global.h" COPYONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/test_typesystem.xml" + "${CMAKE_CURRENT_BINARY_DIR}/test_typesystem.xml" COPYONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/dummygentest-project.txt.in" + "${CMAKE_CURRENT_BINARY_DIR}/dummygentest-project.txt" @ONLY) +declare_test(dummygentest) + +add_dependencies(dummygenerator generatorrunner) + diff --git a/sources/shiboken2/tests/test_generator/dummygenerator.cpp b/sources/shiboken2/tests/test_generator/dummygenerator.cpp new file mode 100644 index 000000000..40d9fb771 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygenerator.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include "dummygenerator.h" + +EXPORT_GENERATOR_PLUGIN(new DummyGenerator) + +using namespace std; + +QString +DummyGenerator::fileNameForClass(const AbstractMetaClass* metaClass) const +{ + return QString("%1_generated.txt").arg(metaClass->name().toLower()); +} + +void +DummyGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass) +{ + s << "// Generated code for class: " << qPrintable(metaClass->name()) << endl; +} + +bool +DummyGenerator::doSetup(const QMap& args) +{ + if (args.contains("dump-arguments") && !args["dump-arguments"].isEmpty()) { + QFile logFile(args["dump-arguments"]); + logFile.open(QIODevice::WriteOnly | QIODevice::Text); + QTextStream out(&logFile); + for (QMap::const_iterator it = args.cbegin(), end = args.cend(); it != end; ++it) { + const QString& key = it.key(); + if (key == "arg-1") + out << "header-file"; + else if (key == "arg-2") + out << "typesystem-file"; + else + out << key; + if (!args[key].isEmpty()) + out << " = " << args[key]; + out << endl; + } + } + return true; +} + diff --git a/sources/shiboken2/tests/test_generator/dummygenerator.h b/sources/shiboken2/tests/test_generator/dummygenerator.h new file mode 100644 index 000000000..5ab95a925 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygenerator.h @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef DUMMYGENERATOR_H +#define DUMMYGENERATOR_H + +#include "generator.h" + +class GENRUNNER_API DummyGenerator : public Generator +{ +public: + DummyGenerator() {} + ~DummyGenerator() {} + bool doSetup(const QMap& args); + const char* name() const { return "DummyGenerator"; } + +protected: + void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {} + void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {} + QString fileNameForClass(const AbstractMetaClass* metaClass) const; + void generateClass(QTextStream& s, const AbstractMetaClass* metaClass); + void finishGeneration() {} +}; + +#endif // DUMMYGENERATOR_H diff --git a/sources/shiboken2/tests/test_generator/dummygentest-project.txt.in b/sources/shiboken2/tests/test_generator/dummygentest-project.txt.in new file mode 100644 index 000000000..0a076d8bd --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygentest-project.txt.in @@ -0,0 +1,20 @@ +[generator-project] + +generator-set = dummy +header-file = @CMAKE_CURRENT_BINARY_DIR@/test_global.h +typesystem-file = @CMAKE_CURRENT_BINARY_DIR@/test_typesystem.xml +output-directory = /tmp/output + +dump-arguments = @CMAKE_CURRENT_BINARY_DIR@/dummygen-args.log + +include-path = /include/path/location1 +include-path = /include/path/location2 + +typesystem-path = /typesystem/path/location1 +typesystem-path = /typesystem/path/location2 + +api-version = 1.2.3 +debug = sparse + +no-suppress-warnings + diff --git a/sources/shiboken2/tests/test_generator/dummygentest.cpp b/sources/shiboken2/tests/test_generator/dummygentest.cpp new file mode 100644 index 000000000..ae028e2c8 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygentest.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "dummygentest.h" +#include "dummygenerator.h" +#include "dummygentestconfig.h" +#include +#include +#include + +#define GENERATED_CONTENTS "// Generated code for class: Dummy" + +void DummyGenTest::initTestCase() +{ + int argc = 0; + char* argv[] = {NULL}; + QCoreApplication app(argc, argv); + workDir = QDir::currentPath(); + + headerFilePath = workDir + "/test_global.h"; + typesystemFilePath = workDir + "/test_typesystem.xml"; + projectFilePath = workDir + "/dummygentest-project.txt"; + generatedFilePath = QString("%1/dummy/dummy_generated.txt").arg(QDir::tempPath()); +} + +void DummyGenTest::testCallGenRunnerWithFullPathToDummyGenModule() +{ + QStringList args; + args.append("--generator-set=" DUMMYGENERATOR_BINARY_DIR "/dummy_generator" MODULE_EXTENSION); + args.append(QString("--output-directory=%1").arg(QDir::tempPath())); + args.append(headerFilePath); + args.append(typesystemFilePath); + int result = QProcess::execute("generatorrunner", args); + QCOMPARE(result, 0); + + QFile generatedFile(generatedFilePath); + generatedFile.open(QIODevice::ReadOnly); + QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); + generatedFile.close(); + + QVERIFY(generatedFile.remove()); +} + +void DummyGenTest::testCallGenRunnerWithNameOfDummyGenModule() +{ + QStringList args; + args.append("--generator-set=dummy"); + args.append(QString("--output-directory=%1").arg(QDir::tempPath())); + args.append(headerFilePath); + args.append(typesystemFilePath); + int result = QProcess::execute("generatorrunner", args); + QCOMPARE(result, 0); + + QFile generatedFile(generatedFilePath); + generatedFile.open(QIODevice::ReadOnly); + QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); + generatedFile.close(); + + QVERIFY(generatedFile.remove()); +} + +void DummyGenTest::testCallDummyGeneratorExecutable() +{ + QStringList args; + args.append(QString("--output-directory=%1").arg(QDir::tempPath())); + args.append(headerFilePath); + args.append(typesystemFilePath); + int result = QProcess::execute(DUMMYGENERATOR_BINARY, args); + QCOMPARE(result, 0); + + QFile generatedFile(generatedFilePath); + generatedFile.open(QIODevice::ReadOnly); + QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); + generatedFile.close(); + + QVERIFY(generatedFile.remove()); +} + +void DummyGenTest::testProjectFileArgumentsReading() +{ + QStringList args(QString("--project-file=%1/dummygentest-project.txt").arg(workDir)); + int result = QProcess::execute("generatorrunner", args); + QCOMPARE(result, 0); + + QFile logFile(workDir + "/dummygen-args.log"); + logFile.open(QIODevice::ReadOnly); + QStringList logContents; + while (!logFile.atEnd()) + logContents << logFile.readLine().trimmed(); + logContents.sort(); + QCOMPARE(logContents[0], QString("api-version = 1.2.3")); + QCOMPARE(logContents[1], QString("debug = sparse")); + QVERIFY(logContents[2].startsWith("dump-arguments = ")); + QVERIFY(logContents[2].endsWith("dummygen-args.log")); + QCOMPARE(logContents[3], QString("generator-set = dummy")); + QVERIFY(logContents[4].startsWith("header-file = ")); + QVERIFY(logContents[4].endsWith("test_global.h")); + QCOMPARE(logContents[5], + QDir::toNativeSeparators(QString("include-paths = /include/path/location1%1/include/path/location2").arg(PATH_SPLITTER))); + QCOMPARE(logContents[6], QString("no-suppress-warnings")); + QCOMPARE(logContents[7], QString("output-directory = /tmp/output")); + QVERIFY(logContents[8].startsWith("project-file = ")); + QVERIFY(logContents[8].endsWith("dummygentest-project.txt")); + QVERIFY(logContents[9].startsWith("typesystem-file = ")); + QVERIFY(logContents[9].endsWith("test_typesystem.xml")); + QCOMPARE(logContents[10], + QDir::toNativeSeparators(QString("typesystem-paths = /typesystem/path/location1%1/typesystem/path/location2").arg(PATH_SPLITTER))); +} + +QTEST_APPLESS_MAIN(DummyGenTest) + +#include "dummygentest.moc" + diff --git a/sources/shiboken2/tests/test_generator/dummygentest.h b/sources/shiboken2/tests/test_generator/dummygentest.h new file mode 100644 index 000000000..be8ca42af --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygentest.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DUMMYGENTABLETEST_H +#define DUMMYGENTABLETEST_H + +#include + +class DummyGenerator; + +class DummyGenTest : public QObject +{ + Q_OBJECT + +private: + QString workDir; + QString headerFilePath; + QString typesystemFilePath; + QString generatedFilePath; + QString projectFilePath; + +private slots: + void initTestCase(); + void testCallGenRunnerWithFullPathToDummyGenModule(); + void testCallGenRunnerWithNameOfDummyGenModule(); + void testCallDummyGeneratorExecutable(); + void testProjectFileArgumentsReading(); +}; + +#endif + diff --git a/sources/shiboken2/tests/test_generator/dummygentestconfig.h.in b/sources/shiboken2/tests/test_generator/dummygentestconfig.h.in new file mode 100644 index 000000000..9da17dcd3 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/dummygentestconfig.h.in @@ -0,0 +1,15 @@ +#ifndef DUMMYGENTESTCONFIG_H +#define DUMMYGENTESTCONFIG_H + +#define MODULE_EXTENSION "@CMAKE_SHARED_LIBRARY_SUFFIX@" +#define DUMMYGENERATOR_BINARY "@DUMMYGENERATOR_EXECUTABLE@" +#define DUMMYGENERATOR_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@" + +#ifdef _WINDOWS + #define PATH_SPLITTER ";" +#else + #define PATH_SPLITTER ":" +#endif + +#endif // DUMMYGENTESTCONFIG_H + diff --git a/sources/shiboken2/tests/test_generator/main.cpp b/sources/shiboken2/tests/test_generator/main.cpp new file mode 100644 index 000000000..5c46ea006 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/main.cpp @@ -0,0 +1,39 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +int main(int argc, char *argv[]) +{ + QStringList args; + args.append("--generator-set=dummy"); + for (int i = 1; i < argc; i++) + args.append(argv[i]); + return QProcess::execute("generatorrunner", args); +} + diff --git a/sources/shiboken2/tests/test_generator/run_test.cmake b/sources/shiboken2/tests/test_generator/run_test.cmake new file mode 100644 index 000000000..34a821d80 --- /dev/null +++ b/sources/shiboken2/tests/test_generator/run_test.cmake @@ -0,0 +1,11 @@ +# 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. + +set(ENV{PATH} "${ENV_PATH}") +set(ENV{QT_PLUGIN_PATH} "${ENV_QT_PLUGIN_PATH}") +execute_process(COMMAND ${TEST} WORKING_DIRECTORY "${WORKDIR}" RESULT_VARIABLE OK) + +if(NOT OK EQUAL 0) + message(SEND_ERROR "${TEST} failed!") +endif() diff --git a/sources/shiboken2/tests/test_generator/test_global.h b/sources/shiboken2/tests/test_generator/test_global.h new file mode 100644 index 000000000..6a95200cf --- /dev/null +++ b/sources/shiboken2/tests/test_generator/test_global.h @@ -0,0 +1 @@ +struct Dummy {}; diff --git a/sources/shiboken2/tests/test_generator/test_typesystem.xml b/sources/shiboken2/tests/test_generator/test_typesystem.xml new file mode 100644 index 000000000..c19a4e95e --- /dev/null +++ b/sources/shiboken2/tests/test_generator/test_typesystem.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index c06c56f6d..000000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,102 +0,0 @@ -find_package(Qt5 REQUIRED COMPONENTS Core) -include_directories(${Qt5Core_INCLUDE_DIRS}) - -add_subdirectory(libminimal) -if(NOT DEFINED MINIMAL_TESTS) - add_subdirectory(libsample) - add_subdirectory(libsmart) - add_subdirectory(libother) -endif() - -if(WIN32 OR DEFINED AVOID_PROTECTED_HACK) - message(STATUS "Tests will be generated avoiding the protected hack!") - set(GENERATOR_EXTRA_FLAGS --avoid-protected-hack) -else() - message(STATUS "Tests will be generated using the protected hack!") - set(GENERATOR_EXTRA_FLAGS ) -endif() - -add_subdirectory(minimalbinding) -if(NOT DEFINED MINIMAL_TESTS) - add_subdirectory(samplebinding) - add_subdirectory(smartbinding) - add_subdirectory(otherbinding) -endif() - -if(DEFINED MINIMAL_TESTS) - file(GLOB TEST_FILES minimalbinding/*_test.py) -else() - file(GLOB TEST_FILES minimalbinding/*_test.py - samplebinding/*_test.py - otherbinding/*_test.py - smartbinding/*_test.py - shibokenmodule/*_test.py) -endif() -list(SORT TEST_FILES) - -set(test_blacklist "") - -find_package(PythonInterp REQUIRED) -if(NOT CTEST_TESTING_TIMEOUT) - set(CTEST_TESTING_TIMEOUT 60) -endif() - -if(CMAKE_VERSION VERSION_LESS 2.8) - message("CMake version greater than 2.8 necessary to run tests") -else() - if(WIN32) - set(TEST_PYTHONPATH "${smart_BINARY_DIR};${minimal_BINARY_DIR};${sample_BINARY_DIR};${other_BINARY_DIR};${shibokenmodule_BINARY_DIR};${CMAKE_CURRENT_SOURCE_DIR}") - set(TEST_LIBRARY_PATH "$ENV{PATH};${libminimal_BINARY_DIR};${libsample_BINARY_DIR};${libother_BINARY_DIR};${libsmart_BINARY_DIR};${libshiboken_BINARY_DIR}") - set(LIBRARY_PATH_VAR "PATH") - string(REPLACE "\\" "/" TEST_PYTHONPATH "${TEST_PYTHONPATH}") - string(REPLACE "\\" "/" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") - string(REPLACE ";" "\\;" TEST_PYTHONPATH "${TEST_PYTHONPATH}") - string(REPLACE ";" "\\;" TEST_LIBRARY_PATH "${TEST_LIBRARY_PATH}") - else() - set(TEST_PYTHONPATH "${smart_BINARY_DIR}:${minimal_BINARY_DIR}:${sample_BINARY_DIR}:${other_BINARY_DIR}:${shibokenmodule_BINARY_DIR}:${CMAKE_CURRENT_SOURCE_DIR}") - set(TEST_LIBRARY_PATH "$ENV{LD_LIBRARY_PATH}:${libminimal_BINARY_DIR}:${libsample_BINARY_DIR}:${libother_BINARY_DIR}:${libsmart_BINARY_DIR}:${libshiboken_BINARY_DIR}") - set(LIBRARY_PATH_VAR "LD_LIBRARY_PATH") - endif() - 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}) - set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "PYTHONPATH=${TEST_PYTHONPATH};${LIBRARY_PATH_VAR}=${TEST_LIBRARY_PATH}") - set_tests_properties(${test_name} PROPERTIES TIMEOUT ${CTEST_TESTING_TIMEOUT}) - if (${expect_fail} GREATER -1) - set_tests_properties(${test_name} PROPERTIES WILL_FAIL TRUE) - endif() - endforeach() -endif() - -add_subdirectory(dumpcodemodel) - -# FIXME Skipped until add an option to choose the generator -# add_subdirectory(test_generator) - -if (NOT APIEXTRACTOR_DOCSTRINGS_DISABLED) -# project(sphinxtabletest) -# -# # TODO -# set(sphinxtabletest_SRC sphinxtabletest.cpp) -# qt4_automoc(${sphinxtabletest_SRC}) -# -# include_directories(${QT_INCLUDE_DIR} -# ${QT_QTCORE_INCLUDE_DIR} -# ${CMAKE_CURRENT_BINARY_DIR} -# ${qtdoc_generator_SOURCE_DIR}) -# -# add_executable(sphinxtabletest ${sphinxtabletest_SRC}) -# -# target_link_libraries(sphinxtabletest -# ${QT_QTTEST_LIBRARY} -# ${APIEXTRACTOR_LIBRARY} -# qtdoc_generator -# genrunner) -# -# add_test("sphinxtable" sphinxtabletest) -# if (INSTALL_TESTS) -# install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/sphinxtabletest DESTINATION ${TEST_INSTALL_DIR}) -# endif() -endif() diff --git a/tests/dumpcodemodel/CMakeLists.txt b/tests/dumpcodemodel/CMakeLists.txt deleted file mode 100644 index af18cb3c8..000000000 --- a/tests/dumpcodemodel/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -add_executable(dumpcodemodel main.cpp) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${apiextractor_SOURCE_DIR} ${Qt5Core_INCLUDE_DIRS}) - -target_link_libraries(dumpcodemodel apiextractor ${Qt5Core_LIBRARIES}) diff --git a/tests/dumpcodemodel/main.cpp b/tests/dumpcodemodel/main.cpp deleted file mode 100644 index 13dab6e8a..000000000 --- a/tests/dumpcodemodel/main.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - - QCommandLineParser parser; - parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); - parser.setApplicationDescription(QStringLiteral("Code model tester")); - parser.addHelpOption(); - parser.addVersionOption(); - QCommandLineOption verboseOption(QStringLiteral("d"), - QStringLiteral("Display verbose output about types")); - parser.addOption(verboseOption); - parser.addPositionalArgument(QStringLiteral("file"), QStringLiteral("C++ source file")); - - parser.process(app); - const QStringList &positionalArguments = parser.positionalArguments(); - if (positionalArguments.isEmpty()) - parser.showHelp(1); - - QByteArrayList arguments; - std::transform(positionalArguments.cbegin(), positionalArguments.cend(), - std::back_inserter(arguments), QFile::encodeName); - const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(arguments, 0); - if (dom.isNull()) { - QString message = QLatin1String("Unable to parse ") + positionalArguments.join(QLatin1Char(' ')); - std::cerr << qPrintable(message) << '\n'; - return -2; - } - - QString output; - { - QDebug debug(&output); - if (parser.isSet(verboseOption)) - debug.setVerbosity(3); - debug << dom.data(); - } - std::cout << qPrintable(output) << '\n'; - - return 0; -} diff --git a/tests/libminimal/CMakeLists.txt b/tests/libminimal/CMakeLists.txt deleted file mode 100644 index a25892571..000000000 --- a/tests/libminimal/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -project(libminimal) - -set(libminimal_SRC -obj.cpp -listuser.cpp -typedef.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBMINIMAL_BUILD") -add_library(libminimal SHARED ${libminimal_SRC}) -set_property(TARGET libminimal PROPERTY PREFIX "") - diff --git a/tests/libminimal/libminimalmacros.h b/tests/libminimal/libminimalmacros.h deleted file mode 100644 index 5c9e62e8a..000000000 --- a/tests/libminimal/libminimalmacros.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIBMINIMALMACROS_H -#define LIBMINIMALMACROS_H - -#if defined _WIN32 || defined __CYGWIN__ - #if LIBMINIMAL_BUILD - #define LIBMINIMAL_API __declspec(dllexport) - #else - #define LIBMINIMAL_API __declspec(dllimport) - #endif -#else -#if __GNUC__ >= 4 - #define LIBMINIMAL_API __attribute__ ((visibility("default"))) -#else - #define LIBMINIMAL_API -#endif -#endif - -#endif diff --git a/tests/libminimal/listuser.cpp b/tests/libminimal/listuser.cpp deleted file mode 100644 index ec2eb3923..000000000 --- a/tests/libminimal/listuser.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include "listuser.h" - -std::list -ListUser::createIntList(int num) -{ - std::list retval; - for (int i = 0; i < num; ++i) - retval.push_back(i); - return retval; -} - -int -ListUser::sumIntList(std::list intList) -{ - int total = 0; - for (std::list::iterator iter = intList.begin(); iter != intList.end(); iter++) - total += *iter; - return total; -} - -std::list -ListUser::createMinBoolList(MinBool mb1, MinBool mb2) -{ - std::list retval; - retval.push_back(mb1); - retval.push_back(mb2); - return retval; -} - -MinBool -ListUser::oredMinBoolList(std::list minBoolList) -{ - MinBool result(false); - for (std::list::iterator iter = minBoolList.begin(); iter != minBoolList.end(); iter++) - result |= *iter; - return result; -} - -std::list -ListUser::createValList(int num) -{ - std::list retval; - for (int i = 0; i < num; ++i) - retval.push_back(Val(i)); - return retval; -} - -int -ListUser::sumValList(std::list valList) -{ - int total = 0; - for (std::list::iterator iter = valList.begin(); iter != valList.end(); iter++) - total += iter->valId(); - return total; -} - -std::list -ListUser::createObjList(Obj* o1, Obj* o2) -{ - std::list retval; - retval.push_back(o1); - retval.push_back(o2); - return retval; -} - -int -ListUser::sumObjList(std::list objList) -{ - int total = 0; - for (std::list::iterator iter = objList.begin(); iter != objList.end(); iter++) - total += (*iter)->objId(); - return total; -} - -std::list > -ListUser::createListOfIntLists(int num) -{ - std::list > retval; - for (int i = 0; i < num; ++i) - retval.push_back(createIntList(num)); - return retval; -} - -int -ListUser::sumListOfIntLists(std::list > intListList) -{ - int total = 0; - for (std::list >::iterator it0 = intListList.begin(); it0 != intListList.end(); it0++) { - for (std::list::iterator it1 = (*it0).begin(); it1 != (*it0).end(); it1++) - total += *it1; - } - return total; -} - diff --git a/tests/libminimal/listuser.h b/tests/libminimal/listuser.h deleted file mode 100644 index 4138b9f3c..000000000 --- a/tests/libminimal/listuser.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LISTUSER_H -#define LISTUSER_H - -#include -#include "obj.h" -#include "val.h" -#include "minbool.h" - -#include "libminimalmacros.h" - -struct LIBMINIMAL_API ListUser -{ - virtual ~ListUser() {} - - // List of C++ primitive type items - virtual std::list createIntList(int num); - std::list callCreateIntList(int num) { return createIntList(num); } - virtual int sumIntList(std::list intList); - int callSumIntList(std::list intList) { return sumIntList(intList); } - - // List of C++ MinBool objects used as primitives in Python - virtual std::list createMinBoolList(MinBool mb1, MinBool mb2); - std::list callCreateMinBoolList(MinBool mb1, MinBool mb2) { return createMinBoolList(mb1, mb2); } - virtual MinBool oredMinBoolList(std::list minBoolList); - MinBool callOredMinBoolList(std::list minBoolList) { return oredMinBoolList(minBoolList); } - - // List of C++ value types - virtual std::list createValList(int num); - std::list callCreateValList(int num) { return createValList(num); } - virtual int sumValList(std::list valList); - int callSumValList(std::list valList) { return sumValList(valList); } - - // List of C++ object types - virtual std::list createObjList(Obj* o1, Obj* o2); - std::list callCreateObjList(Obj* o1, Obj* o2) { return createObjList(o1, o2); } - virtual int sumObjList(std::list objList); - int callSumObjList(std::list objList) { return sumObjList(objList); } - - // List of lists of C++ primitive type items - virtual std::list > createListOfIntLists(int num); - std::list > callCreateListOfIntLists(int num) { return createListOfIntLists(num); } - virtual int sumListOfIntLists(std::list > intListList); - int callSumListOfIntLists(std::list > intListList) { return sumListOfIntLists(intListList); } -}; - -#endif // LISTUSER_H - diff --git a/tests/libminimal/minbool.h b/tests/libminimal/minbool.h deleted file mode 100644 index ebd2f71e2..000000000 --- a/tests/libminimal/minbool.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MINBOOL_H -#define MINBOOL_H - -#include "libminimalmacros.h" - -class LIBMINIMAL_API MinBool -{ -public: - inline explicit MinBool(bool b) : m_value(b) {} - 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; - return *this; - } -private: - bool m_value; -}; - -inline bool operator==(MinBool b1, bool b2) { return (!b1).value() == !b2; } -inline bool operator==(bool b1, MinBool b2) { return (!b1) == (!b2).value(); } -inline bool operator==(MinBool b1, MinBool b2) { return (!b1).value() == (!b2).value(); } -inline bool operator!=(MinBool b1, bool b2) { return (!b1).value() != !b2; } -inline bool operator!=(bool b1, MinBool b2) { return (!b1) != (!b2).value(); } -inline bool operator!=(MinBool b1, MinBool b2) { return (!b1).value() != (!b2).value(); } - -class LIBMINIMAL_API MinBoolUser -{ -public: - MinBoolUser() : m_minbool(MinBool(false)) {} - virtual ~MinBoolUser() {} - 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; -}; - -#endif diff --git a/tests/libminimal/obj.cpp b/tests/libminimal/obj.cpp deleted file mode 100644 index a1d18d0e3..000000000 --- a/tests/libminimal/obj.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "obj.h" - -Obj::Obj(int objId) : m_objId(objId) -{ -} - -Obj::~Obj() -{ -} - -bool -Obj::virtualMethod(int val) -{ - return !bool(val%2); -} - diff --git a/tests/libminimal/obj.h b/tests/libminimal/obj.h deleted file mode 100644 index 16f838e19..000000000 --- a/tests/libminimal/obj.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJ_H -#define OBJ_H - -#include "libminimalmacros.h" - -class LIBMINIMAL_API Obj -{ -public: - explicit Obj(int objId); - virtual ~Obj(); - - int objId() { return m_objId; } - void setObjId(int objId) { m_objId = objId; } - - virtual bool virtualMethod(int val); - bool callVirtualMethod(int val) { return virtualMethod(val); } - - virtual Obj* passObjectType(Obj* obj) { return obj; } - Obj* callPassObjectType(Obj* obj) { return passObjectType(obj); } - - virtual Obj* passObjectTypeReference(Obj& obj) { return &obj; } - Obj* callPassObjectTypeReference(Obj& obj) { return passObjectTypeReference(obj); } - -private: - Obj(const Obj&); - Obj& operator=(const Obj&); - int m_objId; -}; - -#endif // OBJ_H - diff --git a/tests/libminimal/typedef.cpp b/tests/libminimal/typedef.cpp deleted file mode 100644 index 4948d9944..000000000 --- a/tests/libminimal/typedef.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "typedef.h" - -// -// Test wrapping of a typedef -// -bool arrayFuncInt(std::vector a) -{ - return a.empty(); -} - -bool arrayFuncIntTypedef(MyArray a) -{ - return arrayFuncInt(a); -} - -std::vector arrayFuncIntReturn(int size) -{ - return std::vector(size); -} - -MyArray arrayFuncIntReturnTypedef(int size) -{ - return arrayFuncIntReturn(size); -} - -// -// Test wrapping of a typedef of a typedef -// -bool arrayFunc(std::vector a) -{ - return a.empty(); -} - -bool arrayFuncTypedef(MyArray a) -{ - return arrayFunc(a); -} - -std::vector arrayFuncReturn(int size) -{ - return std::vector(size); -} - -MyArray arrayFuncReturnTypedef(int size) -{ - return arrayFuncReturn(size); -} diff --git a/tests/libminimal/typedef.h b/tests/libminimal/typedef.h deleted file mode 100644 index f54a6ed18..000000000 --- a/tests/libminimal/typedef.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TYPEDEF_H -#define TYPEDEF_H - -#include "libminimalmacros.h" - -#include - -// Test wrapping of a typedef -typedef std::vector MyArrayInt; - -LIBMINIMAL_API bool arrayFuncInt(std::vector a); -LIBMINIMAL_API bool arrayFuncIntTypedef(MyArrayInt a); - -LIBMINIMAL_API std::vector arrayFuncIntReturn(int size); -LIBMINIMAL_API MyArrayInt arrayFuncIntReturnTypedef(int size); - -// Test wrapping of a typedef of a typedef -typedef MyArrayInt MyArray; - -LIBMINIMAL_API bool arrayFunc(std::vector a); -LIBMINIMAL_API bool arrayFuncTypedef(MyArray a); - -LIBMINIMAL_API std::vector arrayFuncReturn(int size); -LIBMINIMAL_API MyArray arrayFuncReturnTypedef(int size); - -#endif diff --git a/tests/libminimal/val.h b/tests/libminimal/val.h deleted file mode 100644 index 5ba4b3aff..000000000 --- a/tests/libminimal/val.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VAL_H -#define VAL_H - -#include "libminimalmacros.h" - -class LIBMINIMAL_API Val -{ -public: - explicit Val(int valId) : m_valId(valId) {} - virtual ~Val() {} - - int valId() { return m_valId; } - void setValId(int valId) { m_valId = valId; } - - virtual Val passValueType(Val val) { return val; } - Val callPassValueType(Val val) { return passValueType(val); } - - virtual Val* passValueTypePointer(Val* val) { return val; } - Val* callPassValueTypePointer(Val* val) { return passValueTypePointer(val); } - - virtual Val* passValueTypeReference(Val& val) { return &val; } - Val* callPassValueTypeReference(Val& val) { return passValueTypeReference(val); } - - enum ValEnum { One, Other }; - ValEnum oneOrTheOtherEnumValue(ValEnum enumValue) { return enumValue == One ? Other : One; } -private: - int m_valId; -}; - -#endif // VAL_H - diff --git a/tests/libother/CMakeLists.txt b/tests/libother/CMakeLists.txt deleted file mode 100644 index 9b3cf5552..000000000 --- a/tests/libother/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -project(libother) - -set(libother_SRC -number.cpp -otherderived.cpp -otherobjecttype.cpp -othermultiplederived.cpp -) - -add_definitions("-DLIBOTHER_BUILD") -add_library(libother SHARED ${libother_SRC}) -set_property(TARGET libother PROPERTY PREFIX "") - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${libsample_SOURCE_DIR} - ${libsample_SOURCE_DIR}/..) -target_link_libraries(libother libsample) - diff --git a/tests/libother/extendsnoimplicitconversion.h b/tests/libother/extendsnoimplicitconversion.h deleted file mode 100644 index 744bfdc0d..000000000 --- a/tests/libother/extendsnoimplicitconversion.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef EXTENDSNOIMPLICITCONVERSION_H -#define EXTENDSNOIMPLICITCONVERSION_H - -#include "libothermacros.h" -#include "noimplicitconversion.h" - -class ExtendsNoImplicitConversion -{ -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 - diff --git a/tests/libother/libothermacros.h b/tests/libother/libothermacros.h deleted file mode 100644 index 41a4fb13e..000000000 --- a/tests/libother/libothermacros.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIBOTHERMACROS_H -#define LIBOTHERMACROS_H - -#if defined _WIN32 || defined __CYGWIN__ - #if LIBOTHER_BUILD - #define LIBOTHER_API __declspec(dllexport) - #else - #define LIBOTHER_API __declspec(dllimport) - #endif -#else -#if __GNUC__ >= 4 - #define LIBOTHER_API __attribute__ ((visibility("default"))) -#else - #define LIBOTHER_API -#endif -#endif - -#endif diff --git a/tests/libother/number.cpp b/tests/libother/number.cpp deleted file mode 100644 index 4da254286..000000000 --- a/tests/libother/number.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "number.h" -#include -#include - -using namespace std; - -Str -Number::toStr() const -{ - ostringstream in; - in << m_value; - return in.str().c_str(); -} - -Point -operator*(const Point& p, const Number& n) -{ - return Point(p.x() * n.value(), p.y() * n.value()); -} - -Complex -Number::toComplex() const -{ - return Complex(m_value); -} - -Number -Number::fromComplex(Complex cpx) -{ - return Number(cpx.real()); -} diff --git a/tests/libother/number.h b/tests/libother/number.h deleted file mode 100644 index 4286068d5..000000000 --- a/tests/libother/number.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NUMBER_H -#define NUMBER_H - -#include "libothermacros.h" -#include "str.h" -#include "point.h" -#include "complex.h" - -class LIBOTHER_API Number -{ -public: - explicit Number(int value) : m_value(value) {}; - inline int value() const { return m_value; } - - Str toStr() const; - inline operator Str() const { return toStr(); } - - friend LIBOTHER_API Point operator*(const Point&, const Number&); - - Complex toComplex() const; - static Number fromComplex(Complex cpx); - -private: - int m_value; -}; - -LIBOTHER_API Point operator*(const Point&, const Number&); - -#endif // NUMBER_H diff --git a/tests/libother/otherderived.cpp b/tests/libother/otherderived.cpp deleted file mode 100644 index 4128d73ff..000000000 --- a/tests/libother/otherderived.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "otherderived.h" - -OtherDerived::OtherDerived(int id) : Abstract(id) -{ -} - -OtherDerived::~OtherDerived() -{ -} - -Abstract* -OtherDerived::createObject() -{ - static int id = 100; - return new OtherDerived(id++); -} - -void -OtherDerived::pureVirtual() -{ -} - -void* -OtherDerived::pureVirtualReturningVoidPtr() -{ - return 0; -} - -void -OtherDerived::unpureVirtual() -{ -} - diff --git a/tests/libother/otherderived.h b/tests/libother/otherderived.h deleted file mode 100644 index 792b7c408..000000000 --- a/tests/libother/otherderived.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OTHERDERIVED_H -#define OTHERDERIVED_H - -#include "libothermacros.h" -#include "abstract.h" -#include "derived.h" -#include "objecttype.h" -#include "complex.h" - -class ObjectType; - -class LIBOTHER_API OtherDerived : public Abstract -{ -public: - OtherDerived(int id = -1); - virtual ~OtherDerived(); - virtual void pureVirtual(); - virtual void* pureVirtualReturningVoidPtr(); - virtual void unpureVirtual(); - virtual PrintFormat returnAnEnum() { return Short; } - - 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(); - - void hideFunction(HideType*) {} - -protected: - inline const char* getClassName() { return className(); } - virtual const char* className() { return "OtherDerived"; } -}; -#endif // OTHERDERIVED_H - diff --git a/tests/libother/othermultiplederived.cpp b/tests/libother/othermultiplederived.cpp deleted file mode 100644 index 77fa44b83..000000000 --- a/tests/libother/othermultiplederived.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "othermultiplederived.h" - -VirtualMethods OtherMultipleDerived::returnUselessClass() -{ - return VirtualMethods(); -} - -Base1* OtherMultipleDerived::createObject(const std::string& objName) -{ - if (objName == "Base1") - return new Base1; - else if (objName == "MDerived1") - return new MDerived1; - else if (objName == "SonOfMDerived1") - return new SonOfMDerived1; - else if (objName == "MDerived3") - return new MDerived3; - else if (objName == "OtherMultipleDerived") - return new OtherMultipleDerived; - return 0; -} - diff --git a/tests/libother/othermultiplederived.h b/tests/libother/othermultiplederived.h deleted file mode 100644 index e75504320..000000000 --- a/tests/libother/othermultiplederived.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OTHERMULTIPLEDERIVED_H -#define OTHERMULTIPLEDERIVED_H - -#include "libothermacros.h" -#include "multiple_derived.h" -#include "virtualmethods.h" - -class ObjectType; - -class LIBOTHER_API OtherMultipleDerived : public MDerived1 -{ -public: - // this will use CppCopier from other module (bug#142) - VirtualMethods returnUselessClass(); - static Base1* createObject(const std::string& objName); -}; - -#endif diff --git a/tests/libother/otherobjecttype.cpp b/tests/libother/otherobjecttype.cpp deleted file mode 100644 index 266b2583e..000000000 --- a/tests/libother/otherobjecttype.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "otherobjecttype.h" - -Collector& -operator<<(Collector& collector, const OtherObjectType& obj) -{ - collector << obj.identifier()*2; - return collector; -} diff --git a/tests/libother/otherobjecttype.h b/tests/libother/otherobjecttype.h deleted file mode 100644 index 2bba912b6..000000000 --- a/tests/libother/otherobjecttype.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OTHEROBJECTTYPE_H -#define OTHEROBJECTTYPE_H - -#include -#include "str.h" - -#include "libothermacros.h" -#include "objecttype.h" -#include "collector.h" - -class OtherObjectType : public ObjectType -{ -public: - -}; - - -LIBOTHER_API Collector& operator<<(Collector&, const OtherObjectType&); - -#endif // OTHEROBJECTTYPE_H - diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt deleted file mode 100644 index 7bbc0c3dd..000000000 --- a/tests/libsample/CMakeLists.txt +++ /dev/null @@ -1,57 +0,0 @@ -project(libsample) - -set(libsample_SRC -abstract.cpp -blackbox.cpp -bytearray.cpp -bucket.cpp -collector.cpp -complex.cpp -onlycopy.cpp -derived.cpp -echo.cpp -functions.cpp -handle.cpp -implicitconv.cpp -injectcode.cpp -listuser.cpp -modifications.cpp -mapuser.cpp -modified_constructor.cpp -multiple_derived.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 -sample.cpp -samplenamespace.cpp -sbkdate.cpp -simplefile.cpp -size.cpp -sometime.cpp -str.cpp -strlist.cpp -templateptr.cpp -transform.cpp -virtualmethods.cpp -expression.cpp -filter.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBSAMPLE_BUILD") -add_library(libsample SHARED ${libsample_SRC}) -set_property(TARGET libsample PROPERTY PREFIX "") - diff --git a/tests/libsample/abstract.cpp b/tests/libsample/abstract.cpp deleted file mode 100644 index ab00a3bcc..000000000 --- a/tests/libsample/abstract.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "abstract.h" -#include "objecttype.h" - -using namespace std; - -const int Abstract::staticPrimitiveField = 0; - -Abstract::Abstract(int id) : m_id(id) -{ - primitiveField = 123; - valueTypeField = Point(12, 34); - objectTypeField = 0; - bitField = 0; -} - -Abstract::~Abstract() -{ -} - -void -Abstract::unpureVirtual() -{ -} - -void -Abstract::callUnpureVirtual() -{ - this->unpureVirtual(); -} - - -void -Abstract::callPureVirtual() -{ - this->pureVirtual(); -} - -void -Abstract::show(PrintFormat format) -{ - 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; - } - cout << '>'; -} - -void Abstract::callVirtualGettingEnum(PrintFormat p) -{ - virtualGettingAEnum(p); -} - -void Abstract::virtualGettingAEnum(Abstract::PrintFormat p) -{ -} - diff --git a/tests/libsample/abstract.h b/tests/libsample/abstract.h deleted file mode 100644 index 77a43f3d1..000000000 --- a/tests/libsample/abstract.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ABSTRACT_H -#define ABSTRACT_H - -#include "libsamplemacros.h" -#include "point.h" -#include "complex.h" - -class ObjectType; - -// this class is not exported to python -class HideType -{ -}; - -class LIBSAMPLE_API Abstract -{ -private: - enum PrivateEnum { - PrivValue0, - PrivValue1, - PrivValue2 = PrivValue1 + 2 - }; -public: - enum PrintFormat { - Short, - Verbose, - OnlyId, - ClassNameAndId, - DummyItemToTestPrivateEnum1 = Abstract::PrivValue1, - DummyItemToTestPrivateEnum2 = PrivValue2, - }; - - enum Type { - TpAbstract, TpDerived - }; - - static const int staticPrimitiveField; - int primitiveField; - Complex userPrimitiveField; - Point valueTypeField; - ObjectType* objectTypeField; - - Abstract(int id = -1); - virtual ~Abstract(); - - inline int id() { return m_id; } - - // factory method - inline static Abstract* createObject() { return 0; } - - // method that receives an Object Type - inline static int getObjectId(Abstract* obj) { return obj->id(); } - - virtual void pureVirtual() = 0; - virtual void* pureVirtualReturningVoidPtr() = 0; - virtual void unpureVirtual(); - - virtual PrintFormat returnAnEnum() = 0; - void callVirtualGettingEnum(PrintFormat p); - virtual void virtualGettingAEnum(PrintFormat p); - - void callPureVirtual(); - void callUnpureVirtual(); - - void show(PrintFormat format = Verbose); - virtual Type type() const { return TpAbstract; } - - virtual void hideFunction(HideType* arg) = 0; - -protected: - virtual const char* className() { return "Abstract"; } - - // Protected bit-field structure member. - unsigned int bitField: 1; - -private: - int m_id; -}; -#endif // ABSTRACT_H diff --git a/tests/libsample/blackbox.cpp b/tests/libsample/blackbox.cpp deleted file mode 100644 index 9a10850f3..000000000 --- a/tests/libsample/blackbox.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#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()); - } -} - -int -BlackBox::keepObjectType(ObjectType* object) -{ - m_ticket++; - std::pair item(m_ticket, object); - m_objects.insert(item); - object->setParent(0); - - return m_ticket; -} - -ObjectType* -BlackBox::retrieveObjectType(int ticket) -{ - map::iterator it = m_objects.find(ticket); - if (it != m_objects.end()) { - ObjectType* second = it->second; - m_objects.erase(it); - return second; - } - return 0; -} - -void -BlackBox::disposeObjectType(int ticket) -{ - ObjectType* object = retrieveObjectType(ticket); - if (object) - delete object; -} - -int -BlackBox::keepPoint(Point* point) -{ - m_ticket++; - std::pair item(m_ticket, point); - m_points.insert(item); - - return m_ticket; -} - -Point* -BlackBox::retrievePoint(int ticket) -{ - map::iterator it = m_points.find(ticket); - if (it != m_points.end()) { - Point* second = it->second; - m_points.erase(it); - return second; - } - return 0; -} - -void -BlackBox::disposePoint(int ticket) -{ - Point* point = retrievePoint(ticket); - if (point) - delete point; -} - - -std::list -BlackBox::objects() -{ - std::list l; - map::iterator it; - - for ( it = m_objects.begin() ; it != m_objects.end(); it++ ) - l.push_back((*it).second); - - return l; -} - -std::list -BlackBox::points() -{ - std::list l; - map::iterator it; - - for ( it = m_points.begin() ; it != m_points.end(); it++ ) - l.push_back((*it).second); - - return l; -} - diff --git a/tests/libsample/blackbox.h b/tests/libsample/blackbox.h deleted file mode 100644 index de776668c..000000000 --- a/tests/libsample/blackbox.h +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BLACKBOX_H -#define BLACKBOX_H - -#include "libsamplemacros.h" -#include -#include "objecttype.h" -#include "point.h" - -class LIBSAMPLE_API BlackBox -{ -public: - typedef std::map ObjectTypeMap; - typedef std::map PointMap; - - BlackBox() { m_ticket = -1;} - ~BlackBox(); - - int keepObjectType(ObjectType* object); - ObjectType* retrieveObjectType(int ticket); - void disposeObjectType(int ticket); - - int keepPoint(Point* point); - Point* retrievePoint(int ticket); - void disposePoint(int ticket); - - std::list objects(); - std::list points(); - - inline void referenceToValuePointer(Point*&) {} - inline void referenceToObjectPointer(ObjectType*&) {} - -private: - ObjectTypeMap m_objects; - PointMap m_points; - int m_ticket; -}; - -#endif // BLACKBOX_H - diff --git a/tests/libsample/bucket.cpp b/tests/libsample/bucket.cpp deleted file mode 100644 index 50a1310e7..000000000 --- a/tests/libsample/bucket.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "bucket.h" -#include - -#ifdef _WIN32 // _WIN32 is defined by all Windows 32 and 64 bit compilers, but not by others. -#include -#define SLEEP(x) Sleep(x) -#else -#include -#define SLEEP(x) usleep(x) -#endif - - -using namespace std; - -Bucket::Bucket() : m_locked(false) -{ -} - -void Bucket::push(int x) -{ - m_data.push_back(x); -} - -int Bucket::pop(void) -{ - int x = 0; - - if (m_data.size() > 0) { - x = m_data.front(); - m_data.pop_front(); - } - - return x; -} - -bool Bucket::empty() -{ - return m_data.empty(); -} - -void Bucket::lock() -{ - m_locked = true; - while (m_locked) { SLEEP(300); } -} - -void Bucket::unlock() -{ - m_locked = false; -} - -bool Bucket::virtualBlockerMethod() -{ - lock(); - // The return value was added just for diversity sake. - return true; -} - diff --git a/tests/libsample/bucket.h b/tests/libsample/bucket.h deleted file mode 100644 index bd8648b6b..000000000 --- a/tests/libsample/bucket.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BUCKET_H -#define BUCKET_H - -#include "libsamplemacros.h" -#include "objecttype.h" -#include - -class ObjectType; - -class LIBSAMPLE_API Bucket : public ObjectType -{ -public: - Bucket(); - void push(int); - int pop(); - bool empty(); - void lock(); - inline bool locked() { return m_locked; } - void unlock(); - - virtual bool virtualBlockerMethod(); - inline bool callVirtualBlockerMethodButYouDontKnowThis() { return virtualBlockerMethod(); } - -private: - std::list m_data; - - volatile bool m_locked; -}; - -#endif // BUCKET_H - diff --git a/tests/libsample/bytearray.cpp b/tests/libsample/bytearray.cpp deleted file mode 100644 index c86ada124..000000000 --- a/tests/libsample/bytearray.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "bytearray.h" - -ByteArray::ByteArray() -{ - m_data = std::vector(1); - m_data[0] = '\0'; -} - -ByteArray::ByteArray(char c) -{ - m_data = std::vector(2); - m_data[0] = c; - m_data[1] = '\0'; -} - -ByteArray::ByteArray(const char* data) -{ - size_t len = strlen(data); - m_data = std::vector(len + 1); - memcpy(&m_data[0], data, len); - m_data[len] = '\0'; -} - -ByteArray::ByteArray(const char* data, int len) -{ - m_data = std::vector(len + 1); - memcpy(&m_data[0], data, len); - m_data[len] = '\0'; -} - -ByteArray::ByteArray(const ByteArray& other) -{ - m_data = std::vector(other.size() + 1); - memcpy(&m_data[0], &other.m_data[0], other.size()); - m_data[other.size()] = '\0'; -} - -int -ByteArray::size() const -{ - return m_data.size() - 1; -} - -char -ByteArray::at(int pos) const -{ - return m_data[pos]; -} - -const char* -ByteArray::data() const -{ - return &(m_data[0]); -} - -ByteArray& -ByteArray::append(char c) -{ - m_data.pop_back(); - m_data.push_back(c); - m_data.push_back('\0'); - return *this; -} - -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]); - m_data.push_back('\0'); - return *this; -} - -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]); - m_data.push_back('\0'); - return *this; -} - -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'); - return *this; -} - -static bool compare(const std::vector& mine, const char* other) -{ - for (int i = 0; i < (int)mine.size() - 1; ++i) { - if (mine[i] != other[i]) - return false; - } - return true; -} - -bool -ByteArray::operator==(const ByteArray& other) const -{ - return compare(m_data, &other.m_data[0]); -} -bool -operator==(const ByteArray& ba1, const char* ba2) -{ - return compare(ba1.m_data, ba2); -} -bool -operator==(const char* ba1, const ByteArray& ba2) -{ - return compare(ba2.m_data, ba1); -} - -bool -ByteArray::operator!=(const ByteArray& other) const -{ - return !(m_data == other.m_data); -} -bool -operator!=(const ByteArray& ba1, const char* ba2) -{ - return !(ba1 == ba2); -} -bool -operator!=(const char* ba1, const ByteArray& ba2) -{ - return !(ba1 == ba2); -} - -ByteArray& -ByteArray::operator+=(char c) -{ - return append(c); -} -ByteArray& -ByteArray::operator+=(const char* data) -{ - return append(data); -} -ByteArray& -ByteArray::operator+=(const ByteArray& other) -{ - return append(other); -} - -ByteArray -operator+(const ByteArray& ba1, const ByteArray& ba2) -{ - return ByteArray(ba1) += ba2; -} -ByteArray -operator+(const ByteArray& ba1, const char* ba2) -{ - return ByteArray(ba1) += ByteArray(ba2); -} -ByteArray -operator+(const char* ba1, const ByteArray& ba2) -{ - return ByteArray(ba1) += ba2; -} -ByteArray -operator+(const ByteArray& ba1, char ba2) -{ - return ByteArray(ba1) += ByteArray(ba2); -} -ByteArray -operator+(char ba1, const ByteArray& ba2) -{ - return ByteArray(ba1) += ba2; -} - -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]; - return result; -} diff --git a/tests/libsample/bytearray.h b/tests/libsample/bytearray.h deleted file mode 100644 index d2219ee5d..000000000 --- a/tests/libsample/bytearray.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef BYTEARRAY_H -#define BYTEARRAY_H - -#include "str.h" -#include "libsamplemacros.h" -#include - -class LIBSAMPLE_API ByteArray -{ -public: - ByteArray(); - ByteArray(char data); - ByteArray(const char* data); - ByteArray(const char* data, int len); - ByteArray(const ByteArray& other); - - int size() const; - char at(int i) const; - char operator[](int i) 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); - - 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); - - static unsigned int hash(const ByteArray& byteArray); -private: - std::vector 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 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 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/tests/libsample/collector.cpp b/tests/libsample/collector.cpp deleted file mode 100644 index e60ed3af3..000000000 --- a/tests/libsample/collector.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "collector.h" - -void Collector::clear() -{ - m_items.clear(); -} - -Collector& Collector::operator<<(ObjectType::Identifier item) -{ - m_items.push_back(item); - return *this; -} - -Collector& Collector::operator<<(const ObjectType *obj) -{ - m_items.push_back(obj->identifier()); - return *this; -} - -std::list Collector::items() -{ - return m_items; -} - -int Collector::size() -{ - return (int) m_items.size(); -} - -Collector &operator<<(Collector &s, const IntWrapper &w) -{ - s << w.value; - return s; -} diff --git a/tests/libsample/collector.h b/tests/libsample/collector.h deleted file mode 100644 index fe82909cb..000000000 --- a/tests/libsample/collector.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COLLECTOR_H -#define COLLECTOR_H - -#include -#include "libsamplemacros.h" - -#include "objecttype.h" - -class LIBSAMPLE_API Collector -{ -public: - Collector() {} - virtual ~Collector() {} - - void clear(); - - Collector& operator<<(ObjectType::Identifier item); - - Collector& operator<<(const ObjectType *); - - std::list items(); - int size(); - -private: - std::list m_items; - - Collector(const Collector&); - Collector& operator=(const Collector&); -}; - -/* Helper for testing external operators */ -class IntWrapper -{ -public: - IntWrapper(int x=0):value(x){} - - int value; -}; - -LIBSAMPLE_API Collector &operator<<(Collector&, const IntWrapper&); - -#endif // COLLECTOR_H - diff --git a/tests/libsample/complex.cpp b/tests/libsample/complex.cpp deleted file mode 100644 index 10e4b3f58..000000000 --- a/tests/libsample/complex.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "complex.h" - -using namespace std; - -Complex::Complex(double real, double imag) - : m_real(real), m_imag(imag) -{ -} - -Complex -Complex::operator+(Complex& other) -{ - Complex result; - result.setReal(m_real + other.real()); - result.setImaginary(m_imag + other.imag()); - return result; -} - -void -Complex::show() -{ - cout << "(real: " << m_real << ", imag: " << m_imag << ")"; -} - - diff --git a/tests/libsample/complex.h b/tests/libsample/complex.h deleted file mode 100644 index cb167bde9..000000000 --- a/tests/libsample/complex.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef COMPLEX_H -#define COMPLEX_H - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Complex -{ -public: - Complex(double real = 0.0, double imag = 0.0); - ~Complex() {} - - 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); - - void show(); - -private: - double m_real; - double m_imag; -}; - -#endif // COMPLEX_H - diff --git a/tests/libsample/ctorconvrule.h b/tests/libsample/ctorconvrule.h deleted file mode 100644 index 776f4744c..000000000 --- a/tests/libsample/ctorconvrule.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CTORCONVRULE_H -#define CTORCONVRULE_H - -#include "libsamplemacros.h" - -class CtorConvRule -{ -public: - explicit CtorConvRule(long value) : m_value(value) {} - virtual ~CtorConvRule() {} - virtual void dummyVirtualMethod() {} - long value() { return m_value; } -private: - long m_value; -}; - -#endif diff --git a/tests/libsample/cvlist.h b/tests/libsample/cvlist.h deleted file mode 100644 index c74007945..000000000 --- a/tests/libsample/cvlist.h +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef CONSTVALUELIST_H -#define CONSTVALUELIST_H - -#include -#include "libsamplemacros.h" - -class CVValueType -{ - CVValueType(); -}; - -typedef std::list const_ptr_value_list; - -// 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 -// binding code (the container conversion in particular) is const-valid. - -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; } -}; - -#endif // LIST_H diff --git a/tests/libsample/derived.cpp b/tests/libsample/derived.cpp deleted file mode 100644 index 00ac8ebe5..000000000 --- a/tests/libsample/derived.cpp +++ /dev/null @@ -1,119 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "derived.h" - -using namespace std; - -Derived::Derived(int id) : Abstract(id) -{ -} - -Derived::~Derived() -{ -} - -Abstract* -Derived::createObject() -{ - static int id = 100; - return new Derived(id++); -} - -void -Derived::pureVirtual() -{ -} - -void* -Derived::pureVirtualReturningVoidPtr() -{ - return 0; -} - -void -Derived::unpureVirtual() -{ -} - -bool -Derived::singleArgument(bool b) -{ - return !b; -} - -double -Derived::defaultValue(int n) -{ - return ((double) n) + 0.1; -} - -OverloadedFuncEnum -Derived::overloaded(int i, int d) -{ - return OverloadedFunc_ii; -} - -OverloadedFuncEnum -Derived::overloaded(double n) -{ - return OverloadedFunc_d; -} - -Derived::OtherOverloadedFuncEnum -Derived::otherOverloaded(int a, int b, bool c, double d) -{ - return OtherOverloadedFunc_iibd; -} - -Derived::OtherOverloadedFuncEnum -Derived::otherOverloaded(int a, double b) -{ - return OtherOverloadedFunc_id; -} - -struct SecretClass : public Abstract { - virtual void pureVirtual() {} - virtual void* pureVirtualReturningVoidPtr() { return 0; } - virtual PrintFormat returnAnEnum() { return Short; } - void hideFunction(HideType*){}; -}; - -Abstract* Derived::triggerImpossibleTypeDiscovery() -{ - return new SecretClass; -} - -struct AnotherSecretClass : public Derived { -}; - -Abstract* Derived::triggerAnotherImpossibleTypeDiscovery() -{ - return new AnotherSecretClass; -} diff --git a/tests/libsample/derived.h b/tests/libsample/derived.h deleted file mode 100644 index 5c57e4691..000000000 --- a/tests/libsample/derived.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DERIVED_H -#define DERIVED_H - -#include "libsamplemacros.h" -#include "abstract.h" - -enum OverloadedFuncEnum { - OverloadedFunc_ii, - OverloadedFunc_d -}; - -class LIBSAMPLE_API Derived : public Abstract -{ -public: - enum OtherOverloadedFuncEnum { - OtherOverloadedFunc_iibd, - OtherOverloadedFunc_id - }; - - class SomeInnerClass { - public: - void uselessMethod() {} - SomeInnerClass operator+(const SomeInnerClass& other) { return other; } - bool operator==(const SomeInnerClass& other) { return true; } - }; - - Derived(int id = -1); - virtual ~Derived(); - virtual void pureVirtual(); - virtual void* pureVirtualReturningVoidPtr(); - virtual void unpureVirtual(); - - virtual PrintFormat returnAnEnum() { return Short; } - virtual Type type() const { return TpDerived; } - - // factory method - static Abstract* createObject(); - - // single argument - bool singleArgument(bool b); - - // method with default value - double defaultValue(int n = 0); - - // overloads - OverloadedFuncEnum overloaded(int i = 0, int d = 0); - OverloadedFuncEnum overloaded(double n); - - // more overloads - OtherOverloadedFuncEnum otherOverloaded(int a, int b, bool c, double d); - OtherOverloadedFuncEnum otherOverloaded(int a, double b); - - inline SomeInnerClass returnMyParameter(const SomeInnerClass& s) { return s; } - - static Abstract* triggerImpossibleTypeDiscovery(); - static Abstract* triggerAnotherImpossibleTypeDiscovery(); - - void hideFunction(HideType*) {} -protected: - const char* getClassName() { return className(); } - virtual const char* className() { return "Derived"; } -}; -#endif // DERIVED_H - diff --git a/tests/libsample/echo.cpp b/tests/libsample/echo.cpp deleted file mode 100644 index 00fec78b0..000000000 --- a/tests/libsample/echo.cpp +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "echo.h" diff --git a/tests/libsample/echo.h b/tests/libsample/echo.h deleted file mode 100644 index a976c9cbc..000000000 --- a/tests/libsample/echo.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ECHO_H -#define ECHO_H - -#include "libsamplemacros.h" -#include "str.h" - -class ObjectType; - -class Echo -{ -public: - Echo(){} - ~Echo(){} - - 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; } -}; - -#endif diff --git a/tests/libsample/expression.cpp b/tests/libsample/expression.cpp deleted file mode 100644 index ff87e2ed2..000000000 --- a/tests/libsample/expression.cpp +++ /dev/null @@ -1,137 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include "expression.h" -#include - -Expression::Expression() : m_value(0), m_operation(None), m_operand1(0), m_operand2(0) -{ -} - -Expression::Expression(int number) : m_value(number), m_operation(None), m_operand1(0), m_operand2(0) -{ -} - -Expression::Expression(const Expression& other) -{ - m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; - m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; - m_value = other.m_value; - m_operation = other.m_operation; -} - -Expression& Expression::operator=(const Expression& other) -{ - delete m_operand1; - delete m_operand2; - m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; - m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; - m_operation = other.m_operation; - m_value = other.m_value; - return *this; -} - -Expression::~Expression() -{ - delete m_operand1; - delete m_operand2; -} - -Expression Expression::operator+(const Expression& other) -{ - Expression expr; - expr.m_operation = Add; - expr.m_operand1 = new Expression(*this); - expr.m_operand2 = new Expression(other); - return expr; -} - -Expression Expression::operator-(const Expression& other) -{ - Expression expr; - expr.m_operation = Add; - expr.m_operand1 = new Expression(*this); - expr.m_operand2 = new Expression(other); - return expr; -} - -Expression Expression::operator<(const Expression& other) -{ - Expression expr; - expr.m_operation = LessThan; - expr.m_operand1 = new Expression(*this); - expr.m_operand2 = new Expression(other); - return expr; -} - -Expression Expression::operator>(const Expression& other) -{ - Expression expr; - expr.m_operation = GreaterThan; - expr.m_operand1 = new Expression(*this); - expr.m_operand2 = new Expression(other); - return expr; -} - -std::string Expression::toString() const -{ - if (m_operation == None) { - std::ostringstream s; - s << m_value; - return s.str(); - } - - std::string result; - result += '('; - result += m_operand1->toString(); - char op; - switch (m_operation) { - case Add: - op = '+'; - break; - case Sub: - op = '-'; - break; - case LessThan: - op = '<'; - break; - case GreaterThan: - op = '<'; - break; - case None: // just to avoid the compiler warning - default: - op = '?'; - break; - } - result += op; - result += m_operand2->toString(); - result += ')'; - return result; -} - diff --git a/tests/libsample/expression.h b/tests/libsample/expression.h deleted file mode 100644 index c4bb1a1f5..000000000 --- a/tests/libsample/expression.h +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#ifndef EXPRESSION_H -#define EXPRESSION_H - -#include "libsamplemacros.h" -#include - -class LIBSAMPLE_API Expression -{ -public: - enum Operation { - None, Add, Sub, LessThan, GreaterThan - }; - - Expression(int number); - Expression(const Expression& other); - Expression& operator=(const Expression& other); - - ~Expression(); - - 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; - - Expression(); -}; - -#endif // EXPRESSION_H diff --git a/tests/libsample/filter.cpp b/tests/libsample/filter.cpp deleted file mode 100644 index dac5d5e96..000000000 --- a/tests/libsample/filter.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "filter.h" -Data::Data(Field field, std::string value) - : m_field(field), m_value(value) -{ -} - -Union::Union(const Data& filter) -{ - m_filters.push_back(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) -{ - m_filters.push_back(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 filter; - filter.addFilter(a); - filter.addFilter(b); - - return filter; -} diff --git a/tests/libsample/filter.h b/tests/libsample/filter.h deleted file mode 100644 index 6ee2e6123..000000000 --- a/tests/libsample/filter.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FILTER_H -#define FILTER_H - -#include -#include - -#include "libsamplemacros.h" - -class Intersection; - -class LIBSAMPLE_API Filter -{ -}; - -class LIBSAMPLE_API Data : public Filter -{ - -public: - enum Field { - Name, - Album, - Year - }; - - Data(Field field, std::string value); - - Field field() const { return m_field; } - std::string value() const { return m_value; } - -private: - Field m_field; - std::string m_value; -}; - -class LIBSAMPLE_API Union : public Filter -{ -public: - - Union(const Data&); - Union(const Intersection&); - Union() {}; - Union(const Union&); - - std::list filters() const { return m_filters; } - void addFilter(const Filter& data) { m_filters.push_back(data); } - -private: - std::list m_filters; -}; - -class LIBSAMPLE_API Intersection : public Filter -{ -public: - - Intersection(const Data&); - Intersection(const Union&); - Intersection() {}; - Intersection(const Intersection&); - - std::list filters() const { return m_filters; } - void addFilter(const Filter& data) { m_filters.push_back(data); } - -private: - std::list m_filters; -}; - -LIBSAMPLE_API Intersection operator&(const Intersection& a, const Intersection& b); - -#endif // FILTER_H - - diff --git a/tests/libsample/functions.cpp b/tests/libsample/functions.cpp deleted file mode 100644 index 4a15cdae8..000000000 --- a/tests/libsample/functions.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "functions.h" -#include -#include - -using namespace std; - -void -printSomething() -{ - cout << __FUNCTION__ << endl; -} - -int -gimmeInt() -{ - static int val = 2; - val = val * 1.3; - return val; -} - -double -gimmeDouble() -{ - static double val = 7.77; - val = val * 1.3; - return val; -} - -std::list -gimmeComplexList() -{ - std::list lst; - lst.push_back(Complex()); - lst.push_back(Complex(1.1, 2.2)); - lst.push_back(Complex(1.3, 2.4)); - return lst; -} - -Complex -sumComplexPair(std::pair cpx_pair) -{ - return cpx_pair.first + cpx_pair.second; -} - -double -multiplyPair(std::pair pair) -{ - return pair.first * pair.second; -} - -int -countCharacters(const char* text) -{ - if (!text) - return -1; - int count; - for(count = 0; text[count] != '\0'; count++) - ; - return count; -} - -char* -makeCString() -{ - char* string = new char[strlen(__FUNCTION__) + 1]; - strcpy(string, __FUNCTION__); - return string; -} - -const char* -returnCString() -{ - return __FUNCTION__; -} - -GlobalOverloadFuncEnum -overloadedFunc(int val) -{ - return GlobalOverloadFunc_i; -} - -GlobalOverloadFuncEnum -overloadedFunc(double val) -{ - return GlobalOverloadFunc_d; -} - -char* -returnNullPrimitivePointer() -{ - return 0; -} - -ObjectType* -returnNullObjectTypePointer() -{ - return 0; -} - -Event* -returnNullValueTypePointer() -{ - return 0; -} - -unsigned int -doubleUnsignedInt(unsigned int value) -{ - return value * 2; -} - -long long -doubleLongLong(long long value) -{ - return value * 2; -} - -unsigned long long -doubleUnsignedLongLong(unsigned long long value) -{ - return value * 2; -} - -short -doubleShort(short value) -{ - return value * 2; -} - -int -acceptInt(int x) -{ - return x; -} - -unsigned int -acceptUInt(unsigned int x) -{ - return x; -} - -long -acceptLong(long x) -{ - return x; -} - -unsigned long -acceptULong(unsigned long x) -{ - return x; -} - -double -acceptDouble(double x) -{ - return x; -} - -int -acceptIntReference(int& x) -{ - return x; -} - -OddBool -acceptOddBoolReference(OddBool& x) -{ - return x; -} - -ClassWithFunctionPointer::ClassWithFunctionPointer() -{ - callFunctionPointer(0, &ClassWithFunctionPointer::doNothing); -} - -void ClassWithFunctionPointer::callFunctionPointer(int dummy, void (*fp)(void *)) -{ - size_t a = dummy; - fp(reinterpret_cast(a)); -} - -void ClassWithFunctionPointer::doNothing(void *operand) -{ - (void) operand; -} diff --git a/tests/libsample/functions.h b/tests/libsample/functions.h deleted file mode 100644 index 89a175bc4..000000000 --- a/tests/libsample/functions.h +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef FUNCTIONS_H -#define FUNCTIONS_H - -#include "libsamplemacros.h" -#include -#include -#include "oddbool.h" -#include "complex.h" -#include "objecttype.h" - -enum GlobalEnum { - NoThing, - FirstThing, - SecondThing, - ThirdThing -}; - -enum GlobalOverloadFuncEnum { - GlobalOverloadFunc_i, - GlobalOverloadFunc_d -}; - -LIBSAMPLE_API void printSomething(); -LIBSAMPLE_API int gimmeInt(); -LIBSAMPLE_API double gimmeDouble(); -LIBSAMPLE_API double multiplyPair(std::pair pair); -LIBSAMPLE_API std::list gimmeComplexList(); -LIBSAMPLE_API Complex sumComplexPair(std::pair cpx_pair); - -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(); - -// Tests overloading on functions (!methods) -LIBSAMPLE_API GlobalOverloadFuncEnum overloadedFunc(int val); -LIBSAMPLE_API GlobalOverloadFuncEnum overloadedFunc(double val); - -LIBSAMPLE_API unsigned int doubleUnsignedInt(unsigned int value); -LIBSAMPLE_API long long doubleLongLong(long long value); -LIBSAMPLE_API unsigned long long doubleUnsignedLongLong(unsigned long long value); -LIBSAMPLE_API short doubleShort(short value); - -LIBSAMPLE_API int acceptInt(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); - - -class LIBSAMPLE_API ClassWithFunctionPointer -{ -public: - explicit ClassWithFunctionPointer(); - void callFunctionPointer(int dummy, void (*fp)(void *)); - static void doNothing(void *operand); -}; - -#endif // FUNCTIONS_H diff --git a/tests/libsample/handle.cpp b/tests/libsample/handle.cpp deleted file mode 100644 index e0b1d8d18..000000000 --- a/tests/libsample/handle.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "handle.h" - -HANDLE HandleHolder::createHandle() -{ - return (HANDLE) new OBJ; -} - -bool HandleHolder::compare(HandleHolder* other) -{ - return other->m_handle == m_handle; -} - -bool HandleHolder::compare2(HandleHolder* other) -{ - return other->m_handle2 == m_handle2; -} diff --git a/tests/libsample/handle.h b/tests/libsample/handle.h deleted file mode 100644 index d656f946b..000000000 --- a/tests/libsample/handle.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef HANDLE_H -#define HANDLE_H - -#include "libsamplemacros.h" - -/* See http://bugs.pyside.org/show_bug.cgi?id=1105. */ -namespace Foo { - typedef unsigned long HANDLE; -} - -class LIBSAMPLE_API OBJ -{ -}; - -typedef OBJ* HANDLE; - -class LIBSAMPLE_API HandleHolder -{ -public: - explicit HandleHolder(HANDLE ptr = 0) : m_handle(ptr) {} - explicit HandleHolder(Foo::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; } - - static HANDLE createHandle(); - bool compare(HandleHolder* other); - bool compare2(HandleHolder* other); - -private: - HANDLE m_handle; - Foo::HANDLE m_handle2; -}; - -struct LIBSAMPLE_API PrimitiveStruct {}; -typedef struct PrimitiveStruct* PrimitiveStructPtr; -struct LIBSAMPLE_API PrimitiveStructPointerHolder -{ - PrimitiveStructPtr primitiveStructPtr; -}; - -#endif // HANDLE_H diff --git a/tests/libsample/implicitconv.cpp b/tests/libsample/implicitconv.cpp deleted file mode 100644 index df4af2537..000000000 --- a/tests/libsample/implicitconv.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "implicitconv.h" - -ImplicitConv -ImplicitConv::implicitConvCommon(ImplicitConv implicit) -{ - return implicit; -} - -ImplicitConv -ImplicitConv::implicitConvDefault(ImplicitConv implicit) -{ - return implicit; -} - -ImplicitConv::ICOverloadedFuncEnum -ImplicitConv::implicitConvOverloading(ImplicitConv implicit, int dummyArg) -{ - return ImplicitConv::OverFunc_Ii; -} - -ImplicitConv::ICOverloadedFuncEnum -ImplicitConv::implicitConvOverloading(ImplicitConv implicit, bool dummyArg) -{ - return ImplicitConv::OverFunc_Ib; -} - -ImplicitConv::ICOverloadedFuncEnum -ImplicitConv::implicitConvOverloading(int dummyArg) -{ - return ImplicitConv::OverFunc_i; -} - -ImplicitConv::ICOverloadedFuncEnum -ImplicitConv::implicitConvOverloading(CtorEnum dummyArg) -{ - return ImplicitConv::OverFunc_C; -} - diff --git a/tests/libsample/implicitconv.h b/tests/libsample/implicitconv.h deleted file mode 100644 index 2a8ac66c2..000000000 --- a/tests/libsample/implicitconv.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef IMPLICITCONV_H -#define IMPLICITCONV_H - -#include "libsamplemacros.h" -#include "null.h" - -class ObjectType; - -class LIBSAMPLE_API ImplicitConv -{ -public: - enum CtorEnum { - CtorNone, - CtorOne, - CtorTwo, - CtorThree, - CtorObjectTypeReference, - CtorPrimitiveType - }; - - enum ICOverloadedFuncEnum { - OverFunc_Ii, - OverFunc_Ib, - OverFunc_i, - 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(double value, bool=true) : m_ctorEnum(CtorNone), m_value(value) {} - ImplicitConv(const Null& null) : m_ctorEnum(CtorPrimitiveType) {} - ~ImplicitConv() {} - - inline CtorEnum ctorEnum() { return m_ctorEnum; } - inline int objId() { return m_objId; } - inline double value() { return m_value; } - - static ImplicitConv implicitConvCommon(ImplicitConv implicit); - - static ImplicitConv implicitConvDefault(ImplicitConv implicit = CtorTwo); - - static ICOverloadedFuncEnum implicitConvOverloading(ImplicitConv implicit, int dummyArg); - static ICOverloadedFuncEnum implicitConvOverloading(ImplicitConv implicit, bool dummyArg); - static ICOverloadedFuncEnum implicitConvOverloading(int dummyArg); - static ICOverloadedFuncEnum implicitConvOverloading(CtorEnum dummyArg); - -private: - CtorEnum m_ctorEnum; - int m_objId; - double m_value; -}; - -#endif // IMPLICITCONV_H diff --git a/tests/libsample/injectcode.cpp b/tests/libsample/injectcode.cpp deleted file mode 100644 index 4406cdc5c..000000000 --- a/tests/libsample/injectcode.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "injectcode.h" -#include - -using namespace std; - -InjectCode::InjectCode() -{ -} - -InjectCode::~InjectCode() -{ -} - -template -const char* InjectCode::toStr(const T& value) -{ - std::ostringstream s; - s << value; - m_valueHolder = s.str(); - return m_valueHolder.c_str(); -} - -const char* InjectCode::simpleMethod1(int arg0, int arg1) -{ - return toStr(arg0 + arg1); -} - -const char* InjectCode::simpleMethod2() -{ - return "_"; -} - -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) -{ - toStr(arg0); - m_valueHolder += arg1 ? "true" : "false"; - return m_valueHolder.c_str(); -} - -const char* InjectCode::overloadedMethod(int arg0, double arg1) -{ - return toStr(arg0 + arg1); -} - -const char* InjectCode::overloadedMethod(int argc, char** argv) -{ - return simpleMethod3(argc, argv); -} - -const char* InjectCode::virtualMethod(int arg) -{ - return toStr(arg); -} - -int InjectCode::arrayMethod(int count, int *values) const -{ - int ret = 0; - for (int i=0; i < count; i++) - ret += values[i]; - return ret; -} - -int InjectCode::sumArrayAndLength(int* values) const -{ - int sum = 0; - - while(*values) { - sum = sum + *values + 1; - values++; - } - - return sum; -} diff --git a/tests/libsample/injectcode.h b/tests/libsample/injectcode.h deleted file mode 100644 index ba1bedb17..000000000 --- a/tests/libsample/injectcode.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef INJECTCODE_H -#define INJECTCODE_H - -#include "libsamplemacros.h" -#include -#include - -class LIBSAMPLE_API InjectCode -{ -public: - InjectCode(); - virtual ~InjectCode(); - - 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); - - 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; -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 - // another method of this class. - std::string m_valueHolder; - - template - const char* toStr(const T& value); -}; - -#endif // INJECTCODE_H - diff --git a/tests/libsample/libsamplemacros.h b/tests/libsample/libsamplemacros.h deleted file mode 100644 index 6a1bba88d..000000000 --- a/tests/libsample/libsamplemacros.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIBSAMPLEMACROS_H -#define LIBSAMPLEMACROS_H - -#if defined _WIN32 || defined __CYGWIN__ - #if LIBSAMPLE_BUILD - #define LIBSAMPLE_API __declspec(dllexport) - #else - #define LIBSAMPLE_API __declspec(dllimport) - #endif -#else -#if __GNUC__ >= 4 - #define LIBSAMPLE_API __attribute__ ((visibility("default"))) -#else - #define LIBSAMPLE_API -#endif -#endif - -#endif diff --git a/tests/libsample/list.h b/tests/libsample/list.h deleted file mode 100644 index f1183440c..000000000 --- a/tests/libsample/list.h +++ /dev/null @@ -1,106 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIST_H -#define LIST_H - -#include -#include "libsamplemacros.h" -#include "point.h" - -class ObjectType; - -template -class List : public std::list -{ -}; - -class IntList : public List -{ -public: - enum CtorEnum { - NoParamsCtor, - IntCtor, - CopyCtor, - ListOfIntCtor - }; - - inline IntList() : m_ctorUsed(NoParamsCtor) {} - inline explicit IntList(int val) : m_ctorUsed(IntCtor) { push_back(val); } - inline IntList(const IntList& lst) : List(lst), m_ctorUsed(CopyCtor) {} - inline IntList(const List& lst) : List(lst), m_ctorUsed(ListOfIntCtor) {} - - inline void append(int v) { insert(end(), v); } - CtorEnum constructorUsed() { return m_ctorUsed; } -private: - CtorEnum m_ctorUsed; -}; - -class PointValueList : public List -{ -public: - enum CtorEnum { - NoParamsCtor, - PointCtor, - CopyCtor, - ListOfPointValuesCtor - }; - - inline PointValueList() : m_ctorUsed(NoParamsCtor) {} - inline explicit PointValueList(Point val) : m_ctorUsed(PointCtor) { push_back(val); } - inline PointValueList(const PointValueList& lst) : List(lst), m_ctorUsed(CopyCtor) {} - inline PointValueList(const List& lst) : List(lst), m_ctorUsed(ListOfPointValuesCtor) {} - - inline void append(Point v) { insert(end(), v); } - CtorEnum constructorUsed() { return m_ctorUsed; } -private: - CtorEnum m_ctorUsed; -}; - -class ObjectTypePtrList : public List -{ -public: - enum CtorEnum { - NoParamsCtor, - ObjectTypeCtor, - CopyCtor, - ListOfObjectTypePtrCtor - }; - - inline ObjectTypePtrList() : m_ctorUsed(NoParamsCtor) {} - inline explicit ObjectTypePtrList(ObjectType* val) : m_ctorUsed(ObjectTypeCtor) { push_back(val); } - inline ObjectTypePtrList(const ObjectTypePtrList& lst) : List(lst), m_ctorUsed(CopyCtor) {} - inline ObjectTypePtrList(const List& lst) : List(lst), m_ctorUsed(ListOfObjectTypePtrCtor) {} - - inline void append(ObjectType* v) { insert(end(), v); } - CtorEnum constructorUsed() { return m_ctorUsed; } -private: - CtorEnum m_ctorUsed; -}; - -#endif // LIST_H diff --git a/tests/libsample/listuser.cpp b/tests/libsample/listuser.cpp deleted file mode 100644 index 24389766e..000000000 --- a/tests/libsample/listuser.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include "listuser.h" - -using namespace std; - -std::list -ListUser::callCreateList() -{ - return createList(); -} - -std::list -ListUser::createList() -{ - std::list retval; - for (int i = 0; i < 4; i++) - retval.push_front(rand()); - return retval; -} - -std::list -ListUser::createComplexList(Complex cpx0, Complex cpx1) -{ - std::list retval; - retval.push_back(cpx0); - retval.push_back(cpx1); - return retval; -} - -double -ListUser::sumList(std::list vallist) -{ - return std::accumulate(vallist.begin(), vallist.end(), 0.0); -} - -double -ListUser::sumList(std::list vallist) -{ - return std::accumulate(vallist.begin(), vallist.end(), 0.0); -} - -ListUser::ListOfSomething -ListUser::listOfPoints(const std::list& pointlist) -{ - return ListOfPoint; -} - -ListUser::ListOfSomething -ListUser::listOfPoints(const std::list& pointlist) -{ - return ListOfPointF; -} - -void -ListUser::multiplyPointList(PointList& points, double multiplier) -{ - for(PointList::iterator piter = points.begin(); piter != points.end(); piter++) { - (*piter)->setX((*piter)->x() * multiplier); - (*piter)->setY((*piter)->y() * multiplier); - } -} - diff --git a/tests/libsample/listuser.h b/tests/libsample/listuser.h deleted file mode 100644 index 8f49c80d3..000000000 --- a/tests/libsample/listuser.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LISTUSER_H -#define LISTUSER_H - -#include -#include "complex.h" -#include "point.h" -#include "pointf.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API ListUser -{ -public: - typedef std::list PointList; - - enum ListOfSomething { - ListOfPoint, - ListOfPointF - }; - - ListUser() {} - ListUser(const ListUser& other) : m_lst(other.m_lst) {} - virtual ~ListUser() {} - - virtual std::list createList(); - std::list callCreateList(); - - static std::list createComplexList(Complex cpx0, Complex cpx1); - - double sumList(std::list vallist); - double sumList(std::list vallist); - - static ListOfSomething listOfPoints(const std::list& pointlist); - static ListOfSomething listOfPoints(const std::list& pointlist); - - static void multiplyPointList(PointList& points, double multiplier); - - inline void setList(std::list lst) { m_lst = lst; } - inline std::list getList() { return m_lst; } - -private: - std::list m_lst; -}; - -#endif // LISTUSER_H - diff --git a/tests/libsample/main.cpp b/tests/libsample/main.cpp deleted file mode 100644 index b22d05a36..000000000 --- a/tests/libsample/main.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include "abstract.h" -#include "derived.h" -#include "kindergarten.h" -#include "complex.h" -#include "point.h" -#include "size.h" -#include "listuser.h" -#include "samplenamespace.h" - -using namespace std; - -int -main(int argv, char **argc) -{ - cout << endl; - - Derived derived; - - cout << endl; - - derived.unpureVirtual(); - derived.pureVirtual(); - derived.callPureVirtual(); - - cout << endl; - Abstract* abs; - abs = Abstract::createObject(); - cout << "Abstract::createObject(): " << abs << endl << endl; - delete abs; - - abs = Derived::createObject(); - cout << "Derived::createObject() : "; - abs->show(); - cout << endl; - delete abs; - cout << endl; - - abs = Derived::createObject(); - cout << "Derived::createObject() : "; - abs->show(); - cout << endl; - delete abs; - cout << endl; - - cout << endl << "-----------------------------------------" << endl; - - KinderGarten kg; - Derived* d[] = { 0, 0, 0 }; - - for (int i = 0; i < 3; i++) { - d[i] = new Derived(i); - d[i]->show(); - cout << endl; - kg.addChild(d[i]); - } - - kg.show(); - cout << endl; - - cout << endl << "* kill child "; - d[2]->show(); - cout << " ----------------" << endl; - kg.killChild(d[2]); - kg.show(); - cout << endl; - - cout << endl << "* release child "; - d[1]->show(); - cout << " -------------" << endl; - Abstract* released = kg.releaseChild(d[1]); - cout << "released: "; - released->show(); - cout << endl; - kg.show(); - cout << endl; - - cout << endl << "* kill children ------------------------------------" << endl; - kg.killChildren(); - kg.show(); - cout << endl << endl; - - cout << "-----------------------------------------" << endl; - ListUser lu; - cout << "ListUser::createList()" << endl; - std::list intlist = lu.createList(); - for (std::list::iterator it = intlist.begin(); it != intlist.end(); it++) { - cout << "* " << *it << endl; - } - - cout << "ListUser::createComplexList" << endl; - std::list cpxlist = ListUser::createComplexList(Complex(1.1, 2.2), Complex(3.3, 4.4)); - for (std::list::iterator it = cpxlist.begin(); it != cpxlist.end(); it++) { - cout << "* "; - (*it).show(); - cout << 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; - double val_d = 1.3; - cout << "SampleNamespace::powerOfTwo(" << val_d << "): "; - cout << SampleNamespace::powerOfTwo(val_d) << endl; - int val_i = 7; - cout << "SampleNamespace::powerOfTwo(" << val_i << "): "; - cout << SampleNamespace::powerOfTwo(val_i) << endl; - cout << endl; - - cout << "-----------------------------------------" << endl; - cout << "Point" << endl; - - Point p1(1.1, 2.2); - cout << "p1: "; - p1.show(); - cout << endl; - - Point p2(3.4, 5.6); - cout << "p2: "; - p2.show(); - cout << endl; - - cout << "p1 + p2 == "; - (p1 + p2).show(); - cout << endl; - - cout << "p1 * 2.0 == "; - (p1 * 2.0).show(); - cout << endl; - - cout << "1.5 * p2 == "; - (1.5 * p2).show(); - cout << endl; - - cout << "p1: "; - p1.show(); - cout << endl << "p2: "; - p2.show(); - cout << endl << "p1 += p2" << endl; - p1 += p2; - cout << "p1: "; - p1.show(); - cout << 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; - - cout << "-----------------------------------------" << endl; - cout << "Size" << endl; - - Size s1(2, 2); - cout << "s1: "; - s1.show(); - cout << ", area: " << s1.calculateArea(); - cout << endl; - - Size s2(3, 5); - 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: "; - s1.show(); - cout << endl << "s2: "; - s2.show(); - cout << endl << "s1 += s2" << endl; - s1 += s2; - cout << "s1: "; - s1.show(); - cout << endl; - - cout << endl; - - cout << "s1: "; - s1.show(); - cout << endl << "s1 *= 2.0" << endl; - s1 *= 2.0; - cout << "s1: "; - s1.show(); - cout << endl; - - cout << endl; - - return 0; -} - diff --git a/tests/libsample/mapuser.cpp b/tests/libsample/mapuser.cpp deleted file mode 100644 index 666188512..000000000 --- a/tests/libsample/mapuser.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "mapuser.h" - -using namespace std; - -std::map > -MapUser::callCreateMap() -{ - return createMap(); -} - - -std::map > -MapUser::createMap() -{ - std::map > retval; - - std::pair > - item0("zero", std::pair(Complex(1.2, 3.4), 2)); - retval.insert(item0); - - std::pair > - item1("one", std::pair(Complex(5.6, 7.8), 3)); - retval.insert(item1); - - std::pair > - item2("two", std::pair(Complex(9.1, 2.3), 5)); - retval.insert(item2); - - return retval; -} - -void -MapUser::showMap(std::map mapping) -{ - std::map::iterator it; - cout << __FUNCTION__ << endl; - for (it = mapping.begin() ; it != mapping.end(); it++) - cout << (*it).first << " => " << (*it).second << endl; -} - diff --git a/tests/libsample/mapuser.h b/tests/libsample/mapuser.h deleted file mode 100644 index 90d036945..000000000 --- a/tests/libsample/mapuser.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MAPUSER_H -#define MAPUSER_H - -#include -#include -#include -#include -#include "complex.h" -#include "bytearray.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API MapUser -{ -public: - MapUser() {} - virtual ~MapUser() {} - - virtual std::map > createMap(); - std::map > callCreateMap(); - - void showMap(std::map mapping); - - inline void setMap(std::map > map) { m_map = map; } - inline std::map > getMap() { return m_map; } - - // Compile test - static void pointerToMap(std::map* arg) {} - static void referenceToMap(std::map& arg) {} - - inline const std::map& passMapIntValueType(const std::map& arg) { return arg; } - -private: - std::map > m_map; -}; - -#endif // MAPUSER_H diff --git a/tests/libsample/modelindex.h b/tests/libsample/modelindex.h deleted file mode 100644 index 12cc97ce4..000000000 --- a/tests/libsample/modelindex.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#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; } - inline void setValue(int value) { m_value = value; } - inline int value() const { return m_value; } - static int getValue(const ModelIndex& index) { return index.value(); } -private: - int m_value; -}; - -class ReferentModelIndex -{ -public: - ReferentModelIndex() {} - ReferentModelIndex(const ModelIndex& index) : m_index(index) {} - ReferentModelIndex(const ReferentModelIndex& other) { m_index = other.m_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; -}; - -class PersistentModelIndex -{ -public: - PersistentModelIndex() {} - PersistentModelIndex(const ModelIndex& index) : m_index(index) {} - PersistentModelIndex(const PersistentModelIndex& other) { m_index = other.m_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 diff --git a/tests/libsample/modifications.cpp b/tests/libsample/modifications.cpp deleted file mode 100644 index 4a60a8071..000000000 --- a/tests/libsample/modifications.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "modifications.h" -#include "objecttype.h" - -using namespace std; - -Modifications::Modifications() -{ - m_object = new ObjectType(); - m_object->setObjectName("MyObject"); -} - -Modifications::~Modifications() -{ - delete m_object; -} - -std::pair -Modifications::pointToPair(Point pt, bool* ok) -{ - std::pair retval(pt.x(), pt.y()); - *ok = true; - return retval; -} - -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) -{ - return (2 * value) + plus; -} - -int -Modifications::power(int base, int exponent) -{ - if (exponent == 0) - return 1; - int retval = base; - for (int i = 1; i < exponent; i++) - retval = retval * base; - return retval; -} - -int -Modifications::timesTen(int number) -{ - return number * 10; -} - -int -Modifications::increment(int number) -{ - return ++number; -} - -void -Modifications::exclusiveCppStuff() -{ - cout << __FUNCTION__ << endl; -} - -int -Modifications::cppMultiply(int a, int b) -{ - return a * b; -} - -const char* -Modifications::className() -{ - return "Modifications"; -} - -Point -Modifications::sumPointArray(int arraySize, const Point pointArray[]) -{ - Point point; - for (int i = 0; i < arraySize; ++i) - point = point + pointArray[i]; - return point; -} - -int -Modifications::getSize(const void* data, int size) -{ - (void)data; - return size; -} - -int -Modifications::sumPointCoordinates(const Point* point) -{ - return point->x() + point->y(); -} - -double -Modifications::differenceOfPointCoordinates(const Point* pt, bool* ok) -{ - if (!pt) { - *ok = false; - return 0.0; - } - *ok = true; - double result = pt->x() - pt->y(); - if (result < 0) - result = result * -1.0; - return result; -} - -bool -Modifications::nonConversionRuleForArgumentWithDefaultValue(ObjectType** object) -{ - if (object) - *object = m_object; - return true; -} diff --git a/tests/libsample/modifications.h b/tests/libsample/modifications.h deleted file mode 100644 index 2978270b0..000000000 --- a/tests/libsample/modifications.h +++ /dev/null @@ -1,142 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MODIFICATIONS_H -#define MODIFICATIONS_H - -#include "libsamplemacros.h" -#include -#include "point.h" -#include "oddbool.h" - -class ObjectType; - -class LIBSAMPLE_API Modifications -{ -public: - Modifications(); - virtual ~Modifications(); - - enum OverloadedModFunc { - OverloadedNone, - Overloaded_ibid, - Overloaded_ibib, - Overloaded_ibiP, - Overloaded_ibii, - Overloaded_ibPP - }; - - // 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; } - - inline void argRemoval0(int a0, bool a1, int a2 = 123, int a3 = 456) {} - inline 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) {} - - inline 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) {} - - inline 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) {} - - // '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 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); - - // completely remove 'plus' from the Python side - int doublePlus(int value, int plus = 0); - - // the default value for both arguments must be changed in Python - int power(int base = 1, int exponent = 0); - - // in Python set argument default value to 10 - int timesTen(int number); - - // in Python remove the argument default value - int increment(int number = 0); - - // don't export this method to Python - void exclusiveCppStuff(); - - // change the name of this regular method - int cppMultiply(int a, int b); - - // change the name of this virtual method - virtual const char* className(); - - Point sumPointArray(int arraySize, const Point pointArray[]); - - // Replace 'const void*' by 'ByteArray&'. - int getSize(const void* data, int size); - - // Mark the argument with a tag; - // the test implementation must expect point never to be null. - 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); } - - // Sets an ObjectType in the argument and returns true. - bool nonConversionRuleForArgumentWithDefaultValue(ObjectType** object = 0); - 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; } - -private: - ObjectType* m_object; -}; - -class LIBSAMPLE_API AbstractModifications : public Modifications -{ -public: - AbstractModifications() {} - virtual ~AbstractModifications() {} - - inline bool invert(bool value) { return !value; } - - // completely remove this method in Python - virtual void pointlessPureVirtualMethod() = 0; -}; - -#endif // MODIFICATIONS_H diff --git a/tests/libsample/modified_constructor.cpp b/tests/libsample/modified_constructor.cpp deleted file mode 100644 index 48224358f..000000000 --- a/tests/libsample/modified_constructor.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "modified_constructor.h" - -ModifiedConstructor::ModifiedConstructor(int first_arg) -{ - m_stored_value = first_arg; -} - -int -ModifiedConstructor::retrieveValue() -{ - return m_stored_value; -} - - diff --git a/tests/libsample/modified_constructor.h b/tests/libsample/modified_constructor.h deleted file mode 100644 index 9ac5497d7..000000000 --- a/tests/libsample/modified_constructor.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MODIFIEDCONSTRUCTOR_H -#define MODIFIEDCONSTRUCTOR_H - -#include "libsamplemacros.h" - -class LIBSAMPLE_API ModifiedConstructor -{ -public: - - ModifiedConstructor(int first_arg); - int retrieveValue(); - -private: - int m_stored_value; -}; - -#endif // MODIFIEDCONSTRUCTOR_H - diff --git a/tests/libsample/multiple_derived.cpp b/tests/libsample/multiple_derived.cpp deleted file mode 100644 index 1d7a33cbe..000000000 --- a/tests/libsample/multiple_derived.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "multiple_derived.h" - -MDerived1::MDerived1() : m_value(100) -{ -} - -MDerived2::MDerived2() : m_value(200) -{ -} - -MDerived3::MDerived3() : m_value(3000) -{ -} - -MDerived4::MDerived4() -{ -} - -MDerived5::MDerived5() -{ -} - -MDerived1* -MDerived1::transformFromBase1(Base1* self) -{ - MDerived1* ptr = dynamic_cast(self); - return ptr; -} - -MDerived1* -MDerived1::transformFromBase2(Base2* self) -{ - MDerived1* ptr = dynamic_cast(self); - return ptr; -} - diff --git a/tests/libsample/multiple_derived.h b/tests/libsample/multiple_derived.h deleted file mode 100644 index 5825e59b4..000000000 --- a/tests/libsample/multiple_derived.h +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef MDERIVED_H -#define MDERIVED_H - -#include "libsamplemacros.h" -#include - -class Base1 -{ -public: - Base1() : m_value(1) {} - virtual ~Base1() {} - virtual int base1Method() { return m_value; } - - virtual void publicMethod() {}; -private: - int m_value; -}; - -class Base2 -{ -public: - Base2() : m_value(2) {} - virtual ~Base2() {} - virtual int base2Method() { return m_value; } -private: - int m_value; -}; - -class LIBSAMPLE_API MDerived1 : public Base1, public Base2 -{ -public: - MDerived1(); - virtual ~MDerived1() {} - - virtual int mderived1Method() { return m_value; } - virtual int base1Method() { return Base1::base1Method() * 10; } - virtual int base2Method() { return Base2::base2Method() * 10; } - - inline Base1* castToBase1() { return (Base1*) this; } - inline Base2* castToBase2() { return (Base2*) this; } - - static MDerived1* transformFromBase1(Base1 *self); - static MDerived1* transformFromBase2(Base2 *self); - -private: - virtual void publicMethod() {} - int m_value; -}; - -class SonOfMDerived1 : public MDerived1 -{ -public: - SonOfMDerived1() : m_value(0) {} - ~SonOfMDerived1() {} - - inline MDerived1* castToMDerived1() { return (MDerived1*) this; } - - int sonOfMDerived1Method() { return m_value; } -private: - int m_value; -}; - -class Base3 -{ -public: - explicit Base3(int val = 3) : m_value(val) {} - virtual ~Base3() {} - int base3Method() { return m_value; } -private: - int m_value; -}; - -class Base4 -{ -public: - Base4() : m_value(4) {} - virtual ~Base4() {} - int base4Method() { return m_value; } -private: - int m_value; -}; - -class Base5 -{ -public: - Base5() : m_value(5) {} - virtual ~Base5() {} - virtual int base5Method() { return m_value; } -private: - int m_value; -}; - -class Base6 -{ -public: - Base6() : m_value(6) {} - virtual ~Base6() {} - virtual int base6Method() { return m_value; } -private: - int m_value; -}; - - -class LIBSAMPLE_API MDerived2 : public Base3, public Base4, public Base5, public Base6 -{ -public: - MDerived2(); - virtual ~MDerived2() {} - - 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; } - -private: - int m_value; -}; - -class LIBSAMPLE_API MDerived3 : public MDerived1, public MDerived2 -{ -public: - MDerived3(); - virtual ~MDerived3() {} - - inline virtual int mderived3Method() { return m_value; } - - inline MDerived1* castToMDerived1() { return (MDerived1*) this; } - inline MDerived2* castToMDerived2() { return (MDerived2*) this; } - - inline Base3* castToBase3() { return (Base3*) this; } - -private: - int m_value; -}; - -class LIBSAMPLE_API MDerived4 : public Base3, public Base4 -{ -public: - MDerived4(); - ~MDerived4() {} - - inline int mderived4Method() { return 0; } - inline int justDummyMethod() { return m_value; } - - inline Base3* castToBase3() { return (Base3*) this; } - inline Base4* castToBase4() { return (Base4*) this; } -private: - int m_value; -}; - -class LIBSAMPLE_API MDerived5 : public Base3, public Base4 -{ -public: - MDerived5(); - virtual ~MDerived5() {} - - virtual int mderived5Method() { return 0; } - - inline Base3* castToBase3() { return (Base3*) this; } - inline Base4* castToBase4() { return (Base4*) this; } -}; - -#endif // MDERIVED_H - diff --git a/tests/libsample/noimplicitconversion.h b/tests/libsample/noimplicitconversion.h deleted file mode 100644 index 0a8882d3a..000000000 --- a/tests/libsample/noimplicitconversion.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NOIMPLICITCONVERSION_H -#define NOIMPLICITCONVERSION_H - -#include "libsamplemacros.h" - -// This class must not have implicit conversions AND -// no conversion operators should be defined in its own module. -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; } -private: - int m_objId; -}; - -#endif // NOIMPLICITCONVERSION_H - diff --git a/tests/libsample/nondefaultctor.h b/tests/libsample/nondefaultctor.h deleted file mode 100644 index d2b186bd8..000000000 --- a/tests/libsample/nondefaultctor.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NONDEFAULTCTOR_H -#define NONDEFAULTCTOR_H - -#include "libsamplemacros.h" - -class NonDefaultCtor -{ - int m_value; -public: - NonDefaultCtor(int value) : m_value(value) - { - } - - inline int value() - { - return m_value; - } - - inline NonDefaultCtor returnMyself() - { - return *this; - } - - inline NonDefaultCtor returnMyself(int) - { - return *this; - } - - inline NonDefaultCtor returnMyself(int, NonDefaultCtor) - { - return *this; - } - - virtual NonDefaultCtor returnMyselfVirtual() - { - return *this; - } - - inline NonDefaultCtor callReturnMyselfVirtual() - { - return returnMyselfVirtual(); - } - - virtual ~NonDefaultCtor() {} -}; - -#endif diff --git a/tests/libsample/null.h b/tests/libsample/null.h deleted file mode 100644 index 634262a99..000000000 --- a/tests/libsample/null.h +++ /dev/null @@ -1,44 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef NULL_H -#define NULL_H - -class Null -{ -public: - Null(bool value) : m_isNull(value) {} - Null() : m_isNull(false) {} - void setIsNull(bool flag) { m_isNull = flag; } - -private: - bool m_isNull; -}; - -#endif // STR_H - diff --git a/tests/libsample/objectmodel.cpp b/tests/libsample/objectmodel.cpp deleted file mode 100644 index 370b58aa1..000000000 --- a/tests/libsample/objectmodel.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objectmodel.h" - -void -ObjectModel::setData(ObjectType* data) -{ - m_data = data; -} - -ObjectType* -ObjectModel::data() const -{ - return m_data; -} - diff --git a/tests/libsample/objectmodel.h b/tests/libsample/objectmodel.h deleted file mode 100644 index aa4a64433..000000000 --- a/tests/libsample/objectmodel.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTMODEL_H -#define OBJECTMODEL_H - -#include "objecttype.h" -#include "libsamplemacros.h" - -class LIBSAMPLE_API ObjectModel : public ObjectType -{ -public: - explicit ObjectModel(ObjectType* parent = 0) - : ObjectType(parent), m_data(0) - {} - - 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; } - -private: - // The model holds only one piece of data. - // (This is just a test after all.) - ObjectType* m_data; -}; - -#endif // OBJECTMODEL_H - diff --git a/tests/libsample/objecttype.cpp b/tests/libsample/objecttype.cpp deleted file mode 100644 index 4f10b01df..000000000 --- a/tests/libsample/objecttype.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objecttype.h" -#include "objecttypelayout.h" -#include -#include -#include -#include - -using namespace std; - -ObjectType::ObjectType(ObjectType* parent) : m_parent(0), m_layout(0), m_call_id(-1) -{ - setParent(parent); -} - -ObjectType::~ObjectType() -{ - for (ObjectTypeList::iterator child_iter = m_children.begin(); - child_iter != m_children.end(); ++child_iter) - delete *child_iter; -} - -ObjectType* -ObjectType::createWithChild() -{ - ObjectType* parent = create(); - ObjectType* child = create(); - child->setObjectName("child"); - child->setParent(parent); - return parent; -} - -void -ObjectType::removeChild(ObjectType* child) -{ - if (!child) - return; - - ObjectTypeList::iterator child_iter = std::find(m_children.begin(), m_children.end(), child); - if (child_iter != m_children.end()) { - m_children.erase(child_iter); - child->m_parent = 0; - } -} - -ObjectType* -ObjectType::takeChild(ObjectType* child) -{ - if (!child) - return 0; - - ObjectTypeList::iterator child_iter = std::find(m_children.begin(), m_children.end(), child); - if (child_iter != m_children.end()) { - m_children.erase(child_iter); - child->m_parent = 0; - return child; - } - return 0; -} - -ObjectType* -ObjectType::takeChild(const Str& name) -{ - return takeChild(findChild(name)); - -} - -ObjectType* -ObjectType::findChild(const Str& name) -{ - for (ObjectTypeList::iterator child_iter = m_children.begin(); - child_iter != m_children.end(); ++child_iter) { - - if ((*child_iter)->objectName() == name) - return *child_iter; - } - return 0; -} - -void -ObjectType::killChild(const Str& name) -{ - for (ObjectTypeList::iterator child_iter = m_children.begin(); - child_iter != m_children.end(); ++child_iter) { - - if ((*child_iter)->objectName() == name) { - ObjectType* child = *child_iter; - removeChild(child); - delete child; - break; - } - } -} - -void -ObjectType::setParent(ObjectType* parent) -{ - if (m_parent == parent) - return; - - if (m_parent) - m_parent->removeChild(this); - - m_parent = parent; - if (m_parent) - m_parent->m_children.push_back(this); -} - -void -ObjectType::setObjectName(const Str& name) -{ - m_objectName = name; -} - -Str -ObjectType::objectName() const -{ - return m_objectName; -} - -bool -ObjectType::causeEvent(Event::EventType eventType) -{ - Event e(eventType); - return event(&e); -} - -bool -ObjectType::event(Event* event) -{ - return true; -} - -int -ObjectType::processEvent(ObjectTypeList objects, Event *event) -{ - int evaluated = 0; - - for (ObjectTypeList::iterator obj_iter = objects.begin(); - obj_iter != objects.end(); ++obj_iter) { - if((*obj_iter)->event(event)) - evaluated++; - } - - return evaluated; - -} - -void -ObjectType::callInvalidateEvent(Event* event) -{ - invalidateEvent(event); -} - -void -ObjectType::setLayout(ObjectTypeLayout* l) -{ - if (!l) { - cerr << "[WARNING] ObjectType::setLayout: Cannot set layout to 0." << endl; - 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; - } - return; - } - - 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; - return; - } else { - // Steal the layout from an ObjectType parent. - oldParent->takeLayout(); - } - } - - m_layout = l; - if (oldParent != this) { - l->setParent(this); - l->reparentChildren(this); - } -} - -ObjectTypeLayout* ObjectType::takeLayout() -{ - ObjectTypeLayout* l = layout(); - if (!l) - return 0; - m_layout = 0; - l->setParent(0); - return l; -} - -unsigned int -objectTypeHash(const ObjectType* objectType) -{ - return reinterpret_cast(objectType); -} - -unsigned char -ObjectType::callWithEnum(const Str& prefix, Event::EventType type, unsigned char value){ - return value*value; -} - -unsigned char -ObjectType::callWithEnum(const Str& prefix, unsigned char value) { - return value; -} - -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) -{ - std::string result(name.cstring(), size); - m_objectName = result.c_str(); -} - -void -ObjectType::setObjectNameWithSize(const Str& name, int size) -{ - setObjectNameWithSize("", size, name); -} - -void ObjectType::setObject(ObjectType *) -{ - m_call_id = 0; -} - -void ObjectType::setObject(const Null&) -{ - m_call_id = 1; -} - -int ObjectType::callId() const -{ - return m_call_id; -} - - -void ObjectType::callVirtualCreateChild() -{ - ObjectType* fake_parent = new ObjectType(); - ObjectType* fake_child = createChild(fake_parent); - assert(fake_child->isPython()); - delete fake_parent; -} - -ObjectType* ObjectType::createChild(ObjectType* parent) -{ - return new ObjectType(parent); -} - -std::size_t ObjectType::createObjectType() -{ - void* addr = new ObjectType(); - return (std::size_t) addr; -} - -OtherBase::~OtherBase() -{ -} - -ObjectTypeDerived::~ObjectTypeDerived() -{ -} - -bool -ObjectTypeDerived::event(Event* event) -{ - return true; -} diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h deleted file mode 100644 index eae95b3b1..000000000 --- a/tests/libsample/objecttype.h +++ /dev/null @@ -1,176 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTTYPE_H -#define OBJECTTYPE_H - -#include -#include "str.h" -#include "null.h" - -#include "libsamplemacros.h" - -#include - -struct Event -{ - enum EventType { - NO_EVENT, - BASIC_EVENT, - SOME_EVENT, - ANY_EVENT - }; - Event(EventType eventType) : m_eventType(eventType) {} - EventType eventType() { return m_eventType; } -private: - EventType m_eventType; -}; - -class ObjectTypeLayout; -class ObjectType; -typedef std::list ObjectTypeList; - -class LIBSAMPLE_API ObjectType -{ -public: - // ### Fixme: Use uintptr_t in C++ 11 - typedef size_t Identifier; - - explicit ObjectType(ObjectType* parent = 0); - virtual ~ObjectType(); - - // factory method - 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); - - inline Identifier identifier() const { return reinterpret_cast(this); } - - bool causeEvent(Event::EventType eventType); - - // Returns true if the event is processed. - virtual bool event(Event* event); - static int processEvent(ObjectTypeList objects, 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; } - - // 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); - - //Functions used in test with named arguments - void setObjectSplittedName(const char*, const Str& prefix = Str("")); - void setObjectNameWithSize(const char*, int size=9, const Str& name = Str("")); - void setObjectNameWithSize(const Str& name = Str(""), int size=9); - - //Function used to confuse the generator when two values accept Null as arg - void setObject(ObjectType *); - 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); - static std::size_t createObjectType(); - - //return a parent from C++ - ObjectType* getCppParent() { - if (!m_parent) { - ObjectType* parent = new ObjectType(); - setParent(parent); - } - return m_parent; - } - - void destroyCppParent() { - delete m_parent; - m_parent = 0; - } - - //Deprecated test - bool deprecatedFunction() { return true; } - - // 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; } - -private: - ObjectType(const ObjectType&); - ObjectType& operator=(const ObjectType&); - - ObjectTypeLayout* takeLayout(); - - Str m_objectName; - ObjectType* m_parent; - ObjectTypeList m_children; - - ObjectTypeLayout* m_layout; - - - //used on overload null test - int m_call_id; -}; - -LIBSAMPLE_API unsigned int objectTypeHash(const ObjectType* objectType); - -class LIBSAMPLE_API OtherBase { -public: - OtherBase() {}; - virtual ~OtherBase(); -}; - -class LIBSAMPLE_API ObjectTypeDerived: public ObjectType, public OtherBase { -public: - ObjectTypeDerived(): ObjectType(), OtherBase() {}; - - virtual bool event(Event* event); - virtual ~ObjectTypeDerived(); -}; - -#endif // OBJECTTYPE_H - diff --git a/tests/libsample/objecttypebyvalue.h b/tests/libsample/objecttypebyvalue.h deleted file mode 100644 index 1b61ec4dc..000000000 --- a/tests/libsample/objecttypebyvalue.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTTYPEBYVALUE_H -#define OBJECTTYPEBYVALUE_H -#include -#include "protected.h" - -class ObjectTypeByValue -{ -public: - ObjectTypeByValue returnSomeKindOfMe() { return ObjectTypeByValue(); } - void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe) {} - - void acceptListOfObjectTypeByValue(std::list listOfMe) {} - - // prop used to check for segfaults - ProtectedProperty prop; -}; - -#endif diff --git a/tests/libsample/objecttypeholder.cpp b/tests/libsample/objecttypeholder.cpp deleted file mode 100644 index dabeb2f86..000000000 --- a/tests/libsample/objecttypeholder.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objecttypeholder.h" - -ObjectTypeHolder::ObjectTypeHolder(const char* objectName) -{ - m_objectType = new ObjectType(); - m_objectType->setObjectName(objectName); -} - -ObjectTypeHolder::~ObjectTypeHolder() -{ - delete m_objectType; -} - -Str -ObjectTypeHolder::passObjectTypeAsReference(const ObjectType& objectType) -{ - return objectType.objectName(); -} - -Str -ObjectTypeHolder::callPassObjectTypeAsReference() -{ - return passObjectTypeAsReference(*m_objectType); -} diff --git a/tests/libsample/objecttypeholder.h b/tests/libsample/objecttypeholder.h deleted file mode 100644 index c2e7275d4..000000000 --- a/tests/libsample/objecttypeholder.h +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTTYPEHOLDER_H -#define OBJECTTYPEHOLDER_H - -#include "libsamplemacros.h" -#include "objecttype.h" -#include "str.h" - -class LIBSAMPLE_API ObjectTypeHolder -{ -public: - explicit ObjectTypeHolder(const char* objectName); - virtual ~ObjectTypeHolder(); - - ObjectType* getObjecType() { return m_objectType; } - - virtual Str passObjectTypeAsReference(const ObjectType& objectType); - Str callPassObjectTypeAsReference(); - -private: - ObjectType* m_objectType; -}; - -#endif diff --git a/tests/libsample/objecttypelayout.cpp b/tests/libsample/objecttypelayout.cpp deleted file mode 100644 index d2a7d1bba..000000000 --- a/tests/libsample/objecttypelayout.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objecttypelayout.h" -#include - -using namespace std; - -void ObjectTypeLayout::addObject(ObjectType* obj) -{ - if (obj->isLayoutType()) { - ObjectTypeLayout* l = reinterpret_cast(obj); - if (l->parent()) { - cerr << "[WARNING] ObjectTypeLayout::addObject: layout '" << l->objectName().cstring(); - cerr << "' already has a parent." << endl; - return; - } - - l->setParent(this); - - if (parent() && !parent()->isLayoutType()) - l->reparentChildren(parent()); - } - - m_objects.push_back(obj); -} - -std::list< ObjectType* > ObjectTypeLayout::objects() const -{ - return m_objects; -} - -void ObjectTypeLayout::reparentChildren(ObjectType* parent) -{ - std::list::const_iterator it = m_objects.begin(); - for (; it != m_objects.end(); ++it) { - if ((*it)->isLayoutType()) - reinterpret_cast(*it)->reparentChildren(parent); - else - (*it)->setParent(parent); - } -} - diff --git a/tests/libsample/objecttypelayout.h b/tests/libsample/objecttypelayout.h deleted file mode 100644 index 3fa8b9dbf..000000000 --- a/tests/libsample/objecttypelayout.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTTYPELAYOUT_H -#define OBJECTTYPELAYOUT_H - -#include "libsamplemacros.h" -#include "objecttype.h" -#include - -class ObjectType; - -class LIBSAMPLE_API ObjectTypeLayout : public ObjectType -{ -public: - void addObject(ObjectType* obj); - std::list objects() const; - - virtual bool isLayoutType() { return true; } - inline static ObjectTypeLayout* create() { return new ObjectTypeLayout(); } - - virtual ObjectType* takeChild(const Str& name) { return ObjectType::takeChild(name); } -private: - std::list m_objects; - - void reparentChildren(ObjectType* parent); - friend LIBSAMPLE_API void ObjectType::setLayout(ObjectTypeLayout* l); -}; - -#endif // OBJECTTYPELAYOUT_H - diff --git a/tests/libsample/objecttypeoperators.cpp b/tests/libsample/objecttypeoperators.cpp deleted file mode 100644 index 1bdaded30..000000000 --- a/tests/libsample/objecttypeoperators.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objecttypeoperators.h" - -ObjectTypeOperators::ObjectTypeOperators(const std::string key) : m_key(key) -{ -} - -bool ObjectTypeOperators::operator==(const ObjectTypeOperators& other) const -{ - return m_key == other.m_key; -} - -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) -{ - return obj->key() == str; -} - -bool operator==(const std::string& str, const ObjectTypeOperators* obj) -{ - return str == obj->key(); -} - -std::string operator+(const ObjectTypeOperators* obj, const std::string& str) -{ - return obj->key() + str; -} - -std::string operator+(const std::string& str, const ObjectTypeOperators* obj) -{ - return str + obj->key(); -} diff --git a/tests/libsample/objecttypeoperators.h b/tests/libsample/objecttypeoperators.h deleted file mode 100644 index 5795ac456..000000000 --- a/tests/libsample/objecttypeoperators.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTTYPEOPERATORS_H -#define OBJECTTYPEOPERATORS_H - -#include "libsamplemacros.h" -#include - -class LIBSAMPLE_API ObjectTypeOperators -{ -public: - explicit ObjectTypeOperators(const std::string key); - virtual ~ObjectTypeOperators() {} - - bool operator==(const ObjectTypeOperators& other) const; - const ObjectTypeOperators& operator<(const ObjectTypeOperators& other) const; - - // chaos! - 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); - -#endif // OBJECTTYPEOPERATORS_H diff --git a/tests/libsample/objectview.cpp b/tests/libsample/objectview.cpp deleted file mode 100644 index 08c5f45f6..000000000 --- a/tests/libsample/objectview.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "objectview.h" -#include "objectmodel.h" -#include "str.h" - -Str -ObjectView::displayModelData() -{ - if (!m_model) - return Str("(NULL)"); - return Str("Name: %VAR").arg(m_model->objectName()); -} - -void -ObjectView::modifyModelData(Str& data) -{ - if (m_model) - m_model->setObjectName(data); -} - - -ObjectType* -ObjectView::getRawModelData() -{ - return m_model->data(); -} - diff --git a/tests/libsample/objectview.h b/tests/libsample/objectview.h deleted file mode 100644 index 0bcc09a30..000000000 --- a/tests/libsample/objectview.h +++ /dev/null @@ -1,58 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OBJECTVIEW_H -#define OBJECTVIEW_H - -#include "objecttype.h" -#include "libsamplemacros.h" - -class Str; -class ObjectModel; - -class LIBSAMPLE_API ObjectView : public ObjectType -{ -public: - ObjectView(ObjectModel* model = 0, ObjectType* parent = 0) - : ObjectType(parent), m_model(model) - {} - - inline void setModel(ObjectModel* model) { m_model = model; } - inline ObjectModel* model() const { return m_model; } - - Str displayModelData(); - void modifyModelData(Str& data); - - ObjectType* getRawModelData(); - -private: - ObjectModel* m_model; -}; - -#endif // OBJECTVIEW_H - diff --git a/tests/libsample/oddbool.h b/tests/libsample/oddbool.h deleted file mode 100644 index ee0f4fa03..000000000 --- a/tests/libsample/oddbool.h +++ /dev/null @@ -1,83 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ODDBOOL_H -#define ODDBOOL_H - -#include "libsamplemacros.h" - -class OddBool -{ - -public: - inline explicit OddBool(bool b) : m_value(b) {} - bool value() const { return m_value; } - - inline OddBool operator!() const { return OddBool(!m_value); } - -private: - bool m_value; -}; - -inline bool operator==(OddBool b1, bool b2) { return (!b1).value() == !b2; } -inline bool operator==(bool b1, OddBool b2) { return (!b1) == (!b2).value(); } -inline bool operator==(OddBool b1, OddBool b2) { return (!b1).value() == (!b2).value(); } -inline bool operator!=(OddBool b1, bool b2) { return (!b1).value() != !b2; } -inline bool operator!=(bool b1, OddBool b2) { return (!b1) != (!b2).value(); } -inline bool operator!=(OddBool b1, OddBool b2) { return (!b1).value() != (!b2).value(); } - -class OddBoolUser -{ -public: - OddBoolUser() : m_oddbool(OddBool(false)) {} - OddBoolUser(const OddBool& oddBool) : m_oddbool(oddBool) {} - virtual ~OddBoolUser() {} - - inline OddBool oddBool() { return m_oddbool; } - inline void setOddBool(OddBool oddBool) { m_oddbool = oddBool; } - - virtual OddBool invertedOddBool() - { - return !m_oddbool; - } - - inline OddBool callInvertedOddBool() - { - return invertedOddBool(); - } - - static inline OddBool getOddBool(const OddBoolUser& oddBoolUser) - { - return oddBoolUser.m_oddbool; - } - -private: - OddBool m_oddbool; -}; - -#endif diff --git a/tests/libsample/onlycopy.cpp b/tests/libsample/onlycopy.cpp deleted file mode 100644 index 5407f9d33..000000000 --- a/tests/libsample/onlycopy.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "onlycopy.h" - -OnlyCopy::OnlyCopy(const OnlyCopy& other) -{ - m_value = other.m_value; -} - -OnlyCopy& -OnlyCopy::operator=(const OnlyCopy& other) -{ - m_value = other.m_value; - return *this; -} - -OnlyCopy -FriendOfOnlyCopy::createOnlyCopy(int value) -{ - - return OnlyCopy(value); -} - -std::list -FriendOfOnlyCopy::createListOfOnlyCopy(int quantity) -{ - std::list list; - for (int i = 0; i < quantity; ++i) - list.push_back(createOnlyCopy(i)); - return list; -} diff --git a/tests/libsample/onlycopy.h b/tests/libsample/onlycopy.h deleted file mode 100644 index 6abad7382..000000000 --- a/tests/libsample/onlycopy.h +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef ONLYCOPYCLASS_H -#define ONLYCOPYCLASS_H - -#include "libsamplemacros.h" -#include - -// These classes simulate a situation found in -// QtWebKit's QWebDatabase and QWebSecurityOrigin. - -class LIBSAMPLE_API OnlyCopy -{ -public: - OnlyCopy(const OnlyCopy& other); - OnlyCopy& operator=(const OnlyCopy& other); - int value() const { return m_value; } - static int getValue(OnlyCopy onlyCopy) { return onlyCopy.m_value; } - static int getValueFromReference(const OnlyCopy& onlyCopy) { return onlyCopy.m_value; } -private: - int m_value; - OnlyCopy(int value) : m_value(value) {}; - friend class FriendOfOnlyCopy; -}; - -class LIBSAMPLE_API FriendOfOnlyCopy -{ -public: - static OnlyCopy createOnlyCopy(int value); - static std::list createListOfOnlyCopy(int quantity); -}; - -#endif diff --git a/tests/libsample/overload.cpp b/tests/libsample/overload.cpp deleted file mode 100644 index 753407e35..000000000 --- a/tests/libsample/overload.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "overload.h" - -Overload::FunctionEnum Overload::overloaded() -{ - return Function0; -} - -Overload::FunctionEnum Overload::overloaded(Size* size) -{ - return Function1; -} - -Overload::FunctionEnum Overload::overloaded(Point* point, ParamEnum param) -{ - return Function2; -} - -Overload::FunctionEnum Overload::overloaded(const Point& point) -{ - return Function3; -} - diff --git a/tests/libsample/overload.h b/tests/libsample/overload.h deleted file mode 100644 index 5005b4f8c..000000000 --- a/tests/libsample/overload.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OVERLOAD_H -#define OVERLOAD_H - -#include "echo.h" -#include "str.h" -#include "size.h" -#include "point.h" -#include "pointf.h" -#include "polygon.h" -#include "rect.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Overload -{ -public: - enum FunctionEnum { - Function0, - Function1, - Function2, - Function3, - Function4, - Function5, - Function6 - }; - - enum ParamEnum { - Param0, - Param1 - }; - - Overload() {} - virtual ~Overload() {} - - FunctionEnum overloaded(); - 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; } - - 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; } - - inline FunctionEnum intDoubleOverloads(int a0, int a1) const { return Function0; } - inline FunctionEnum intDoubleOverloads(double a0, double a1) const { return Function1; } - - 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; } - - // Similar to QImage constructor - FunctionEnum strBufferOverloads(const Str& arg0, const char* arg1 = 0, bool arg2 = true) { return Function0; } - FunctionEnum strBufferOverloads(unsigned char* arg0, int arg1) { return Function1; } - 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; } - - // 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; } - - // 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; } - - // 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 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; } - // The type must be changed to PySequence. - FunctionEnum acceptSequence(const char* const a0[]) { return Function4; } - FunctionEnum acceptSequence(void* a0) { return Function5; } -}; - -class LIBSAMPLE_API Overload2 : public Overload -{ -public: - // test bug#616, public and private method differ only by const - void doNothingInPublic() const {} - void doNothingInPublic(int) {} - virtual void doNothingInPublic3() const {} - void doNothingInPublic3(int) const {} -protected: - void doNothingInPublic2() const {} - void doNothingInPublic2(int) {} -private: - void doNothingInPublic() {} - void doNothingInPublic2() {} - void doNothingInPublic3() {} -}; - -#endif // OVERLOAD_H - diff --git a/tests/libsample/overloadsort.cpp b/tests/libsample/overloadsort.cpp deleted file mode 100644 index f1bc9665b..000000000 --- a/tests/libsample/overloadsort.cpp +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "overloadsort.h" - diff --git a/tests/libsample/overloadsort.h b/tests/libsample/overloadsort.h deleted file mode 100644 index 9145504ae..000000000 --- a/tests/libsample/overloadsort.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OVERLOADSORT_H -#define OVERLOADSORT_H - -#include "libsamplemacros.h" - -#include - -class ImplicitTarget -{ -public: - ImplicitTarget(){} -}; - -class ImplicitBase -{ -public: - ImplicitBase(){} - ImplicitBase(const ImplicitTarget &b){} -}; - -class SortedOverload -{ -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 &x) { - return "list(ImplicitBase)"; - } - - inline int implicit_overload(const ImplicitBase &x) { - return 1; - } - - inline const char *overloadDeep(int x, ImplicitBase &y) { - return "ImplicitBase"; - } - - - inline const char* pyObjOverload(int, int) { return "int,int"; } - inline const char* pyObjOverload(unsigned char*, int) { return "PyObject,int"; } - -}; - -#endif // OVERLOADSORT_H - diff --git a/tests/libsample/pairuser.cpp b/tests/libsample/pairuser.cpp deleted file mode 100644 index b4b51b8cf..000000000 --- a/tests/libsample/pairuser.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "pairuser.h" - -using namespace std; - -std::pair -PairUser::callCreatePair() -{ - return createPair(); -} - -std::pair -PairUser::createPair() -{ - return std::pair(10, 20); -} - -std::pair -PairUser::createComplexPair(Complex cpx0, Complex cpx1) -{ - return std::pair(cpx0, cpx1); -} - -double -PairUser::sumPair(std::pair pair) -{ - return ((double) pair.first) + pair.second; -} - diff --git a/tests/libsample/pairuser.h b/tests/libsample/pairuser.h deleted file mode 100644 index 7b87ba65b..000000000 --- a/tests/libsample/pairuser.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PAIRUSER_H -#define PAIRUSER_H - -#include -#include "complex.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API PairUser -{ -public: - PairUser() {} - virtual ~PairUser() {} - - virtual std::pair createPair(); - std::pair callCreatePair(); - static std::pair createComplexPair(Complex cpx0, Complex cpx1); - double sumPair(std::pair pair); - - inline void setPair(std::pair pair) { m_pair = pair; } - inline std::pair getPair() { return m_pair; } - -private: - std::pair m_pair; -}; -#endif // PAIRUSER_H - diff --git a/tests/libsample/pen.cpp b/tests/libsample/pen.cpp deleted file mode 100644 index 509b47c76..000000000 --- a/tests/libsample/pen.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "pen.h" - -Color::Color() : m_null(true) -{ -} - -Color::Color(SampleNamespace::InValue arg) : m_null(false) -{ -} - -Color::Color(unsigned int arg) : m_null(false) -{ -} - -bool Color::isNull() const -{ - return m_null; -} - -Pen::Pen() : m_ctor(EmptyCtor) -{ -} - -Pen::Pen(SampleNamespace::Option option) : m_ctor(EnumCtor) -{ -} - -Pen::Pen(const Color& color) : m_ctor(ColorCtor) -{ -} - -Pen::Pen(const Pen& pen) : m_ctor(CopyCtor) -{ -} - -int Pen::ctorType() -{ - return m_ctor; -} diff --git a/tests/libsample/pen.h b/tests/libsample/pen.h deleted file mode 100644 index e1fb641d3..000000000 --- a/tests/libsample/pen.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PEN_H -#define PEN_H - -#include "libsamplemacros.h" -#include "samplenamespace.h" - -class LIBSAMPLE_API Color -{ -public: - Color(); - Color(SampleNamespace::InValue arg); - Color(unsigned int arg); - - bool isNull() const; -private: - bool m_null; -}; - -class LIBSAMPLE_API Pen -{ -public: - enum { EmptyCtor, EnumCtor, ColorCtor, CopyCtor }; - - Pen(); - Pen(SampleNamespace::Option option); - Pen(const Color& color); - Pen(const Pen& pen); - - int ctorType(); -private: - int m_ctor; -}; - -#endif diff --git a/tests/libsample/photon.cpp b/tests/libsample/photon.cpp deleted file mode 100644 index debc9f116..000000000 --- a/tests/libsample/photon.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "photon.h" - -namespace Photon -{ -const ClassType Base::staticType; -int callCalculateForValueDuplicatorPointer(ValueDuplicator* value) -{ - return value->calculate(); -} -int callCalculateForValueDuplicatorReference(ValueDuplicator& value) -{ - return value.calculate(); -} -int countValueIdentities(const std::list& values) -{ - return values.size(); -} -int countValueDuplicators(const std::list >& values) -{ - return values.size(); -} -} // namespace Photon diff --git a/tests/libsample/photon.h b/tests/libsample/photon.h deleted file mode 100644 index d8b1be423..000000000 --- a/tests/libsample/photon.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PHOTON_H -#define PHOTON_H - -#include -#include "libsamplemacros.h" - -// This namespace and classes simulate -// situations found in Qt's phonon module. - -namespace Photon -{ - -enum ClassType { - BaseType = 0, - IdentityType = 1, - DuplicatorType = 2 -}; - -class LIBSAMPLE_API Base -{ -public: - explicit Base(int value) : m_value(value) {} - virtual ~Base() {} - inline void setValue(int value) { m_value = value; } - inline int value() const { return m_value; } - - template bool isType() { return type() == T::staticType; } - bool isType(ClassType t) { return type() == t; } - - virtual ClassType type() const { return BaseType; }; - static const ClassType staticType = BaseType; - -protected: - int m_value; -}; - -template -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); } - static inline ClassType classType() { return CLASS_TYPE; } - - inline int sumValueUsingPointer(TemplateBase* other) const { return m_value + other->m_value; } - inline int sumValueUsingReference(TemplateBase& other) const { return m_value + other.m_value; } - - inline std::list > getListOfThisTemplateBase() - { - std::list > objs; - objs.push_back(*this); - objs.push_back(*this); - return objs; - } - - static inline TemplateBase* passPointerThrough(TemplateBase* obj) { return obj; } - - virtual ClassType type() const { return CLASS_TYPE; } - static const ClassType staticType = CLASS_TYPE; -}; - -#if defined _WIN32 || defined __CYGWIN__ -template class LIBSAMPLE_API TemplateBase; -template class LIBSAMPLE_API TemplateBase; -#endif - -typedef TemplateBase ValueIdentity; -typedef TemplateBase ValueDuplicator; - -LIBSAMPLE_API int callCalculateForValueDuplicatorPointer(ValueDuplicator* value); -LIBSAMPLE_API int callCalculateForValueDuplicatorReference(ValueDuplicator& value); -LIBSAMPLE_API int countValueIdentities(const std::list& values); -LIBSAMPLE_API int countValueDuplicators(const std::list >& 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 -class Pointer -{ -public: - Pointer() PHOTON_NOEXCEPT : px(0) {} - Pointer(int* p) : px(p) {} - - void reset() PHOTON_NOEXCEPT { Pointer().swap(*this); } - - int* get() const PHOTON_NOEXCEPT { return px; } - int& operator*() const { return *px; } - - void swap(Pointer& rhs) PHOTON_NOEXCEPT - { - int* tmp = px; - px = rhs.px; - rhs.px = tmp; - } - -private: - int* px; -}; - -} // namespace Photon - -#endif // PHOTON_H diff --git a/tests/libsample/point.cpp b/tests/libsample/point.cpp deleted file mode 100644 index 30275393b..000000000 --- a/tests/libsample/point.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "point.h" - -using namespace std; - -Point::Point(int x, int y) : m_x(x), m_y(y) -{ -} - -Point::Point(double x, double y) : m_x(x), m_y(y) -{ -} - -void -Point::midpoint(const Point& other, Point* midpoint) const -{ - if (!midpoint) - return; - midpoint->setX((m_x + other.m_x) / 2.0); - midpoint->setY((m_y + other.m_y) / 2.0); -} - -Point* -Point::copy() const -{ - Point* pt = new Point(); - pt->m_x = m_x; - pt->m_y = m_y; - return pt; -} - -void -Point::show() -{ - cout << "(x: " << m_x << ", y: " << m_y << ")"; -} - -bool -Point::operator==(const Point& other) -{ - return m_x == other.m_x && m_y == other.m_y; -} - -Point -Point::operator+(const Point& other) -{ - return Point(m_x + other.m_x, m_y + other.m_y); -} - -Point -Point::operator-(const Point& other) -{ - return Point(m_x - other.m_x, m_y - other.m_y); -} - -Point& -Point::operator+=(Point &other) -{ - m_x += other.m_x; - m_y += other.m_y; - return *this; -} - -Point& -Point::operator-=(Point &other) -{ - m_x -= other.m_x; - m_y -= other.m_y; - return *this; -} - -Point -operator*(const Point& pt, double mult) -{ - return Point(pt.m_x * mult, pt.m_y * mult); -} - -Point -operator*(const Point& pt, int mult) -{ - return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); -} - -Point -operator*(double mult, const Point& pt) -{ - return Point(pt.m_x * mult, pt.m_y * mult); -} - -Point -operator*(int mult, const Point& pt) -{ - return Point(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); -} - -Point -operator-(const Point& pt) -{ - return Point(-pt.m_x, -pt.m_y); -} - -bool -operator!(const Point& pt) -{ - return (pt.m_x == 0.0 && pt.m_y == 0.0); -} - -Point -Point::operator/(int operand) -{ - return Point(m_x/operand, m_y/operand); -} - -Complex -transmutePointIntoComplex(const Point& point) -{ - Complex cpx(point.x(), point.y()); - return cpx; -} - -Point -transmuteComplexIntoPoint(const Complex& cpx) -{ - Point pt(cpx.real(), cpx.imag()); - return pt; -} - diff --git a/tests/libsample/point.h b/tests/libsample/point.h deleted file mode 100644 index 9416d6ddf..000000000 --- a/tests/libsample/point.h +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef POINT_H -#define POINT_H - -#include "complex.h" -#include - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Point -{ -public: - Point(int x = 0, int y = 0); - Point(double x, double y); - ~Point() {} - - inline double x() const { return m_x; } - inline double y() const { return m_y; } - - inline void setX(double x) { m_x = x; } - inline void setY(double y) { m_y = y; } - inline void setXAsUint(unsigned int x) { m_x = x; } - inline void setYAsUint(unsigned int y) { m_y = y; } - - // 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; - - Point* copy() const; - - 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); - - 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); - - Point& operator+=(Point &other); - Point& operator-=(Point &other); - - void show(); - -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 Complex transmutePointIntoComplex(const Point& point); -LIBSAMPLE_API Point transmuteComplexIntoPoint(const Complex& cpx); - -LIBSAMPLE_API Point operator*(const Point& pt, double multiplier); - -#endif // POINT_H diff --git a/tests/libsample/pointerholder.h b/tests/libsample/pointerholder.h deleted file mode 100644 index 84e709d38..000000000 --- a/tests/libsample/pointerholder.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef POINTERHOLDER_H -#define POINTERHOLDER_H - -#include "libsamplemacros.h" - -class PointerHolder -{ -public: - explicit PointerHolder(void* ptr) : m_pointer(ptr) {} - ~PointerHolder() {} - inline void* pointer() const { return m_pointer; } -private: - void* m_pointer; -}; - -#endif // POINTERHOLDER_H - diff --git a/tests/libsample/pointf.cpp b/tests/libsample/pointf.cpp deleted file mode 100644 index 0719bdb87..000000000 --- a/tests/libsample/pointf.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "pointf.h" - -using namespace std; - -PointF::PointF(const Point& point) : m_x(point.x()), m_y(point.y()) -{ -} - -PointF::PointF(double x, double y) : m_x(x), m_y(y) -{ -} - -void -PointF::midpoint(const PointF& other, PointF* midpoint) const -{ - if (!midpoint) - return; - midpoint->setX((m_x + other.m_x) / 2.0); - midpoint->setY((m_y + other.m_y) / 2.0); -} - -void -PointF::show() -{ - cout << "(x: " << m_x << ", y: " << m_y << ")"; -} - -bool -PointF::operator==(const PointF& other) -{ - return m_x == other.m_x && m_y == other.m_y; -} - -PointF -PointF::operator+(const PointF& other) -{ - return PointF(m_x + other.m_x, m_y + other.m_y); -} - -PointF -PointF::operator-(const PointF& other) -{ - return PointF(m_x - other.m_x, m_y - other.m_y); -} - -PointF& -PointF::operator+=(PointF &other) -{ - m_x += other.m_x; - m_y += other.m_y; - return *this; -} - -PointF& -PointF::operator-=(PointF &other) -{ - m_x -= other.m_x; - m_y -= other.m_y; - return *this; -} - -PointF -operator*(const PointF& pt, double mult) -{ - return PointF(pt.m_x * mult, pt.m_y * mult); -} - -PointF -operator*(const PointF& pt, int mult) -{ - return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); -} - -PointF -operator*(double mult, const PointF& pt) -{ - return PointF(pt.m_x * mult, pt.m_y * mult); -} - -PointF -operator*(int mult, const PointF& pt) -{ - return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); -} - -PointF -operator-(const PointF& pt) -{ - return PointF(-pt.m_x, -pt.m_y); -} - -bool -operator!(const PointF& pt) -{ - return (pt.m_x == 0.0 && pt.m_y == 0.0); -} - diff --git a/tests/libsample/pointf.h b/tests/libsample/pointf.h deleted file mode 100644 index c80739fea..000000000 --- a/tests/libsample/pointf.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef POINTF_H -#define POINTF_H - -#include "point.h" -#include - -#include "libsamplemacros.h" - -class LIBSAMPLE_API PointF -{ -public: - PointF(const Point& point); - PointF(double x = 0.0, double y = 0.0); - ~PointF() {} - - inline double x() const { return m_x; } - inline double y() const { return m_y; } - - inline void setX(double x) { m_x = x; } - inline void setY(double y) { m_y = y; } - - // 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; - - // 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); - - 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); - - PointF& operator+=(PointF &other); - PointF& operator-=(PointF &other); - - void show(); - -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 multiplier); - -#endif // POINTF_H diff --git a/tests/libsample/polygon.cpp b/tests/libsample/polygon.cpp deleted file mode 100644 index cb553a75c..000000000 --- a/tests/libsample/polygon.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "polygon.h" - -using namespace std; - -Polygon::Polygon(double x, double y) -{ - m_points.push_back(Point(x, y)); -} - -Polygon::Polygon(Point point) -{ - m_points.push_back(point); -} - -Polygon::Polygon(PointList points) -{ - m_points = points; -} - -void -Polygon::addPoint(Point point) -{ - m_points.push_back(point); -} - -Polygon -Polygon::doublePolygonScale(Polygon polygon) -{ - Polygon result; - for(PointList::const_iterator piter = result.points().begin(); piter != result.points().end(); piter++) - result.addPoint((*piter) * 2.0); - return result; -} - -void -Polygon::stealOwnershipFromPython(Point* point) -{ - delete point; -} - -void -Polygon::stealOwnershipFromPython(Polygon* polygon) -{ - delete polygon; -} - diff --git a/tests/libsample/polygon.h b/tests/libsample/polygon.h deleted file mode 100644 index 5e0769e0f..000000000 --- a/tests/libsample/polygon.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef POLYGON_H -#define POLYGON_H - -#include -#include "point.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Polygon -{ -public: - typedef std::list PointList; - - Polygon() {} - Polygon(double x, double y); - Polygon(Point point); - Polygon(PointList points); - ~Polygon() {} - - void addPoint(Point point); - - 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); - - // This method invalidates the argument to be used in a call to doublePolygonScale(Polygon). - static void stealOwnershipFromPython(Polygon* polygon); - -private: - PointList m_points; -}; - -#endif // POLYGON_H - diff --git a/tests/libsample/privatector.h b/tests/libsample/privatector.h deleted file mode 100644 index 4f4699761..000000000 --- a/tests/libsample/privatector.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PRIVATECTOR_H -#define PRIVATECTOR_H - -#include "libsamplemacros.h" - -class PrivateCtor -{ -public: - inline static PrivateCtor* instance() - { - static PrivateCtor self; - self.m_instanciations++; - return &self; - } - - inline int instanceCalls() - { - return m_instanciations; - } - -private: - int m_instanciations; - - PrivateCtor() : m_instanciations(0) {} -}; - -#endif diff --git a/tests/libsample/privatedtor.h b/tests/libsample/privatedtor.h deleted file mode 100644 index a0c4d4769..000000000 --- a/tests/libsample/privatedtor.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PRIVATEDTOR_H -#define PRIVATEDTOR_H - -#include "libsamplemacros.h" - -class PrivateDtor -{ -public: - inline static PrivateDtor* instance() - { - static PrivateDtor self; - self.m_instanciations++; - return &self; - } - - inline int instanceCalls() - { - return m_instanciations; - } - -protected: - inline int protectedInstanceCalls() { return m_instanciations; } - -private: - int m_instanciations; - - PrivateDtor() : m_instanciations(0) {} - PrivateDtor(const PrivateDtor&) {} - ~PrivateDtor() {} -}; - -#endif diff --git a/tests/libsample/protected.cpp b/tests/libsample/protected.cpp deleted file mode 100644 index 08c9fd065..000000000 --- a/tests/libsample/protected.cpp +++ /dev/null @@ -1,32 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "protected.h" - -int ProtectedVirtualDestructor::dtor_called = 0; - diff --git a/tests/libsample/protected.h b/tests/libsample/protected.h deleted file mode 100644 index c33bdf4b2..000000000 --- a/tests/libsample/protected.h +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef PROTECTED_H -#define PROTECTED_H - -#include "libsamplemacros.h" -#include "objecttype.h" -#include "point.h" -#include -#include - -class LIBSAMPLE_API ProtectedNonPolymorphic -{ -public: - explicit ProtectedNonPolymorphic(const char *name) : m_name(name) {} - ~ProtectedNonPolymorphic() {} - - inline const char* publicName() { return m_name.c_str(); } - - inline static ProtectedNonPolymorphic* create() { return new ProtectedNonPolymorphic("created"); } - -protected: - 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 = 0) const { return "pointer"; } - inline const char* dataTypeName(int data) const { return "integer"; } - -private: - std::string m_name; -}; - -class LIBSAMPLE_API ProtectedPolymorphic -{ -public: - explicit ProtectedPolymorphic(const char *name) : m_name(name) {} - virtual ~ProtectedPolymorphic() {} - - 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(); } - -private: - std::string m_name; -}; - -class LIBSAMPLE_API ProtectedPolymorphicDaughter : public ProtectedPolymorphic -{ -public: - 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"); } -}; - -class LIBSAMPLE_API ProtectedVirtualDestructor -{ -public: - ProtectedVirtualDestructor() {} - inline static ProtectedVirtualDestructor* create() { return new ProtectedVirtualDestructor(); } - inline static int dtorCalled() { return dtor_called; } - inline static void resetDtorCounter() { dtor_called = 0; } -protected: - virtual ~ProtectedVirtualDestructor() { dtor_called++; } -private: - static int dtor_called; -}; - -class LIBSAMPLE_API ProtectedEnumClass -{ -public: - ProtectedEnumClass() {} - virtual ~ProtectedEnumClass() {} - enum PublicEnum { - PublicItem0, - PublicItem1 - }; -protected: - enum ProtectedEnum { - ProtectedItem0, - ProtectedItem1 - }; - 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(0), - protectedObjectTypeProperty(0) - {} -protected: - // This is deliberately the first member to test wrapper registration - // for value type members sharing the same memory address. - Point protectedValueTypeProperty; - int protectedProperty; - std::list protectedContainerProperty; - Event::EventType protectedEnumProperty; - Point* protectedValueTypePointerProperty; - ObjectType* protectedObjectTypeProperty; -}; - -LIBSAMPLE_API inline ProtectedProperty* createProtectedProperty() { - return new ProtectedProperty; -} - -#endif // PROTECTED_H diff --git a/tests/libsample/rect.h b/tests/libsample/rect.h deleted file mode 100644 index b7ce6e890..000000000 --- a/tests/libsample/rect.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef RECT_H -#define RECT_H - -#include "libsamplemacros.h" - -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) - : m_left(left), m_top(top), m_right(right), m_bottom(bottom) { } - ~Rect() {} - 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; -}; - -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) - : 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() {} - 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; -}; - -#endif // RECT_H - diff --git a/tests/libsample/reference.cpp b/tests/libsample/reference.cpp deleted file mode 100644 index 31a11a8ae..000000000 --- a/tests/libsample/reference.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "reference.h" - -using namespace std; - -void -Reference::show() const -{ - cout << "Reference.objId: " << m_objId << ", address: " << this; -} - -int -Reference::usesReferenceVirtual(Reference& r, int inc) -{ - return r.m_objId + inc; -} - -int -Reference::usesConstReferenceVirtual(const Reference& r, int inc) -{ - return r.m_objId + inc; -} - -int -Reference::callUsesReferenceVirtual(Reference& r, int inc) -{ - return usesReferenceVirtual(r, inc); -} - -int -Reference::callUsesConstReferenceVirtual(const Reference& r, int inc) -{ - return usesConstReferenceVirtual(r, inc); -} - -void -Reference::alterReferenceIdVirtual(Reference& r) -{ - r.setObjId(r.objId() * Reference::multiplier()); -} - -void -Reference::callAlterReferenceIdVirtual(Reference& r) -{ - alterReferenceIdVirtual(r); -} - -ObjTypeReference::~ObjTypeReference() -{ -} diff --git a/tests/libsample/reference.h b/tests/libsample/reference.h deleted file mode 100644 index 4ec8ee7fd..000000000 --- a/tests/libsample/reference.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef REFERENCE_H -#define REFERENCE_H - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Reference -{ -public: - explicit Reference(int objId = -1) - : m_objId(objId) {} - virtual ~Reference() {} - - inline int objId() { 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; } - - 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); - - 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; } - - // nonsense operator to test if Shiboken is ignoring dereference operators. - int operator*() { return m_objId; } -private: - int m_objId; -}; - -class LIBSAMPLE_API ObjTypeReference -{ -public: - ObjTypeReference() {} - ObjTypeReference(const ObjTypeReference&) {} - virtual ~ObjTypeReference(); - virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; } - virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; } - virtual ObjTypeReference& justAPureVirtualFunc(ObjTypeReference& ref) = 0; -}; - -#endif // REFERENCE_H - diff --git a/tests/libsample/removednamespaces.h b/tests/libsample/removednamespaces.h deleted file mode 100644 index 4520b6a27..000000000 --- a/tests/libsample/removednamespaces.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef REMOVEDNAMESPACE_H -#define REMOVEDNAMESPACE_H - -#include "libsamplemacros.h" - -namespace RemovedNamespace1 -{ - -enum RemovedNamespace1_Enum { - RemovedNamespace1_Enum_Value0 -}; - -enum { - RemovedNamespace1_AnonymousEnum_Value0 -}; - -namespace RemovedNamespace2 { - enum RemovedNamespace2_Enum { - RemovedNamespace2_Enum_Value0 - }; -} - -} - -namespace UnremovedNamespace -{ -namespace RemovedNamespace3 -{ - enum RemovedNamespace3_Enum { - RemovedNamespace3_Enum_Value0 - }; - - enum { - RemovedNamespace3_AnonymousEnum_Value0 - }; -} -} - -#endif // REMOVEDNAMESPACE_H - diff --git a/tests/libsample/sample.cpp b/tests/libsample/sample.cpp deleted file mode 100644 index fa1e1fda3..000000000 --- a/tests/libsample/sample.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sample.h" - -sample::sample::sample(int value) : m_value(value) -{ -} - -int sample::sample::value() const -{ - return m_value; -} - diff --git a/tests/libsample/sample.h b/tests/libsample/sample.h deleted file mode 100644 index 46e3d0d1a..000000000 --- a/tests/libsample/sample.h +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SAMPLE_H -#define SAMPLE_H - -#include "libsamplemacros.h" - -// namespace with the same name of the current package to try to mess up with the generator -namespace sample -{ - // to increase the mess we add a class with the same name of the package/namespace - class LIBSAMPLE_API sample - { - public: - sample(int value = 0); - int value() const; - private: - int m_value; - }; -} - -#endif diff --git a/tests/libsample/samplenamespace.cpp b/tests/libsample/samplenamespace.cpp deleted file mode 100644 index 1fc6dff40..000000000 --- a/tests/libsample/samplenamespace.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "samplenamespace.h" - -using namespace std; - -namespace SampleNamespace -{ - -OutValue -enumInEnumOut(InValue in) -{ - OutValue retval; - switch(in) { - case ZeroIn: - retval = ZeroOut; - break; - case OneIn: - retval = OneOut; - break; - case TwoIn: - retval = TwoOut; - break; - default: - retval = (OutValue) -1; - } - return retval; -} - -Option -enumArgumentWithDefaultValue(Option opt) -{ - return opt; -} - -int -getNumber(Option opt) -{ - int retval; - switch(opt) { - case RandomNumber: - retval = rand() % 100; - break; - case UnixTime: - retval = (int) time(0); - break; - default: - retval = 0; - } - return retval; -} - -void -doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format) -{ - // 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) -{ - return value; -} - -void -forceDecisorSideA(ObjectType* object) -{ -} - -void -forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object) -{ -} - -void -forceDecisorSideB(int a, ObjectType* object) -{ -} - -void -forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object) -{ -} - -double -passReferenceToValueType(const Point& point, double multiplier) -{ - return (point.x() + point.y()) * multiplier; -} - -int -passReferenceToObjectType(const ObjectType& obj, int multiplier) -{ - return obj.objectName().size() * multiplier; -} - -} // namespace SampleNamespace diff --git a/tests/libsample/samplenamespace.h b/tests/libsample/samplenamespace.h deleted file mode 100644 index 3ce410941..000000000 --- a/tests/libsample/samplenamespace.h +++ /dev/null @@ -1,162 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SAMPLENAMESPACE_H -#define SAMPLENAMESPACE_H - -#include -#include "libsamplemacros.h" -#include "str.h" -#include "point.h" -#include "objecttype.h" - -// Anonymous global enum -enum { - AnonymousGlobalEnum_Value0, - AnonymousGlobalEnum_Value1 -}; - -// Invisible namespace -namespace Invisible -{ - -enum EnumOnNamespace { - Option1 = 1, - Option2 = 2, - Option3 = 3 -}; - -}; - -namespace SampleNamespace -{ - -enum Option { - None_, - RandomNumber, - UnixTime -}; - -enum InValue { - ZeroIn, - OneIn, - TwoIn -}; - -enum OutValue { - ZeroOut, - OneOut, - TwoOut -}; - -// Anonymous non-global enum. -// This counts as a class enum, since C++ namespaces -// are represented as classes in Python. -enum { - AnonymousClassEnum_Value0, - AnonymousClassEnum_Value1 -}; - -LIBSAMPLE_API OutValue enumInEnumOut(InValue in); - -LIBSAMPLE_API Option enumArgumentWithDefaultValue(Option opt = UnixTime); - -LIBSAMPLE_API int getNumber(Option opt); - -inline double powerOfTwo(double num) { - return num * num; -} - -LIBSAMPLE_API void doSomethingWithArray(const unsigned char* data, unsigned int size, const char* format = 0); - -LIBSAMPLE_API int enumItemAsDefaultValueToIntArgument(int value = ZeroIn); - -class SomeClass -{ -public: - class SomeInnerClass - { - public: - class OkThisIsRecursiveEnough - { - public: - virtual ~OkThisIsRecursiveEnough() {} - enum NiceEnum { - NiceValue1, NiceValue2 - }; - - inline int someMethod(SomeInnerClass*) { return 0; } - virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } - }; - protected: - enum ProtectedEnum { - ProtectedItem0, - ProtectedItem1 - }; - }; - struct SomeOtherInnerClass { - std::list someInnerClasses; - }; -protected: - enum ProtectedEnum { - ProtectedItem0, - ProtectedItem1 - }; -}; - -class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough -{ -public: - // FIXME Uncomment this when the fix for MSVC is available - // only to cause namespace confusion -// enum SampleNamespace { -// }; - virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } - inline OkThisIsRecursiveEnough* methodReturningTypeFromParentScope() { return 0; } -}; - -// 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 = 0); -LIBSAMPLE_API void forceDecisorSideA(const Point& pt, const Str& text, ObjectType* object = 0); - -// 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 = 0); -LIBSAMPLE_API void forceDecisorSideB(int a, const Point& pt, const Str& text, ObjectType* object = 0); - -// Add a new signature on type system with only a Point value as parameter. -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); - -} // namespace SampleNamespace - -#endif // SAMPLENAMESPACE_H - diff --git a/tests/libsample/sbkdate.cpp b/tests/libsample/sbkdate.cpp deleted file mode 100644 index e823521ec..000000000 --- a/tests/libsample/sbkdate.cpp +++ /dev/null @@ -1,48 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sbkdate.h" - -SbkDate::SbkDate(int d, int m, int y) : m_d(d), m_m(m), m_y(y) -{ -} - -int SbkDate::day() const -{ - return m_d; -} - -int SbkDate::month() const -{ - return m_m; -} - -int SbkDate::year() const -{ - return m_y; -} diff --git a/tests/libsample/sbkdate.h b/tests/libsample/sbkdate.h deleted file mode 100644 index 7d0893cbb..000000000 --- a/tests/libsample/sbkdate.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SBKDATE_H -#define SBKDATE_H - -#include "libsamplemacros.h" - -class LIBSAMPLE_API SbkDate -{ -public: - SbkDate(int d, int m, int y); - - int day() const; - int month() const; - int year() const; - -private: - int m_d; - int m_m; - int m_y; -}; - -#endif // SBKDATE_H - diff --git a/tests/libsample/simplefile.cpp b/tests/libsample/simplefile.cpp deleted file mode 100644 index bdbd3d1f5..000000000 --- a/tests/libsample/simplefile.cpp +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include "simplefile.h" - -class SimpleFile_p -{ -public: - SimpleFile_p(const char* filename) : m_descriptor(0), m_size(0) - { - m_filename = strdup(filename); - } - - ~SimpleFile_p() - { - free(m_filename); - } - - char* m_filename; - FILE* m_descriptor; - long m_size; -}; - -SimpleFile::SimpleFile(const char* filename) -{ - p = new SimpleFile_p(filename); -} - -SimpleFile::~SimpleFile() -{ - close(); - delete p; -} - -const char* SimpleFile::filename() -{ - return p->m_filename; -} - -long SimpleFile::size() -{ - return p->m_size; -} - -bool -SimpleFile::open() -{ - if ((p->m_descriptor = fopen(p->m_filename, "rb")) == 0) - return false; - - fseek(p->m_descriptor, 0, SEEK_END); - p->m_size = ftell(p->m_descriptor); - rewind(p->m_descriptor); - - return true; -} - -void -SimpleFile::close() -{ - if (p->m_descriptor) { - fclose(p->m_descriptor); - p->m_descriptor = 0; - } -} - -bool -SimpleFile::exists() const -{ - std::ifstream ifile(p->m_filename); - return !ifile.fail(); -} - -bool -SimpleFile::exists(const char* filename) -{ - std::ifstream ifile(filename); - return !ifile.fail(); -} - diff --git a/tests/libsample/simplefile.h b/tests/libsample/simplefile.h deleted file mode 100644 index bae3b9998..000000000 --- a/tests/libsample/simplefile.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SIMPLEFILE_H -#define SIMPLEFILE_H - -#include "libsamplemacros.h" -#include - -class SimpleFile_p; - -class LIBSAMPLE_API SimpleFile -{ -public: - explicit SimpleFile(const char* filename); - ~SimpleFile(); - - const char* filename(); - long size(); - bool open(); - void close(); - - bool exists() const; - static bool exists(const char* filename); - -private: - SimpleFile_p *p; -}; - -#endif // SIMPLEFILE_H - diff --git a/tests/libsample/size.cpp b/tests/libsample/size.cpp deleted file mode 100644 index 1faf5dfb2..000000000 --- a/tests/libsample/size.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "size.h" - -using namespace std; - -void -Size::show() const -{ - cout << "(width: " << m_width << ", height: " << m_height << ")"; -} - diff --git a/tests/libsample/size.h b/tests/libsample/size.h deleted file mode 100644 index 433aba770..000000000 --- a/tests/libsample/size.h +++ /dev/null @@ -1,206 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SIZE_H -#define SIZE_H - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Size -{ -public: - Size(double width = 0.0, double height = 0.0) : m_width(width), m_height(height) {} - ~Size() {} - - inline double width() { return m_width; } - inline void setWidth(double width) { m_width = width; } - inline double height() { 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) - { - return m_width == other.m_width && m_height == other.m_height; - } - - inline bool operator<(const Size& other) - { - return calculateArea() < other.calculateArea(); - } - - 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 - // simplify comparison expressions by putting partial results in - // variables. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323#c109 - // for details. - double a = calculateArea(); - double b = other.calculateArea(); - return a > b; - } - - inline bool operator<=(const Size& other) - { - // See comments for operator>() - double a = calculateArea(); - double b = other.calculateArea(); - return a <= b; - } - - inline bool operator>=(const Size& other) - { - return calculateArea() >= other.calculateArea(); - } - - inline bool operator<(double area) { return calculateArea() < area; } - inline bool operator>(double area) { return calculateArea() > area; } - inline bool operator<=(double area) { return calculateArea() <= area; } - inline bool operator>=(double area) { return calculateArea() >= area; } - - // Arithmetic Operators - inline Size& operator+=(const Size& s) - { - m_width += s.m_width; - m_height += s.m_height; - return *this; - } - - inline Size& operator-=(const Size& s) - { - m_width -= s.m_width; - m_height -= s.m_height; - return *this; - } - - inline Size& operator*=(double mult) - { - m_width *= mult; - m_height *= mult; - return *this; - } - - inline Size& operator/=(double div) - { - m_width /= div; - m_height /= div; - return *this; - } - - // TODO: add ++size, size++, --size, size-- - - // External operators - 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 bool operator<(double, const Size&); - friend inline bool operator>(double, const Size&); - friend inline bool operator<=(double, const Size&); - friend inline bool operator>=(double, const Size&); - - void show() const; - -private: - double m_width; - double m_height; -}; - -// Comparison Operators -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) -{ - return area < s.calculateArea(); -} - -inline bool operator>(double area, const Size& s) -{ - return area > s.calculateArea(); -} - -inline bool operator<=(double area, const Size& s) -{ - return area <= s.calculateArea(); -} - -inline bool operator>=(double area, const Size& s) -{ - return area >= s.calculateArea(); -} - -// Arithmetic Operators -inline const 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) -{ - return Size(s1.m_width - s2.m_width, s1.m_height - s2.m_height); -} - -inline const 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) -{ - return Size(s.m_width * mult, s.m_height * mult); -} - -inline const Size operator/(const Size& s, double div) -{ - return Size(s.m_width / div, s.m_height / div); -} - -typedef double real; -typedef unsigned short ushort; -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; } - static inline ushort passTypedefOfUnsignedShort(ushort value) { return value; } -private: - real m_width; - real m_height; -}; - -#endif // SIZE_H - diff --git a/tests/libsample/sometime.cpp b/tests/libsample/sometime.cpp deleted file mode 100644 index 3038e26ca..000000000 --- a/tests/libsample/sometime.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sometime.h" -#include - -void -Time::setTime() -{ - m_hour = 0; - m_minute = 0; - m_second = 0; - m_msec = 0; - m_is_null = true; -} - -void -Time::setTime(int h, int m, int s, int ms) -{ - m_hour = h; - m_minute = m; - m_second = s; - m_msec = ms; - m_is_null = false; -} - - -Time::NumArgs -Time::somethingCompletelyDifferent() -{ - return ZeroArgs; -} - -Time::NumArgs -Time::somethingCompletelyDifferent(int h, int m, ImplicitConv ic, ObjectType* type) -{ - if (type) - return FourArgs; - if (ic.ctorEnum() == ImplicitConv::CtorThree && ic.objId() == -1) - return TwoArgs; - return ThreeArgs; -} - -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); - return Str(buffer); -} - -bool -Time::operator==(const Time& other) const -{ - return m_hour == other.m_hour - && m_minute == other.m_minute - && m_second == other.m_second - && m_msec == other.m_msec - && m_is_null == other.m_is_null; -} - -bool -Time::operator!=(const Time& other) const -{ - return !operator==(other); -} - -Time::operator Str() const -{ - return Time::toString(); -} - diff --git a/tests/libsample/sometime.h b/tests/libsample/sometime.h deleted file mode 100644 index 5f2ccf88a..000000000 --- a/tests/libsample/sometime.h +++ /dev/null @@ -1,92 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SOMETIME_H -#define SOMETIME_H - -#include "libsamplemacros.h" -#include "str.h" -#include "implicitconv.h" -#include "objecttype.h" - -class LIBSAMPLE_API Time -{ -public: - enum NumArgs { - ZeroArgs, - TwoArgs, - ThreeArgs, - 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() {} - - inline bool isNull() const { return m_is_null; } - - inline int hour() const { return m_hour; } - inline int minute() const { return m_minute; } - inline int second() const { return m_second; } - inline int msec() const { return m_msec; } - - void setTime(); - void setTime(int h, int m, int s = 0, int ms = 0); - - // This one is completely different from the other methods in this class, - // it was added to give the overload decisor a really hard time with - // an value-type with implicit conversion and a default argument, and also - // an object-type, just because I feel like it. - NumArgs somethingCompletelyDifferent(); - NumArgs somethingCompletelyDifferent(int h, int m, - ImplicitConv ic = ImplicitConv::CtorThree, - ObjectType* type = 0); - - Str toString() 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; - - bool m_is_null; -}; - -#endif // SOMETIME_H - diff --git a/tests/libsample/str.cpp b/tests/libsample/str.cpp deleted file mode 100644 index f3be2591e..000000000 --- a/tests/libsample/str.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "str.h" -#include -#include -#include -#include - -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) -{ - init(cstr); -} - -void -Str::init(const char* cstr) -{ - if (cstr) - m_str = cstr; -} - -Str::~Str() -{ -} - -Str -Str::arg(const Str& s) const -{ - size_t idx = m_str.find_first_of("%VAR"); - if (idx == std::string::npos) { - return *this; - } else { - std::string result = m_str; - result.replace(idx, 4, s.m_str); - return result.c_str(); - } -} - -Str& -Str::append(const Str& s) -{ - m_str += s.m_str; - return *this; -} - -Str& -Str::prepend(const Str& s) -{ - m_str = s.m_str + m_str; - return *this; -} - -const char* -Str::cstring() const -{ - return m_str.c_str(); -} - -int -Str::toInt(bool* ok, int base) const -{ - bool my_ok; - int result = 0; - 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; - } - my_ok = istringstream::eofbit & conv.rdstate(); - if (!my_ok) - result = 0; - if (ok) - *ok = my_ok; - return result; -} - -void -Str::show() const -{ - printf("%s", cstring()); -} - -char -Str::get_char(int pos) const -{ - return m_str[pos]; -} - -bool -Str::set_char(int pos, char ch) -{ - m_str[pos] = ch; - return true; -} - -Str Str::operator+(int number) const -{ - ostringstream in; - in << m_str << number; - return in.str().c_str(); -} - -bool Str::operator==(const Str& other) const -{ - return m_str == other.m_str; -} - -Str operator+(int number, const Str& str) -{ - ostringstream in; - in << number << str.m_str; - return in.str().c_str(); -} - -bool Str::operator<(const Str& other) const -{ - return m_str < other.m_str; -} - -unsigned int strHash(const Str& str) -{ - unsigned int result = 0; - const std::string& cppStr = str.m_str; - std::string::const_iterator it = cppStr.begin(); - for (; it != cppStr.end(); ++it) - result = 5 * result + *it; - return result; -} - -void changePStr(PStr* pstr, const char* suffix) -{ - pstr->append(suffix); -} - -void duplicatePStr(PStr* pstr) -{ - if (!pstr) - return; - pstr->append(*pstr); -} diff --git a/tests/libsample/str.h b/tests/libsample/str.h deleted file mode 100644 index 9c1e8c0a8..000000000 --- a/tests/libsample/str.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef STR_H -#define STR_H -#include - -#include "libsamplemacros.h" - -class LIBSAMPLE_API Str -{ -public: - Str(const Str& s); - Str(char c); - Str(const char* cstr = ""); - ~Str(); - - Str arg(const Str& s) const; - - Str& append(const Str& s); - Str& prepend(const Str& s); - - const char* cstring() const; - char get_char(int pos) const; - bool set_char(int pos, char ch); - - int toInt(bool* ok = 0, int base = 10) const; - - void show() const; - - inline int size() const { return 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; - -private: - 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); -}; - -LIBSAMPLE_API Str operator+(int number, const Str& str); -LIBSAMPLE_API unsigned int strHash(const Str& str); - -typedef Str PStr; -LIBSAMPLE_API void changePStr(PStr* pstr, const char* suffix); -LIBSAMPLE_API void duplicatePStr(PStr* pstr = 0); - -#endif // STR_H diff --git a/tests/libsample/strlist.cpp b/tests/libsample/strlist.cpp deleted file mode 100644 index 8956110d8..000000000 --- a/tests/libsample/strlist.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "strlist.h" - -bool -StrList::operator==(const std::list& other) const -{ - if (size() != other.size()) - return false; - StrList::const_iterator this_it = begin(); - StrList::const_iterator other_it = begin(); - while (this_it != end()) { - if (!((*this_it) == (*other_it))) - return false; - ++this_it; - ++other_it; - } - return true; -} - -Str -StrList::join(const Str& sep) const -{ - Str result; - for (StrList::const_iterator it = begin(); it != end(); ++it) { - if (it != begin()) - result.append(sep); - result.append(*it); - } - return result; -} diff --git a/tests/libsample/strlist.h b/tests/libsample/strlist.h deleted file mode 100644 index be908d5d5..000000000 --- a/tests/libsample/strlist.h +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef STRLIST_H -#define STRLIST_H - -#include -#include "str.h" - -#include "libsamplemacros.h" - -class LIBSAMPLE_API StrList : public std::list -{ -public: - enum CtorEnum { - NoParamsCtor, - StrCtor, - CopyCtor, - 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(lst), m_ctorUsed(CopyCtor) {} - inline StrList(const std::list& lst) : std::list(lst), m_ctorUsed(ListOfStrCtor) {} - - inline void append(Str str) { push_back(str); } - Str join(const Str& sep) const; - - bool operator==(const std::list& other) const; - inline bool operator!=(const std::list& other) const { return !(*this == other); } - - CtorEnum constructorUsed() { return m_ctorUsed; } -private: - CtorEnum m_ctorUsed; -}; - -typedef StrList PStrList; - -#endif // STRLIST_H diff --git a/tests/libsample/templateptr.cpp b/tests/libsample/templateptr.cpp deleted file mode 100644 index 571184776..000000000 --- a/tests/libsample/templateptr.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "templateptr.h" - -void TemplatePtr::dummy(std::list > & items) -{ -} \ No newline at end of file diff --git a/tests/libsample/templateptr.h b/tests/libsample/templateptr.h deleted file mode 100644 index 67e154b1c..000000000 --- a/tests/libsample/templateptr.h +++ /dev/null @@ -1,43 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TEMPLATEPTR_H -#define TEMPLATEPTR_H - -#include -#include -#include "libsamplemacros.h" -#include "blackbox.h" - -class LIBSAMPLE_API TemplatePtr -{ -public: - void dummy(std::list > & items); -}; - -#endif diff --git a/tests/libsample/transform.cpp b/tests/libsample/transform.cpp deleted file mode 100644 index 951e2ca5b..000000000 --- a/tests/libsample/transform.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2013 Kitware, Inc. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "transform.h" - -#ifdef _WIN32 -#include -#include -static inline bool isfinite(double a) { return _finite(a); } -#else -#include -#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) -{ - 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 (okay) - *okay = true; - return Point(x / w, y / w); - } - else - { - if (okay) - *okay = false; - return Point(); - } -} diff --git a/tests/libsample/transform.h b/tests/libsample/transform.h deleted file mode 100644 index fda5b33c5..000000000 --- a/tests/libsample/transform.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2013 Kitware, Inc. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef TRANSFORM_H -#define TRANSFORM_H - -#include "point.h" - -#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); - -#endif // TRANSFORM_H diff --git a/tests/libsample/valueandvirtual.h b/tests/libsample/valueandvirtual.h deleted file mode 100644 index 54e8114b5..000000000 --- a/tests/libsample/valueandvirtual.h +++ /dev/null @@ -1,47 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VALUEANDVIRTUAL_H -#define VALUEANDVIRTUAL_H - -class ValueAndVirtual -{ -public: - ValueAndVirtual(int id) : m_id(id) {} - ValueAndVirtual(const ValueAndVirtual &other) { m_id = other.m_id; } - - bool operator()(int id, int id2) { return id == id2; } - - inline int id() { return m_id; } - virtual ~ValueAndVirtual() {}; -private: - int m_id; -}; - -#endif // VALUEANDVIRTUAL_H - diff --git a/tests/libsample/virtualmethods.cpp b/tests/libsample/virtualmethods.cpp deleted file mode 100644 index 05b854e08..000000000 --- a/tests/libsample/virtualmethods.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "virtualmethods.h" - -int VirtualDtor::dtor_called = 0; - -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) -{ - if (!text) { - ret = 0; - return false; - } - - ret = new Str(text); - return true; -} - -void -VirtualMethods::getMargins(int* left, int* top, int* right, int* bottom) const -{ - *left = m_left; - *top = m_top; - *right = m_right; - *bottom = m_bottom; -} - diff --git a/tests/libsample/virtualmethods.h b/tests/libsample/virtualmethods.h deleted file mode 100644 index 5754d0d5d..000000000 --- a/tests/libsample/virtualmethods.h +++ /dev/null @@ -1,139 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VIRTUALMETHODS_H -#define VIRTUALMETHODS_H - -#include "point.h" -#include "complex.h" -#include "str.h" - -#include "libsamplemacros.h" -#include "strlist.h" - -class LIBSAMPLE_API VirtualMethods -{ -public: - VirtualMethods(Str name = "VirtualMethods") : m_name(name) - { - m_left = m_top = m_right = m_bottom = 0; - } - virtual ~VirtualMethods() {} - - virtual double virtualMethod0(Point pt, int val, Complex cpx, bool b); - double callVirtualMethod0(Point pt, int val, Complex cpx, bool b) - { - return virtualMethod0(pt, val, cpx, b); - } - - // Binding modification: rename. - virtual int sum0(int a0, int a1, int a2) { return a0 + a1 + a2; } - int callSum0(int a0, int a1, int a2) { return sum0(a0, a1, a2); } - - // Binding modification: set default value for the last argument. - virtual int sum1(int a0, int a1, int a2) { return a0 + a1 + a2; } - int callSum1(int a0, int a1, int a2) { return sum1(a0, a1, a2); } - - // Binding modification: remove the last argument and set a default value for it. - virtual int sum2(int a0, int a1, int a2) { return a0 + a1 + a2; } - int callSum2(int a0, int a1, int a2) { return sum2(a0, a1, a2); } - - // Binding modification: remove the second argument. - virtual int sum3(int a0, int a1, int a2) { return a0 + a1 + a2; } - int callSum3(int a0, int a1, int a2) { return sum3(a0, a1, a2); } - - // Binding modification: remove the second argument and set its default - // value, then inject code on the binding reimplementation of the virtual - // (with a native inject-code) to sum the value of the removed - // argument to the first argument before the method is called. - virtual int sum4(int a0, int a1, int a2) { return a0 + a1 + a2; } - int callSum4(int a0, int a1, int a2) { return sum4(a0, a1, a2); } - - // Binding modification: prepend a string to the results of a Python override. - virtual Str name() { return m_name; } - Str callName() { return name(); } - - // Binding modification: code injection that calls the Python override by itself. - virtual void callMe() {} - 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); } - - // Return a non-binded method - std::list callStrListToStdList(const StrList& strList) { return strListToStdList(strList); } - virtual std::list strListToStdList(const StrList& strList ) { return strList; } - - void setMargins(int left, int top, int right, int bottom) - { - m_left = left; - m_top = top; - 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 - { - getMargins(left, top, right, bottom); - } - - virtual int recursionOnModifiedVirtual(Str arg) const { return 0; } - int callRecursionOnModifiedVirtual(Str arg) const { return recursionOnModifiedVirtual(arg); } - -private: - Str m_name; - int m_left; - int m_top; - int m_right; - int m_bottom; -}; - -class LIBSAMPLE_API VirtualDaughter : public VirtualMethods -{ -public: - VirtualDaughter() : VirtualMethods() {} - VirtualDaughter(Str name) : VirtualMethods(name) {} -}; - -class LIBSAMPLE_API VirtualDtor -{ -public: - VirtualDtor() {} - virtual ~VirtualDtor() { dtor_called++; } - - static VirtualDtor* create() { return new VirtualDtor(); } - static int dtorCalled() { return dtor_called; } - static void resetDtorCounter() { dtor_called = 0; } - -private: - static int dtor_called; -}; - -#endif // VIRTUALMETHODS_H - diff --git a/tests/libsample/voidholder.h b/tests/libsample/voidholder.h deleted file mode 100644 index 228bbae3f..000000000 --- a/tests/libsample/voidholder.h +++ /dev/null @@ -1,50 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef VOIDHOLDER_H -#define VOIDHOLDER_H - -#include "libsamplemacros.h" - -class VoidHolder -{ -public: - explicit VoidHolder(void* ptr = 0) : m_ptr(ptr) {} - ~VoidHolder() {} - inline void* voidPointer() { return m_ptr; } - inline static void* gimmeMeSomeVoidPointer() - { - static void* pointerToSomething = new VoidHolder(); - return pointerToSomething; - } -private: - void* m_ptr; -}; - -#endif // VOIDHOLDER_H - diff --git a/tests/libsmart/CMakeLists.txt b/tests/libsmart/CMakeLists.txt deleted file mode 100644 index 66c27cdae..000000000 --- a/tests/libsmart/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -project(libsmart) - -set(libsmart_SRC -smart.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) -add_definitions("-DLIBSMART_BUILD") -add_library(libsmart SHARED ${libsmart_SRC}) -set_property(TARGET libsmart PROPERTY PREFIX "") - diff --git a/tests/libsmart/libsmartmacros.h b/tests/libsmart/libsmartmacros.h deleted file mode 100644 index e4166caff..000000000 --- a/tests/libsmart/libsmartmacros.h +++ /dev/null @@ -1,46 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef LIB_SMART_MACROS_H -#define LIB_SMART_MACROS_H - -#if defined _WIN32 || defined __CYGWIN__ - #if LIBSMART_BUILD - #define LIB_SMART_API __declspec(dllexport) - #else - #define LIB_SMART_API __declspec(dllimport) - #endif -#else -#if __GNUC__ >= 4 - #define LIB_SMART_API __attribute__ ((visibility("default"))) -#else - #define LIB_SMART_API -#endif -#endif - -#endif diff --git a/tests/libsmart/smart.cpp b/tests/libsmart/smart.cpp deleted file mode 100644 index 28c9cf055..000000000 --- a/tests/libsmart/smart.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "smart.h" - -bool shouldPrint() { - return Registry::getInstance()->shouldPrint(); -} - -Obj::Obj() : m_integer(123), m_internalInteger(new Integer) -{ - Registry::getInstance()->add(this); - if (shouldPrint()) - std::cout << "Object constructor " << this << '\n'; -} - -Obj::~Obj() -{ - Registry::getInstance()->remove(this); - delete m_internalInteger; - if (shouldPrint()) - std::cout << "Object destructor " << this << '\n'; -} - - -void Obj::printObj() { - if (shouldPrint()) { - std::cout << "integer value: " << m_integer - << " internal integer value: " << m_internalInteger->m_int << '\n'; - } -} - - -SharedPtr Obj::giveSharedPtrToObj() -{ - SharedPtr o(new Obj); - return o; -} - -SharedPtr Obj::giveSharedPtrToInteger() -{ - SharedPtr o(new Integer); - return o; -} - -int Obj::takeSharedPtrToObj(SharedPtr pObj) -{ - pObj->printObj(); - return pObj->m_integer; -} - -int Obj::takeSharedPtrToInteger(SharedPtr pInt) -{ - pInt->printInteger(); - return pInt->m_int; -} - -Integer Obj::takeInteger(Integer val) -{ - return val; -} - -Integer::Integer() : m_int(456) -{ - Registry::getInstance()->add(this); - if (shouldPrint()) - std::cout << "Integer constructor " << this << '\n'; -} - -Integer::Integer(const Integer &other) -{ - Registry::getInstance()->add(this); - if (shouldPrint()) - std::cout << "Integer copy constructor " << this << '\n'; - m_int = other.m_int; -} - -Integer &Integer::operator=(const Integer &other) -{ - Registry::getInstance()->add(this); - if (shouldPrint()) - std::cout << "Integer operator= " << this << '\n'; - m_int = other.m_int; - return *this; -} - -Integer::~Integer() -{ - Registry::getInstance()->remove(this); - if (shouldPrint()) - std::cout << "Integer destructor " << this << '\n'; -} - -void Integer::printInteger() -{ - if (shouldPrint()) - std::cout << "Integer value for object " << this << " is " << m_int << '\n'; -} - -Registry *Registry::getInstance() -{ - static Registry registry; - return ®istry; -} - -Registry::Registry() : m_printStuff(false) -{ - -} - -void Registry::add(Obj *p) -{ - m_objects.push_back(p); -} - -void Registry::add(Integer *p) -{ - m_integers.push_back(p); -} - -void Registry::remove(Obj *p) -{ - m_objects.erase(std::remove(m_objects.begin(), m_objects.end(), p), m_objects.end()); -} - -void Registry::remove(Integer *p) -{ - m_integers.erase(std::remove(m_integers.begin(), m_integers.end(), p), m_integers.end()); -} - -int Registry::countObjects() const -{ - return static_cast(m_objects.size()); -} - -int Registry::countIntegers() const -{ - return static_cast(m_integers.size()); -} - -bool Registry::shouldPrint() const -{ - return m_printStuff; -} - -void Registry::setShouldPrint(bool flag) -{ - m_printStuff = flag; -} diff --git a/tests/libsmart/smart.h b/tests/libsmart/smart.h deleted file mode 100644 index c6b0dbbca..000000000 --- a/tests/libsmart/smart.h +++ /dev/null @@ -1,210 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SMART_H -#define SMART_H - -#include -#include -#include - -#include "libsmartmacros.h" - -// Forward declarations. -template -class SharedPtr; -class Integer; -class Obj; - -LIB_SMART_API bool shouldPrint(); - -// Used to track which C++ objects are alive. -class LIB_SMART_API Registry { -public: - static Registry *getInstance(); - - void add(Obj *p); - void add(Integer *p); - void remove(Obj *p); - void remove(Integer *p); - int countObjects() const; - int countIntegers() const; - bool shouldPrint() const; - void setShouldPrint(bool flag); - -protected: - Registry(); - -private: - bool m_printStuff; - std::vector m_objects; - std::vector m_integers; -}; - -template -class RefData { -public: - RefData(T *ptr) : m_refCount(1), m_heldPtr(ptr) {} - ~RefData() { delete m_heldPtr; } - int inc() { return ++m_refCount; } - int dec() { return --m_refCount; } - int useCount() { return m_refCount; } - int m_refCount; - T *m_heldPtr; -}; - -template -class SharedPtr { -public: - SharedPtr() : m_refData(0) { - if (shouldPrint()) - std::cout << "shared_ptr default constructor " << this << "\n"; - } - - SharedPtr(T *v) - { - if (shouldPrint()) - std::cout << "shared_ptr constructor " << this << " with pointer " << v << "\n"; - if (v) - m_refData = new RefData(v); - } - - SharedPtr(const SharedPtr &other) : m_refData(other.m_refData) - { - if (shouldPrint()) - std::cout << "shared_ptr copy constructor " << this << " with pointer " - << other.m_refData << "\n"; - if (m_refData) - m_refData->inc(); - } - - SharedPtr &operator=(const SharedPtr& other) - { - if (this != &other) { - if (shouldPrint()) - std::cout << "shared_ptr assignment operator " << this << " with pointer " - << other.m_refData << "\n"; - if (m_refData && m_refData->dec() == 0) - delete m_refData; - m_refData = other.m_refData; - if (m_refData) - m_refData->inc(); - } - return *this; - } - - T *data() const - { - if (m_refData) - return m_refData->m_heldPtr; - return 0; - } - - int useCount() const - { - if (m_refData) - return m_refData->useCount(); - return 0; - } - - void dummyMethod1() - { - - } - - T& operator*() const - { - // Crashes if smart pointer is empty (just like std::shared_ptr). - return *(m_refData->m_heldPtr); - } - - T *operator->() const - { - if (m_refData) - return m_refData->m_heldPtr; - return 0; - } - - bool operator!() const - { - return !m_refData || !m_refData->m_heldPtr; - } - - bool isNull() const - { - return !m_refData || !m_refData->m_heldPtr; - } - - operator bool() const - { - return m_refData && m_refData->m_heldPtr; - } - - ~SharedPtr() - { - if (m_refData) { - if (shouldPrint()) - std::cout << "shared_ptr destructor " << this << " remaining refcount " - << m_refData->useCount() - 1 << "\n"; - } - if (m_refData && m_refData->dec() == 0) - delete m_refData; - } - - RefData *m_refData; -}; - -class LIB_SMART_API Integer { -public: - Integer(); - Integer(const Integer &other); - Integer &operator=(const Integer &other); - ~Integer(); - void printInteger(); - int m_int; -}; - -// Couldn't name it Object because it caused some namespace clashes. -class LIB_SMART_API Obj { -public: - Obj(); - virtual ~Obj(); - - void printObj(); - Integer takeInteger(Integer val); - SharedPtr giveSharedPtrToObj(); - SharedPtr giveSharedPtrToInteger(); - int takeSharedPtrToObj(SharedPtr pObj); - int takeSharedPtrToInteger(SharedPtr pInt); - - int m_integer; - Integer *m_internalInteger; -}; - -#endif // SMART_H - diff --git a/tests/minimalbinding/CMakeLists.txt b/tests/minimalbinding/CMakeLists.txt deleted file mode 100644 index fb0b2cc74..000000000 --- a/tests/minimalbinding/CMakeLists.txt +++ /dev/null @@ -1,38 +0,0 @@ -project(minimal) - -set(minimal_TYPESYSTEM -${CMAKE_CURRENT_SOURCE_DIR}/typesystem_minimal.xml -) - -set(minimal_SRC -${CMAKE_CURRENT_BINARY_DIR}/minimal/minimal_module_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/minbooluser_wrapper.cpp -) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/minimal-binding.txt.in" - "${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt" @ONLY) - -add_custom_command(OUTPUT ${minimal_SRC} -COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/minimal-binding.txt ${GENERATOR_EXTRA_FLAGS} -DEPENDS ${minimal_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 -WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -COMMENT "Running generator for 'minimal' test binding..." -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${libminimal_SOURCE_DIR} - ${libshiboken_SOURCE_DIR}) -add_library(minimal MODULE ${minimal_SRC}) -set_property(TARGET minimal PROPERTY PREFIX "") -if(WIN32) - set_property(TARGET minimal PROPERTY SUFFIX ".pyd") -endif() -target_link_libraries(minimal - libminimal - ${SBK_PYTHON_LIBRARIES} - libshiboken) diff --git a/tests/minimalbinding/global.h b/tests/minimalbinding/global.h deleted file mode 100644 index 93eb38ed5..000000000 --- a/tests/minimalbinding/global.h +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "obj.h" -#include "val.h" -#include "minbool.h" -#include "listuser.h" -#include "typedef.h" diff --git a/tests/minimalbinding/listuser_test.py b/tests/minimalbinding/listuser_test.py deleted file mode 100644 index d3b7f01e7..000000000 --- a/tests/minimalbinding/listuser_test.py +++ /dev/null @@ -1,323 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from minimal import ListUser, Val, Obj -from py3kcompat import IS_PY3K - -if IS_PY3K: - import functools - reduce = functools.reduce - - -class ExtListUser(ListUser): - def __init__(self): - ListUser.__init__(self) - - def createIntList(self, num): - return list(range(0, num * 2, 2)) - - def sumIntList(self, intList): - return sum(intList) * 2 - - def createMinBoolList(self, mb1, mb2): - return [not mb1, not mb2] - - def oredMinBoolList(self, 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)] - - def sumValList(self, valList): - return sum([val.valId() for val in valList]) * 2 - - def createObjList(self, o1, o2): - o1.setObjId(o1.objId() * 2) - o2.setObjId(o2.objId() * 2) - return [o1, o2] - - def sumObjList(self, objList): - return sum([obj.objId() for obj in objList]) * 2 - - def createListOfIntLists(self, num): - return [self.createIntList(num)] * 4 - - def sumListOfIntLists(self, intListList): - return sum([sum(line) for line in intListList]) * 2 - - -class IntListConversionTest(unittest.TestCase): - - def testCreateIntList(self): - num = 4 - lu = ListUser() - lst = lu.createIntList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), int) - self.assertEqual(lst, list(range(num))) - lst = lu.callCreateIntList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), int) - self.assertEqual(lst, list(range(num))) - - def testCreateIntListFromExtendedClass(self): - lu = ExtListUser() - num = 4 - lst = lu.createIntList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), int) - self.assertEqual(lst, list(range(0, num * 2, 2))) - lst = lu.callCreateIntList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), int) - self.assertEqual(lst, list(range(0, num * 2, 2))) - - def testSumIntList(self): - lu = ListUser() - lst = range(4) - self.assertEqual(lu.sumIntList(lst), sum(lst)) - self.assertEqual(lu.callSumIntList(lst), sum(lst)) - - def testSumIntListFromExtendedClass(self): - lu = ExtListUser() - lst = range(4) - self.assertEqual(lu.sumIntList(lst), sum(lst) * 2) - self.assertEqual(lu.callSumIntList(lst), sum(lst) * 2) - - -class MinBoolListConversionTest(unittest.TestCase): - - def testCreateMinBoolList(self): - lu = ListUser() - lst = lu.createMinBoolList(True, False) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), bool) - self.assertEqual(lst, [True, False]) - - lst = lu.callCreateMinBoolList(False, True) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), bool) - self.assertEqual(lst, [False, True]) - - def testCreateMinBoolListFromExtendedClass(self): - lu = ExtListUser() - lst = lu.createMinBoolList(True, False) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), bool) - self.assertEqual(lst, [False, True]) - - lst = lu.callCreateMinBoolList(False, True) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), bool) - self.assertEqual(lst, [True, False]) - - def testOredMinBoolList(self): - lu = ListUser() - lst = [False, False, True] - self.assertTrue(lu.oredMinBoolList(lst)) - self.assertTrue(lu.callOredMinBoolList(lst)) - lst = [False, False, False] - self.assertFalse(lu.oredMinBoolList(lst)) - self.assertFalse(lu.callOredMinBoolList(lst)) - - def testOredMinBoolListFromExtendedClass(self): - lu = ExtListUser() - lst = [False, False, True] - self.assertFalse(lu.oredMinBoolList(lst)) - self.assertFalse(lu.callOredMinBoolList(lst)) - lst = [False, False, False] - self.assertTrue(lu.oredMinBoolList(lst)) - self.assertTrue(lu.callOredMinBoolList(lst)) - - -class ValListConversionTest(unittest.TestCase): - - def testCreateValList(self): - num = 4 - lu = ListUser() - lst = lu.createValList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), Val) - self.assertEqual([val.valId() for val in lst], list(range(num))) - lst = lu.callCreateValList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), Val) - self.assertEqual([val.valId() for val in lst], list(range(num))) - - def testCreateValListFromExtendedClass(self): - lu = ExtListUser() - num = 4 - lst = lu.createValList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), Val) - self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) - lst = lu.callCreateValList(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), Val) - self.assertEqual([val.valId() for val in lst], list(range(0, num * 2, 2))) - - def testSumValList(self): - lu = ListUser() - lst = [Val(i) for i in range(4)] - self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst])) - self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst])) - - def testSumValListFromExtendedClass(self): - lu = ExtListUser() - lst = [Val(i) for i in range(4)] - self.assertEqual(lu.sumValList(lst), sum([val.valId() for val in lst]) * 2) - self.assertEqual(lu.callSumValList(lst), sum([val.valId() for val in lst]) * 2) - - -class ObjListConversionTest(unittest.TestCase): - - def testCreateObjList(self): - o1 = Obj(1) - o2 = Obj(2) - lu = ListUser() - lst = lu.createObjList(o1, o2) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), Obj) - self.assertEqual(lst, [o1, o2]) - self.assertEqual([obj.objId() for obj in lst], [1, 2]) - - lst = lu.callCreateObjList(o1, o2) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), Obj) - self.assertEqual(lst, [o1, o2]) - self.assertEqual([obj.objId() for obj in lst], [1, 2]) - - def testCreateObjListFromExtendedClass(self): - o1 = Obj(1) - o2 = Obj(2) - lu = ExtListUser() - lst = lu.createObjList(o1, o2) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), Obj) - self.assertEqual(lst, [o1, o2]) - self.assertEqual([obj.objId() for obj in lst], [2, 4]) - - lst = lu.callCreateObjList(o1, o2) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), 2) - for i in lst: - self.assertEqual(type(i), Obj) - self.assertEqual(lst, [o1, o2]) - self.assertEqual([obj.objId() for obj in lst], [4, 8]) - - def testSumObjList(self): - lu = ListUser() - lst = [Obj(i) for i in list(range(4))] - self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst])) - self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst])) - - def testSumObjListFromExtendedClass(self): - lu = ExtListUser() - lst = [Obj(i) for i in list(range(4))] - self.assertEqual(lu.sumObjList(lst), sum([obj.objId() for obj in lst]) * 2) - self.assertEqual(lu.callSumObjList(lst), sum([obj.objId() for obj in lst]) * 2) - - -class ListOfIntListConversionTest(unittest.TestCase): - - def testCreateListOfIntLists(self): - num = 4 - lu = ListUser() - lst = lu.createListOfIntLists(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), list) - self.assertEqual(i, list(range(num))) - for j in i: - self.assertEqual(type(j), int) - self.assertEqual(lst, [list(range(num))] * 4) - - def testCreateListOfIntListsFromExtendedClass(self): - num = 4 - lu = ExtListUser() - lst = lu.createListOfIntLists(num) - self.assertEqual(type(lst), list) - self.assertEqual(len(lst), num) - for i in lst: - self.assertEqual(type(i), list) - self.assertEqual(i, list(range(0, num * 2, 2))) - for j in i: - self.assertEqual(type(j), int) - self.assertEqual(lst, [list(range(0, num * 2, 2))] * 4) - - def testSumListIntLists(self): - lu = ListUser() - lst = [range(4)] * 4 - self.assertEqual(lu.sumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) - self.assertEqual(lu.callSumListOfIntLists(lst), sum([sum(line) for line in [range(4)] * 4])) - - 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) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/minimalbinding/minbool_test.py b/tests/minimalbinding/minbool_test.py deleted file mode 100644 index b7830a79b..000000000 --- a/tests/minimalbinding/minbool_test.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -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.assertEqual(mbuTrue.minBool() == True, True) - self.assertEqual(False == mbuFalse.minBool(), True) - self.assertEqual(mbuTrue.minBool() == mbuFalse.minBool(), False) - - self.assertEqual(mbuFalse.minBool() != True, True) - self.assertEqual(True != mbuFalse.minBool(), True) - self.assertEqual(mbuTrue.minBool() != mbuFalse.minBool(), True) - - def testVirtuals(self): - dmbu = DerivedMinBoolUser() - self.assertEqual(dmbu.invertedMinBool(), True) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/minimalbinding/minimal-binding.txt.in b/tests/minimalbinding/minimal-binding.txt.in deleted file mode 100644 index 85b139676..000000000 --- a/tests/minimalbinding/minimal-binding.txt.in +++ /dev/null @@ -1,15 +0,0 @@ -[generator-project] - -generator-set = shiboken - -header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h -typesystem-file = @minimal_TYPESYSTEM@ - -output-directory = @CMAKE_CURRENT_BINARY_DIR@ - -include-path = @libminimal_SOURCE_DIR@ - -typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ - -enable-parent-ctor-heuristic -use-isnull-as-nb_nonzero diff --git a/tests/minimalbinding/obj_test.py b/tests/minimalbinding/obj_test.py deleted file mode 100644 index bf00f1c92..000000000 --- a/tests/minimalbinding/obj_test.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from minimal import Obj - -class ExtObj(Obj): - def __init__(self, objId): - Obj.__init__(self, objId) - self.virtual_method_called = False - - def virtualMethod(self, val): - self.virtual_method_called = True - return not Obj.virtualMethod(self, val) - - def passObjectType(self, obj): - obj.setObjId(obj.objId() + 1) - return obj - - def passObjectTypeReference(self, obj): - obj.setObjId(obj.objId() + 1) - return obj - - -class ObjTest(unittest.TestCase): - - def testNormalMethod(self): - objId = 123 - obj = Obj(objId) - self.assertEqual(obj.objId(), objId) - - def testNormalMethodFromExtendedClass(self): - objId = 123 - obj = ExtObj(objId) - self.assertEqual(obj.objId(), objId) - - def testVirtualMethod(self): - obj = Obj(0) - even_number = 8 - self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) - - def testVirtualMethodFromExtendedClass(self): - obj = ExtObj(0) - even_number = 8 - self.assertEqual(obj.virtualMethod(even_number), obj.callVirtualMethod(even_number)) - self.assertTrue(obj.virtual_method_called) - - def testPassObjectType(self): - obj = Obj(0) - self.assertEqual(obj, obj.passObjectType(obj)) - self.assertEqual(obj, obj.callPassObjectType(obj)) - - def testPassObjectTypeNone(self): - obj = Obj(0) - self.assertEqual(None, obj.passObjectType(None)) - self.assertEqual(None, obj.callPassObjectType(None)) - - def testPassObjectTypeReference(self): - obj = Obj(0) - self.assertEqual(obj, obj.passObjectTypeReference(obj)) - self.assertEqual(obj, obj.callPassObjectTypeReference(obj)) - - def testPassObjectTypeFromExtendedClass(self): - obj = ExtObj(0) - self.assertEqual(obj.objId(), 0) - sameObj = obj.passObjectType(obj) - self.assertEqual(obj, sameObj) - self.assertEqual(sameObj.objId(), 1) - sameObj = obj.callPassObjectType(obj) - self.assertEqual(obj, sameObj) - self.assertEqual(sameObj.objId(), 2) - - def testPassObjectTypeReferenceFromExtendedClass(self): - obj = ExtObj(0) - self.assertEqual(obj.objId(), 0) - sameObj = obj.passObjectTypeReference(obj) - self.assertEqual(obj, sameObj) - self.assertEqual(sameObj.objId(), 1) - sameObj = obj.callPassObjectTypeReference(obj) - self.assertEqual(obj, sameObj) - self.assertEqual(sameObj.objId(), 2) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/minimalbinding/typedef_test.py b/tests/minimalbinding/typedef_test.py deleted file mode 100644 index 62df9cbea..000000000 --- a/tests/minimalbinding/typedef_test.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from minimal import * -from py3kcompat import IS_PY3K - -try: - import numpy as np -except ImportError as e: - print(e) - np = None - - -if IS_PY3K: - import functools - reduce = functools.reduce - - -class TypedefTest(unittest.TestCase): - - def setUp(self): - self.the_size = 8 - - def test_arrayFuncInt(self): - none = () - full = range(self.the_size) - 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") - - 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(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") - - 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") - - def test_arrayFunc(self): - none = () - full = range(self.the_size) - self.assertTrue(arrayFunc(none), "None is empty, arrayFunc should return true") - 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") - - 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(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") - - 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") - - -if __name__ == '__main__': - if np != None: - unittest.main() diff --git a/tests/minimalbinding/typesystem_minimal.xml b/tests/minimalbinding/typesystem_minimal.xml deleted file mode 100644 index 968b27c53..000000000 --- a/tests/minimalbinding/typesystem_minimal.xml +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - - - - - return PyBool_FromLong(%in.value()); - - - - %out = %OUTTYPE(%in == Py_True); - - - - - - - - - - PyObject* %out = PyList_New((int) %in.size()); - %INTYPE::const_iterator it = %in.begin(); - for (int idx = 0; it != %in.end(); ++it, ++idx) { - %INTYPE_0 cppItem(*it); - PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); - } - return %out; - - - - Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); - for (int i = 0; i < PySequence_Fast_GET_SIZE(seq.object()); i++) { - PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), i); - %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); - %out.push_back(cppItem); - } - - - - - - - - - - - - - - - - - %INTYPE::size_type vectorSize = %in.size(); - PyObject* %out = PyList_New((int) vectorSize); - for (%INTYPE::size_type idx = 0; idx < vectorSize; ++idx) { - %INTYPE_0 cppItem(%in[idx]); - PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem)); - } - return %out; - - - - Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); - int vectorSize = PySequence_Fast_GET_SIZE(seq.object()); - %out.reserve(vectorSize); - for (int idx = 0; idx < vectorSize; ++idx ) { - PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), idx); - %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem); - %out.push_back(cppItem); - } - - - - - - - - - - - - - - - - - - - - diff --git a/tests/minimalbinding/val_test.py b/tests/minimalbinding/val_test.py deleted file mode 100644 index 97e4e4778..000000000 --- a/tests/minimalbinding/val_test.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from minimal import Val - - -class ExtVal(Val): - def __init__(self, valId): - Val.__init__(self, valId) - - def passValueType(self, val): - return ExtVal(val.valId() + 1) - - def passValueTypePointer(self, val): - val.setValId(val.valId() + 1) - return val - - def passValueTypeReference(self, val): - val.setValId(val.valId() + 1) - return val - - -class ValTest(unittest.TestCase): - - def testNormalMethod(self): - valId = 123 - val = Val(valId) - self.assertEqual(val.valId(), valId) - - def testPassValueType(self): - val = Val(123) - val1 = val.passValueType(val) - self.assertNotEqual(val, val1) - self.assertEqual(val1.valId(), 123) - val2 = val.callPassValueType(val) - self.assertNotEqual(val, val2) - self.assertEqual(val2.valId(), 123) - - def testPassValueTypePointer(self): - val = Val(0) - self.assertEqual(val, val.passValueTypePointer(val)) - self.assertEqual(val, val.callPassValueTypePointer(val)) - - def testPassValueTypeReference(self): - val = Val(0) - self.assertEqual(val, val.passValueTypeReference(val)) - self.assertEqual(val, val.callPassValueTypeReference(val)) - - def testPassAndReceiveEnumValue(self): - val = Val(0) - self.assertEqual(val.oneOrTheOtherEnumValue(Val.One), Val.Other) - self.assertEqual(val.oneOrTheOtherEnumValue(Val.Other), Val.One) - - def testPassValueTypeFromExtendedClass(self): - val = ExtVal(0) - val1 = val.passValueType(val) - self.assertNotEqual(val, val1) - self.assertEqual(val1.valId(), val.valId() + 1) - val2 = val.callPassValueType(val) - self.assertNotEqual(val, val2) - self.assertEqual(val2.valId(), val.valId() + 1) - - def testPassValueTypePointerFromExtendedClass(self): - val = ExtVal(0) - self.assertEqual(val.valId(), 0) - sameVal = val.passValueTypePointer(val) - self.assertEqual(val, sameVal) - self.assertEqual(sameVal.valId(), 1) - sameVal = val.callPassValueTypePointer(val) - self.assertEqual(val, sameVal) - self.assertEqual(sameVal.valId(), 2) - - def testPassValueTypeReferenceFromExtendedClass(self): - val = ExtVal(0) - self.assertEqual(val.valId(), 0) - sameVal = val.passValueTypeReference(val) - self.assertEqual(val, sameVal) - self.assertEqual(sameVal.valId(), 1) - sameVal = val.callPassValueTypeReference(val) - self.assertEqual(val, sameVal) - self.assertEqual(sameVal.valId(), 2) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/CMakeLists.txt b/tests/otherbinding/CMakeLists.txt deleted file mode 100644 index ac7178e5d..000000000 --- a/tests/otherbinding/CMakeLists.txt +++ /dev/null @@ -1,48 +0,0 @@ -project(other) - -set(other_TYPESYSTEM -${CMAKE_CURRENT_SOURCE_DIR}/typesystem_other.xml -) - -set(other_SRC -${CMAKE_CURRENT_BINARY_DIR}/other/extendsnoimplicitconversion_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/other/number_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/other/otherderived_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/other/othermultiplederived_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/other/otherobjecttype_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/other/other_module_wrapper.cpp -) - - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/other-binding.txt.in" - "${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt" @ONLY) - -add_custom_command(OUTPUT ${other_SRC} -COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/other-binding.txt ${GENERATOR_EXTRA_FLAGS} -DEPENDS ${other_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 -WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -COMMENT "Running generator for 'other' test binding..." -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${libother_SOURCE_DIR} - ${libsample_SOURCE_DIR} - ${libsample_SOURCE_DIR}/.. - ${sample_BINARY_DIR} - ${sample_BINARY_DIR}/sample - ${libshiboken_SOURCE_DIR}) -add_library(other MODULE ${other_SRC}) -set_property(TARGET other PROPERTY PREFIX "") -if(WIN32) - set_property(TARGET other PROPERTY SUFFIX ".pyd") -endif() -target_link_libraries(other - libother - libsample - ${SBK_PYTHON_LIBRARIES} - libshiboken) - -add_dependencies(other sample) - diff --git a/tests/otherbinding/collector_external_operator_test.py b/tests/otherbinding/collector_external_operator_test.py deleted file mode 100644 index 328aec837..000000000 --- a/tests/otherbinding/collector_external_operator_test.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Collector shift operators defined in other modules.''' - -import unittest - -from sample import Collector, ObjectType -from other import OtherObjectType - -class CollectorOtherObjectType(unittest.TestCase): - '''Test cases for Collector << OtherObjectType''' - - def testLShiftWithExpectedType(self): - '''Collector << ObjectType # libsample << operator''' - collector = Collector() - obj = ObjectType() - collector << obj - self.assertEqual(collector.items()[0], obj.identifier()) - - def testOtherReversal(self): - '''Collector << OtherObjectType # libother << operator''' - collector = Collector() - obj = OtherObjectType() - collector << obj - self.assertEqual(collector.items()[0], obj.identifier() * 2) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py b/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py deleted file mode 100755 index 5c3733dc2..000000000 --- a/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests calling NoImplicitConversion using a ExtendsNoImplicitConversion parameter, - being that the latter defines a new conversion operator for the former, and this one - has no implicit conversions.''' - -import unittest - -from sample import NoImplicitConversion -from other import ExtendsNoImplicitConversion - -class ConversionOperatorForClassWithoutImplicitConversionsTest(unittest.TestCase): - '''Tests calling NoImplicitConversion constructor using a ExtendsNoImplicitConversion parameter.''' - - def testNoImplicitConversion(self): - '''Basic test to see if the NoImplicitConversion is Ok.''' - obj = NoImplicitConversion(123) - # NoImplicitConversion.receivesNoImplicitConversionByValue(NoImplicitConversion) - self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByValue(obj)) - # NoImplicitConversion.receivesNoImplicitConversionByPointer(NoImplicitConversion*) - self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByPointer(obj)) - # NoImplicitConversion.receivesNoImplicitConversionByReference(NoImplicitConversion&) - self.assertEqual(obj.objId(), NoImplicitConversion.receivesNoImplicitConversionByReference(obj)) - - def testPassingExtendsNoImplicitConversionAsNoImplicitConversionByValue(self): - '''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.''' - obj = ExtendsNoImplicitConversion(123) - 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.''' - obj = ExtendsNoImplicitConversion(123) - self.assertRaises(TypeError, NoImplicitConversion.receivesNoImplicitConversionByPointer, obj) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/extended_multiply_operator_test.py b/tests/otherbinding/extended_multiply_operator_test.py deleted file mode 100755 index 4acc53024..000000000 --- a/tests/otherbinding/extended_multiply_operator_test.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for libsample's Point multiply operator defined in libother module.''' - -import unittest - -from sample import Point -from other import Number - -class PointOperationsWithNumber(unittest.TestCase): - '''Test cases for libsample's Point multiply operator defined in libother module.''' - - def testPointTimesInt(self): - '''sample.Point * int''' - pt1 = Point(2, 7) - num = 3 - pt2 = Point(pt1.x() * num, pt1.y() * num) - self.assertEqual(pt1 * num, pt2) - - def testIntTimesPoint(self): - '''int * sample.Point''' - pt1 = Point(2, 7) - num = 3 - pt2 = Point(pt1.x() * num, pt1.y() * num) - self.assertEqual(num * pt1, pt2) - - def testPointTimesNumber(self): - '''sample.Point * other.Number''' - pt = Point(2, 7) - num = Number(11) - self.assertEqual(pt * num, pt * 11) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/global.h b/tests/otherbinding/global.h deleted file mode 100644 index cc6634ab4..000000000 --- a/tests/otherbinding/global.h +++ /dev/null @@ -1,35 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../samplebinding/global.h" -#include "extendsnoimplicitconversion.h" -#include "number.h" -#include "otherderived.h" -#include "otherobjecttype.h" -#include "othermultiplederived.h" - diff --git a/tests/otherbinding/module_reload_test.py b/tests/otherbinding/module_reload_test.py deleted file mode 100644 index 0f601d1a3..000000000 --- a/tests/otherbinding/module_reload_test.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import os -import sys -import shutil -import unittest - -from py3kcompat import IS_PY3K - -if IS_PY3K: - from imp import reload - -orig_path = os.path.join(os.path.dirname(__file__)) -workdir = os.getcwd() -src = os.path.join(orig_path, 'test_module_template.py') -dst = os.path.join(workdir, 'test_module.py') -shutil.copyfile(src, dst) -sys.path.append(workdir) - -class TestModuleReloading(unittest.TestCase): - - def testModuleReloading(self): - '''Test module reloading with on-the-fly modifications.''' - import test_module - for i in range(3): - oldObject = test_module.obj - self.assertTrue(oldObject is test_module.obj) - reload(test_module) - self.assertFalse(oldObject is test_module.obj) - -if __name__ == "__main__": - unittest.main() diff --git a/tests/otherbinding/new_ctor_operator_test.py b/tests/otherbinding/new_ctor_operator_test.py deleted file mode 100755 index 634106cea..000000000 --- a/tests/otherbinding/new_ctor_operator_test.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests calling Str constructor using a Number parameter, being that number defines a cast operator to Str.''' - -import unittest - -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.''' - - def testNumber(self): - '''Basic test to see if the Number class is Ok.''' - value = 123 - num = Number(value) - self.assertEqual(num.value(), value) - - def testStrCtorWithNumberArgument(self): - '''Try to build a Str from 'sample' module with a Number argument from 'other' module.''' - value = 123 - num = Number(value) - string = Str(num) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/objtypehashes_test.py b/tests/otherbinding/objtypehashes_test.py deleted file mode 100644 index 753aec1a1..000000000 --- a/tests/otherbinding/objtypehashes_test.py +++ /dev/null @@ -1,53 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import * -from other import * -import shiboken2 as shiboken - -class TestHashFuncs (unittest.TestCase): - - def testIt(self): - obj1 = HandleHolder() - obj2 = HandleHolder() - - hash1 = hash(obj1) - hash2 = hash(obj2) - self.assertNotEqual(hash1, hash2) - - # Now invalidate the object and test its hash. It shouldn't segfault. - shiboken.invalidate(obj1) - - hash1_2 = hash(obj1) - self.assertEqual(hash1_2, hash1) - - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/otherbinding/other-binding.txt.in b/tests/otherbinding/other-binding.txt.in deleted file mode 100644 index a17b70fc1..000000000 --- a/tests/otherbinding/other-binding.txt.in +++ /dev/null @@ -1,18 +0,0 @@ -[generator-project] - -generator-set = shiboken - -header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h -typesystem-file = @other_TYPESYSTEM@ - -output-directory = @CMAKE_CURRENT_BINARY_DIR@ - -include-path = @libother_SOURCE_DIR@ -include-path = @libsample_SOURCE_DIR@ -include-path = @libsample_SOURCE_DIR@/.. - -typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ -typesystem-path = @sample_SOURCE_DIR@ - -enable-parent-ctor-heuristic - diff --git a/tests/otherbinding/otherderived_test.py b/tests/otherbinding/otherderived_test.py deleted file mode 100644 index f6906c88a..000000000 --- a/tests/otherbinding/otherderived_test.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for OtherDerived class''' - -import sys -import unittest - -from sample import Abstract, Derived -from other import OtherDerived, Number - -class Multiple(Derived, Number): - def __init__(self): - Derived.__init__(self, 42) - Number.__init__(self, 42) - - def testCall(self): - return True - -class OtherDeviant(OtherDerived): - def __init__(self): - OtherDerived.__init__(self) - self.pure_virtual_called = False - self.unpure_virtual_called = False - - def pureVirtual(self): - self.pure_virtual_called = True - - def unpureVirtual(self): - self.unpure_virtual_called = True - - def className(self): - return 'OtherDeviant' - -class MultipleTest(unittest.TestCase): - '''Test case for Multiple derived class''' - - def testConstructor(self): - o = Multiple() - self.assertTrue(isinstance(o, Multiple)) - self.assertTrue(isinstance(o, Number)) - self.assertTrue(isinstance(o, Derived)) - del o - - def testMethodCall(self): - o = Multiple() - self.assertTrue(o.id_(), 42) - self.assertTrue(o.value(), 42) - self.assertTrue(o.testCall()) - -class OtherDerivedTest(unittest.TestCase): - '''Test case for OtherDerived class''' - - def testParentClassMethodsAvailability(self): - '''Test if OtherDerived class really inherits its methods from parent.''' - inherited_methods = set(['callPureVirtual', 'callUnpureVirtual', - 'id_', 'pureVirtual', 'unpureVirtual']) - 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++.''' - 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++.''' - d = OtherDeviant() - d.callUnpureVirtual() - self.assertTrue(d.unpure_virtual_called) - - def testVirtualMethodCallString(self): - '''Test virtual method call returning string.''' - d = OtherDerived() - self.assertEqual(d.className(), 'OtherDerived') - self.assertEqual(d.getClassName(), 'OtherDerived') - - def testReimplementedVirtualMethodCallReturningString(self): - '''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') - - def testCallToMethodWithAbstractArgument(self): - '''Call to method that expects an Abstract argument.''' - objId = 123 - d = OtherDerived(objId) - self.assertEqual(Abstract.getObjectId(d), objId) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/otherbinding/test_module_template.py b/tests/otherbinding/test_module_template.py deleted file mode 100644 index ddde85c2e..000000000 --- a/tests/otherbinding/test_module_template.py +++ /dev/null @@ -1,40 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -from other import * -from sample import * - - -class MyObjectType(ObjectType): - pass - -class MyOtherObjectType(OtherObjectType): - value = 10 - - -obj = MyObjectType() diff --git a/tests/otherbinding/typediscovery_test.py b/tests/otherbinding/typediscovery_test.py deleted file mode 100644 index 507c5be94..000000000 --- a/tests/otherbinding/typediscovery_test.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for type discovery''' - -import unittest - -from sample import Abstract, Base1, Derived, MDerived1, MDerived3, SonOfMDerived1 -from other import OtherMultipleDerived - -class TypeDiscoveryTest(unittest.TestCase): - - def testPureVirtualsOfImpossibleTypeDiscovery(self): - a = Derived.triggerImpossibleTypeDiscovery() - self.assertEqual(type(a), Abstract) - # call some pure virtual method - a.pureVirtual() - - def testAnotherImpossibleTypeDiscovery(self): - a = Derived.triggerAnotherImpossibleTypeDiscovery() - self.assertEqual(type(a), Derived) - - def testMultipleInheritance(self): - obj = OtherMultipleDerived.createObject("Base1"); - self.assertEqual(type(obj), Base1) - 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) - obj = OtherMultipleDerived.createObject("OtherMultipleDerived"); - self.assertEqual(type(obj), OtherMultipleDerived) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/otherbinding/typesystem_other.xml b/tests/otherbinding/typesystem_other.xml deleted file mode 100644 index 63ccdd518..000000000 --- a/tests/otherbinding/typesystem_other.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/tests/otherbinding/usersprimitivefromothermodule_test.py b/tests/otherbinding/usersprimitivefromothermodule_test.py deleted file mode 100755 index 06cfce371..000000000 --- a/tests/otherbinding/usersprimitivefromothermodule_test.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests user defined primitive type from a required module.''' - -import unittest -from other import Number - -class UserDefinedPrimitiveTypeFromRequiredModuleTest(unittest.TestCase): - - def testUsersPrimitiveFromRequiredModuleAsArgument(self): - '''static Number Number::fromComplex(Complex)''' - cpx = complex(3.0, 1.2) - number = Number.fromComplex(cpx) - self.assertEqual(number.value(), int(cpx.real)) - - def testUsersPrimitiveFromRequiredModuleAsReturnValue(self): - '''Complex Number::toComplex()''' - number = Number(12) - cpx = number.toComplex() - self.assertEqual(number.value(), int(cpx.real)) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/otherbinding/wrongctor_test.py b/tests/otherbinding/wrongctor_test.py deleted file mode 100644 index 61317fe66..000000000 --- a/tests/otherbinding/wrongctor_test.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import * -from other import * - -class Foo(OtherDerived): - def __init__(self): - 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 - - -class WrongCtorTest(unittest.TestCase): - def testIt(self): - self.assertRaises(TypeError, Foo) - self.assertRaises(TypeError, Foo2) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/py3k.py b/tests/py3k.py deleted file mode 100644 index 5f2961a6a..000000000 --- a/tests/py3k.py +++ /dev/null @@ -1,2 +0,0 @@ -def printToFile(f, str): - print(str, file=f) diff --git a/tests/py3kcompat.py b/tests/py3kcompat.py deleted file mode 100644 index 45550efb3..000000000 --- a/tests/py3kcompat.py +++ /dev/null @@ -1,54 +0,0 @@ -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import sys - -IS_PY3K = sys.version_info[0] == 3 - -if IS_PY3K: - def unicode(s): - return s - - def b(s): - return bytes(s, "UTF8") - - def l(n): - return n - - long = int -else: - def b(s): - return s - - def l(n): - return long(n) - - unicode = unicode - long = long diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt deleted file mode 100644 index f897712f4..000000000 --- a/tests/samplebinding/CMakeLists.txt +++ /dev/null @@ -1,145 +0,0 @@ -project(sample) - -set(sample_TYPESYSTEM -${CMAKE_CURRENT_SOURCE_DIR}/typesystem_sample.xml -) - -set(sample_SRC -${CMAKE_CURRENT_BINARY_DIR}/sample/abstractmodifications_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/abstract_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base1_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base2_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base3_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base4_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base5_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/bytearray_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/classwithfunctionpointer_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/color_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/ctorconvrule_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/derived_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/event_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/expression_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/friendofonlycopy_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/handleholder_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/implicitconv_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/implicitbase_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/implicittarget_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/intlist_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/sortedoverload_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/intwrapper_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/injectcode_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/listuser_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mapuser_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mderived1_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mderived2_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mderived3_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mderived4_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/mderived5_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/modelindex_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/modifications_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/modifiedconstructor_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/noimplicitconversion_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objectmodel_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypebyvalue_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeholder_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypederived_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypelayout_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeptrlist_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeoperators_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objectview_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/objtypereference_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/onlycopy_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/otherbase_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/overload_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/overload2_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/pairuser_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/pen_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/persistentmodelindex_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/photon_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/photon_base_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/photon_valueidentity_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/photon_valueduplicator_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/point_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/pointerholder_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/pointf_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/pointvaluelist_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/polygon_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/primitivestructpointerholder_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/privatector_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/privatedtor_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedenumclass_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectednonpolymorphic_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphic_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphicdaughter_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedpolymorphicgranddaughter_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedproperty_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/protectedvirtualdestructor_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/rect_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/rectf_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/reference_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/referentmodelindex_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/sample_module_wrapper.cpp -${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_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/simplefile_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/size_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/sizef_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/sonofmderived1_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/str_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/strlist_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/time_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/templateptr_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/unremovednamespace_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdaughter_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdtor_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/virtualmethods_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/voidholder_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/valueandvirtual_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/filter_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/data_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/sample/intersection_wrapper.cpp -${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) - -add_custom_command(OUTPUT ${sample_SRC} -COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/sample-binding.txt ${GENERATOR_EXTRA_FLAGS} -DEPENDS ${sample_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 -WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -COMMENT "Running generator for 'sample' test binding..." -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${libsample_SOURCE_DIR} - ${libshiboken_SOURCE_DIR}) -add_library(sample MODULE ${sample_SRC}) -set_property(TARGET sample PROPERTY PREFIX "") -if(WIN32) - set_property(TARGET sample PROPERTY SUFFIX ".pyd") -endif() -target_link_libraries(sample - libsample - ${SBK_PYTHON_LIBRARIES} - libshiboken) diff --git a/tests/samplebinding/__del___test.py b/tests/samplebinding/__del___test.py deleted file mode 100644 index fd787b5f0..000000000 --- a/tests/samplebinding/__del___test.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -import sample - -delCalled = False - -class MyObject(sample.ObjectType): - def __del__(self): - global delCalled - delCalled = True - -class TestDel(unittest.TestCase): - def testIt(self): - a = MyObject() - del a - self.assertTrue(delCalled) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/abstract_test.py b/tests/samplebinding/abstract_test.py deleted file mode 100644 index 46aad3260..000000000 --- a/tests/samplebinding/abstract_test.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Abstract class''' - -import sys -import unittest - -from sample import Abstract - -class Incomplete(Abstract): - def __init__(self): - Abstract.__init__(self) - -class Concrete(Abstract): - def __init__(self): - Abstract.__init__(self) - self.pure_virtual_called = False - self.unpure_virtual_called = False - - def pureVirtual(self): - self.pure_virtual_called = True - - def pureVirtualReturningVoidPtr(self): - return 42 - - def unpureVirtual(self): - self.unpure_virtual_called = True - - def virtualGettingAEnum(self, enum): - self.virtual_getting_enum = True - - -class AbstractTest(unittest.TestCase): - '''Test case for Abstract class''' - - def testAbstractPureVirtualMethodAvailability(self): - '''Test if Abstract class pure virtual method was properly wrapped.''' - self.assertTrue('pureVirtual' in dir(Abstract)) - - def testAbstractInstanciation(self): - '''Test if instanciation of an abstract class raises the correct exception.''' - self.assertRaises(NotImplementedError, Abstract) - - def testUnimplementedPureVirtualMethodCall(self): - '''Test if calling a pure virtual method raises the correct exception.''' - i = Incomplete() - self.assertRaises(NotImplementedError, i.pureVirtual) - - def testPureVirtualReturningVoidPtrReturnValue(self): - '''Test if a pure virtual method returning void ptr can be properly reimplemented''' - # Note that the semantics of reimplementing the pure virtual method in - # 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) - - def testReimplementedVirtualMethodCall(self): - '''Test if a Python override of a virtual method is correctly called from C++.''' - c = Concrete() - c.callUnpureVirtual() - self.assertTrue(c.unpure_virtual_called) - - def testImplementedPureVirtualMethodCall(self): - '''Test if a Python override of a pure virtual method is correctly called from C++.''' - c = Concrete() - c.callPureVirtual() - self.assertTrue(c.pure_virtual_called) - - def testEnumParameterOnVirtualMethodCall(self): - '''testEnumParameterOnVirtualMethodCall''' - c = Concrete() - c.callVirtualGettingEnum(Abstract.Short) - self.assertTrue(c.virtual_getting_enum) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/addedfunction_test.py b/tests/samplebinding/addedfunction_test.py deleted file mode 100644 index 1620a5114..000000000 --- a/tests/samplebinding/addedfunction_test.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for added functions.''' - -import unittest -from sample import SampleNamespace, ObjectType, Point - -class TestAddedFunctionsWithSimilarTypes(unittest.TestCase): - '''Adds new signatures very similar to already existing ones.''' - - def testValueTypeReferenceAndValue(self): - '''In C++ we have "function(const ValueType&, double)", - in Python we add "function(ValueType)".''' - point = Point(10, 20) - multiplier = 4.0 - control = (point.x() + point.y()) * multiplier - self.assertEqual(SampleNamespace.passReferenceToValueType(point, multiplier), control) - control = point.x() + point.y() - self.assertEqual(SampleNamespace.passReferenceToValueType(point), control) - - def testObjectTypeReferenceAndPointer(self): - '''In C++ we have "function(const ObjectType&, int)", - in Python we add "function(ValueType)".''' - obj = ObjectType() - obj.setObjectName('sbrubbles') - multiplier = 3.0 - control = len(obj.objectName()) * multiplier - self.assertEqual(SampleNamespace.passReferenceToObjectType(obj, multiplier), control) - control = len(obj.objectName()) - self.assertEqual(SampleNamespace.passReferenceToObjectType(obj), control) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/addedfunction_with_container_args_test.py b/tests/samplebinding/addedfunction_with_container_args_test.py deleted file mode 100644 index da2406698..000000000 --- a/tests/samplebinding/addedfunction_with_container_args_test.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for added functions with nested and multi-argument container types.''' - -import unittest -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]] - self.assertEqual(sum2d(values), 21) - - def testMultiArgContainerType(self): - '''Test added function with a two-argument container.''' - values = [(1,2),(3,4),(5,6)] - self.assertEqual(sumproduct(values), 44) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/argumentmodifications_test.py b/tests/samplebinding/argumentmodifications_test.py deleted file mode 100644 index 90db99f91..000000000 --- a/tests/samplebinding/argumentmodifications_test.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for method arguments modifications performed as described on typesystem.''' - -import sys -import unittest - -from sample import Modifications, Point - -class ArgumentModificationsTest(unittest.TestCase): - '''Test cases for method arguments modifications performed as described on typesystem.''' - - def setUp(self): - self.mods = Modifications() - - def tearDown(self): - del self.mods - - def testArgRemoval0(self): - '''Tests argument removal modifications on Modifications.argRemoval0.''' - # void [-> PyObject*] argRemoval0(int, bool, int = 123 [removed, new val = 321], int = 456) - # code-injection: returns tuple with received parameters plus removed ones - a0, a1, a2 = 1, True, 2 - self.assertEqual(self.mods.argRemoval0(a0, a1), (a0, a1, 321, 456)) - self.assertEqual(self.mods.argRemoval0(a0, a1, a2), (a0, a1, 321, a2)) - # the other wasn't modified - # void argRemoval0(int, bool, int, bool) - self.assertEqual(self.mods.argRemoval0(0, False, 0, False), None) - - 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) - # 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)) - self.assertEqual(self.mods.argRemoval1(a0, a1, a2), (a0, a1, Point(1, 2), Point(3, 4), a2)) - # the other wasn't modified - # void argRemoval1(int, bool, int, bool) - self.assertEqual(self.mods.argRemoval1(0, False, 0, False), None) - - 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) - # 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)) - self.assertEqual(self.mods.argRemoval2(a0, a1, a2), (a0, a1, Point(1, 2), Point(3, 4), a2)) - - 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) - # 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)) - self.assertEqual(self.mods.argRemoval3(a0, a1), (a0, Point(1, 2), a1, Point(3, 4), 333)) - self.assertEqual(self.mods.argRemoval3(a0, a1, a2), (a0, Point(1, 2), a1, Point(3, 4), a2)) - - 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) - # code-injection: returns tuple with received parameters plus removed ones - a0, a1, a2 = 1, True, 2 - self.assertRaises(TypeError, self.mods.argRemoval4, a0) - self.assertEqual(self.mods.argRemoval4(a0, a1), (a0, Point(6, 9), a1, Point(3, 4), 333)) - self.assertEqual(self.mods.argRemoval4(a0, a1, a2), (a0, Point(6, 9), a1, Point(3, 4), a2)) - - def testArgRemoval5(self): - '''Tests argument removal modifications on Modifications.argRemoval5.''' - # void [-> PyObject*] argRemoval5(int [removed, new val = 100], 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 = True, 2, True - self.assertEqual(self.mods.argRemoval5(a0), (100, a0, Point(1, 2), Point(3, 4), 333)) - self.assertEqual(self.mods.argRemoval5(a0, a1), (100, a0, Point(1, 2), Point(3, 4), a1)) - # void [-> PyObject*] argRemoval5(int [removed, new val = 200], bool, int, bool) - # 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/tests/samplebinding/bug_554_test.py b/tests/samplebinding/bug_554_test.py deleted file mode 100644 index 0bcce92cf..000000000 --- a/tests/samplebinding/bug_554_test.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Unit test for bug#554''' - -from sample import * - -class Bug554: - def crash(self): - class Crasher(ObjectType): - pass - -if __name__ == '__main__': - bug = Bug554() - bug.crash() - - diff --git a/tests/samplebinding/bug_704_test.py b/tests/samplebinding/bug_704_test.py deleted file mode 100644 index 6b393f3b1..000000000 --- a/tests/samplebinding/bug_704_test.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from py3kcompat import IS_PY3K - -from sample import ObjectType - - -class NewStyle(object): - def name(self): - return "NewStyle" - -class OldStyle: - def name(self): - return "OldStyle" - -def defineNewStyle(): - class MyObjectNew(ObjectType, NewStyle): - pass - -def defineOldStyle(): - class MyObjectOld(ObjectType, OldStyle): - pass - -class ObjectTypeTest(unittest.TestCase): - '''Test cases to avoid declaring Shiboken classes with multiple inheritance from old style classes.''' - - def testObjectTypeNewStype(self): - defineNewStyle() - - def testObjectTypeOldStype(self): - # Py 3k doesn't have old style classes - if not IS_PY3K: - self.assertRaises(TypeError, defineOldStyle) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/bytearray_bufferprotocol.cpp b/tests/samplebinding/bytearray_bufferprotocol.cpp deleted file mode 100644 index 39fb8d353..000000000 --- a/tests/samplebinding/bytearray_bufferprotocol.cpp +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#if PY_VERSION_HEX < 0x03000000 -// ByteArray buffer protocol functions -// See: http://www.python.org/dev/peps/pep-3118/ -extern "C" { -static Py_ssize_t SbkByteArray_segcountproc(PyObject* self, Py_ssize_t* lenp) -{ - if (lenp) - *lenp = self->ob_type->tp_as_sequence->sq_length(self); - return 1; -} -static Py_ssize_t SbkByteArray_readbufferproc(PyObject* self, Py_ssize_t segment, void** ptrptr) -{ - if (segment || !Shiboken::Object::isValid(self)) - return -1; - - ByteArray* cppSelf = %CONVERTTOCPP[ByteArray*](self); - *ptrptr = reinterpret_cast(const_cast(cppSelf->data())); - return cppSelf->size(); -} -PyBufferProcs SbkByteArrayBufferProc = { - /*bf_getreadbuffer*/ &SbkByteArray_readbufferproc, - /*bf_getwritebuffer*/ (writebufferproc)&SbkByteArray_readbufferproc, - /*bf_getsegcount*/ &SbkByteArray_segcountproc, - /*bf_getcharbuffer*/ (charbufferproc)&SbkByteArray_readbufferproc -}; -} -#endif diff --git a/tests/samplebinding/bytearray_test.py b/tests/samplebinding/bytearray_test.py deleted file mode 100644 index 0e8039469..000000000 --- a/tests/samplebinding/bytearray_test.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from os.path import isdir -from sample import ByteArray -from py3kcompat import b - - -class ByteArrayBufferProtocolTest(unittest.TestCase): - '''Tests ByteArray implementation of Python buffer protocol.''' - - def testByteArrayBufferProtocol(self): - # Tests ByteArray implementation of Python buffer protocol using the os.path.isdir - # function which an unicode object or other object implementing the Python buffer protocol. - isdir(str(ByteArray('/tmp'))) - - -class ByteArrayConcatenationOperatorTest(unittest.TestCase): - '''Test cases for ByteArray concatenation with '+' operator.''' - - def testConcatByteArrayAndPythonString(self): - # Test concatenation of a ByteArray with a Python string, in this order. - ba = ByteArray('foo') - result = ba + '\x00bar' - self.assertEqual(type(result), ByteArray) - self.assertEqual(result, 'foo\x00bar') - - def testConcatPythonStringAndByteArray(self): - # Test concatenation of a Python string with a ByteArray, in this order. - concat_python_string_add_qbytearray_worked = True - ba = ByteArray('foo') - result = 'bar\x00' + ba - self.assertEqual(type(result), ByteArray) - self.assertEqual(result, 'bar\x00foo') - - -class ByteArrayOperatorEqual(unittest.TestCase): - '''TestCase for operator ByteArray == ByteArray.''' - - def testDefault(self): - # ByteArray() == ByteArray() - obj1 = ByteArray() - obj2 = ByteArray() - self.assertEqual(obj1, obj2) - - def testSimple(self): - # ByteArray(some_string) == ByteArray(some_string) - string = 'egg snakes' - self.assertEqual(ByteArray(string), ByteArray(string)) - - def testPyString(self): - # ByteArray(string) == string - string = 'my test string' - self.assertEqual(ByteArray(string), string) - - def testQString(self): - # ByteArray(string) == string - string = 'another test string' - self.assertEqual(ByteArray(string), string) - - -class ByteArrayOperatorAt(unittest.TestCase): - '''TestCase for operator ByteArray[]''' - - def testInRange(self): - # ByteArray[x] where x is a valid index. - string = 'abcdefgh' - obj = ByteArray(string) - for i in range(len(string)): - self.assertEqual(obj[i], b(string[i])) - - def testInRangeReverse(self): - # ByteArray[x] where x is a valid index (reverse order). - string = 'abcdefgh' - obj = ByteArray(string) - for i in range(len(string)-1, 0, -1): - self.assertEqual(obj[i], b(string[i])) - - def testOutOfRange(self): - # ByteArray[x] where x is out of index. - string = '1234567' - obj = ByteArray(string) - self.assertRaises(IndexError, lambda :obj[len(string)]) - - def testNullStrings(self): - ba = ByteArray('\x00') - self.assertEqual(ba.at(0), '\x00') - self.assertEqual(ba[0], b('\x00')) - - -class ByteArrayOperatorLen(unittest.TestCase): - '''Test case for __len__ operator of ByteArray''' - - def testBasic(self): - '''ByteArray __len__''' - self.assertEqual(len(ByteArray()), 0) - self.assertEqual(len(ByteArray('')), 0) - self.assertEqual(len(ByteArray(' ')), 1) - self.assertEqual(len(ByteArray('yabadaba')), 8) - - -class ByteArrayAndPythonStr(unittest.TestCase): - '''Test case for __str__ operator of ByteArray''' - - def testStrOperator(self): - '''ByteArray __str__''' - self.assertEqual(ByteArray().__str__(), '') - self.assertEqual(ByteArray('').__str__(), '') - self.assertEqual(ByteArray('aaa').__str__(), 'aaa') - - def testPythonStrAndNull(self): - s1 = b('123\000321') - ba = ByteArray(s1) - s2 = ba.data() - self.assertEqual(s1, s2) - self.assertEqual(type(s1), type(s2)) - self.assertEqual(s1, ba) - self.assertNotEqual(type(s1), type(ba)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/child_return_test.py b/tests/samplebinding/child_return_test.py deleted file mode 100644 index 30859dc5a..000000000 --- a/tests/samplebinding/child_return_test.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''The BlackBox class has cases of ownership transference between C++ and Python.''' - -import sys -import unittest - -from sample import * - -class ReturnOfChildTest(unittest.TestCase): - '''The BlackBox class has cases of ownership transference between C++ and Python.''' - - def testKillParentKeepingChild(self): - '''Ownership transference from Python to C++ and back again.''' - o1 = ObjectType.createWithChild() - child = o1.children()[0] - del o1 - self.assertRaises(RuntimeError, child.objectName) - - def testKillParentKeepingChild2(self): - '''Ownership transference from Python to C++ and back again.''' - o1 = ObjectType.createWithChild() - child = o1.findChild("child") - del o1 - self.assertRaises(RuntimeError, child.objectName) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/class_fields_test.py b/tests/samplebinding/class_fields_test.py deleted file mode 100644 index 0a2491cf2..000000000 --- a/tests/samplebinding/class_fields_test.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Simple test case for accessing the exposed C++ class fields.''' - -from sys import getrefcount -import unittest - -from sample import Derived, Point, ObjectType - -class TestAccessingCppFields(unittest.TestCase): - '''Simple test case for accessing the exposed C++ class fields.''' - - def testAccessingPrimitiveTypeField(self): - '''Reads and writes a primitive type (in this case an 'int') field.''' - d = Derived() - self.assertEqual(type(d.primitiveField), int) - - # attribution - old_value = d.primitiveField - new_value = 2255 - d.primitiveField = new_value - self.assertEqual(d.primitiveField, new_value) - self.assertNotEqual(d.primitiveField, old_value) - - # attribution with a convertible type - value = 1.2 - d.primitiveField = value - self.assertEqual(d.primitiveField, int(value)) - - # attribution with invalid type - self.assertRaises(TypeError, lambda : setattr(d, 'primitiveField', None)) - - def testAccessingUsersPrimitiveTypeField(self): - '''Reads and writes an user's primitive type (in this case an 'Complex') field.''' - d = Derived() - self.assertEqual(type(d.userPrimitiveField), complex) - - # attribution - old_value = d.userPrimitiveField - new_value = complex(1.1, 2.2) - d.userPrimitiveField = new_value - self.assertEqual(d.userPrimitiveField, new_value) - self.assertNotEqual(d.userPrimitiveField, old_value) - - # attribution with invalid type - self.assertRaises(TypeError, lambda : setattr(d, 'userPrimitiveField', None)) - - def testAccessingValueTypeField(self): - '''Reads and writes a value type (in this case a 'Point') field.''' - d = Derived() - self.assertEqual(type(d.valueTypeField), Point) - - # attribution - old_value = d.valueTypeField - new_value = Point(-10, 537) - d.valueTypeField = new_value - self.assertEqual(d.valueTypeField, new_value) - - #object modify - d.valueTypeField.setX(10) - d.valueTypeField.setY(20) - self.assertEqual(d.valueTypeField.x(), 10) - self.assertEqual(d.valueTypeField.y(), 20) - - # attribution with invalid type - self.assertRaises(TypeError, lambda : setattr(d, 'valueTypeField', 123)) - - def testAccessingObjectTypeField(self): - '''Reads and writes a object type (in this case an 'ObjectType') field.''' - d = Derived() - - # attribution - old_value = d.objectTypeField - new_value = ObjectType() - d.objectTypeField = new_value - self.assertEqual(d.objectTypeField, new_value) - self.assertNotEqual(d.objectTypeField, old_value) - - # attribution with a convertible type - value = None - d.objectTypeField = value - self.assertEqual(d.objectTypeField, value) - - # attribution with invalid type - self.assertRaises(TypeError, lambda : setattr(d, 'objectTypeField', 123)) - - def testRefCountingAccessingObjectTypeField(self): - '''Accessing a object type field should respect the reference counting rules.''' - d = Derived() - - # attributing object to instance's field should increase its reference count - o1 = ObjectType() - refcount1 = getrefcount(o1) - d.objectTypeField = o1 - self.assertEqual(d.objectTypeField, o1) - self.assertEqual(getrefcount(d.objectTypeField), refcount1 + 1) - - # attributing a new object to instance's field should decrease the previous object's reference count - o2 = ObjectType() - refcount2 = getrefcount(o2) - d.objectTypeField = o2 - self.assertEqual(d.objectTypeField, o2) - self.assertEqual(getrefcount(o1), refcount1) - self.assertEqual(getrefcount(d.objectTypeField), refcount2 + 1) - - def testRefCountingOfReferredObjectAfterDeletingReferrer(self): - '''Deleting the object referring to other object should decrease the reference count of the referee.''' - d = Derived() - o = ObjectType() - refcount = getrefcount(o) - d.objectTypeField = o - self.assertEqual(getrefcount(o), refcount + 1) - del d - self.assertEqual(getrefcount(o), refcount) - - def testStaticField(self): - self.assertEqual(Derived.staticPrimitiveField, 0) - - def testAccessingUnsignedIntBitField(self): - d = Derived() - - # attribution - old_value = d.bitField - new_value = 1 - d.bitField= new_value - self.assertEqual(d.bitField, new_value) - self.assertNotEqual(d.bitField, old_value) - - # attribution with a convertible type - value = 1.2 - d.bitField = value - self.assertEqual(d.bitField, int(value)) - - # attribution with invalid type - self.assertRaises(TypeError, lambda : setattr(d, 'bitField', None)) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/collector_test.py b/tests/samplebinding/collector_test.py deleted file mode 100644 index cbd6326e6..000000000 --- a/tests/samplebinding/collector_test.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Collector class' shift operators.''' - -import sys -import unittest - -from sample import Collector, IntWrapper, ObjectType - - -class CollectorTest(unittest.TestCase): - '''Test cases for Collector class' shift operators.''' - - def testLShiftOperatorSingleUse(self): - '''Test case for using the Collector.__lshift__ operator just one time.''' - collector = Collector() - collector << 13 - self.assertEqual(collector.size(), 1) - self.assertEqual(collector.items(), [13]) - - def testLShiftOperatorMultipleUses(self): - '''Test case for using the Collector.__lshift__ operator many times in the same line.''' - collector = Collector() - collector << 2 << 3 << 5 << 7 << 11 - 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''' - - def testLShiftExternal(self): - '''Collector external operator''' - collector = Collector() - collector << IntWrapper(5) - self.assertEqual(collector.size(), 1) - self.assertEqual(collector.items(), [5]) - - -class CollectorObjectType(unittest.TestCase): - '''Test cases for Collector ObjectType''' - - def testBasic(self): - '''Collector << ObjectType # greedy collector''' - collector = Collector() - obj = ObjectType() - collector << obj - self.assertEqual(collector.items()[0], obj.identifier()) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/complex_test.py b/tests/samplebinding/complex_test.py deleted file mode 100644 index 3a14f4d15..000000000 --- a/tests/samplebinding/complex_test.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Complex class''' - -import sys -import unittest - -import sample -from sample import Point - -class ComplexTest(unittest.TestCase): - '''Test case for conversions between C++ Complex class to Python complex class''' - - def testFunctionReturningComplexObject(self): - '''Test function returning a C++ Complex object.''' - cpx = sample.transmutePointIntoComplex(Point(5.0, 2.3)) - self.assertEqual(cpx, complex(5.0, 2.3)) - - def testFunctionReceivingComplexObjectAsArgument(self): - '''Test function returning a C++ Complex object.''' - pt = sample.transmuteComplexIntoPoint(complex(1.2, 3.4)) - # these assertions intentionally avoids to test the == operator, - # it should have its own test cases. - self.assertEqual(pt.x(), 1.2) - self.assertEqual(pt.y(), 3.4) - - def testComplexList(self): - '''Test list of C++ Complex objects conversion to a list of Python complex objects.''' - # the global function gimmeComplexList() is expected to return a list - # containing the following Complex values: [0j, 1.1+2.2j, 1.3+2.4j] - cpxlist = sample.gimmeComplexList() - self.assertEqual(cpxlist, [complex(), complex(1.1, 2.2), complex(1.3, 2.4)]) - - def testSumComplexPair(self): - '''Test sum of a tuple containing two complex objects.''' - cpx1 = complex(1.2, 3.4) - cpx2 = complex(5.6, 7.8) - self.assertEqual(sample.sumComplexPair((cpx1, cpx2)), cpx1 + cpx2) - - 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)))) - cpx1, cpx2 = (1, 3), (5, 7) - 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)))) - cpx1, cpx2 = (1, 2, 3), (4, 5, 7) - self.assertRaises(TypeError, sample.sumComplexPair, (cpx1, cpx2)) - cpx1, cpx2 = ('1', '2'), ('4', '5') - self.assertRaises(TypeError, sample.sumComplexPair, (cpx1, cpx2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/conversion_operator_test.py b/tests/samplebinding/conversion_operator_test.py deleted file mode 100644 index 01ac102e8..000000000 --- a/tests/samplebinding/conversion_operator_test.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for implicit conversion generated by conversion operator.''' - -import unittest - -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.''' - t = Time(1, 2, 3) - t_str = t.toString() - sl = StrList() - - # StrList.append expects a Str object. - sl.append(t) - - self.assertEqual(len(sl), 1) - self.assertEqual(sl[0], t_str) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/copy_test.py b/tests/samplebinding/copy_test.py deleted file mode 100644 index 09c8e4cbc..000000000 --- a/tests/samplebinding/copy_test.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for deep copy of objects''' - -import copy -import unittest - -try: - import cPickle as pickle -except ImportError: - import pickle - - -from sample import Point - - -class SimpleCopy(unittest.TestCase): - '''Simple copy of objects''' - - def testCopy(self): - point = Point(0.1, 2.4) - new_point = copy.copy(point) - - self.assertTrue(point is not new_point) - self.assertEqual(point, new_point) - - -class DeepCopy(unittest.TestCase): - '''Deep copy with shiboken objects''' - - def testDeepCopy(self): - '''Deep copy of value types''' - point = Point(3.1, 4.2) - new_point = copy.deepcopy([point])[0] - - self.assertTrue(point is not new_point) - self.assertEqual(point, new_point) - - -class PicklingTest(unittest.TestCase): - '''Support pickling''' - - def testSimple(self): - '''Simple pickling and unpickling''' - - point = Point(10.2, 43.5) - - data = pickle.dumps(point) - new_point = pickle.loads(data) - - self.assertEqual(point, new_point) - self.assertTrue(point is not new_point) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ctorconvrule_test.py b/tests/samplebinding/ctorconvrule_test.py deleted file mode 100644 index d1ebdc9d3..000000000 --- a/tests/samplebinding/ctorconvrule_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for proper generation of constructor altered by conversion-rule tag.''' - -import unittest - -from sample import CtorConvRule - -class TestCtorConvRule(unittest.TestCase): - '''Simple test case for CtorConvRule''' - - def testCtorConvRule(self): - '''Test CtorConvRule argument modification through conversion-rule tag.''' - value = 123 - obj = CtorConvRule(value) - self.assertEqual(obj.value(), value + 1) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/cyclic_test.py b/tests/samplebinding/cyclic_test.py deleted file mode 100644 index e92b3605f..000000000 --- a/tests/samplebinding/cyclic_test.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import ObjectType -from sample import ObjectView -from sample import ObjectModel - - - -class ObjTest(unittest.TestCase): - - def test_cyclic_dependency_withParent(self): - """Create 2 objects with a cyclic dependency, so that they can - only be removed by the garbage collector, and then invoke the - garbage collector in a different thread. - """ - import gc - - class CyclicChildObject(ObjectType): - def __init__(self, parent): - super(CyclicChildObject, self).__init__(parent) - self._parent = parent - - class CyclicObject(ObjectType): - def __init__(self): - super(CyclicObject, self).__init__() - CyclicChildObject(self) - - # 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() ) - - # - # first proof that the wizard is only destructed by the garbage - # collector - # - cycle = CyclicObject() - self.assertTrue(alive()) - del cycle - self.assertTrue(alive()) - gc.collect() - self.assertFalse(alive()) - - def test_cyclic_dependency_withKeepRef(self): - """Create 2 objects with a cyclic dependency, so that they can - only be removed by the garbage collector, and then invoke the - garbage collector in a different thread. - """ - import gc - - class CyclicChildObject(ObjectView): - def __init__(self, model): - super(CyclicChildObject, self).__init__(None) - self.setModel(model) - - class CyclicObject(ObjectModel): - def __init__(self): - super(CyclicObject, self).__init__() - self._view = CyclicChildObject(self) - - # 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() ) - - # - # first proof that the wizard is only destructed by the garbage - # collector - # - cycle = CyclicObject() - self.assertTrue(alive()) - del cycle - self.assertTrue(alive()) - gc.collect() - self.assertFalse(alive()) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/date_test.py b/tests/samplebinding/date_test.py deleted file mode 100644 index 800774a57..000000000 --- a/tests/samplebinding/date_test.py +++ /dev/null @@ -1,58 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for python conversions types ''' - -import sys -import unittest -from datetime import date - -from sample import SbkDate - -class DateConversionTest(unittest.TestCase): - - def testConstructorWithDateObject(self): - pyDate = date(2010, 12, 12) - cDate = SbkDate(pyDate) - self.assertTrue(cDate.day(), pyDate.day) - self.assertTrue(cDate.month(), pyDate.month) - self.assertTrue(cDate.year(), pyDate.year) - - def testToPythonFunction(self): - cDate = SbkDate(2010, 12, 12) - pyDate = cDate.toPython() - self.assertTrue(cDate.day(), pyDate.day) - self.assertTrue(cDate.month(), pyDate.month) - self.assertTrue(cDate.year(), pyDate.year) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/decisor_test.py b/tests/samplebinding/decisor_test.py deleted file mode 100644 index 33f41b9ff..000000000 --- a/tests/samplebinding/decisor_test.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for the method overload decisor.''' - -import unittest - -from sample import SampleNamespace, Point, ObjectType, ObjectModel - -class DecisorTest(unittest.TestCase): - '''Test cases for the method overload decisor.''' - - def testCallWithInvalidParametersSideA(self): - '''Call a method missing with the last argument missing. - This can trigger the bug #262, which means using an argument - not provided by the user.''' - pt = Point() - self.assertRaises(TypeError, SampleNamespace.forceDecisorSideA, pt) - - def testCallWithInvalidParametersSideB(self): - '''Same as the previous test, but with an integer as first argument, - just to complicate things for the overload method decisor.''' - pt = Point() - self.assertRaises(TypeError, SampleNamespace.forceDecisorSideB, 1, pt) - - def testDecideCallWithInheritance(self): - '''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) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/delete_test.py b/tests/samplebinding/delete_test.py deleted file mode 100644 index bc20ea234..000000000 --- a/tests/samplebinding/delete_test.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -import sample -import shiboken2 as shiboken - -class DeleteTest(unittest.TestCase): - def testNonCppWrapperClassDelete(self): - """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/tests/samplebinding/deprecated_test.py b/tests/samplebinding/deprecated_test.py deleted file mode 100644 index 6c850cd10..000000000 --- a/tests/samplebinding/deprecated_test.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import warnings -import unittest - -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/tests/samplebinding/derived_test.py b/tests/samplebinding/derived_test.py deleted file mode 100644 index b19835fef..000000000 --- a/tests/samplebinding/derived_test.py +++ /dev/null @@ -1,153 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Derived class''' - -import sys -import unittest - -import sample -from sample import Abstract, Derived, OverloadedFuncEnum - -class Deviant(Derived): - def __init__(self): - Derived.__init__(self) - self.pure_virtual_called = False - self.unpure_virtual_called = False - - def pureVirtual(self): - self.pure_virtual_called = True - - def unpureVirtual(self): - self.unpure_virtual_called = True - - def className(self): - return 'Deviant' - -class DerivedTest(unittest.TestCase): - '''Test case for Derived class''' - - def testParentClassMethodsAvailability(self): - '''Test if Derived class really inherits its methods from parent.''' - inherited_methods = set(['callPureVirtual', 'callUnpureVirtual', - 'id_', 'pureVirtual', 'unpureVirtual']) - self.assertTrue(inherited_methods.issubset(dir(Derived))) - - 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) - - def testOtherOverloadedMethodCall(self): - '''Another test to check overloaded method calling, just to double check.''' - derived = Derived() - - result = derived.otherOverloaded(1, 2, True, 3.3) - self.assertEqual(type(result), Derived.OtherOverloadedFuncEnum) - self.assertEqual(result, sample.Derived.OtherOverloadedFunc_iibd) - - result = derived.otherOverloaded(1, 2.2) - self.assertEqual(type(result), Derived.OtherOverloadedFuncEnum) - self.assertEqual(result, Derived.OtherOverloadedFunc_id) - - 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.''' - 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++.''' - 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++.''' - d = Deviant() - d.callUnpureVirtual() - self.assertTrue(d.unpure_virtual_called) - - def testVirtualMethodCallString(self): - '''Test virtual method call returning string.''' - d = Derived() - self.assertEqual(d.className(), 'Derived') - self.assertEqual(d.getClassName(), 'Derived') - - def testReimplementedVirtualMethodCallReturningString(self): - '''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') - - def testSingleArgument(self): - '''Test singleArgument call.''' - d = Derived() - self.assertTrue(d.singleArgument(False)) - self.assertTrue(not d.singleArgument(True)) - - def testMethodCallWithDefaultValue(self): - '''Test method call with default value.''' - d = Derived() - self.assertEqual(d.defaultValue(3), 3.1) - self.assertEqual(d.defaultValue(), 0.1) - - def testCallToMethodWithAbstractArgument(self): - '''Call to method that expects an Abstract argument.''' - objId = 123 - d = Derived(objId) - 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.''' - obj = Derived.createObject() - self.assertEqual(type(obj), Derived) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/duck_punching_test.py b/tests/samplebinding/duck_punching_test.py deleted file mode 100644 index fd60a96af..000000000 --- a/tests/samplebinding/duck_punching_test.py +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for virtual methods.''' - -import types -import unittest -from py3kcompat import IS_PY3K - -from sample import VirtualMethods, SimpleFile, Point - -def MethodTypeCompat(func, instance): - if IS_PY3K: - return types.MethodType(func, instance) - else: - return types.MethodType(func, instance, type(instance)) - -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").''' - - def setUp(self): - self.multiplier = 2.0 - self.duck_method_called = False - self.call_counter = 0 - - def testMonkeyPatchOnVirtualMethod(self): - '''Injects new 'virtualMethod0' on a VirtualMethods instance and makes C++ call it.''' - vm = VirtualMethods() - pt, val, cpx, b = Point(1.1, 2.2), 4, complex(3.3, 4.4), True - - result1 = vm.virtualMethod0(pt, val, cpx, b) - result2 = vm.callVirtualMethod0(pt, val, cpx, b) - self.assertEqual(result1, result2) - self.assertEqual(result1, VirtualMethods.virtualMethod0(vm, pt, val, cpx, b)) - - def myVirtualMethod0(obj, pt, val, cpx, b): - self.duck_method_called = True - return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) * self.multiplier - vm.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, vm) - - result1 = vm.callVirtualMethod0(pt, val, cpx, b) - self.assertTrue(self.duck_method_called) - - result2 = vm.virtualMethod0(pt, val, cpx, b) - self.assertEqual(result1, result2) - 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 - # BindingManager. This is useful when compiling Shiboken - # for debug, since the BindingManager destructor has an - # assert that checks if the wrapper mapper is empty. - vm.virtualMethod0 = None - - def testMonkeyPatchOnVirtualMethodWithInheritance(self): - '''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 - - result1 = duck.virtualMethod0(pt, val, cpx, b) - result2 = duck.callVirtualMethod0(pt, val, cpx, b) - self.assertEqual(result1, result2) - self.assertEqual(result1, VirtualMethods.virtualMethod0(duck, pt, val, cpx, b)) - - def myVirtualMethod0(obj, pt, val, cpx, b): - self.duck_method_called = True - return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) * self.multiplier - duck.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, duck) - - result1 = duck.callVirtualMethod0(pt, val, cpx, b) - self.assertTrue(self.duck_method_called) - - result2 = duck.virtualMethod0(pt, val, cpx, b) - self.assertEqual(result1, result2) - self.assertEqual(result1, VirtualMethods.virtualMethod0(duck, pt, val, cpx, b) * self.multiplier) - - duck.virtualMethod0 = None - - def testMonkeyPatchOnMethodWithStaticAndNonStaticOverloads(self): - '''Injects new 'exists' on a SimpleFile instance and makes C++ call it.''' - simplefile = SimpleFile('foobar') - - # Static 'exists' - simplefile.exists('sbrubbles') - self.assertFalse(self.duck_method_called) - # Non-static 'exists' - simplefile.exists() - self.assertFalse(self.duck_method_called) - - def myExists(obj): - self.duck_method_called = True - return False - simplefile.exists = MethodTypeCompat(myExists, simplefile) - - # Static 'exists' was overridden by the monkey patch, which accepts 0 arguments - self.assertRaises(TypeError, simplefile.exists, 'sbrubbles') - # Monkey patched exists - simplefile.exists() - self.assertTrue(self.duck_method_called) - - simplefile.exists = None - - def testMonkeyPatchOnMethodWithStaticAndNonStaticOverloadsWithInheritance(self): - '''Injects new 'exists' on an object that inherits from SimpleFile and makes C++ call it.''' - monkey = Monkey('foobar') - - # Static 'exists' - monkey.exists('sbrubbles') - self.assertFalse(self.duck_method_called) - # Non-static 'exists' - monkey.exists() - self.assertFalse(self.duck_method_called) - - def myExists(obj): - self.duck_method_called = True - return False - monkey.exists = MethodTypeCompat(myExists, monkey) - - # Static 'exists' was overridden by the monkey patch, which accepts 0 arguments - self.assertRaises(TypeError, monkey.exists, 'sbrubbles') - # Monkey patched exists - monkey.exists() - self.assertTrue(self.duck_method_called) - - monkey.exists = None - - def testForInfiniteRecursion(self): - def myVirtualMethod0(obj, pt, val, cpx, b): - self.call_counter += 1 - return VirtualMethods.virtualMethod0(obj, pt, val, cpx, b) - vm = VirtualMethods() - vm.virtualMethod0 = MethodTypeCompat(myVirtualMethod0, vm) - pt, val, cpx, b = Point(1.1, 2.2), 4, complex(3.3, 4.4), True - vm.virtualMethod0(pt, val, cpx, b) - self.assertEqual(self.call_counter, 1) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/echo_test.py b/tests/samplebinding/echo_test.py deleted file mode 100644 index 1b0b6a2cc..000000000 --- a/tests/samplebinding/echo_test.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for with const char* as argument''' - -import unittest - -from sample import Echo - -class TestEcho(unittest.TestCase): - '''Simple test case for Echo.echo''' - - def testEcho(self): - '''Test function added with const char * as arg''' - x = 'Foobar' - y = Echo().echo(x) - self.assertEqual(x, y) - - def testCallOperator(self): - e = Echo() - self.assertEqual(e("Hello", 3), "Hello3"); -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/enum_test.py b/tests/samplebinding/enum_test.py deleted file mode 100644 index 6468d3cc4..000000000 --- a/tests/samplebinding/enum_test.py +++ /dev/null @@ -1,168 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Python representation of C++ enums.''' - -import os -import sys -import unittest - -import sample -from sample import SampleNamespace, ObjectType, Event -from py3kcompat import IS_PY3K, b - -def createTempFile(): - if sys.version_info >= (2, 6): - import tempfile - return tempfile.SpooledTemporaryFile(mode='rw') - else: - return os.tmpfile() - -class EnumTest(unittest.TestCase): - '''Test case for Python representation of C++ enums.''' - - 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.values: - enum_item1 = getattr(SampleNamespace.Option, value_name) - enum_item2 = getattr(SampleNamespace, value_name) - self.assertEqual(enum_item1, enum_item2) - - def testPassingIntegerOnEnumArgument(self): - '''Tries to use an integer in place of an enum argument.''' - self.assertRaises(TypeError, SampleNamespace.getNumber, 1) - - def testBuildingEnumFromIntegerValue(self): - '''Tries to build the proper enum using an integer.''' - SampleNamespace.getNumber(SampleNamespace.Option(1)) - - def testBuildingEnumWithDefaultValue(self): - '''Enum constructor with default value''' - enum = SampleNamespace.Option() - self.assertEqual(enum, SampleNamespace.None_) - - def testEnumConversionToAndFromPython(self): - '''Conversion of enum objects from Python to C++ back again.''' - enumout = SampleNamespace.enumInEnumOut(SampleNamespace.TwoIn) - self.assertTrue(enumout, SampleNamespace.TwoOut) - self.assertEqual(repr(enumout), repr(SampleNamespace.TwoOut)) - - def testEnumConstructorWithTooManyParameters(self): - '''Calling the constructor of non-extensible enum with the wrong number of parameters.''' - self.assertRaises(TypeError, SampleNamespace.InValue, 13, 14) - - def testEnumConstructorWithNonNumberParameter(self): - '''Calling the constructor of non-extensible enum with a string.''' - self.assertRaises(TypeError, SampleNamespace.InValue, '1') - - 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(123), 123) - - def testAnonymousGlobalEnums(self): - '''Checks availability of anonymous global enum items.''' - self.assertEqual(sample.AnonymousGlobalEnum_Value0, 0) - self.assertEqual(sample.AnonymousGlobalEnum_Value1, 1) - - def testAnonymousClassEnums(self): - '''Checks availability of anonymous class enum items.''' - self.assertEqual(SampleNamespace.AnonymousClassEnum_Value0, 0) - self.assertEqual(SampleNamespace.AnonymousClassEnum_Value1, 1) - - def testEnumTpPrintImplementation(self): - '''Without SbkEnum.tp_print 'print' returns the enum represented as an int.''' - tmpfile = createTempFile() - if IS_PY3K: - from py3k import printToFile - printToFile(tmpfile, Event.ANY_EVENT) - else: - sys.stdout = tmpfile - print(Event.ANY_EVENT) - sys.stdout = sys.__stdout__ - tmpfile.seek(0) - text = tmpfile.read().strip() - tmpfile.close() - self.assertEqual(text, str(Event.ANY_EVENT)) - self.assertEqual(text, repr(Event.ANY_EVENT)) - - def testEnumArgumentWithDefaultValue(self): - '''Option enumArgumentWithDefaultValue(Option opt = UnixTime);''' - self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(), SampleNamespace.UnixTime) - self.assertEqual(SampleNamespace.enumArgumentWithDefaultValue(SampleNamespace.RandomNumber), SampleNamespace.RandomNumber) - - -class MyEvent(Event): - def __init__(self): - Event.__init__(self, Event.EventType(999)) - -class OutOfBoundsTest(unittest.TestCase): - def testValue(self): - e = MyEvent() - self.assertEqual(repr(e.eventType()), 'sample.Event.EventType(999)') - - def testNoneName(self): - e = MyEvent() - t = e.eventType() - self.assertEqual(t.name, None) - -class EnumOverloadTest(unittest.TestCase): - '''Test case for overloads involving enums''' - - def testWithInt(self): - '''Overload with Enums and ints with default value''' - o = ObjectType() - - self.assertEqual(o.callWithEnum('', Event.ANY_EVENT, 9), 81) - self.assertEqual(o.callWithEnum('', 9), 9) - -class EnumOperators(unittest.TestCase): - '''Test case for operations on enums''' - - def testInequalitySameObject(self): - self.assertFalse(Event.ANY_EVENT != Event.ANY_EVENT) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/enumfromremovednamespace_test.py b/tests/samplebinding/enumfromremovednamespace_test.py deleted file mode 100644 index 820e21f7c..000000000 --- a/tests/samplebinding/enumfromremovednamespace_test.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -import sample - -class TestEnumFromRemovedNamespace(unittest.TestCase): - def testEnumPromotedToGlobal(self): - sample.RemovedNamespace1_Enum - sample.RemovedNamespace1_Enum_Value0 - sample.RemovedNamespace1_AnonymousEnum_Value0 - sample.RemovedNamespace2_Enum - sample.RemovedNamespace2_Enum_Value0 - - def testEnumPromotedToUpperNamespace(self): - sample.UnremovedNamespace - sample.UnremovedNamespace.RemovedNamespace3_Enum - sample.UnremovedNamespace.RemovedNamespace3_Enum_Value0 - sample.UnremovedNamespace.RemovedNamespace3_AnonymousEnum_Value0 - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/event_loop_call_virtual_test.py b/tests/samplebinding/event_loop_call_virtual_test.py deleted file mode 100644 index d8ed028c4..000000000 --- a/tests/samplebinding/event_loop_call_virtual_test.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python - -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Simple event loop dispatcher test.''' - -import time -import unittest -from random import random - -from sample import ObjectType, Event - - -class NoOverride(ObjectType): - - pass - - -class Override(ObjectType): - - def __init__(self): - ObjectType.__init__(self) - self.called = False - - def event(self, event): - self.called = True - return True - - -class TestEventLoop(unittest.TestCase): - - def testEventLoop(self): - '''Calling virtuals in a event loop''' - objs = [ObjectType(), NoOverride(), Override()] - - evaluated = ObjectType.processEvent(objs, - Event(Event.BASIC_EVENT)) - - self.assertEqual(evaluated, 3) - self.assertTrue(objs[2].called) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/event_loop_thread_test.py b/tests/samplebinding/event_loop_thread_test.py deleted file mode 100644 index 8211ecd15..000000000 --- a/tests/samplebinding/event_loop_thread_test.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python - -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import time -import threading -import unittest -from random import random - -from sample import ObjectType, Event - - -class Producer(ObjectType): - - def __init__(self): - ObjectType.__init__(self) - self.data = None - self.read = False - - def event(self, event): - self.data = random() - - while not self.read: - time.sleep(0.01) - - return True - - -class Collector(threading.Thread): - - def __init__(self, objects): - threading.Thread.__init__(self) - self.max_runs = len(objects) - self.objects = objects - self.data = [] - - def run(self): - i = 0 - while i < self.max_runs: - if self.objects[i].data is not None: - self.data.append(self.objects[i].data) - self.objects[i].read = True - i += 1 - time.sleep(0.01) - - -class TestEventLoopWithThread(unittest.TestCase): - '''Communication between a python thread and an simple - event loop in C++''' - - def testBasic(self): - '''Allowing threads and calling virtuals from C++''' - number = 10 - objs = [Producer() for x in range(number)] - thread = Collector(objs) - - thread.start() - - evaluated = ObjectType.processEvent(objs, - Event(Event.BASIC_EVENT)) - - thread.join() - - producer_data = [x.data for x in objs] - self.assertEqual(evaluated, number) - self.assertEqual(producer_data, thread.data) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/filter_test.py b/tests/samplebinding/filter_test.py deleted file mode 100644 index eb84a932c..000000000 --- a/tests/samplebinding/filter_test.py +++ /dev/null @@ -1,45 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import Data, Intersection, Union - -class TestFilters(unittest.TestCase): - - def testAnd(self): - - f1 = Data(Data.Name, "joe") - f2 = Union() - - inter = f1 & f2 - - self.assertEqual(type(inter), Intersection) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h deleted file mode 100644 index d273de961..000000000 --- a/tests/samplebinding/global.h +++ /dev/null @@ -1,90 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "abstract.h" -#include "blackbox.h" -#include "bytearray.h" -#include "bucket.h" -#include "collector.h" -#include "complex.h" -#include "ctorconvrule.h" -#include "cvlist.h" -#include "sbkdate.h" -#include "derived.h" -#include "echo.h" -#include "functions.h" -#include "implicitconv.h" -#include "overloadsort.h" -#include "handle.h" -#include "injectcode.h" -#include "list.h" -#include "listuser.h" -#include "mapuser.h" -#include "modelindex.h" -#include "modifications.h" -#include "modified_constructor.h" -#include "multiple_derived.h" -#include "noimplicitconversion.h" -#include "nondefaultctor.h" -#include "objectmodel.h" -#include "objecttype.h" -#include "objecttypebyvalue.h" -#include "objecttypeholder.h" -#include "objecttypelayout.h" -#include "objecttypeoperators.h" -#include "objectview.h" -#include "oddbool.h" -#include "onlycopy.h" -#include "overload.h" -#include "pairuser.h" -#include "pen.h" -#include "photon.h" -#include "point.h" -#include "pointf.h" -#include "pointerholder.h" -#include "polygon.h" -#include "privatector.h" -#include "privatedtor.h" -#include "protected.h" -#include "rect.h" -#include "reference.h" -#include "removednamespaces.h" -#include "sample.h" -#include "samplenamespace.h" -#include "simplefile.h" -#include "size.h" -#include "str.h" -#include "strlist.h" -#include "sometime.h" -#include "templateptr.h" -#include "transform.h" -#include "virtualmethods.h" -#include "voidholder.h" -#include "valueandvirtual.h" -#include "expression.h" -#include "filter.h" diff --git a/tests/samplebinding/handleholder_test.py b/tests/samplebinding/handleholder_test.py deleted file mode 100644 index 6d945e499..000000000 --- a/tests/samplebinding/handleholder_test.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -''' Test case for a class that holds a unknown handle object. - Test case for BUG #1105. -''' - -import unittest - -from sample import HandleHolder - -class HandleHolderTest(unittest.TestCase): - def testCreation(self): - holder = HandleHolder(HandleHolder.createHandle()) - holder2 = HandleHolder(HandleHolder.createHandle()) - self.assertEqual(holder.compare(holder2), False) - - def testTransfer(self): - holder = HandleHolder() - holder2 = HandleHolder(holder.handle()) - self.assertTrue(holder.compare(holder2)) - - def testUseDefinedType(self): - holder = HandleHolder(8) - holder2 = HandleHolder(holder.handle2()) - self.assertTrue(holder.compare2(holder2)) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/hashabletype_test.py b/tests/samplebinding/hashabletype_test.py deleted file mode 100644 index 069824ca7..000000000 --- a/tests/samplebinding/hashabletype_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for __hash__''' - -import unittest - -from sample import * - -class HashableTest(unittest.TestCase): - - def testStrHash(self): - h = {} - s = Str("Hi") - h[s] = 2 - self.assertTrue(h.get(s), 2) - - def testObjectTypeHash(self): - h = {} - o = ObjectType() - h[o] = 2 - self.assertTrue(h.get(o), 2) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ignorederefop_test.py b/tests/samplebinding/ignorederefop_test.py deleted file mode 100644 index dc3fe8b13..000000000 --- a/tests/samplebinding/ignorederefop_test.py +++ /dev/null @@ -1,38 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import * - -class TestLackOfDereferenceOperators (unittest.TestCase): - def testIf(self): - r = Reference() - self.assertFalse(hasattr(r, "__mul__")) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/implicitconv_numerical_test.py b/tests/samplebinding/implicitconv_numerical_test.py deleted file mode 100644 index 3fe66e30c..000000000 --- a/tests/samplebinding/implicitconv_numerical_test.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for inplicit converting C++ numeric types.''' - -import unittest -import sys -import sample -from py3kcompat import IS_PY3K, l, long - -# Hardcode the limits of the underlying C-types depending on architecture and memory -# model (taking MSVC using LLP64 into account). -cIntMin = -2147483648 -cIntMax = 2147483647 -cLongMin = cIntMin -cLongMax = cIntMax -maxRepresentableInt = sys.maxsize if IS_PY3K else sys.maxint -is64bitArchitecture = maxRepresentableInt > 2**32 -if is64bitArchitecture and sys.platform != 'win32': - cLongMin = -9223372036854775808 - cLongMax = 9223372036854775807 - -class NumericTester(unittest.TestCase): - '''Helper class for numeric comparison testing''' - - def check_value(self, source, expected, callback, desired_type=None): - result = callback(source) - self.assertEqual(result, expected) - - if desired_type: - self.assertEqual(type(result), desired_type) - - -class FloatImplicitConvert(NumericTester): - '''Test case for implicit converting C++ numeric types.''' - - def testFloatAsInt(self): - '''Float as Int''' - self.check_value(3.14, 3, sample.acceptInt, int) - self.assertRaises(OverflowError, sample.acceptInt, cIntMax + 400) - - def testFloatAsLong(self): - '''Float as Long''' - #C++ longs are python ints for us - self.check_value(3.14, 3, sample.acceptLong, int) - self.assertRaises(OverflowError, sample.acceptLong, cLongMax + 400) - - def testFloatAsUInt(self): - '''Float as unsigned Int''' - self.check_value(3.14, 3, sample.acceptUInt, long) - self.assertRaises(OverflowError, sample.acceptUInt, -3.14) - - def testFloatAsULong(self): - '''Float as unsigned Long''' - #FIXME Breaking with SystemError "bad argument to internal function" - self.check_value(3.14, 3, sample.acceptULong, long) - self.assertRaises(OverflowError, sample.acceptULong, -3.14) - - def testFloatAsDouble(self): - '''Float as double''' - self.check_value(3.14, 3.14, sample.acceptDouble, float) - - -class IntImplicitConvert(NumericTester): - '''Test case for implicit converting C++ numeric types.''' - - def testIntAsInt(self): - '''Int as Int''' - self.check_value(3, 3, sample.acceptInt, int) - - def testIntAsLong(self): - '''Int as Long''' - self.check_value(3, 3, sample.acceptLong, int) - - # cLongMax goes here as CPython implements int as a C long - self.check_value(cLongMax, cLongMax, sample.acceptLong, int) - self.check_value(cLongMin, cLongMin, sample.acceptLong, int) - - def testIntAsUInt(self): - '''Int as unsigned Int''' - self.check_value(3, 3, sample.acceptUInt, long) - self.assertRaises(OverflowError, sample.acceptUInt, -3) - - def testIntAsULong(self): - '''Int as unsigned Long''' - self.check_value(3, 3, sample.acceptULong, long) - self.assertRaises(OverflowError, sample.acceptULong, -3) - - def testFloatAsDouble(self): - '''Float as double''' - self.check_value(3.14, 3.14, sample.acceptDouble, float) - - -class LongImplicitConvert(NumericTester): - '''Test case for implicit converting C++ numeric types.''' - - def testLongAsInt(self): - '''Long as Int''' - self.check_value(l(24224), 24224, sample.acceptInt, int) - self.assertRaises(OverflowError, sample.acceptInt, cIntMax + 20) - - def testLongAsLong(self): - '''Long as Long''' - self.check_value(l(2405), 2405, sample.acceptLong, int) - self.assertRaises(OverflowError, sample.acceptLong, cLongMax + 20) - - def testLongAsUInt(self): - '''Long as unsigned Int''' - self.check_value(l(260), 260, sample.acceptUInt, long) - self.assertRaises(OverflowError, sample.acceptUInt, -42) - - def testLongAsULong(self): - '''Long as unsigned Long''' - self.check_value(l(128), 128, sample.acceptULong, long) - self.assertRaises(OverflowError, sample.acceptULong, l(-334)) - - def testLongAsDouble(self): - '''Float as double''' - self.check_value(l(42), 42, sample.acceptDouble, float) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/implicitconv_test.py b/tests/samplebinding/implicitconv_test.py deleted file mode 100644 index a94151d80..000000000 --- a/tests/samplebinding/implicitconv_test.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for implicit conversions''' - -import unittest - -from sample import ImplicitConv, ObjectType - -class ImplicitConvTest(unittest.TestCase): - '''Test case for implicit conversions''' - - def testImplicitConversions(self): - '''Test if overloaded function call decisor takes implicit conversions into account.''' - ic = ImplicitConv.implicitConvCommon(ImplicitConv()) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorNone) - - ic = ImplicitConv.implicitConvCommon(3) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorOne) - self.assertEqual(ic.objId(), 3) - - ic = ImplicitConv.implicitConvCommon(ImplicitConv.CtorThree) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorThree) - - obj = ObjectType() - ic = ImplicitConv.implicitConvCommon(obj) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorObjectTypeReference) - - ic = ImplicitConv.implicitConvCommon(42.42) - self.assertEqual(ic.value(), 42.42) - - ic = ImplicitConv(None) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorPrimitiveType) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/inheritanceandscope_test.py b/tests/samplebinding/inheritanceandscope_test.py deleted file mode 100755 index a8ede0548..000000000 --- a/tests/samplebinding/inheritanceandscope_test.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for finding scope in cases involving inheritance.''' - -import unittest - -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') - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/injectcode_test.py b/tests/samplebinding/injectcode_test.py deleted file mode 100644 index 99847f891..000000000 --- a/tests/samplebinding/injectcode_test.py +++ /dev/null @@ -1,132 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for std::list container conversions''' - -import unittest -from sample import InjectCode - -class MyInjectCode(InjectCode): - def __init__(self): - InjectCode.__init__(self) - self.multiplier = 2 - - def arrayMethod(self, values): - return self.multiplier * sum(values) - -class InjectCodeTest(unittest.TestCase): - - def testTypeNativeBeginning_TypeTargetBeginning(self): - ic = InjectCode() - self.assertEqual(str(ic), "Hi! I'm the inject code dummy class.") - - def testFunctionTargetBeginning_FunctionTargetEnd(self): - ic = InjectCode() - ret = ic.simpleMethod1(2, 1) - self.assertEqual(ret, "4end") - ret = ic.simpleMethod1(4, 2) - self.assertEqual(ret, "7end") - - def testFunctionTargetBeginning(self): - ic = InjectCode() - ret = ic.simpleMethod2() - self.assertEqual(ret, "_end") - - def testArgsModification(self): - ic = InjectCode() - ret = ic.overloadedMethod(["1", "2", "3", "4"]) - self.assertEqual(ret, "1234") - ret = ic.overloadedMethod(2, 0.5) - self.assertEqual(ret, "2.5") - ret = ic.overloadedMethod(6, True) - self.assertEqual(ret, "6true") - - def testArgsModification2(self): - ic = InjectCode() - ret = ic.simpleMethod3(["1", "2", "3", "4"]) - self.assertEqual(ret, "1234") - - def testArgumentRemovalAndArgumentTypeModification(self): - '''A method has its first argument removed and the second modified.''' - ic = InjectCode() - values = (1, 2, 3, 4, 5) - result = ic.arrayMethod(values) - self.assertEqual(result, sum(values)) - - def testCallVirtualMethodWithArgumentRemovalAndArgumentTypeModification(self): - '''A virtual method has its first argument removed and the second modified.''' - ic = InjectCode() - values = (1, 2, 3, 4, 5) - result = ic.callArrayMethod(values) - self.assertEqual(result, sum(values)) - - def testCallReimplementedVirtualMethodWithArgumentRemovalAndArgumentTypeModification(self): - '''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.''' - 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)) - - -class IntArrayTest(unittest.TestCase): - '''Test case for converting python sequence to int array''' - - def testBasic(self): - '''Shiboken::sequenceToIntArray - basic case''' - args = [1, 2, 3, 4] - ic = InjectCode() - self.assertEqual(sum(args) + len(args), ic.sumArrayAndLength(args)) - - def testEmpty(self): - '''Shiboken::sequenceToIntArray - empty sequence''' - args = [] - ic = InjectCode() - self.assertEqual(sum(args) + len(args), ic.sumArrayAndLength(args)) - - def testWithZero(self): - '''Shiboken::sequenceToIntArray - count only up to zero''' - args = [1, 2, 0, 3] - ic = InjectCode() - self.assertEqual(sum([1, 2]) + len([1, 2]), ic.sumArrayAndLength(args)) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/innerclass_test.py b/tests/samplebinding/innerclass_test.py deleted file mode 100644 index 0df636857..000000000 --- a/tests/samplebinding/innerclass_test.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import Derived - -class TestInnerClass(unittest.TestCase): - def testInstaciate(self): - d = Derived.SomeInnerClass() - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/intlist_test.py b/tests/samplebinding/intlist_test.py deleted file mode 100644 index 6d21ef053..000000000 --- a/tests/samplebinding/intlist_test.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import IntList - -class IntListTest(unittest.TestCase): - - def testAutoFunctionsToBaseList(self): - lst = IntList() - self.assertEqual(len(lst), 0) - lst.append(10) - self.assertEqual(lst[0], 10) - lst.append(20) - self.assertEqual(lst[1], 20) - lst.append(30) - self.assertEqual(lst[2], 30) - lst[1] = 25 - self.assertEqual(lst[0], 10) - self.assertEqual(lst[1], 25) - self.assertEqual(lst[2], 30) - self.assertEqual(len(lst), 3) - - def testIntListCtor_NoParams(self): - '''IntList constructor receives no parameter.''' - il = IntList() - self.assertEqual(len(il), 0) - self.assertEqual(il.constructorUsed(), IntList.NoParamsCtor) - - def testIntListCtor_int(self): - '''IntList constructor receives an integer.''' - value = 123 - il = IntList(value) - self.assertEqual(len(il), 1) - self.assertEqual(il[0], value) - self.assertEqual(il.constructorUsed(), IntList.IntCtor) - - def testIntListCtor_IntList(self): - '''IntList constructor receives an IntList object.''' - il1 = IntList(123) - il2 = IntList(il1) - self.assertEqual(len(il1), len(il2)) - for i in range(len(il1)): - self.assertEqual(il1[i], il2[i]) - self.assertEqual(il2.constructorUsed(), IntList.CopyCtor) - - def testIntListCtor_ListOfInts(self): - '''IntList constructor receives an integer list.''' - ints = [123, 456] - il = IntList(ints) - self.assertEqual(len(il), len(ints)) - for i in range(len(il)): - self.assertEqual(il[i], ints[i]) - self.assertEqual(il.constructorUsed(), IntList.ListOfIntCtor) - - def testIntListAttributeTypeCheck(self): - '''Attribute values to IntList.''' - il = IntList([0, 1, 2]) - self.assertEqual(len(il), 3) - il[0] = 123 - self.assertEqual(len(il), 3) - self.assertEqual(il[0], 123) - il[1] = 432.1 - self.assertEqual(len(il), 3) - self.assertEqual(il[1], int(432.1)) - self.assertRaises(TypeError, il.__setitem__, 2, '78') - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/invalid_virtual_return_test.py b/tests/samplebinding/invalid_virtual_return_test.py deleted file mode 100644 index f160f1e07..000000000 --- a/tests/samplebinding/invalid_virtual_return_test.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for returning invalid types in a virtual function''' - -import unittest -from sample import ObjectModel, ObjectType, ObjectView - -import warnings - - -class MyObject(ObjectType): - pass - - -class ListModelWrong(ObjectModel): - - def __init__(self, parent=None): - ObjectModel.__init__(self, parent) - self.obj = 0 - - def data(self): - warnings.simplefilter('error') - # Shouldn't segfault. Must set TypeError - return self.obj - - -class ModelWrongReturnTest(unittest.TestCase): - - def testWrongTypeReturn(self): - model = ListModelWrong() - view = ObjectView(model) - self.assertRaises(RuntimeWarning, view.getRawModelData) # calls model.data() - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/keep_reference_test.py b/tests/samplebinding/keep_reference_test.py deleted file mode 100644 index a8f63f6df..000000000 --- a/tests/samplebinding/keep_reference_test.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' - -import unittest -from sys import getrefcount - -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).''' - - def testReferenceCounting(self): - '''Tests reference count of model-like object referred by view-like objects.''' - model1 = ObjectModel() - refcount1 = getrefcount(model1) - view1 = ObjectView() - view1.setModel(model1) - self.assertEqual(getrefcount(view1.model()), refcount1 + 1) - - view2 = ObjectView() - view2.setModel(model1) - self.assertEqual(getrefcount(view2.model()), refcount1 + 2) - - model2 = ObjectModel() - view2.setModel(model2) - self.assertEqual(getrefcount(view1.model()), refcount1 + 1) - - def testReferenceCountingWhenDeletingReferrer(self): - '''Tests reference count of model-like object referred by deceased view-like object.''' - model = ObjectModel() - refcount1 = getrefcount(model) - view = ObjectView() - view.setModel(model) - self.assertEqual(getrefcount(view.model()), refcount1 + 1) - - del view - self.assertEqual(getrefcount(model), refcount1) - - def testReferreedObjectSurvivalAfterContextEnd(self): - '''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() - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/list_test.py b/tests/samplebinding/list_test.py deleted file mode 100644 index 22cb4c04b..000000000 --- a/tests/samplebinding/list_test.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for std::list container conversions''' - -import unittest - -from sample import ListUser, Point, PointF - -class ExtendedListUser(ListUser): - def __init__(self): - ListUser.__init__(self) - self.create_list_called = False - - def createList(self): - self.create_list_called = True - return [2, 3, 5, 7, 13] - -class ListConversionTest(unittest.TestCase): - '''Test case for std::list container conversions''' - - def testReimplementedVirtualMethodCall(self): - '''Test if a Python override of a virtual method is correctly called from C++.''' - lu = ExtendedListUser() - lst = lu.callCreateList() - self.assertTrue(lu.create_list_called) - self.assertEqual(type(lst), list) - for item in lst: - self.assertEqual(type(item), int) - - def testPrimitiveConversionInsideContainer(self): - '''Test primitive type conversion inside conversible std::list container.''' - cpx0 = complex(1.2, 3.4) - cpx1 = complex(5.6, 7.8) - lst = ListUser.createComplexList(cpx0, cpx1) - self.assertEqual(type(lst), list) - for item in lst: - self.assertEqual(type(item), complex) - self.assertEqual(lst, [cpx0, cpx1]) - - def testSumListIntegers(self): - '''Test method that sums a list of integer values.''' - lu = ListUser() - lst = [3, 5, 7] - result = lu.sumList(lst) - self.assertEqual(result, sum(lst)) - - def testSumListFloats(self): - '''Test method that sums a list of float values.''' - lu = ListUser() - lst = [3.3, 4.4, 5.5] - result = lu.sumList(lst) - self.assertEqual(result, sum(lst)) - - def testConversionInBothDirections(self): - '''Test converting a list from Python to C++ and back again.''' - lu = ListUser() - lst = [3, 5, 7] - lu.setList(lst) - result = lu.getList() - self.assertEqual(result, lst) - - def testConversionInBothDirectionsWithSimilarContainer(self): - '''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) - result = lu.getList() - self.assertNotEqual(result, lst) - self.assertEqual(result, list(lst)) - - def testConversionOfListOfObjectsPassedAsArgument(self): - '''Calls method with a Python list of wrapped objects to be converted to a C++ list.''' - mult = 3 - pts0 = (Point(1.0, 2.0), Point(3.3, 4.4), Point(5, 6)) - pts1 = (Point(1.0, 2.0), Point(3.3, 4.4), Point(5, 6)) - ListUser.multiplyPointList(pts1, mult) - for pt0, pt1 in zip(pts0, pts1): - self.assertEqual(pt0.x() * mult, pt1.x()) - self.assertEqual(pt0.y() * mult, pt1.y()) - - def testConversionOfInvalidLists(self): - mult = 3 - pts = (Point(1.0, 2.0), 3, Point(5, 6)) - self.assertRaises(TypeError, ListUser.multiplyPointList, pts, mult) - - def testOverloadMethodReceivingRelatedContainerTypes(self): - self.assertEqual(ListUser.ListOfPointF, ListUser.listOfPoints([PointF()])) - self.assertEqual(ListUser.ListOfPoint, ListUser.listOfPoints([Point()])) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/lock_test.py b/tests/samplebinding/lock_test.py deleted file mode 100644 index 35bf5149d..000000000 --- a/tests/samplebinding/lock_test.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python - -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Simple test with a blocking C++ method that should allow python - threads to run.''' - -import unittest -import threading - -from sample import Bucket - - -class Unlocker(threading.Thread): - - def __init__(self, bucket): - threading.Thread.__init__(self) - self.bucket = bucket - - def run(self): - while not self.bucket.locked(): - pass - - self.bucket.unlock() - - -class MyBucket(Bucket): - - def __init__(self): - Bucket.__init__(self) - - def virtualBlockerMethod(self): - self.lock() - return True - - -class TestLockUnlock(unittest.TestCase): - - def testBasic(self): - '''Locking in C++ and releasing in a python thread''' - bucket = Bucket() - unlocker = Unlocker(bucket) - - unlocker.start() - bucket.lock() - unlocker.join() - - def testVirtualBlocker(self): - '''Same as the basic case but blocker method is a C++ virtual called from C++.''' - bucket = Bucket() - unlocker = Unlocker(bucket) - - unlocker.start() - result = bucket.callVirtualBlockerMethodButYouDontKnowThis() - unlocker.join() - 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++.''' - mybucket = MyBucket() - unlocker = Unlocker(mybucket) - - unlocker.start() - result = mybucket.callVirtualBlockerMethodButYouDontKnowThis() - unlocker.join() - self.assertTrue(result) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/map_test.py b/tests/samplebinding/map_test.py deleted file mode 100644 index 18cefd857..000000000 --- a/tests/samplebinding/map_test.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for std::map container conversions''' - -import unittest - -from sample import MapUser - -class ExtendedMapUser(MapUser): - def __init__(self): - MapUser.__init__(self) - self.create_map_called = False - - 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)} - -class MapConversionTest(unittest.TestCase): - '''Test case for std::map container conversions''' - - def testReimplementedVirtualMethodCall(self): - '''Test if a Python override of a virtual method is correctly called from C++.''' - mu = ExtendedMapUser() - map_ = mu.callCreateMap() - self.assertTrue(mu.create_map_called) - self.assertEqual(type(map_), dict) - for key, value in map_.items(): - self.assertEqual(type(key), str) - self.assertEqual(type(value[0]), complex) - self.assertEqual(type(value[1]), int) - - 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]} - mu.setMap(map_) - result = mu.getMap() - self.assertEqual(result, map_) - - def testConversionMapIntKeyValueTypeValue(self): - '''C++ signature: MapUser::passMapIntValueType(const std::map&)''' - mu = MapUser() - map_ = {0 : 'string'} - result = mu.passMapIntValueType(map_) - self.assertEqual(map_, result) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/metaclass_test.py b/tests/samplebinding/metaclass_test.py deleted file mode 100644 index 972a2f17d..000000000 --- a/tests/samplebinding/metaclass_test.py +++ /dev/null @@ -1,61 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -from sample import * -import unittest - -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.setX(1) - w1.setY(2) - - w2 = D() # should work! - w2.setX(3) - w2.setY(4) - - w3 = w1 + w2 - self.assertEqual(w3.x(), 4) - self.assertEqual(w3.y(), 6) diff --git a/tests/samplebinding/mi_virtual_methods_test.py b/tests/samplebinding/mi_virtual_methods_test.py deleted file mode 100644 index 0905dead9..000000000 --- a/tests/samplebinding/mi_virtual_methods_test.py +++ /dev/null @@ -1,88 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for virtual methods in multiple inheritance scenarios''' - -import unittest - -from sample import VirtualMethods, ObjectType, Event - - -class ImplementsNone(ObjectType, VirtualMethods): - '''Implements no virtual methods''' - - def __init__(self): - ObjectType.__init__(self) - VirtualMethods.__init__(self) - - -class ImplementsBoth(ObjectType, VirtualMethods): - '''Implements ObjectType.event and VirtualMethods.sum1''' - - def __init__(self): - ObjectType.__init__(self) - VirtualMethods.__init__(self) - self.event_processed = False - - def event(self, event): - self.event_processed = True - return True - - def sum1(self, arg0, arg1, arg2): - return (arg0 + arg1 + arg2) * 2 - - -class CppVirtualTest(unittest.TestCase): - '''Virtual method defined in c++ called from C++''' - - def testCpp(self): - '''C++ calling C++ virtual method in multiple inheritance scenario''' - obj = ImplementsNone() - self.assertTrue(ObjectType.processEvent([obj], Event(Event.BASIC_EVENT))) - self.assertRaises(AttributeError, getattr, obj, 'event_processed') - - self.assertEqual(obj.callSum0(1, 2, 3), 6) - - -class PyVirtualTest(unittest.TestCase): - '''Virtual method reimplemented in python called from C++''' - - def testEvent(self): - '''C++ calling Python reimplementation of virtual in multiple inheritance''' - obj = ImplementsBoth() - self.assertTrue(ObjectType.processEvent([obj], Event(Event.BASIC_EVENT))) - self.assertTrue(obj.event_processed) - - self.assertEqual(obj.callSum1(1, 2, 3), 12) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/mixed_mi_test.py b/tests/samplebinding/mixed_mi_test.py deleted file mode 100644 index b6268cf2c..000000000 --- a/tests/samplebinding/mixed_mi_test.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for multiple inheritance in mixed Python/C++ scenarios''' - -import unittest - -from sample import ObjectType - - -class Base(object): - '''Base Python class''' - - def __init__(self): - self.name = '' - - def pythonName(self): - return self.name - - def setPythonName(self, name): - self.name = name - - -class Child(Base, ObjectType): - '''Dummy class with mixed parents''' - - def __init__(self): - Base.__init__(self) - ObjectType.__init__(self) - - -class MixedInheritanceTest(unittest.TestCase): - - def testMixed(self): - '''Mixed Python/C++ multiple inheritance''' - obj = Child() - - obj.setObjectName('aaa') - self.assertEqual(obj.objectName(), 'aaa') - - obj.setPythonName('python') - self.assertEqual(obj.pythonName(), 'python') - - -if __name__ == '__main__': - unittest.main() - - diff --git a/tests/samplebinding/modelindex_test.py b/tests/samplebinding/modelindex_test.py deleted file mode 100644 index 5dd7d3bc7..000000000 --- a/tests/samplebinding/modelindex_test.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import ModelIndex, ReferentModelIndex, PersistentModelIndex - -class TestCastOperator(unittest.TestCase): - - def testCastOperatorReturningValue(self): - index = PersistentModelIndex() - index.setValue(123) - self.assertEqual(index.value(), 123) - self.assertEqual(index.value(), ModelIndex.getValue(index)) - - def testCastOperatorReturningReference(self): - index = ReferentModelIndex() - index.setValue(123) - self.assertEqual(index.value(), 123) - self.assertEqual(index.value(), ModelIndex.getValue(index)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/modelview_test.py b/tests/samplebinding/modelview_test.py deleted file mode 100644 index 081de303d..000000000 --- a/tests/samplebinding/modelview_test.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' - -import unittest -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) - self.obj = MyObject() - self.obj.setObjectName(object_name) - - def data(self): - return self.obj - -class ListModelDoesntKeepsReference(ObjectModel): - def data(self): - obj = MyObject() - obj.setObjectName(object_name) - return obj - - -class ModelViewTest(unittest.TestCase): - - def testListModelDoesntKeepsReference(self): - model = ListModelDoesntKeepsReference() - view = ObjectView(model) - obj = view.getRawModelData() - self.assertEqual(type(obj), MyObject) - self.assertEqual(obj.objectName(), object_name) - - def testListModelKeepsReference(self): - model = ListModelKeepsReference() - view = ObjectView(model) - obj = view.getRawModelData() - self.assertEqual(type(obj), MyObject) - self.assertEqual(obj.objectName(), object_name) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/modifications_test.py b/tests/samplebinding/modifications_test.py deleted file mode 100644 index 44748dc8c..000000000 --- a/tests/samplebinding/modifications_test.py +++ /dev/null @@ -1,224 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for method modifications performed as described on type system. ''' - -import unittest - -from sample import Modifications, Point, ByteArray - -class ExtModifications(Modifications): - def __init__(self): - Modifications.__init__(self) - self.multiplier = 3.0 - self.increment = 10.0 - - def name(self): - return 'ExtModifications' - - def differenceOfPointCoordinates(self, point): - ok, res = Modifications.differenceOfPointCoordinates(self, point) - return ok, res * self.multiplier + self.increment - - -class ModificationsTest(unittest.TestCase): - '''Test cases for method modifications performed as described on type system. ''' - - def setUp(self): - self.mods = Modifications() - - def tearDown(self): - del self.mods - - 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'.''' - 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.''' - em = ExtModifications() - self.assertEqual(self.mods.name(), 'Modifications') - self.assertEqual(em.name(), 'ExtModifications') - - def testRegularMethodRenaming(self): - '''Test if Modifications::cppMultiply was correctly renamed to calculateArea.''' - self.assertTrue('cppMultiply' not in dir(Modifications)) - self.assertTrue('calculateArea' in dir(Modifications)) - self.assertEqual(self.mods.calculateArea(3, 6), 3 * 6) - - def testRegularMethodRemoval(self): - '''Test if 'Modifications::exclusiveCppStuff' was removed from Python bindings.''' - self.assertTrue('exclusiveCppStuff' not in dir(Modifications)) - - def testArgumentRemoval(self): - '''Test if second argument of Modifications::doublePlus(int, int) was removed.''' - self.assertRaises(TypeError, self.mods.doublePlus, 3, 7) - self.assertEqual(self.mods.doublePlus(7), 14) - - def testDefaultValueRemoval(self): - '''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.''' - # 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); - self.assertEqual(self.mods.power(), 2) - self.assertEqual(self.mods.power(3), 3) - 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).''' - 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).''' - result, ok = self.mods.pointToPair(Point(2, 5)) - self.assertEqual(type(ok), bool) - self.assertEqual(type(result), tuple) - self.assertEqual(len(result), 2) - self.assertEqual(type(result[0]), float) - self.assertEqual(type(result[1]), float) - self.assertEqual(result[0], 2.0) - self.assertEqual(result[1], 5.0) - - def testArgumentRemovalAndReturnTypeModificationWithTypesystemTemplates2(self): - '''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) - self.assertEqual(result, 14.1) - - def testOverloadedMethodModifications(self): - '''Tests modifications to an overloaded method''' - # overloaded(int, bool[removed], int, double) - self.assertEqual(self.mods.overloaded(1, 2, 3.1), Modifications.Overloaded_ibid) - # overloaded(int, bool, int[removed,default=321], int) - 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.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) - - def testPointArrayModification(self): - points = (Point(1, 1), Point(2, 2)) - summedPoint = Point(1, 1) + Point(2, 2) - self.assertEqual(self.mods.sumPointArray(points), summedPoint) - - def testTypeSystemVariableReplacementInFunctionModification(self): - ba = ByteArray('12345') - self.assertEqual(self.mods.getSize(ba), len(ba)) - self.assertEqual(self.mods.getSize(ba, 20), 20) - - def testNoNulPointerTag(self): - point = Point(12, 34) - self.assertEqual(self.mods.sumPointCoordinates(point), 12 + 34) - self.assertRaises(TypeError, self.mods.sumPointCoordinates, None) - - def testNonConversionRuleForArgumentWithDefaultValue(self): - status, obj = self.mods.nonConversionRuleForArgumentWithDefaultValue() - self.assertTrue(status) - self.assertEqual(obj, self.mods.getObject()) - self.assertEqual(obj.objectName(), 'MyObject') - - def testInjectCodeWithConversionVariableForUserPrimitive(self): - self.assertTrue(Modifications.invertBoolean(False)) - self.assertFalse(Modifications.invertBoolean(True)) - - def testConversionRuleForReturnType(self): - x, y = 11, 2 - diff = float(abs(x - y)) - point = Point(x, y) - - ok, res = self.mods.differenceOfPointCoordinates(point) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, diff) - - ok, res = self.mods.callDifferenceOfPointCoordinates(point) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, diff) - - ok, res = self.mods.differenceOfPointCoordinates(None) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, 0.0) - - ok, res = self.mods.callDifferenceOfPointCoordinates(None) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, 0.0) - - def testConversionRuleForReturnTypeOnExtendedClass(self): - x, y = 11, 2 - diff = float(abs(x - y)) - point = Point(x, y) - em = ExtModifications() - - ok, res = em.differenceOfPointCoordinates(point) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, diff * em.multiplier + em.increment) - - ok, res = em.callDifferenceOfPointCoordinates(point) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, diff * em.multiplier + em.increment) - - ok, res = em.differenceOfPointCoordinates(None) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, em.increment) - - ok, res = em.callDifferenceOfPointCoordinates(None) - self.assertTrue(isinstance(ok, bool)) - self.assertTrue(isinstance(res, float)) - self.assertEqual(res, em.increment) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/modified_constructor_test.py b/tests/samplebinding/modified_constructor_test.py deleted file mode 100644 index 859f89452..000000000 --- a/tests/samplebinding/modified_constructor_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests cases for ConstructorWithModifiedArgument class.''' - -import sys -import unittest - -from sample import * - - -class ConstructorWithModifiedArgumentTest(unittest.TestCase): - '''Test cases for ConstructorWithModifiedArgument class.''' - - def testConstructorWithModifiedArgument(self): - sampleClass = ModifiedConstructor("10") - self.assertTrue(sampleClass.retrieveValue(), 10) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/modifiedvirtualmethods_test.py b/tests/samplebinding/modifiedvirtualmethods_test.py deleted file mode 100644 index 3121a9cc2..000000000 --- a/tests/samplebinding/modifiedvirtualmethods_test.py +++ /dev/null @@ -1,248 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for modified virtual methods.''' - -import unittest - -from sample import VirtualMethods, Str - -class ExtendedVirtualMethods(VirtualMethods): - def __init__(self): - VirtualMethods.__init__(self) - self.name_called = False - self.sum0_called = False - self.sum1_called = False - self.sum2_called = False - self.sum3_called = False - self.sum4_called = False - self.sumThree_called = False - self.callMe_called = 0 - self.multiplier = 12345 - - def sum0(self, a0, a1, a2): - self.sum0_called = True - return VirtualMethods.sumThree(self, a0, a1, a2) * self.multiplier - - def sumThree(self, a0, a1, a2): - self.sumThree_called = True - return VirtualMethods.sumThree(self, a0, a1, a2) * self.multiplier - - def sum1(self, a0, a1, a2): - self.sum1_called = True - return VirtualMethods.sum1(self, a0, a1, a2) * self.multiplier - - def sum2(self, a0, a1): - self.sum2_called = True - return VirtualMethods.sum2(self, a0, a1) * self.multiplier - - def sum3(self, a0, a1): - self.sum3_called = True - return VirtualMethods.sum3(self, a0, a1) * self.multiplier - - def sum4(self, a0, a1): - self.sum4_called = True - return VirtualMethods.sum4(self, a0, a1) * self.multiplier - - def name(self): - self.name_called = True - return Str('ExtendedVirtualMethods') - - def callMe(self): - self.callMe_called += 1 - - def getMargins(self): - return tuple([m*2 for m in VirtualMethods.getMargins(self)]) - - -class VirtualMethodsTest(unittest.TestCase): - '''Test case for modified virtual methods.''' - - def setUp(self): - self.vm = VirtualMethods() - self.evm = ExtendedVirtualMethods() - - def tearDown(self): - del self.vm - del self.evm - - def testModifiedVirtualMethod0(self): - '''Renamed virtual method.''' - a0, a1, a2 = 2, 3, 5 - result0 = self.vm.callSum0(a0, a1, a2) - result1 = self.vm.sumThree(a0, a1, a2) - self.assertEqual(result0, a0 + a1 + a2) - self.assertEqual(result0, result1) - self.assertRaises(AttributeError, getattr, self.vm, 'sum0') - - def testReimplementedModifiedVirtualMethod0(self): - '''Override of a renamed virtual method.''' - a0, a1, a2 = 2, 3, 5 - result0 = self.vm.callSum0(a0, a1, a2) - result1 = self.vm.sumThree(a0, a1, a2) - result2 = self.evm.callSum0(a0, a1, a2) - self.assertEqual(result0, result1) - self.assertEqual(result0 * self.evm.multiplier, result2) - self.assertTrue(self.evm.sumThree_called) - self.assertFalse(self.evm.sum0_called) - - def testModifiedVirtualMethod1(self): - '''Virtual method with three arguments and the last one - changed to have the default value set to 1000.''' - a0, a1, a2 = 2, 3, 5 - result0 = self.vm.sum1(a0, a1) - self.assertEqual(result0, a0 + a1 + 1000) - result1 = self.vm.sum1(a0, a1, a2) - result2 = self.vm.callSum1(a0, a1, a2) - self.assertEqual(result1, result2) - - def testReimplementedModifiedVirtualMethod1(self): - '''Override of the virtual method with three arguments and - the last one changed to have the default value set to 1000.''' - a0, a1 = 2, 3 - result0 = self.vm.sum1(a0, a1) - result1 = self.evm.callSum1(a0, a1, 1000) - self.assertEqual(result0 * self.evm.multiplier, result1) - self.assertTrue(self.evm.sum1_called) - - def testModifiedVirtualMethod2(self): - '''Virtual method originally with three arguments, the last - one was removed and the default value set to 2000.''' - a0, a1 = 1, 2 - result0 = self.vm.sum2(a0, a1) - self.assertEqual(result0, a0 + a1 + 2000) - result1 = self.vm.sum2(a0, a1) - result2 = self.vm.callSum2(a0, a1, 2000) - self.assertEqual(result1, result2) - self.assertRaises(TypeError, self.vm.sum2, 1, 2, 3) - - def testReimplementedModifiedVirtualMethod2(self): - '''Override of the virtual method originally with three arguments, - the last one was removed and the default value set to 2000.''' - a0, a1 = 1, 2 - ignored = 54321 - result0 = self.vm.sum2(a0, a1) - result1 = self.evm.callSum2(a0, a1, ignored) - self.assertEqual(result0 * self.evm.multiplier, result1) - self.assertTrue(self.evm.sum2_called) - - def testModifiedVirtualMethod3(self): - '''Virtual method originally with three arguments have the second - one removed and replaced by custom code that replaces it by the sum - of the first and the last arguments.''' - a0, a1 = 1, 2 - result0 = self.vm.sum3(a0, a1) - self.assertEqual(result0, a0 + (a0 + a1) + a1) - result1 = self.vm.callSum3(a0, 10, a1) - self.assertNotEqual(result0, result1) - result2 = self.vm.callSum3(a0, a0 + a1, a1) - self.assertEqual(result0, result2) - self.assertRaises(TypeError, self.vm.sum3, 1, 2, 3) - - def testReimplementedModifiedVirtualMethod3(self): - '''Override of the virtual method originally with three arguments - have the second one removed and replaced by custom code that - replaces it by the sum of the first and the last arguments.''' - a0, a1 = 1, 2 - ignored = 54321 - result0 = self.vm.sum3(a0, a1) - result1 = self.evm.callSum3(a0, ignored, a1) - self.assertEqual(result0 * self.evm.multiplier, result1) - self.assertTrue(self.evm.sum3_called) - - def testModifiedVirtualMethod4(self): - '''Virtual method originally with three arguments, the - last one was removed and the default value set to 3000.''' - a0, a1 = 1, 2 - default_value = 3000 - result0 = self.vm.sum4(a0, a1) - self.assertEqual(result0, a0 + default_value + a1) - removed_arg_value = 100 - result1 = self.vm.callSum4(a0, removed_arg_value, a1) - self.assertEqual(result1, a0 + removed_arg_value + a1) - self.assertRaises(TypeError, self.vm.sum4, 1, 2, 3) - - def testReimplementedModifiedVirtualMethod4(self): - '''Override of the virtual method originally with three arguments, - the last one was removed and the default value set to 3000. - The method was modified with code injection on the binding override - (the one that receives calls from C++ with the original signature - and forwards it to Python overrides) that subtracts the value of the - second argument (removed in Python) from the value of the first - before sending them to Python.''' - a0, a1 = 1, 2 - 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.assertTrue(self.evm.sum4_called) - - def testOverridenMethodResultModification(self): - '''Injected code modifies the result of a call to a virtual - method overridden in Python.''' - orig_name = self.vm.callName() - self.assertEqual(orig_name, 'VirtualMethods') - name = self.evm.callName() - self.assertEqual(name, 'PimpedExtendedVirtualMethods') - self.assertEqual(name, Str('PimpedExtendedVirtualMethods')) - self.assertTrue(self.evm.name_called) - - def testInjectCodeCallsPythonVirtualMethodOverride(self): - '''When injected code calls the Python override by itself - no code for the method call should be generated.''' - self.evm.callCallMe() - self.assertEqual(self.evm.callMe_called, 1) - - def testAllArgumentsRemoved(self): - values = (10, 20, 30, 40) - self.vm.setMargins(*values) - self.assertEqual(self.vm.getMargins(), values) - - def testAllArgumentsRemovedCallVirtual(self): - values = (10, 20, 30, 40) - self.vm.setMargins(*values) - self.assertEqual(self.vm.callGetMargins(), values) - - def testExtendedAllArgumentsRemoved(self): - values = (10, 20, 30, 40) - self.evm.setMargins(*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]) - self.assertEqual(self.evm.callGetMargins(), double) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/multi_cpp_inheritance_test.py b/tests/samplebinding/multi_cpp_inheritance_test.py deleted file mode 100644 index 6546c3ac6..000000000 --- a/tests/samplebinding/multi_cpp_inheritance_test.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for multiple inheritance''' - -import sys -import unittest - -from sample import * - -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): - s = SimpleUseCase("Hi") - self.assertEqual(s, "Hi") - s.setObjectName(s) - self.assertEqual(s.objectName(), "Hi") - - def testInstanciation2(self): - s = SimpleUseCase2("Hi") - self.assertEqual(s, "Hi") - s.setObjectName(s) - self.assertEqual(s.objectName(), "Hi") - - def testComplexInstanciation(self): - c = ComplexUseCase("Hi") - self.assertEqual(c, "Hi") - c.setObjectName(c) - self.assertEqual(c.objectName(), "Hi") - c.setX(2); - self.assertEqual(c.x(), 2) - -class MultipleCppDerivedReverseTest(unittest.TestCase): - def testInstanciation(self): - s = SimpleUseCaseReverse("Hi") - self.assertEqual(s, "Hi") - s.setObjectName(s) - self.assertEqual(s.objectName(), "Hi") - - def testInstanciation2(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)) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/multiple_derived_test.py b/tests/samplebinding/multiple_derived_test.py deleted file mode 100644 index e84cc76fd..000000000 --- a/tests/samplebinding/multiple_derived_test.py +++ /dev/null @@ -1,221 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for multiple inheritance''' - -import sys -import unittest - -from sample import Base1, Base2, Base3, Base4, Base5, Base6 -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''' - - def testIsInstance(self): - '''MDerived1 is instance of its parents Base1 and Base2.''' - a = MDerived1() - self.assertTrue(isinstance(a, MDerived1)) - self.assertTrue(isinstance(a, Base1)) - self.assertTrue(isinstance(a, Base2)) - - def testIsSubclass(self): - '''MDerived1 is subclass of its parents Base1 and Base2.''' - self.assertTrue(issubclass(MDerived1, Base1)) - 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.''' - 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.''' - 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.''' - a = ExtMDerived1() - self.assertTrue(isinstance(a, ExtMDerived1)) - self.assertTrue(isinstance(a, MDerived1)) - self.assertTrue(isinstance(a, Base1)) - self.assertTrue(isinstance(a, Base2)) - - def testPythonClassIsSubclass(self): - '''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)) - - def testCastFromMDerived1ToBases(self): - '''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() - b2 = a.castToBase2() - self.assertTrue(isinstance(b1, MDerived1)) - self.assertTrue(isinstance(b2, MDerived1)) - self.assertEqual(a, b1) - self.assertEqual(a, b2) - self.assertEqual(sys.getrefcount(a), refcnt + 2) - - def testCastFromExtMDerived1ToMDerived1Bases(self): - '''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() - self.assertTrue(isinstance(b1, MDerived1)) - self.assertTrue(isinstance(b1, ExtMDerived1)) - b2 = a.castToBase2() - self.assertTrue(isinstance(b2, MDerived1)) - self.assertTrue(isinstance(b2, ExtMDerived1)) - self.assertEqual(a, b1) - self.assertEqual(a, b2) - self.assertEqual(sys.getrefcount(a), refcnt + 2) - - def testCastFromSonOfMDerived1ToBases(self): - '''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() - b1 = a.castToBase1() - b2 = a.castToBase2() - self.assertTrue(isinstance(md1, SonOfMDerived1)) - self.assertTrue(isinstance(b2, SonOfMDerived1)) - self.assertTrue(isinstance(b2, SonOfMDerived1)) - self.assertEqual(a, md1) - self.assertEqual(a, b1) - self.assertEqual(a, b2) - self.assertEqual(sys.getrefcount(a), refcnt + 3) - - def testReimplementedBase2VirtualMethodOnClassInheritingFromMDerived1(self): - a = ExtMDerived1() - value = a.base2Method() - self.assertTrue(value, Base2.base2Method(a) * a.multiplier) - - def testCastFromMDerived2ToBases(self): - '''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() - b4 = a.castToBase4() - b5 = a.castToBase5() - b6 = a.castToBase6() - self.assertTrue(isinstance(b3, MDerived2)) - self.assertTrue(isinstance(b4, MDerived2)) - self.assertTrue(isinstance(b5, MDerived2)) - self.assertTrue(isinstance(b6, MDerived2)) - self.assertEqual(a, b3) - self.assertEqual(a, b4) - self.assertEqual(a, b5) - self.assertEqual(a, b6) - self.assertEqual(sys.getrefcount(a), refcnt + 4) - - def testCastFromMDerived3ToBases(self): - '''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() - md2 = a.castToMDerived2() - b1 = a.castToBase1() - b2 = a.castToBase2() - b3 = a.castToBase3() - b4 = a.castToBase4() - b5 = a.castToBase5() - b6 = a.castToBase6() - self.assertTrue(isinstance(md1, MDerived3)) - self.assertTrue(isinstance(md2, MDerived3)) - self.assertTrue(isinstance(b1, MDerived3)) - self.assertTrue(isinstance(b2, MDerived3)) - self.assertTrue(isinstance(b3, MDerived3)) - self.assertTrue(isinstance(b4, MDerived3)) - self.assertTrue(isinstance(b5, MDerived3)) - self.assertTrue(isinstance(b6, MDerived3)) - self.assertEqual(a, md1) - self.assertEqual(a, md2) - self.assertEqual(a, b1) - self.assertEqual(a, b2) - self.assertEqual(a, b3) - self.assertEqual(a, b4) - self.assertEqual(a, b5) - self.assertEqual(a, b6) - self.assertEqual(sys.getrefcount(a), refcnt + 8) - - def testCastFromMDerived4ToBases(self): - '''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() - b4 = a.castToBase4() - self.assertTrue(isinstance(b3, MDerived4)) - self.assertTrue(isinstance(b4, MDerived4)) - self.assertEqual(a, b3) - self.assertEqual(a, b4) - self.assertEqual(sys.getrefcount(a), refcnt + 2) - - def testCastFromMDerived5ToBases(self): - '''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() - b4 = a.castToBase4() - self.assertTrue(isinstance(b3, MDerived5)) - self.assertTrue(isinstance(b4, MDerived5)) - self.assertEqual(a, b3) - self.assertEqual(a, b4) - self.assertEqual(sys.getrefcount(a), refcnt + 2) - - def testCastFromMDerived3ToBase3(self): - '''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() - b3_inherited = MDerived2.castToBase3(a) - self.assertTrue(isinstance(b3_reimplemented, MDerived3)) - self.assertTrue(isinstance(b3_inherited, MDerived3)) - self.assertEqual(a, b3_reimplemented) - self.assertEqual(a, b3_inherited) - self.assertEqual(sys.getrefcount(a), refcnt + 2) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/namespace_test.py b/tests/samplebinding/namespace_test.py deleted file mode 100644 index 653b9081b..000000000 --- a/tests/samplebinding/namespace_test.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for std::map container conversions''' - -import unittest -from sample import * -from py3kcompat import IS_PY3K - -if IS_PY3K: - TYPE_STR = "class" -else: - TYPE_STR = "type" - -class TestEnumUnderNamespace(unittest.TestCase): - def testInvisibleNamespace(self): - o1 = EnumOnNamespace.Option1 - self.assertEqual(o1, 1) - -class TestClassesUnderNamespace(unittest.TestCase): - def testIt(self): - 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() - - def testFunctionAddedOnNamespace(self): - res = SampleNamespace.ImInsideANamespace(2, 2) - self.assertEqual(res, 4) - - def testTpNames(self): - self.assertEqual(str(SampleNamespace.SomeClass), "<%s 'sample.SampleNamespace.SomeClass'>"%TYPE_STR) - self.assertEqual(str(SampleNamespace.SomeClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.ProtectedEnum'>"%TYPE_STR) - self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.ProtectedEnum'>"%TYPE_STR) - self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough'>"%TYPE_STR) - self.assertEqual(str(SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum), "<%s 'sample.SampleNamespace.SomeClass.SomeInnerClass.OkThisIsRecursiveEnough.NiceEnum'>"%TYPE_STR) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/newdivision_test.py b/tests/samplebinding/newdivision_test.py deleted file mode 100644 index d1a2eda75..000000000 --- a/tests/samplebinding/newdivision_test.py +++ /dev/null @@ -1,42 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -from __future__ import division -from sample import * -import unittest - -class TestNewDivision(unittest.TestCase): - - def testIt(self): - p = Point(4, 4) - p2 = p/2 - self.assertEqual(p2, Point(2, 2)) - -if __name__ == "__main__": - unittest.main() - diff --git a/tests/samplebinding/nondefaultctor_test.py b/tests/samplebinding/nondefaultctor_test.py deleted file mode 100644 index e38dc9455..000000000 --- a/tests/samplebinding/nondefaultctor_test.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for ...''' - -import sys -import unittest - -from sample import NonDefaultCtor - -class DerivedNonDefaultCtor (NonDefaultCtor): - def returnMyselfVirtual(self): - return NonDefaultCtor(self.value()+1) - -class AnotherDerivedNonDefaultCtor (NonDefaultCtor): - def __init__(self, some_string): - pass - -class NonDefaultCtorTest(unittest.TestCase): - - def testNonDefaultCtor(self): - c = NonDefaultCtor(2) - # these functions returns NonDefaultCtor by value, so a PyObjecy is created every time - self.assertNotEqual(c.returnMyself(), c) - self.assertEqual(c.returnMyself().value(), 2) - self.assertNotEqual(c.returnMyself(3), c) - self.assertEqual(c.returnMyself(3).value(), 2) - self.assertNotEqual(c.returnMyself(4, c), c) - self.assertEqual(c.returnMyself(4, c).value(), 2) - - def testVirtuals(self): - c = DerivedNonDefaultCtor(3) - # these functions returns NonDefaultCtor by value, so a PyObjecy is created every time - self.assertNotEqual(c.returnMyselfVirtual(), c) - self.assertEqual(c.returnMyselfVirtual().value(), 4) - self.assertEqual(c.callReturnMyselfVirtual().value(), 4) - - def testCtorOverload(self): - c = AnotherDerivedNonDefaultCtor("testing") - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/nonzero_test.py b/tests/samplebinding/nonzero_test.py deleted file mode 100644 index 7020d30a8..000000000 --- a/tests/samplebinding/nonzero_test.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import * - -class TestNonZeroOperator(unittest.TestCase): - def testIt(self): - c = Color() - self.assertFalse(c) - c = Color(2) - self.assertTrue(c) - -if __name__ == "__main__": - unittest.main() diff --git a/tests/samplebinding/numericaltypedef_test.py b/tests/samplebinding/numericaltypedef_test.py deleted file mode 100644 index 774b7f1d1..000000000 --- a/tests/samplebinding/numericaltypedef_test.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import SizeF - -class NumericalTypedefTest(unittest.TestCase): - - def testNumericalTypedefExact(self): - width, height = (1.1, 2.2) - size = SizeF(width, height) - self.assertEqual(size.width(), width) - self.assertEqual(size.height(), height) - - def testNumericalTypedefConvertible(self): - width, height = (1, 2) - size = SizeF(width, height) - self.assertEqual(size.width(), float(width)) - self.assertEqual(size.height(), float(height)) - - def testNumericalTypedefOfUnsignedShort(self): - self.assertEqual(SizeF.passTypedefOfUnsignedShort(123), 123) - self.assertEqual(SizeF.passTypedefOfUnsignedShort(321), 321) - self.assertNotEqual(SizeF.passTypedefOfUnsignedShort(123), 0) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/numpy_test.py b/tests/samplebinding/numpy_test.py deleted file mode 100644 index 65861e864..000000000 --- a/tests/samplebinding/numpy_test.py +++ /dev/null @@ -1,58 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import sys - -try: - from distutils import sysconfig - if bool(sysconfig.get_config_var('Py_DEBUG')): - sys.exit(0) - import numpy -except: - sys.exit(0) - -import unittest -from sample import PointF - -class TestNumpyTypes(unittest.TestCase): - - def testNumpyConverted(self): - x, y = (0.1, 0.2) - p = PointF(float(numpy.float32(x)), float(numpy.float32(y))) - self.assertAlmostEqual(p.x(), x) - self.assertAlmostEqual(p.y(), y) - - def testNumpyAsIs(self): - x, y = (0.1, 0.2) - p = PointF(numpy.float32(x), numpy.float32(y)) - self.assertAlmostEqual(p.x(), x) - self.assertAlmostEqual(p.y(), y) - -if __name__ == "__main__": - unittest.main() - diff --git a/tests/samplebinding/objecttype_test.py b/tests/samplebinding/objecttype_test.py deleted file mode 100644 index 1a06e7e08..000000000 --- a/tests/samplebinding/objecttype_test.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests ObjectType class of object-type with privates copy constructor and = operator.''' - -import unittest -import sys - -from sample import ObjectType, Str -import shiboken2 as shiboken - - -class ObjectTypeTest(unittest.TestCase): - '''Test cases ObjectType class of object-type with privates copy constructor and = operator.''' - - def testObjectTypeSetObjectNameWithStrVariable(self): - '''ObjectType.setObjectName with Str variable as argument.''' - s = Str('object name') - o = ObjectType() - o.setObjectName(s) - self.assertEqual(str(o.objectName()), str(s)) - - def testObjectTypeSetObjectNameWithStrInstantiation(self): - '''ObjectType.setObjectName with Str instantiation as argument.''' - s = 'object name' - o = ObjectType() - o.setObjectName(Str(s)) - self.assertEqual(str(o.objectName()), s) - - def testObjectTypeSetObjectNameWithPythonString(self): - '''ObjectType.setObjectName with Python string as argument.''' - o = ObjectType() - o.setObjectName('object name') - self.assertEqual(str(o.objectName()), 'object name') - - def testNullOverload(self): - o = ObjectType() - o.setObject(None) - self.assertEqual(o.callId(), 0) - o.setNullObject(None) - self.assertEqual(o.callId(), 1) - - def testParentFromCpp(self): - o = ObjectType() - self.assertEqual(sys.getrefcount(o), 2) - o.getCppParent().setObjectName('parent') - self.assertEqual(sys.getrefcount(o), 3) - o.getCppParent().setObjectName('parent') - self.assertEqual(sys.getrefcount(o), 3) - o.getCppParent().setObjectName('parent') - self.assertEqual(sys.getrefcount(o), 3) - o.getCppParent().setObjectName('parent') - self.assertEqual(sys.getrefcount(o), 3) - o.getCppParent().setObjectName('parent') - self.assertEqual(sys.getrefcount(o), 3) - o.destroyCppParent() - self.assertEqual(sys.getrefcount(o), 2) - - def testNextInFocusChainCycle(self): - parent = ObjectType() - child = ObjectType(parent) - next_focus = child.nextInFocusChain() - - shiboken.invalidate(parent) - - def testNextInFocusChainCycleList(self): - '''As above but in for a list of objects''' - parents = [] - children = [] - focus_chains = [] - for i in range(10): - parent = ObjectType() - child = ObjectType(parent) - next_focus = child.nextInFocusChain() - parents.append(parent) - children.append(child) - focus_chains.append(next_focus) - - shiboken.invalidate(parents) - - def testClassDecref(self): - # Bug was that class PyTypeObject wasn't decrefed when instance died - before = sys.getrefcount(ObjectType) - - for i in range(1000): - obj = ObjectType() - shiboken.delete(obj) - - after = sys.getrefcount(ObjectType) - - self.assertLess(abs(before - after), 5) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/objecttype_with_named_args_test.py b/tests/samplebinding/objecttype_with_named_args_test.py deleted file mode 100755 index 533b5a5d1..000000000 --- a/tests/samplebinding/objecttype_with_named_args_test.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import ObjectType - -class NamedArgsTest(unittest.TestCase): - - def testOneArgument(self): - p = ObjectType() - o = ObjectType(parent=p) - self.assertEqual(o.parent(), p) - - def testMoreArguments(self): - o = ObjectType() - - o.setObjectSplittedName("", prefix="pys", suffix="ide") - self.assertEqual(o.objectName(), "pyside") - - o.setObjectSplittedName("", suffix="ide", prefix="pys") - self.assertEqual(o.objectName(), "pyside") - - o.setObjectNameWithSize(name="pyside", size=6) - self.assertEqual(o.objectName(), "pyside") - - o.setObjectNameWithSize(size=6, name="pyside") - self.assertEqual(o.objectName(), "pyside") - - - def testUseDefaultValues(self): - o = ObjectType() - - o.setObjectNameWithSize(size=3) - self.assertEqual(o.objectName(), "") # user prefix=' b) - self.assertEqual(a.key(), "aoperator>") - - def testPointerOpeators(self): - a = ObjectTypeOperators("a") - b = ObjectTypeOperators("b") - self.assertEqual(a + "bc", "abc") - self.assertEqual("bc" + a, "bca") - self.assertEqual("a", a) - self.assertEqual(a, "a") - - def testOperatorInjection(self): - a = ObjectTypeOperators("a") - self.assertNotEqual(a, "b") - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py b/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py deleted file mode 100644 index 3f09df200..000000000 --- a/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import ObjectTypeHolder - -class TestObjectTypeReferenceAsVirtualMethodArgument(unittest.TestCase): - - def testBasic(self): - holder = ObjectTypeHolder('TheObjectFromC++') - self.assertEqual(holder.callPassObjectTypeAsReference(), 'TheObjectFromC++') - - def testExtended(self): - class Holder(ObjectTypeHolder): - def passObjectTypeAsReference(self, objectType): - return objectType.objectName().prepend(('ThisIs')) - holder = Holder('TheObjectFromC++') - self.assertEqual(holder.callPassObjectTypeAsReference(), 'ThisIsTheObjectFromC++') - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/oddbool_test.py b/tests/samplebinding/oddbool_test.py deleted file mode 100644 index 3424d9dc0..000000000 --- a/tests/samplebinding/oddbool_test.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for OddBool user's primitive type conversion.''' - -import unittest - -from sample import OddBoolUser - -class DerivedOddBoolUser (OddBoolUser): - def returnMyselfVirtual(self): - return OddBoolUser() - pass - -class OddBoolTest(unittest.TestCase): - - def testOddBoolUser(self): - obuTrue = OddBoolUser() - obuFalse = OddBoolUser() - obuTrue.setOddBool(True) - self.assertEqual(obuFalse.oddBool(), False) - 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.assertEqual(obuFalse.oddBool() != True, True) - self.assertEqual(True != obuFalse.oddBool(), True) - self.assertEqual(obuTrue.oddBool() != obuFalse.oddBool(), True) - - def testVirtuals(self): - dobu = DerivedOddBoolUser() - self.assertEqual(dobu.invertedOddBool(), True) - - def testImplicitConversionWithUsersPrimitiveType(self): - obu = OddBoolUser(True) - self.assertTrue(obu.oddBool()) - obu = OddBoolUser(False) - self.assertFalse(obu.oddBool()) - cpx = complex(1.0, 0.0) - obu = OddBoolUser(cpx) - self.assertTrue(obu.oddBool()) - cpx = complex(0.0, 0.0) - obu = OddBoolUser(cpx) - self.assertFalse(obu.oddBool()) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/oldstyleclass_as_number_test.py b/tests/samplebinding/oldstyleclass_as_number_test.py deleted file mode 100644 index a4f52e1fe..000000000 --- a/tests/samplebinding/oldstyleclass_as_number_test.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -import sample -from py3kcompat import IS_PY3K - -class OldStyle: - pass - -class NewStyle(object): - pass - -class OldStyleNumber: - def __init__(self, value): - self.value = value - def __trunc__(self): - return self.value - -class NewStyleNumber(object): - def __init__(self, value): - self.value = value - def __int__(self): - return int(self.value) - def __trunc__(self): - return self.value - -class TestOldStyleClassAsNumber(unittest.TestCase): - - def testBasic(self): - '''For the sake of calibration...''' - self.assertEqual(sample.acceptInt(123), 123) - - def testOldStyleClassPassedAsInteger(self): - '''Old-style classes aren't numbers and shouldn't be accepted.''' - obj = OldStyle() - self.assertRaises(TypeError, sample.acceptInt, obj) - - def testNewStyleClassPassedAsInteger(self): - '''New-style classes aren't numbers and shouldn't be accepted.''' - obj = NewStyle() - self.assertRaises(TypeError, sample.acceptInt, obj) - - def testOldStyleClassWithNumberProtocol(self): - obj = OldStyleNumber(123) - self.assertEqual(sample.acceptInt(obj), obj.value) - - def testNewStyleClassWithNumberProtocol(self): - obj = NewStyleNumber(123) - self.assertEqual(sample.acceptInt(obj), obj.value) - -if __name__ == "__main__" and not IS_PY3K: - unittest.main() - diff --git a/tests/samplebinding/onlycopyclass_test.py b/tests/samplebinding/onlycopyclass_test.py deleted file mode 100644 index 647d2cdd7..000000000 --- a/tests/samplebinding/onlycopyclass_test.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import OnlyCopy, FriendOfOnlyCopy - -class ClassWithOnlyCopyCtorTest(unittest.TestCase): - def testGetOne(self): - obj = FriendOfOnlyCopy.createOnlyCopy(123) - self.assertEqual(type(obj), OnlyCopy) - self.assertEqual(obj.value(), 123) - - def testGetMany(self): - objs = FriendOfOnlyCopy.createListOfOnlyCopy(3) - self.assertEqual(type(objs), list) - self.assertEqual(len(objs), 3) - for value, obj in enumerate(objs): - self.assertEqual(obj.value(), value) - - def testPassAsValue(self): - obj = FriendOfOnlyCopy.createOnlyCopy(123) - self.assertEqual(obj.value(), OnlyCopy.getValue(obj)) - - def testPassAsReference(self): - obj = FriendOfOnlyCopy.createOnlyCopy(123) - self.assertEqual(obj.value(), OnlyCopy.getValueFromReference(obj)) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/overflow_test.py b/tests/samplebinding/overflow_test.py deleted file mode 100644 index 8a0fff45d..000000000 --- a/tests/samplebinding/overflow_test.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for overflowing C++ numeric types.''' - -import sys -import unittest - -from sample import * -from py3kcompat import IS_PY3K, long - -class OverflowTest(unittest.TestCase): - '''Test case for overflowing C++ numeric types.''' - - def testUnsignedInt(self): - '''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.''' - val = 100 - self.assertEqual(doubleLongLong(val), 2 * val) - val = long(100) - self.assertEqual(doubleLongLong(val), 2 * val) - val = (2 << 64) + 1 - self.assertRaises(OverflowError, doubleLongLong, val) - - def testUnsignedLongLong(self): - '''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 = long(100) - self.assertEqual(doubleUnsignedLongLong(val), 2 * val) - val = -100 - self.assertRaises(OverflowError, doubleUnsignedLongLong, val) - val = long(-200) - self.assertRaises(OverflowError, doubleUnsignedLongLong, val) - - def testOverflow(self): - '''Calls function with unsigned int parameter using an overflowing value.''' - self.assertRaises(OverflowError, doubleUnsignedInt, 42415335332353253) - doubleUnsignedInt(0xdeadbeef) - - 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) - - 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/tests/samplebinding/overload_sorting_test.py b/tests/samplebinding/overload_sorting_test.py deleted file mode 100644 index 30e1ad955..000000000 --- a/tests/samplebinding/overload_sorting_test.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for overload sorting''' - -import unittest - -from sample import * - -class Dummy(object): - pass - -class SimpleOverloadSorting(unittest.TestCase): - - def setUp(self): - self.obj = SortedOverload() - - def testIntDouble(self): - '''Overloads with int and double''' - self.assertEqual(self.obj.overload(3), "int") - self.assertEqual(self.obj.overload(3.14), "double") - - def testImplicitConvert(self): - '''Overloads with implicit convertible types''' - self.assertEqual(self.obj.overload(ImplicitTarget()), "ImplicitTarget") - self.assertEqual(self.obj.overload(ImplicitBase()), "ImplicitBase") - - def testContainer(self): - '''Overloads with containers arguments''' - self.assertEqual(self.obj.overload([ImplicitBase()]), "list(ImplicitBase)") - - def testPyObject(self): - '''Overloads with PyObject args''' - self.assertEqual(self.obj.overload(Dummy()), "PyObject") - - def testImplicitOnly(self): - '''Passing an implicit convertible object to an overload''' - self.assertTrue(self.obj.implicit_overload(ImplicitTarget())) - - def testPyObjectSort(self): - self.assertEqual(self.obj.pyObjOverload(1, 2), "int,int") - self.assertEqual(self.obj.pyObjOverload(object(), 2), "PyObject,int") - - -class DeepOverloadSorting(unittest.TestCase): - - def setUp(self): - self.obj = SortedOverload() - - def testPyObject(self): - '''Deep Overload - (int, PyObject *)''' - self.assertEqual(self.obj.overloadDeep(1, Dummy()), "PyObject") - - def testImplicit(self): - '''Deep Overload - (int, ImplicitBase *)''' - self.assertEqual(self.obj.overloadDeep(1, ImplicitBase()), "ImplicitBase") - -class EnumOverIntSorting(unittest.TestCase): - def testEnumOverInt(self): - ic = ImplicitConv(ImplicitConv.CtorTwo) - self.assertEqual(ic.ctorEnum(), ImplicitConv.CtorTwo) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/overload_test.py b/tests/samplebinding/overload_test.py deleted file mode 100644 index efcd3bed8..000000000 --- a/tests/samplebinding/overload_test.py +++ /dev/null @@ -1,209 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Overload class''' - -import unittest -from sample import Echo, Overload, Point, PointF, Polygon, Rect, RectF, Size, Str - - -def raisesWithErrorMessage(func, arguments, errorType, errorMsg): - '''NOTE: Using 'try' because assertRaisesRegexp is not available - to check the error message.''' - try: - func(*arguments) - return False - except Exception as err: - if type(err) != TypeError: - return False - if not errorMsg in str(err): - return False - return True - - -class OverloadTest(unittest.TestCase): - '''Test case for Overload class''' - - def testOverloadMethod0(self): - '''Check overloaded method call for signature "overloaded()".''' - overload = Overload() - self.assertEqual(overload.overloaded(), Overload.Function0) - - def testOverloadMethod1(self): - '''Check overloaded method call for signature "overloaded(Size*)".''' - overload = Overload() - size = Size() - self.assertEqual(overload.overloaded(size), Overload.Function1) - - def testOverloadMethod2(self): - '''Check overloaded method call for signature "overloaded(Point*, ParamEnum)".''' - overload = Overload() - point = Point() - self.assertEqual(overload.overloaded(point, Overload.Param1), Overload.Function2) - - def testOverloadMethod3(self): - '''Check overloaded method call for signature "overloaded(const Point&)".''' - overload = Overload() - point = Point() - self.assertEqual(overload.overloaded(point), Overload.Function3) - - def testDifferentReturnTypes(self): - '''Check method calls for overloads with different return types.''' - overload = Overload() - self.assertEqual(overload.differentReturnTypes(), None) - self.assertEqual(overload.differentReturnTypes(Overload.Param1), None) - self.assertEqual(overload.differentReturnTypes(Overload.Param0, 13), 13) - - def testIntOverloads(self): - overload = Overload() - self.assertEqual(overload.intOverloads(2, 3), 2) - self.assertEqual(overload.intOverloads(2, 4.5), 3) - self.assertEqual(overload.intOverloads(Point(0, 0), 3), 1) - - def testIntDoubleOverloads(self): - overload = Overload() - self.assertEqual(overload.intDoubleOverloads(1, 2), Overload.Function0) - self.assertEqual(overload.intDoubleOverloads(1, 2.0), Overload.Function0) - self.assertEqual(overload.intDoubleOverloads(1.0, 2), Overload.Function1) - self.assertEqual(overload.intDoubleOverloads(1.0, 2.0), Overload.Function1) - - def testWrapperIntIntOverloads(self): - overload = Overload() - self.assertEqual(overload.wrapperIntIntOverloads(Point(), 1, 2), Overload.Function0) - self.assertEqual(overload.wrapperIntIntOverloads(Polygon(), 1, 2), Overload.Function1) - - def testDrawTextPointAndStr(self): - overload = Overload() - self.assertEqual(overload.drawText(Point(), Str()), Overload.Function0) - self.assertEqual(overload.drawText(Point(), ''), Overload.Function0) - self.assertEqual(overload.drawText(PointF(), Str()), Overload.Function1) - self.assertEqual(overload.drawText(PointF(), ''), Overload.Function1) - - def testDrawTextRectIntStr(self): - overload = Overload() - self.assertEqual(overload.drawText(Rect(), 1, Str()), Overload.Function2) - self.assertEqual(overload.drawText(Rect(), 1, ''), Overload.Function2) - self.assertEqual(overload.drawText(RectF(), 1, Str()), Overload.Function3) - self.assertEqual(overload.drawText(RectF(), 1, ''), Overload.Function3) - - def testDrawTextRectFStrEcho(self): - overload = Overload() - self.assertEqual(overload.drawText(RectF(), Str()), Overload.Function4) - self.assertEqual(overload.drawText(RectF(), ''), Overload.Function4) - self.assertEqual(overload.drawText(RectF(), Str(), Echo()), Overload.Function4) - self.assertEqual(overload.drawText(RectF(), '', Echo()), Overload.Function4) - self.assertEqual(overload.drawText(Rect(), Str()), Overload.Function4) - self.assertEqual(overload.drawText(Rect(), ''), Overload.Function4) - self.assertEqual(overload.drawText(Rect(), Str(), Echo()), Overload.Function4) - self.assertEqual(overload.drawText(Rect(), '', Echo()), Overload.Function4) - - def testDrawTextIntIntStr(self): - overload = Overload() - self.assertEqual(overload.drawText(1, 2, Str()), Overload.Function5) - self.assertEqual(overload.drawText(1, 2, ''), Overload.Function5) - - def testDrawTextIntIntIntIntStr(self): - overload = Overload() - self.assertEqual(overload.drawText(1, 2, 3, 4, 5, Str()), Overload.Function6) - self.assertEqual(overload.drawText(1, 2, 3, 4, 5, ''), Overload.Function6) - - def testDrawText2IntIntIntIntStr(self): - overload = Overload() - self.assertEqual(overload.drawText2(1, 2, 3, 4, 5, Str()), Overload.Function6) - self.assertEqual(overload.drawText2(1, 2, 3, 4, 5, ''), Overload.Function6) - self.assertEqual(overload.drawText2(1, 2, 3, 4, 5), Overload.Function6) - self.assertEqual(overload.drawText2(1, 2, 3, 4), Overload.Function6) - self.assertEqual(overload.drawText2(1, 2, 3), Overload.Function6) - - def testDrawText3(self): - overload = Overload() - self.assertEqual(overload.drawText3(Str(), Str(), Str()), Overload.Function0) - self.assertEqual(overload.drawText3('', '', ''), Overload.Function0) - self.assertEqual(overload.drawText3(1, 2, 3, 4, 5), Overload.Function1) - self.assertEqual(overload.drawText3(1, 2, 3, 4, 5), Overload.Function1) - - def testDrawText3Exception(self): - overload = Overload() - args = (Str(), Str(), Str(), 4, 5) - result = raisesWithErrorMessage(overload.drawText3, args, - TypeError, 'called with wrong argument types:') - self.assertTrue(result) - - def testDrawText4(self): - overload = Overload() - self.assertEqual(overload.drawText4(1, 2, 3), Overload.Function0) - self.assertEqual(overload.drawText4(1, 2, 3, 4, 5), Overload.Function1) - - def testAcceptSequence(self): - # Overload.acceptSequence() - overload = Overload() - self.assertEqual(overload.acceptSequence(), Overload.Function0) - - def testAcceptSequenceIntInt(self): - # Overload.acceptSequence(int,int) - overload = Overload() - self.assertEqual(overload.acceptSequence(1, 2), Overload.Function1) - - def testAcceptSequenceStrParamEnum(self): - # Overload.acceptSequence(Str,Overload::ParamEnum) - overload = Overload() - self.assertEqual(overload.acceptSequence(''), Overload.Function2) - self.assertEqual(overload.acceptSequence('', Overload.Param0), Overload.Function2) - self.assertEqual(overload.acceptSequence(Str('')), Overload.Function2) - self.assertEqual(overload.acceptSequence(Str(''), Overload.Param0), Overload.Function2) - - def testAcceptSequenceSize(self): - # Overload.acceptSequence(Size) - overload = Overload() - self.assertEqual(overload.acceptSequence(Size()), Overload.Function3) - - def testAcceptSequenceStringList(self): - # Overload.acceptSequence(const char**) - overload = Overload() - strings = ['line 1', 'line 2'] - self.assertEqual(overload.acceptSequence(strings), Overload.Function4) - args = (['line 1', 2], ) - result = raisesWithErrorMessage(overload.acceptSequence, args, - TypeError, 'The argument must be a sequence of strings.') - self.assertTrue(result) - - 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/tests/samplebinding/overloadwithdefault_test.py b/tests/samplebinding/overloadwithdefault_test.py deleted file mode 100644 index 9f243a573..000000000 --- a/tests/samplebinding/overloadwithdefault_test.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import Overload, Str -from py3kcompat import b - -class OverloadTest(unittest.TestCase): - - def testNoArgument(self): - overload = Overload() - self.assertEqual(overload.strBufferOverloads(), Overload.Function2) - - def testStrArgument(self): - overload = Overload() - self.assertEqual(overload.strBufferOverloads(Str('')), Overload.Function0) - self.assertEqual(overload.strBufferOverloads(Str(''), ''), Overload.Function0) - self.assertEqual(overload.strBufferOverloads(Str(''), '', False), Overload.Function0) - - def testStringArgumentAsStr(self): - overload = Overload() - self.assertEqual(overload.strBufferOverloads('', ''), Overload.Function0) - self.assertEqual(overload.strBufferOverloads('', '', False), Overload.Function0) - - def testStringArgumentAsBuffer(self): - overload = Overload() - self.assertEqual(overload.strBufferOverloads(b'', 0), Overload.Function1) - - def testBufferArgument(self): - overload = Overload() - self.assertEqual(overload.strBufferOverloads(b(''), 0), Overload.Function1) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_argument_invalidation_test.py b/tests/samplebinding/ownership_argument_invalidation_test.py deleted file mode 100644 index 5c6f31395..000000000 --- a/tests/samplebinding/ownership_argument_invalidation_test.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Wrapper validity tests for arguments.''' - -import sys -import unittest - -from sample import Polygon, Point - -class WrapperValidityOfArgumentsTest(unittest.TestCase): - '''Wrapper validity tests for arguments.''' - - def testInvalidArgumentToMethod(self): - '''Call to method using invalidated Python wrapper as argument should raise RuntimeError.''' - poly = Polygon() - Polygon.stealOwnershipFromPython(poly) - self.assertRaises(RuntimeError, Polygon.doublePolygonScale, poly) - - def testInvalidArgumentToConstructor(self): - '''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.''' - pt = Point(1, 2) - Polygon.stealOwnershipFromPython(pt) - self.assertRaises(RuntimeError, Polygon.doublePolygonScale, pt) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_delete_child_in_cpp_test.py b/tests/samplebinding/ownership_delete_child_in_cpp_test.py deleted file mode 100644 index 829cabd81..000000000 --- a/tests/samplebinding/ownership_delete_child_in_cpp_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for destroy a child object in C++''' - -import unittest - -from sample import ObjectType - - -class DeleteChildInCpp(unittest.TestCase): - '''Test case for destroying a child in c++''' - - def testDeleteChild(self): - '''Delete child in C++ should invalidate child - using C++ wrapper''' - parent = ObjectType() - parent.setObjectName('parent') - child = ObjectType(parent) - child.setObjectName('child') - - parent.killChild('child') - self.assertRaises(RuntimeError, child.objectName) - self.assertEqual(parent.objectName(), 'parent') - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/ownership_delete_child_in_python_test.py b/tests/samplebinding/ownership_delete_child_in_python_test.py deleted file mode 100644 index 32312af7f..000000000 --- a/tests/samplebinding/ownership_delete_child_in_python_test.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for deleting a child object in python''' - -import unittest -import random -import string - -from sample import ObjectType -from py3kcompat import IS_PY3K - -if IS_PY3K: - string.letters = string.ascii_letters - - -class DeleteChildInPython(unittest.TestCase): - '''Test case for deleting (unref) a child in python''' - - def testDeleteChild(self): - '''Delete child in python should not invalidate child''' - parent = ObjectType() - child = ObjectType(parent) - name = ''.join(random.sample(string.letters, 5)) - child.setObjectName(name) - - del child - new_child = parent.children()[0] - self.assertEqual(new_child.objectName(), name) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/ownership_delete_parent_test.py b/tests/samplebinding/ownership_delete_parent_test.py deleted file mode 100644 index 1c135a4aa..000000000 --- a/tests/samplebinding/ownership_delete_parent_test.py +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for destroying the parent''' - -import sys -import unittest - -from sample import ObjectType - - -class DeleteParentTest(unittest.TestCase): - '''Test case for deleting a parent object''' - - def testParentDestructor(self): - '''Delete parent object should invalidate child''' - parent = ObjectType() - child = ObjectType() - child.setParent(parent) - - refcount_before = sys.getrefcount(child) - - del parent - self.assertRaises(RuntimeError, child.objectName) - self.assertEqual(sys.getrefcount(child), refcount_before-1) - - def testParentDestructorMultipleChildren(self): - '''Delete parent object should invalidate all children''' - parent = ObjectType() - children = [ObjectType() for _ in range(10)] - - for child in children: - child.setParent(parent) - - del parent - for i, child in enumerate(children): - self.assertRaises(RuntimeError, child.objectName) - self.assertEqual(sys.getrefcount(child), 4) - - def testRecursiveParentDelete(self): - '''Delete parent should invalidate grandchildren''' - parent = ObjectType() - child = ObjectType(parent) - grandchild = ObjectType(child) - - del parent - self.assertRaises(RuntimeError, child.objectName) - self.assertEqual(sys.getrefcount(child), 2) - self.assertRaises(RuntimeError, grandchild.objectName) - self.assertEqual(sys.getrefcount(grandchild), 2) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/ownership_invalidate_after_use_test.py b/tests/samplebinding/ownership_invalidate_after_use_test.py deleted file mode 100644 index 8b3e84738..000000000 --- a/tests/samplebinding/ownership_invalidate_after_use_test.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Ownership tests for cases of invalidation of Python wrapper after use.''' - -import sys -import unittest - -from sample import ObjectType, ObjectTypeDerived, Event - - -class ExtObjectType(ObjectType): - def __init__(self): - 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__() - self.fail = False - - def event(self, ev): - self.callInvalidateEvent(ev) - try: - ev.eventType() - except: - self.fail = True - raise - return True - - 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.''' - eot = ExtObjectType() - eot.causeEvent(Event.SOME_EVENT) - self.assertEqual(eot.type_of_last_event, Event.SOME_EVENT) - self.assertRaises(RuntimeError, eot.last_event.eventType) - - def testObjectInvalidatedAfterUseAsParameter(self): - '''Tries to use wrapper invalidated after use as a parameter to another method.''' - eot = ExtObjectType() - ot = ObjectType() - eot.causeEvent(Event.ANY_EVENT) - self.assertEqual(eot.type_of_last_event, Event.ANY_EVENT) - self.assertRaises(RuntimeError, ot.event, eot.last_event) - - def testit(self): - obj = MyObjectType() - obj.causeEvent(Event.BASIC_EVENT) - self.assertFalse(obj.fail) - - def testInvalidateAfterUseInDerived(self): - '''Invalidate was failing in a derived C++ class that also inherited - other base classes''' - eot = ExtObjectTypeDerived() - eot.causeEvent(Event.SOME_EVENT) - 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/tests/samplebinding/ownership_invalidate_child_test.py b/tests/samplebinding/ownership_invalidate_child_test.py deleted file mode 100644 index e92fa39f5..000000000 --- a/tests/samplebinding/ownership_invalidate_child_test.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for invalidating a C++ created child that was already on the care of a parent.''' - -import unittest - -from sample import ObjectType, BlackBox - - -class InvalidateChildTest(unittest.TestCase): - '''Tests for invalidating a C++ created child that was already on the care of a parent.''' - - def testInvalidateChild(self): - '''Invalidating method call should remove child from the care of a parent if it has one.''' - parent = ObjectType() - child1 = ObjectType(parent) - child1.setObjectName('child1') - child2 = ObjectType.create() - child2.setParent(parent) - child2.setObjectName('child2') - - self.assertEqual(parent.children(), [child1, child2]) - - bbox = BlackBox() - - # This method steals ownership from Python to C++. - bbox.keepObjectType(child1) - self.assertEqual(parent.children(), [child2]) - - bbox.keepObjectType(child2) - self.assertEqual(parent.children(), []) - - del parent - - self.assertEqual(child1.objectName(), 'child1') - self.assertRaises(RuntimeError, child2.objectName) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py b/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py deleted file mode 100644 index 69527974c..000000000 --- a/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''The BlackBox class has cases of ownership transference between Python and C++.''' - -import sys -import unittest - -from sample import Point, BlackBox - -class OwnershipInvalidateNonPolymorphicTest(unittest.TestCase): - '''The BlackBox class has cases of ownership transference between Python and C++.''' - - def testOwnershipTransference(self): - '''Ownership transference from Python to C++ and back again.''' - p1 = Point(10, 20) - bb = BlackBox() - p1_ticket = bb.keepPoint(p1) - self.assertRaises(RuntimeError, p1.x) - p1_ret = bb.retrievePoint(p1_ticket) - self.assertEqual(p1_ret, Point(10, 20)) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_invalidate_parent_test.py b/tests/samplebinding/ownership_invalidate_parent_test.py deleted file mode 100644 index 848c982ce..000000000 --- a/tests/samplebinding/ownership_invalidate_parent_test.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for invalidating a parent of other objects.''' - -import unittest - -from sample import ObjectType, BlackBox - - -class InvalidateParentTest(unittest.TestCase): - '''Tests for invalidating a parent of other objects.''' - - def testInvalidateParent(self): - '''Invalidate parent should invalidate children''' - parent = ObjectType.create() - child1 = ObjectType(parent) - child1.setObjectName("child1") - child2 = ObjectType.create() - child2.setObjectName("child2") - child2.setParent(parent) - grandchild1 = ObjectType(child1) - grandchild1.setObjectName("grandchild1") - grandchild2 = ObjectType.create() - grandchild2.setObjectName("grandchild2") - grandchild2.setParent(child2) - bbox = BlackBox() - - bbox.keepObjectType(parent) # Should invalidate the parent - - self.assertRaises(RuntimeError, parent.objectName) - # some children still valid they are wrapper classes - self.assertEqual(child1.objectName(), "child1") - self.assertRaises(RuntimeError, child2.objectName) - self.assertEqual(grandchild1.objectName(), "grandchild1") - self.assertRaises(RuntimeError, grandchild2.objectName) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_reparenting_test.py b/tests/samplebinding/ownership_reparenting_test.py deleted file mode 100644 index 20e6aca03..000000000 --- a/tests/samplebinding/ownership_reparenting_test.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests for object reparenting.''' - -import unittest -import sys - -from sample import ObjectType - -class ExtObjectType(ObjectType): - def __init__(self): - ObjectType.__init__(self) - - -class ReparentingTest(unittest.TestCase): - '''Tests for object reparenting.''' - - def testReparentedObjectTypeIdentity(self): - '''Reparent children from one parent to another.''' - object_list = [] - old_parent = ObjectType() - new_parent = ObjectType() - for i in range(3): - obj = ObjectType() - object_list.append(obj) - obj.setParent(old_parent) - for obj in object_list: - obj.setParent(new_parent) - for child in new_parent.children(): - self.assertTrue(child in object_list) - - def testReparentWithTheSameParent(self): - '''Set the same parent twice to check if the ref continue the same''' - obj = ObjectType() - parent = ObjectType() - self.assertEqual(sys.getrefcount(obj), 2) - obj.setParent(parent) - self.assertEqual(sys.getrefcount(obj), 3) - obj.setParent(parent) - self.assertEqual(sys.getrefcount(obj), 3) - - def testReparentedExtObjectType(self): - '''Reparent children from one extended parent to another.''' - object_list = [] - old_parent = ExtObjectType() - new_parent = ExtObjectType() - for i in range(3): - obj = ExtObjectType() - object_list.append(obj) - obj.setParent(old_parent) - for obj in object_list: - obj.setParent(new_parent) - for orig, child in zip(object_list, new_parent.children()): - self.assertEqual(type(orig), type(child)) - - def testReparentedObjectTypeIdentityWithParentsCreatedInCpp(self): - '''Reparent children from one parent to another, both created in C++.''' - object_list = [] - old_parent = ObjectType.create() - new_parent = ObjectType.create() - for i in range(3): - obj = ObjectType() - object_list.append(obj) - obj.setParent(old_parent) - for obj in object_list: - obj.setParent(new_parent) - for child in new_parent.children(): - self.assertTrue(child in object_list) - - def testReparentedObjectTypeIdentityWithChildrenCreatedInCpp(self): - '''Reparent children created in C++ from one parent to another.''' - object_list = [] - old_parent = ObjectType() - new_parent = ObjectType() - for i in range(3): - obj = ObjectType.create() - object_list.append(obj) - obj.setParent(old_parent) - for obj in object_list: - obj.setParent(new_parent) - for child in new_parent.children(): - self.assertTrue(child in object_list) - - def testReparentedObjectTypeIdentityWithParentsAndChildrenCreatedInCpp(self): - '''Reparent children from one parent to another. Parents and children are created in C++.''' - object_list = [] - old_parent = ObjectType.create() - new_parent = ObjectType.create() - for i in range(3): - obj = ObjectType.create() - object_list.append(obj) - obj.setParent(old_parent) - for obj in object_list: - obj.setParent(new_parent) - for child in new_parent.children(): - self.assertTrue(child in object_list) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/ownership_transference_test.py b/tests/samplebinding/ownership_transference_test.py deleted file mode 100644 index 0df2a09ba..000000000 --- a/tests/samplebinding/ownership_transference_test.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''The BlackBox class has cases of ownership transference between C++ and Python.''' - -import sys -import unittest - -from sample import ObjectType, BlackBox - -class BlackBoxTest(unittest.TestCase): - '''The BlackBox class has cases of ownership transference between C++ and Python.''' - - def testOwnershipTransference(self): - '''Ownership transference from Python to C++ and back again.''' - o1 = ObjectType() - o1.setObjectName('object1') - o1_refcnt = sys.getrefcount(o1) - o2 = ObjectType() - o2.setObjectName('object2') - o2_refcnt = sys.getrefcount(o2) - bb = BlackBox() - o1_ticket = bb.keepObjectType(o1) - 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 - self.assertEqual(sys.getrefcount(o2), o2_refcnt + 1) - o2 = bb.retrieveObjectType(o2_ticket) - self.assertEqual(sys.getrefcount(o2), o2_refcnt) - del bb - self.assertRaises(RuntimeError, o1.objectName) - self.assertEqual(str(o2.objectName()), 'object2') - self.assertEqual(sys.getrefcount(o2), o2_refcnt) - - def testBlackBoxReleasingUnknownObjectType(self): - '''Asks BlackBox to release an unknown ObjectType.''' - o1 = ObjectType() - o2 = ObjectType() - bb = BlackBox() - o1_ticket = bb.keepObjectType(o1) - o3 = bb.retrieveObjectType(-5) - self.assertEqual(o3, None) - - def testOwnershipTransferenceCppCreated(self): - '''Ownership transference using a C++ created object.''' - o1 = ObjectType.create() - o1.setObjectName('object1') - o1_refcnt = sys.getrefcount(o1) - bb = BlackBox() - o1_ticket = bb.keepObjectType(o1) - self.assertRaises(RuntimeError, o1.objectName) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/pair_test.py b/tests/samplebinding/pair_test.py deleted file mode 100644 index 4786213c5..000000000 --- a/tests/samplebinding/pair_test.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for std::pair container conversions''' - -import sys -import unittest - -from sample import PairUser - -class ExtendedPairUser(PairUser): - def __init__(self): - PairUser.__init__(self) - self.create_pair_called = False - - def createPair(self): - self.create_pair_called = True - return (7, 13) - -class PairConversionTest(unittest.TestCase): - '''Test case for std::pair container conversions''' - - def testReimplementedVirtualMethodCall(self): - '''Test if a Python override of a virtual method is correctly called from C++.''' - pu = ExtendedPairUser() - pair = pu.callCreatePair() - self.assertTrue(pu.create_pair_called) - self.assertEqual(type(pair), tuple) - self.assertEqual(type(pair[0]), int) - self.assertEqual(type(pair[1]), int) - self.assertEqual(pair, (7, 13)) - - def testPrimitiveConversionInsideContainer(self): - '''Test primitive type conversion inside conversible std::pair container.''' - cpx0 = complex(1.2, 3.4) - cpx1 = complex(5.6, 7.8) - cp = PairUser.createComplexPair(cpx0, cpx1) - self.assertEqual(type(cp), tuple) - self.assertEqual(type(cp[0]), complex) - self.assertEqual(type(cp[1]), complex) - 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)''' - 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)''' - pu = PairUser() - pair = (3.3, 7) - result = pu.sumPair(pair) - self.assertNotEqual(result, sum(pair)) - self.assertEqual(result, int(pair[0]) + pair[1]) - - def testConversionInBothDirections(self): - '''Test converting a pair from Python to C++ and the other way around.''' - pu = PairUser() - pair = (3, 5) - pu.setPair(pair) - result = pu.getPair() - 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.''' - pu = PairUser() - pair = [3, 5] - pu.setPair(pair) - result = pu.getPair() - self.assertNotEqual(result, pair) - self.assertEqual(result, tuple(pair)) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/pen_test.py b/tests/samplebinding/pen_test.py deleted file mode 100644 index 54c96b9c8..000000000 --- a/tests/samplebinding/pen_test.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for with const char* as argument''' - -import unittest - -from sample import Color, Pen, SampleNamespace - -class TestPen(unittest.TestCase): - '''Simple test case for Pen.''' - - def testPenWithEmptyConstructor(self): - pen = Pen() - self.assertEqual(pen.ctorType(), Pen.EmptyCtor) - - def testPenWithEnumConstructor(self): - pen = Pen(SampleNamespace.RandomNumber) - self.assertEqual(pen.ctorType(), Pen.EnumCtor) - - def testPenWithColorConstructor(self): - pen = Pen(Color()) - self.assertEqual(pen.ctorType(), Pen.ColorCtor) - - def testPenWithCopyConstructor(self): - pen = Pen(Pen()) - self.assertEqual(pen.ctorType(), Pen.CopyCtor) - - def testPenWithIntConvertedToColor(self): - pen = Pen(1) - self.assertEqual(pen.ctorType(), Pen.ColorCtor) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/point_test.py b/tests/samplebinding/point_test.py deleted file mode 100644 index 6f84ac999..000000000 --- a/tests/samplebinding/point_test.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for Point class''' - -import sys -import unittest - -from sample import Point -from py3kcompat import unicode - -class PointTest(unittest.TestCase): - '''Test case for Point class, including operator overloads.''' - - def testConstructor(self): - '''Test Point class constructor.''' - pt = Point(5.0, 2.3) - self.assertEqual(pt.x(), 5.0) - self.assertEqual(pt.y(), 2.3) - - def testPlusOperator(self): - '''Test Point class + operator.''' - pt1 = Point(5.0, 2.3) - pt2 = Point(0.5, 3.2) - self.assertEqual(pt1 + pt2, Point(5.0 + 0.5, 2.3 + 3.2)) - - def testEqualOperator(self): - '''Test Point class == operator.''' - pt1 = Point(5.0, 2.3) - pt2 = Point(5.0, 2.3) - pt3 = Point(0.5, 3.2) - self.assertTrue(pt1 == pt1) - self.assertTrue(pt1 == pt2) - self.assertFalse(pt1 == pt3) - self.assertFalse(pt1 == object()) - - def testNotEqualOperator(self): - '''Test Point class != operator.''' - pt1 = Point(5.0, 2.3) - pt2 = Point(5.0, 2.3) - self.assertRaises(NotImplementedError, pt1.__ne__, pt2) - - def testReturnNewCopy(self): - '''Point returns a copy of itself.''' - pt1 = Point(1.1, 2.3) - pt2 = pt1.copy() - self.assertEqual(pt1, pt2) - pt2 += pt1 - self.assertFalse(pt1 == pt2) - - def testReturnConstPointer(self): - '''Point returns a const pointer for itself.''' - pt1 = Point(5.0, 2.3) - refcount1 = sys.getrefcount(pt1) - pt2 = pt1.getSelf() - self.assertEqual(pt1, pt2) - self.assertEqual(sys.getrefcount(pt1), refcount1 + 1) - self.assertEqual(sys.getrefcount(pt1), sys.getrefcount(pt2)) - - def testUintOverflow(self): - pt1 = Point(0.0, 0.0) - self.assertRaises(OverflowError, pt1.setXAsUint, 840835495615213080) - self.assertEqual(pt1.x(), 0.0) - - def testAddedOperator(self): - p = Point(0.0, 0.0) - r = p - unicode('Hi') - self.assertEqual(r, unicode('Hi')) - - # now the reverse op. - r = unicode('Hi') - p - self.assertEqual(r, unicode('Hi')) - - def testModifiedMethod(self): - pt1 = Point(0.0, 0.0) - pt2 = Point(10.0, 10.0) - 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/tests/samplebinding/pointerholder_test.py b/tests/samplebinding/pointerholder_test.py deleted file mode 100644 index 32ef99d5c..000000000 --- a/tests/samplebinding/pointerholder_test.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for a class that holds an arbitraty pointer and is modified to hold an PyObject.''' - -import sys -import unittest - -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.''' - - def testStoringAndRetrievingPointer(self): - ph = PointerHolder('Hello') - self.assertEqual(ph.pointer(), 'Hello') - a = (1, 2, 3) - ph = PointerHolder(a) - self.assertEqual(ph.pointer(), a) - - def testReferenceCounting(self): - '''Test reference counting when retrieving data with PointerHolder.pointer().''' - a = (1, 2, 3) - refcnt = sys.getrefcount(a) - ph = PointerHolder(a) - ptr = ph.pointer() - self.assertEqual(sys.getrefcount(a), refcnt + 1) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/pointf_test.py b/tests/samplebinding/pointf_test.py deleted file mode 100644 index 9318dca24..000000000 --- a/tests/samplebinding/pointf_test.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for PointF class''' - -import unittest - -from sample import PointF - -class PointFTest(unittest.TestCase): - '''Test case for PointF class, including operator overloads.''' - - def testConstructor(self): - '''Test PointF class constructor.''' - pt = PointF(5.0, 2.3) - self.assertEqual(pt.x(), 5.0) - self.assertEqual(pt.y(), 2.3) - - def testPlusOperator(self): - '''Test PointF class + operator.''' - pt1 = PointF(5.0, 2.3) - pt2 = PointF(0.5, 3.2) - self.assertEqual(pt1 + pt2, PointF(5.0 + 0.5, 2.3 + 3.2)) - - def testEqualOperator(self): - '''Test PointF class == operator.''' - pt1 = PointF(5.0, 2.3) - pt2 = PointF(5.0, 2.3) - pt3 = PointF(0.5, 3.2) - self.assertTrue(pt1 == pt1) - self.assertTrue(pt1 == pt2) - self.assertFalse(pt1 == pt3) - - def testModifiedMethod(self): - pt1 = PointF(0.0, 0.0) - pt2 = PointF(10.0, 10.0) - 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/tests/samplebinding/primitivereferenceargument_test.py b/tests/samplebinding/primitivereferenceargument_test.py deleted file mode 100644 index e973c0d78..000000000 --- a/tests/samplebinding/primitivereferenceargument_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -import sample - -class PrimitiveReferenceArgumentTest(unittest.TestCase): - - def testIntReferenceArgument(self): - '''C++ signature: int acceptIntReference(int&)''' - self.assertEqual(sample.acceptIntReference(123), 123) - - def testOddBoolReferenceArgument(self): - '''C++ signature: OddBool acceptOddBoolReference(OddBool&)''' - self.assertEqual(sample.acceptOddBoolReference(True), True) - self.assertEqual(sample.acceptOddBoolReference(False), False) - self.assertNotEqual(sample.acceptOddBoolReference(True), False) - self.assertNotEqual(sample.acceptOddBoolReference(False), True) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/privatector_test.py b/tests/samplebinding/privatector_test.py deleted file mode 100644 index 471f735cb..000000000 --- a/tests/samplebinding/privatector_test.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for a class with only a private constructor.''' - -import gc -import sys -import unittest - -from sample import PrivateCtor - - -class PrivateCtorTest(unittest.TestCase): - '''Test case for PrivateCtor class''' - - def testPrivateCtorInstanciation(self): - '''Test if instanciation of class with a private constructor raises an exception.''' - self.assertRaises(TypeError, PrivateCtor) - - def testPrivateCtorInheritance(self): - '''Test if inheriting from PrivateCtor raises an exception.''' - def inherit(): - class Foo(PrivateCtor): - pass - self.assertRaises(TypeError, inherit) - - def testPrivateCtorInstanceMethod(self): - '''Test if PrivateCtor.instance() method return the proper singleton.''' - pd1 = PrivateCtor.instance() - calls = pd1.instanceCalls() - self.assertEqual(type(pd1), PrivateCtor) - pd2 = PrivateCtor.instance() - self.assertEqual(pd2, pd1) - self.assertEqual(pd2.instanceCalls(), calls + 1) - - def testPrivateCtorRefCounting(self): - '''Test refcounting of the singleton returned by PrivateCtor.instance().''' - pd1 = PrivateCtor.instance() - calls = pd1.instanceCalls() - refcnt = sys.getrefcount(pd1) - pd2 = PrivateCtor.instance() - self.assertEqual(pd2.instanceCalls(), calls + 1) - self.assertEqual(sys.getrefcount(pd2), sys.getrefcount(pd1)) - self.assertEqual(sys.getrefcount(pd2), refcnt + 1) - del pd1 - self.assertEqual(sys.getrefcount(pd2), refcnt) - del pd2 - gc.collect() - pd3 = PrivateCtor.instance() - self.assertEqual(type(pd3), PrivateCtor) - self.assertEqual(pd3.instanceCalls(), calls + 2) - self.assertEqual(sys.getrefcount(pd3), refcnt) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/privatedtor_test.py b/tests/samplebinding/privatedtor_test.py deleted file mode 100644 index 3048a9848..000000000 --- a/tests/samplebinding/privatedtor_test.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for a class with a private destructor.''' - -import gc -import sys -import unittest - -import shiboken2 as shiboken -from sample import PrivateDtor - - -class PrivateDtorTest(unittest.TestCase): - '''Test case for PrivateDtor class''' - - def testPrivateDtorInstanciation(self): - '''Test if instanciation of class with a private destructor raises an exception.''' - self.assertRaises(TypeError, PrivateDtor) - - def testPrivateDtorInheritance(self): - '''Test if inheriting from PrivateDtor raises an exception.''' - def inherit(): - class Foo(PrivateDtor): - pass - self.assertRaises(TypeError, inherit) - - def testPrivateDtorInstanceMethod(self): - '''Test if PrivateDtor.instance() method return the proper singleton.''' - pd1 = PrivateDtor.instance() - calls = pd1.instanceCalls() - self.assertEqual(type(pd1), PrivateDtor) - pd2 = PrivateDtor.instance() - self.assertEqual(pd2, pd1) - self.assertEqual(pd2.instanceCalls(), calls + 1) - - def testPrivateDtorRefCounting(self): - '''Test refcounting of the singleton returned by PrivateDtor.instance().''' - pd1 = PrivateDtor.instance() - calls = pd1.instanceCalls() - refcnt = sys.getrefcount(pd1) - pd2 = PrivateDtor.instance() - self.assertEqual(pd2.instanceCalls(), calls + 1) - self.assertEqual(sys.getrefcount(pd2), sys.getrefcount(pd1)) - self.assertEqual(sys.getrefcount(pd2), refcnt + 1) - del pd1 - self.assertEqual(sys.getrefcount(pd2), refcnt) - del pd2 - gc.collect() - pd3 = PrivateDtor.instance() - self.assertEqual(type(pd3), PrivateDtor) - self.assertEqual(pd3.instanceCalls(), calls + 2) - self.assertEqual(sys.getrefcount(pd3), refcnt) - - def testClassDecref(self): - # Bug was that class PyTypeObject wasn't decrefed when instance - # was invalidated - - before = sys.getrefcount(PrivateDtor) - - for i in range(1000): - obj = PrivateDtor.instance() - shiboken.invalidate(obj) - - after = sys.getrefcount(PrivateDtor) - - self.assertLess(abs(before - after), 5) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/protected_test.py b/tests/samplebinding/protected_test.py deleted file mode 100644 index 9201a63cf..000000000 --- a/tests/samplebinding/protected_test.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for protected methods.''' - -import unittest - -from sample import cacheSize -from sample import ProtectedNonPolymorphic, ProtectedVirtualDestructor -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.''' - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testProtectedCall(self): - '''Calls a non-virtual protected method.''' - p = ProtectedNonPolymorphic('NonPoly') - self.assertEqual(p.publicName(), p.protectedName()) - a0, a1 = 1, 2 - self.assertEqual(p.protectedSum(a0, a1), a0 + a1) - - def testProtectedCallWithInstanceCreatedOnCpp(self): - '''Calls a non-virtual protected method on an instance created in C++.''' - p = ProtectedNonPolymorphic.create() - self.assertEqual(p.publicName(), p.protectedName()) - a0, a1 = 1, 2 - self.assertEqual(p.protectedSum(a0, a1), a0 + a1) - - def testModifiedProtectedCall(self): - '''Calls a non-virtual protected method modified with code injection.''' - p = ProtectedNonPolymorphic('NonPoly') - self.assertEqual(p.dataTypeName(), 'integer') - 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.''' - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testProtectedCall(self): - '''Calls a virtual protected method.''' - p = ProtectedNonPolymorphic('Poly') - self.assertEqual(p.publicName(), p.protectedName()) - a0, a1 = 1, 2 - self.assertEqual(p.protectedSum(a0, a1), a0 + a1) - - def testProtectedCallWithInstanceCreatedOnCpp(self): - '''Calls a virtual protected method on an instance created in C++.''' - p = ProtectedPolymorphic.create() - self.assertEqual(p.publicName(), p.protectedName()) - self.assertEqual(p.callProtectedName(), p.protectedName()) - - def testReimplementedProtectedCall(self): - '''Calls a reimplemented virtual protected method.''' - original_name = 'Poly' - p = ExtendedProtectedPolymorphic(original_name) - name = p.callProtectedName() - 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.''' - - def testProtectedCallWithInstanceCreatedOnCpp(self): - '''Calls a virtual protected method from parent class on an instance created in C++.''' - p = ProtectedPolymorphicDaughter.create() - self.assertEqual(p.publicName(), p.protectedName()) - self.assertEqual(p.callProtectedName(), p.protectedName()) - - def testReimplementedProtectedCall(self): - '''Calls a reimplemented virtual protected method from parent class.''' - original_name = 'Poly' - p = ExtendedProtectedPolymorphicDaughter(original_name) - name = p.callProtectedName() - self.assertTrue(p.protectedName_called) - self.assertEqual(p.protectedName(), name) - self.assertEqual(ProtectedPolymorphicDaughter.protectedName(p), original_name) - - -class ProtectedPolymorphicGrandDaugherTest(unittest.TestCase): - '''Test cases for protected method in a class inheriting for a class that inherits from - another with protected virtual methods.''' - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testProtectedCallWithInstanceCreatedOnCpp(self): - '''Calls a virtual protected method from parent class on an instance created in C++.''' - p = ProtectedPolymorphicGrandDaughter.create() - self.assertEqual(p.publicName(), p.protectedName()) - self.assertEqual(p.callProtectedName(), p.protectedName()) - - def testReimplementedProtectedCall(self): - '''Calls a reimplemented virtual protected method from parent class.''' - original_name = 'Poly' - p = ExtendedProtectedPolymorphicGrandDaughter(original_name) - name = p.callProtectedName() - self.assertTrue(p.protectedName_called) - self.assertEqual(p.protectedName(), name) - self.assertEqual(ProtectedPolymorphicGrandDaughter.protectedName(p), original_name) - -class ProtectedVirtualDtorTest(unittest.TestCase): - '''Test cases for protected virtual destructor.''' - - def setUp(self): - ProtectedVirtualDestructor.resetDtorCounter() - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testVirtualProtectedDtor(self): - '''Original protected virtual destructor is being called.''' - dtor_called = ProtectedVirtualDestructor.dtorCalled() - for i in range(1, 10): - pvd = ProtectedVirtualDestructor() - del pvd - self.assertEqual(ProtectedVirtualDestructor.dtorCalled(), dtor_called + i) - - def testVirtualProtectedDtorOnCppCreatedObject(self): - '''Original protected virtual destructor is being called for a C++ created object.''' - dtor_called = ProtectedVirtualDestructor.dtorCalled() - for i in range(1, 10): - pvd = ProtectedVirtualDestructor.create() - del pvd - self.assertEqual(ProtectedVirtualDestructor.dtorCalled(), dtor_called + i) - - def testProtectedDtorOnDerivedClass(self): - '''Original protected virtual destructor is being called for a derived class.''' - dtor_called = ExtendedProtectedVirtualDestructor.dtorCalled() - for i in range(1, 10): - pvd = ExtendedProtectedVirtualDestructor() - del pvd - self.assertEqual(ExtendedProtectedVirtualDestructor.dtorCalled(), dtor_called + i) - - -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.''' - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testProtectedMethodWithProtectedEnumArgument(self): - '''Calls protected method with protected enum argument.''' - obj = ProtectedEnumClass() - - 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) - - 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.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(ProtectedEnumClass.protectedEnumMethod(obj, ProtectedEnumClass.ProtectedItem0), 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) - - 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(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) - - -class ProtectedPropertyTest(unittest.TestCase): - '''Test cases for a class with a protected property (or field in C++).''' - - def setUp(self): - self.obj = ProtectedProperty() - - def tearDown(self): - del self.obj - self.assertEqual(cacheSize(), 0) - - def testProtectedProperty(self): - '''Writes and reads a protected integer property.''' - self.obj.protectedProperty = 3 - self.assertEqual(self.obj.protectedProperty, 3) - - def testProtectedContainerProperty(self): - '''Writes and reads a protected list of integers property.''' - lst = [1, 2, 3, 4] - self.obj.protectedContainerProperty = lst - self.assertEqual(self.obj.protectedContainerProperty, lst) - - def testProtectedEnumProperty(self): - '''Writes and reads a protected enum property.''' - self.obj.protectedEnumProperty = Event.SOME_EVENT - self.assertEqual(self.obj.protectedEnumProperty, Event.SOME_EVENT) - - def testProtectedValueTypeProperty(self): - '''Writes and reads a protected value type property.''' - point = Point(12, 34) - self.obj.protectedValueTypeProperty = point - self.assertEqual(self.obj.protectedValueTypeProperty, point) - self.assertFalse(self.obj.protectedValueTypeProperty is point) - pointProperty = self.obj.protectedValueTypeProperty - self.assertTrue(self.obj.protectedValueTypeProperty is pointProperty) - - def testProtectedValueTypePropertyWrapperRegistration(self): - '''Access colocated protected value type property.''' - cache_size = cacheSize() - point = Point(12, 34) - obj = createProtectedProperty() - obj.protectedValueTypeProperty - self.assertEqual(obj.protectedValueTypeProperty.copy(), - obj.protectedValueTypeProperty) - obj.protectedValueTypeProperty = point - self.assertEqual(obj.protectedValueTypeProperty, point) - self.assertFalse(obj.protectedValueTypeProperty is point) - pointProperty = obj.protectedValueTypeProperty - self.assertTrue(obj.protectedValueTypeProperty is pointProperty) - del obj, point, pointProperty - self.assertEqual(cacheSize(), cache_size) - - def testProtectedValueTypePointerProperty(self): - '''Writes and reads a protected value type pointer property.''' - pt1 = Point(12, 34) - pt2 = Point(12, 34) - self.obj.protectedValueTypePointerProperty = pt1 - self.assertEqual(self.obj.protectedValueTypePointerProperty, pt1) - self.assertEqual(self.obj.protectedValueTypePointerProperty, pt2) - self.assertTrue(self.obj.protectedValueTypePointerProperty is pt1) - self.assertFalse(self.obj.protectedValueTypePointerProperty is pt2) - - def testProtectedObjectTypeProperty(self): - '''Writes and reads a protected object type property.''' - obj = ObjectType() - self.obj.protectedObjectTypeProperty = obj - self.assertEqual(self.obj.protectedObjectTypeProperty, obj) - - -class PrivateDtorProtectedMethodTest(unittest.TestCase): - '''Test cases for classes with private destructors and protected methods.''' - - def tearDown(self): - self.assertEqual(cacheSize(), 0) - - def testProtectedMethod(self): - '''Calls protected method of a class with a private destructor.''' - obj = PrivateDtor.instance() - - self.assertEqual(type(obj), PrivateDtor) - self.assertEqual(obj.instanceCalls(), 1) - self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) - obj = PrivateDtor.instance() - self.assertEqual(obj.instanceCalls(), 2) - self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/pstrlist_test.py b/tests/samplebinding/pstrlist_test.py deleted file mode 100644 index 47e89bacb..000000000 --- a/tests/samplebinding/pstrlist_test.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -import sample - -class PStrListTest(unittest.TestCase): - - def testPStrList(self): - a = 'str0' - b = 'str1' - lst = sample.createPStrList(a, b) - self.assertEqual(lst, [a, b]) - - def testListOfPStr(self): - a = 'str0' - b = 'str1' - lst = sample.createListOfPStr(a, b) - self.assertEqual(lst, [a, b]) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/pystr_test.py b/tests/samplebinding/pystr_test.py deleted file mode 100644 index 9056e96b7..000000000 --- a/tests/samplebinding/pystr_test.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for definition of __str__ method.''' - -import sys -import unittest - -from sample import Point - -class PyStrTest(unittest.TestCase): - '''Test case for definition of __str__ method.''' - - def testPyStr(self): - '''Test case for defined __str__ method.''' - pt = Point(5, 2) - self.assertEqual(str(pt), 'Point(5.0, 2.0)') - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/python_thread_test.py b/tests/samplebinding/python_thread_test.py deleted file mode 100644 index dcd59ee1f..000000000 --- a/tests/samplebinding/python_thread_test.py +++ /dev/null @@ -1,116 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -#!/usr/bin/env python - -'''Tests for using Shiboken-based bindings with python threads''' - -import unittest -import threading -import sample -import time - -import logging - -#logging.basicConfig(level=logging.DEBUG) - -from random import random - -class Producer(threading.Thread): - '''Producer thread''' - - def __init__(self, bucket, max_runs, *args): - #Constructor. Receives the bucket - super(Producer, self).__init__(*args) - self.runs = 0 - self.bucket = bucket - self.max_runs = max_runs - self.production_list = [] - - def run(self): - while self.runs < self.max_runs: - value = int(random()*10) % 10 - self.bucket.push(value) - self.production_list.append(value) - logging.debug('PRODUCER - pushed %d' % value) - self.runs += 1 - #self.msleep(5) - time.sleep(0.01) - - -class Consumer(threading.Thread): - '''Consumer thread''' - def __init__(self, bucket, max_runs, *args): - #Constructor. Receives the bucket - super(Consumer, self).__init__(*args) - self.runs = 0 - self.bucket = bucket - self.max_runs = max_runs - self.consumption_list = [] - - def run(self): - while self.runs < self.max_runs: - if not self.bucket.empty(): - value = self.bucket.pop() - self.consumption_list.append(value) - logging.debug('CONSUMER - got %d' % value) - self.runs += 1 - else: - logging.debug('CONSUMER - empty bucket') - time.sleep(0.01) - -class ProducerConsumer(unittest.TestCase): - '''Basic test case for producer-consumer QThread''' - - def finishCb(self): - #Quits the application - self.app.exit(0) - - def testProdCon(self): - #QThread producer-consumer example - bucket = sample.Bucket() - prod = Producer(bucket, 10) - cons = Consumer(bucket, 10) - - prod.start() - cons.start() - - #QObject.connect(prod, SIGNAL('finished()'), self.finishCb) - #QObject.connect(cons, SIGNAL('finished()'), self.finishCb) - - prod.join() - cons.join() - - self.assertEqual(prod.production_list, cons.consumption_list) - - - - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/receive_null_cstring_test.py b/tests/samplebinding/receive_null_cstring_test.py deleted file mode 100644 index 12cc67142..000000000 --- a/tests/samplebinding/receive_null_cstring_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for a function that could receive a NULL pointer in a '[const] char*' parameter.''' - -import unittest - -from sample import countCharacters - -class ReceiveNullCStringTest(unittest.TestCase): - '''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.''' - a = '' - b = 'abc' - self.assertEqual(countCharacters(a), len(a)) - self.assertEqual(countCharacters(b), len(b)) - - def testReceiveNull(self): - '''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/tests/samplebinding/reference_test.py b/tests/samplebinding/reference_test.py deleted file mode 100644 index aaf809451..000000000 --- a/tests/samplebinding/reference_test.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for methods that receive references to objects.''' - -import sys -import unittest - -from sample import * - -class ExtendedReference(Reference): - def __init__(self): - Reference.__init__(self) - self.uses_reference_virtual_called = False - self.uses_const_reference_virtual_called = False - self.reference_inc = 1 - self.const_reference_inc = 2 - self.multiplier = 333 - - def usesReferenceVirtual(self, ref, inc): - self.uses_reference_virtual_called = True - return ref.objId() + inc + self.reference_inc - - def usesConstReferenceVirtual(self, ref, inc): - self.uses_const_reference_virtual_called = True - return ref.objId() + inc + self.const_reference_inc - - def alterReferenceIdVirtual(self, ref): - ref.setObjId(ref.objId() * self.multiplier) - - -class ReferenceTest(unittest.TestCase): - '''Test case for methods that receive references to objects.''' - - def testMethodThatReceivesReference(self): - '''Test a method that receives a reference to an object as argument.''' - objId = 123 - r = Reference(objId) - self.assertEqual(Reference.usesReference(r), objId) - - def testCantSegFaultWhenReceiveNone(self): - '''do not segfault when receiving None as argument.''' - s = Str() - self.assertTrue(None == s) - - def testMethodThatReceivesConstReference(self): - '''Test a method that receives a const reference to an object as argument.''' - objId = 123 - r = Reference(objId) - 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++.''' - 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.''' - 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.''' - objId = 123 - r = Reference(objId) - er = ExtendedReference() - result = er.callAlterReferenceIdVirtual(r) - 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++.''' - inc = 9 - objId = 123 - r = Reference(objId) - er = ExtendedReference() - result = er.callUsesReferenceVirtual(r, inc) - 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++.''' - inc = 9 - objId = 123 - r = Reference(objId) - er = ExtendedReference() - result = er.callUsesConstReferenceVirtual(r, inc) - self.assertEqual(result, objId + inc + er.const_reference_inc) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/referencetopointer_test.py b/tests/samplebinding/referencetopointer_test.py deleted file mode 100644 index 8d85032a0..000000000 --- a/tests/samplebinding/referencetopointer_test.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for a reference to pointer argument type.''' - -import unittest - -from sample import VirtualMethods, Str - -class ExtendedVirtualMethods(VirtualMethods): - def __init__(self): - VirtualMethods.__init__(self) - self.prefix = 'Ext' - - def createStr(self, text): - ext_text = text - if text is not None: - ext_text = self.prefix + text - return VirtualMethods.createStr(self, ext_text) - - -class ReferenceToPointerTest(unittest.TestCase): - '''Test cases for a reference to pointer argument type.''' - - def testSimpleCallWithNone(self): - '''Simple call to createStr method with a None argument.''' - obj = VirtualMethods() - ok, string = obj.createStr(None) - self.assertFalse(ok) - self.assertEqual(string, None) - - def testSimpleCallWithString(self): - '''Simple call to createStr method with a Python string argument.''' - obj = VirtualMethods() - ok, string = obj.createStr('foo') - self.assertTrue(ok) - self.assertEqual(string, Str('foo')) - - def testCallNonReimplementedMethodWithNone(self): - '''Calls createStr method from C++ with a None argument.''' - obj = VirtualMethods() - ok, string = obj.callCreateStr(None) - self.assertFalse(ok) - self.assertEqual(string, None) - - def testCallNonReimplementedMethodWithString(self): - '''Calls createStr method from C++ with a Python string argument.''' - obj = VirtualMethods() - ok, string = obj.callCreateStr('foo') - self.assertTrue(ok) - self.assertEqual(string, Str('foo')) - - def testCallReimplementedMethodWithNone(self): - '''Calls reimplemented createStr method from C++ with a None argument.''' - obj = ExtendedVirtualMethods() - ok, string = obj.callCreateStr(None) - self.assertFalse(ok) - self.assertEqual(string, None) - - def testCallReimplementedMethodWithString(self): - '''Calls reimplemented createStr method from C++ with a Python string argument.''' - obj = ExtendedVirtualMethods() - ok, string = obj.callCreateStr('foo') - self.assertTrue(ok) - self.assertEqual(string, Str(obj.prefix + 'foo')) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/return_null_test.py b/tests/samplebinding/return_null_test.py deleted file mode 100644 index 377624482..000000000 --- a/tests/samplebinding/return_null_test.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for functions that could return a NULL pointer.''' - -import sys -import unittest - -from sample import returnNullPrimitivePointer, returnNullValueTypePointer, returnNullObjectTypePointer - -class ReturnNullTest(unittest.TestCase): - '''Test case for functions that could return a NULL pointer.''' - - def testReturnNull(self): - '''Function returns a NULL pointer to a primitive type.''' - o = returnNullPrimitivePointer() - self.assertEqual(o, None) - - def testReturnNullObjectType(self): - '''Function returns a NULL pointer to an object-type.''' - o = returnNullObjectTypePointer() - self.assertEqual(o, None) - - def testReturnNullValueType(self): - '''Function returns a NULL pointer to a value-type.''' - o = returnNullValueTypePointer() - self.assertEqual(o, None) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/richcompare_test.py b/tests/samplebinding/richcompare_test.py deleted file mode 100644 index 8c5eea694..000000000 --- a/tests/samplebinding/richcompare_test.py +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import * - -class TestRichCompare(unittest.TestCase): - - def testIt(self): - a = Expression(2) - b = Expression(3) - c = a + b - d = a + c < b + a - self.assertEqual(d.toString(), "((2+(2+3))<(3+2))") - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/sample-binding.txt.in b/tests/samplebinding/sample-binding.txt.in deleted file mode 100644 index 317f76f09..000000000 --- a/tests/samplebinding/sample-binding.txt.in +++ /dev/null @@ -1,15 +0,0 @@ -[generator-project] - -generator-set = shiboken - -header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h -typesystem-file = @sample_TYPESYSTEM@ - -output-directory = @CMAKE_CURRENT_BINARY_DIR@ - -include-path = @libsample_SOURCE_DIR@ - -typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ - -enable-parent-ctor-heuristic -use-isnull-as-nb_nonzero diff --git a/tests/samplebinding/sample_test.py b/tests/samplebinding/sample_test.py deleted file mode 100644 index 65d1d2871..000000000 --- a/tests/samplebinding/sample_test.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for libsample bindings module''' - -import unittest - -import sample - -class ModuleTest(unittest.TestCase): - '''Test case for module and global functions''' - - 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))) - - 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))) - - 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' - self.assertEqual(sample.multiplyString(str1, 3), str1 * 3) - self.assertEqual(sample.multiplyString(str1, 0), str1 * 0) - - def testAddedFunctionWithVarargs(self): - '''Calls function that receives varargs added to module from type system description.''' - self.assertEqual(sample.countVarargs(1), 0) - self.assertEqual(sample.countVarargs(1, 2), 1) - self.assertEqual(sample.countVarargs(1, 2, 3, 'a', 'b', 4, (5, 6)), 6) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/simplefile_glue.cpp b/tests/samplebinding/simplefile_glue.cpp deleted file mode 100644 index a7f05eb99..000000000 --- a/tests/samplebinding/simplefile_glue.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -if (!%CPPSELF.%FUNCTION_NAME()) { - PyObject* error_msg = PyBytes_FromFormat( - "Could not open file: \"%s\"", %CPPSELF->filename()); - PyErr_SetObject(PyExc_IOError, error_msg); - return 0; -} diff --git a/tests/samplebinding/simplefile_test.py b/tests/samplebinding/simplefile_test.py deleted file mode 100644 index c2a1afe59..000000000 --- a/tests/samplebinding/simplefile_test.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for SimpleFile class''' - -import os -import unittest - -from sample import SimpleFile - -class SimpleFileTest(unittest.TestCase): - '''Test cases for SimpleFile class.''' - - def setUp(self): - filename = 'simplefile%d.txt' % os.getpid() - self.existing_filename = os.path.join(os.path.curdir, filename) - self.delete_file = False - if not os.path.exists(self.existing_filename): - f = open(self.existing_filename, 'w') - for line in range(10): - f.write('sbrubbles\n') - f.close() - self.delete_file = True - - self.non_existing_filename = os.path.join(os.path.curdir, 'inexistingfile.txt') - i = 0 - while os.path.exists(self.non_existing_filename): - i += 1 - filename = 'inexistingfile-%d.txt' % i - self.non_existing_filename = os.path.join(os.path.curdir, filename) - - def tearDown(self): - if self.delete_file: - os.remove(self.existing_filename) - - def testExistingFile(self): - '''Test SimpleFile class with existing file.''' - f = SimpleFile(self.existing_filename) - self.assertEqual(f.filename(), self.existing_filename) - f.open() - self.assertNotEqual(f.size(), 0) - f.close() - - def testNonExistingFile(self): - '''Test SimpleFile class with non-existing file.''' - f = SimpleFile(self.non_existing_filename) - self.assertEqual(f.filename(), self.non_existing_filename) - self.assertRaises(IOError, f.open) - self.assertEqual(f.size(), 0) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/size_test.py b/tests/samplebinding/size_test.py deleted file mode 100644 index 502539689..000000000 --- a/tests/samplebinding/size_test.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for operator overloads on Size class''' - -import unittest - -from sample import Size - -class PointTest(unittest.TestCase): - '''Test case for Size class, including operator overloads.''' - - def testConstructor(self): - '''Test Size class constructor.''' - width, height = (5.0, 2.3) - size = Size(width, height) - self.assertEqual(size.width(), width) - self.assertEqual(size.height(), height) - self.assertEqual(size.calculateArea(), width * height) - - def testCopyConstructor(self): - '''Test Size class copy constructor.''' - width, height = (5.0, 2.3) - s1 = Size(width, height) - s2 = Size(s1) - self.assertFalse(s1 is s2) - self.assertEqual(s1, s2) - - def testPlusOperator(self): - '''Test Size class + operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(0.5, 3.2) - self.assertEqual(s1 + s2, Size(5.0 + 0.5, 2.3 + 3.2)) - - def testEqualOperator(self): - '''Test Size class == operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(5.0, 2.3) - s3 = Size(0.5, 3.2) - self.assertTrue(s1 == s1) - self.assertTrue(s1 == s2) - self.assertFalse(s1 == s3) - - def testNotEqualOperator(self): - '''Test Size class != operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(5.0, 2.3) - s3 = Size(0.5, 3.2) - self.assertFalse(s1 != s1) - self.assertFalse(s1 != s2) - self.assertTrue(s1 != s3) - - def testMinorEqualOperator(self): - '''Test Size class <= operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(5.0, 2.3) - s3 = Size(0.5, 3.2) - self.assertTrue(s1 <= s1) - self.assertTrue(s1 <= s2) - self.assertTrue(s3 <= s1) - self.assertFalse(s1 <= s3) - - def testMinorOperator(self): - '''Test Size class < operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(0.5, 3.2) - self.assertFalse(s1 < s1) - self.assertFalse(s1 < s2) - self.assertTrue(s2 < s1) - - def testMajorEqualOperator(self): - '''Test Size class >= operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(5.0, 2.3) - s3 = Size(0.5, 3.2) - self.assertTrue(s1 >= s1) - self.assertTrue(s1 >= s2) - self.assertTrue(s1 >= s3) - self.assertFalse(s3 >= s1) - - def testMajorOperator(self): - '''Test Size class > operator.''' - s1 = Size(5.0, 2.3) - s2 = Size(0.5, 3.2) - self.assertFalse(s1 > s1) - self.assertTrue(s1 > s2) - self.assertFalse(s2 > s1) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/static_nonstatic_methods_test.py b/tests/samplebinding/static_nonstatic_methods_test.py deleted file mode 100644 index 6451c4440..000000000 --- a/tests/samplebinding/static_nonstatic_methods_test.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for overloads involving static and non-static versions of a method.''' - -import os -import unittest - -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.''' - - def setUp(self): - filename = 'simplefile%d.txt' % os.getpid() - self.existing_filename = os.path.join(os.path.curdir, filename) - self.delete_file = False - if not os.path.exists(self.existing_filename): - f = open(self.existing_filename, 'w') - for line in range(10): - f.write('sbrubbles\n') - f.close() - self.delete_file = True - - self.non_existing_filename = os.path.join(os.path.curdir, 'inexistingfile.txt') - i = 0 - while os.path.exists(self.non_existing_filename): - i += 1 - filename = 'inexistingfile-%d.txt' % i - self.non_existing_filename = os.path.join(os.path.curdir, filename) - - def tearDown(self): - if self.delete_file: - os.remove(self.existing_filename) - - def testCallingStaticMethodWithClass(self): - '''Call static method using class.''' - self.assertTrue(SimpleFile.exists(self.existing_filename)) - self.assertFalse(SimpleFile.exists(self.non_existing_filename)) - - def testCallingStaticMethodWithInstance(self): - '''Call static method using instance of class.''' - f = SimpleFile(self.non_existing_filename) - self.assertTrue(f.exists(self.existing_filename)) - self.assertFalse(f.exists(self.non_existing_filename)) - - def testCallingInstanceMethod(self): - '''Call instance method.''' - f1 = SimpleFile(self.non_existing_filename) - self.assertFalse(f1.exists()) - f2 = SimpleFile(self.existing_filename) - self.assertTrue(f2.exists()) - - def testOverridingStaticNonStaticMethod(self): - f = SimpleFile2(self.existing_filename) - self.assertEqual(f.exists(), "Mooo") - - f = SimpleFile3(self.existing_filename) - self.assertTrue(f.exists()) - - f = SimpleFile4(self.existing_filename) - self.assertEqual(f.exists, 5) - - def testDuckPunchingStaticNonStaticMethod(self): - f = SimpleFile(self.existing_filename) - f.exists = lambda : "Meee" - self.assertEqual(f.exists(), "Meee") - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/str_test.py b/tests/samplebinding/str_test.py deleted file mode 100644 index dca7e1f44..000000000 --- a/tests/samplebinding/str_test.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for a method that receives a reference to class that is implicitly convertible from a Python native type.''' - -import unittest - -from sample import Str - -class StrTest(unittest.TestCase): - '''Test cases for thr Str class.''' - - def test__str__Method(self): - '''Test if the binding correcly implements the Python __str__ method.''' - s1 = 'original string' - s2 = Str(s1) - self.assertEqual(s1, s2) - self.assertEqual(s1, str(s2)) - - def testPassExactClassAsReferenceToArgument(self): - '''Test passing the expected class as an argument to a method that expects a reference.''' - s1 = Str('This is %VAR!').arg(Str('Sparta')) - 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.''' - 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); - - # 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.assertRaises(TypeError, s1.__getitem__, 6) - - # setitem - s1[0] = 'A' - 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") - - def testToIntError(self): - self.assertEqual(Str('Z').toInt(), (0, False)) - - def testToIntWithDecimal(self): - decimal = Str('37') - val, ok = decimal.toInt() - self.assertEqual(type(val), int) - self.assertEqual(type(ok), bool) - self.assertEqual(val, int(str(decimal))) - - def testToIntWithOctal(self): - octal = Str('52') - val, ok = octal.toInt(8) - self.assertEqual(type(val), int) - self.assertEqual(type(ok), bool) - self.assertEqual(val, int(str(octal), 8)) - - def testToIntWithHexadecimal(self): - hexa = Str('2A') - val, ok = hexa.toInt(16) - self.assertEqual(type(val), int) - self.assertEqual(type(ok), bool) - self.assertEqual(val, int(str(hexa), 16)) - self.assertEqual(hexa.toInt(), (0, False)) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/strlist_test.py b/tests/samplebinding/strlist_test.py deleted file mode 100644 index 341fcfa32..000000000 --- a/tests/samplebinding/strlist_test.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for StrList class that inherits from std::list.''' - -import unittest - -from sample import Str, StrList - -class StrListTest(unittest.TestCase): - '''Test cases for StrList class that inherits from std::list.''' - - def testStrListCtor_NoParams(self): - '''StrList constructor receives no parameter.''' - sl = StrList() - self.assertEqual(len(sl), 0) - self.assertEqual(sl.constructorUsed(), StrList.NoParamsCtor) - - def testStrListCtor_Str(self): - '''StrList constructor receives a Str object.''' - s = Str('Foo') - sl = StrList(s) - self.assertEqual(len(sl), 1) - self.assertEqual(sl[0], s) - self.assertEqual(sl.constructorUsed(), StrList.StrCtor) - - def testStrListCtor_PythonString(self): - '''StrList constructor receives a Python string.''' - s = 'Foo' - sl = StrList(s) - self.assertEqual(len(sl), 1) - self.assertEqual(sl[0], s) - self.assertEqual(sl.constructorUsed(), StrList.StrCtor) - - def testStrListCtor_StrList(self): - '''StrList constructor receives a StrList object.''' - sl1 = StrList(Str('Foo')) - sl2 = StrList(sl1) - #self.assertEqual(len(sl1), len(sl2)) - #self.assertEqual(sl1, sl2) - self.assertEqual(sl2.constructorUsed(), StrList.CopyCtor) - - def testStrListCtor_ListOfStrs(self): - '''StrList constructor receives a Python list of Str objects.''' - strs = [Str('Foo'), Str('Bar')] - sl = StrList(strs) - self.assertEqual(len(sl), len(strs)) - self.assertEqual(sl, strs) - self.assertEqual(sl.constructorUsed(), StrList.ListOfStrCtor) - - def testStrListCtor_MixedListOfStrsAndPythonStrings(self): - '''StrList constructor receives a Python list of mixed Str objects and Python strings.''' - strs = [Str('Foo'), 'Bar'] - sl = StrList(strs) - self.assertEqual(len(sl), len(strs)) - self.assertEqual(sl, strs) - self.assertEqual(sl.constructorUsed(), StrList.ListOfStrCtor) - - def testCompareStrListWithTupleOfStrs(self): - '''Compares StrList with a Python tuple of Str objects.''' - sl = StrList() - sl.append(Str('Foo')) - sl.append(Str('Bar')) - self.assertEqual(len(sl), 2) - self.assertEqual(sl, (Str('Foo'), Str('Bar'))) - - def testCompareStrListWithTupleOfPythonStrings(self): - '''Compares StrList with a Python tuple of Python strings.''' - sl = StrList() - sl.append(Str('Foo')) - sl.append(Str('Bar')) - self.assertEqual(len(sl), 2) - self.assertEqual(sl, ('Foo', 'Bar')) - - def testCompareStrListWithTupleOfStrAndPythonString(self): - '''Compares StrList with a Python tuple of mixed Str objects and Python strings.''' - sl = StrList() - sl.append(Str('Foo')) - sl.append(Str('Bar')) - self.assertEqual(len(sl), 2) - self.assertEqual(sl, (Str('Foo'), 'Bar')) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/templateinheritingclass_test.py b/tests/samplebinding/templateinheritingclass_test.py deleted file mode 100644 index 7acb6a597..000000000 --- a/tests/samplebinding/templateinheritingclass_test.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import Photon - -'''This tests classes that inherit from template classes, -simulating a situation found in Qt's phonon module.''' - -class TemplateInheritingClassTest(unittest.TestCase): - def testClassBasics(self): - self.assertEqual(Photon.ValueIdentity.classType(), Photon.IdentityType) - self.assertEqual(Photon.ValueDuplicator.classType(), Photon.DuplicatorType) - - def testInstanceBasics(self): - value = 123 - samer = Photon.ValueIdentity(value) - self.assertEqual(samer.multiplicator(), 1) - doubler = Photon.ValueDuplicator(value) - self.assertEqual(doubler.multiplicator(), 2) - self.assertEqual(samer.value(), doubler.value()) - self.assertEqual(samer.calculate() * 2, doubler.calculate()) - - def testPassToFunctionAsPointer(self): - obj = Photon.ValueDuplicator(123) - self.assertEqual(Photon.callCalculateForValueDuplicatorPointer(obj), obj.calculate()) - - def testPassToFunctionAsReference(self): - obj = Photon.ValueDuplicator(321) - self.assertEqual(Photon.callCalculateForValueDuplicatorReference(obj), obj.calculate()) - - def testPassToMethodAsValue(self): - value1, value2 = 123, 321 - one = Photon.ValueIdentity(value1) - other = Photon.ValueIdentity(value2) - self.assertEqual(one.sumValueUsingPointer(other), value1 + value2) - - def testPassToMethodAsReference(self): - value1, value2 = 123, 321 - one = Photon.ValueDuplicator(value1) - other = Photon.ValueDuplicator(value2) - self.assertEqual(one.sumValueUsingReference(other), value1 + value2) - - def testPassPointerThrough(self): - obj1 = Photon.ValueIdentity(123) - self.assertEqual(obj1, obj1.passPointerThrough(obj1)) - obj2 = Photon.ValueDuplicator(321) - self.assertEqual(obj2, obj2.passPointerThrough(obj2)) - self.assertRaises(TypeError, obj1.passPointerThrough, obj2) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/time_test.py b/tests/samplebinding/time_test.py deleted file mode 100644 index db8818fd3..000000000 --- a/tests/samplebinding/time_test.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for constructor and method signature decisor on Time class.''' - -import sys -import unittest -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 - CTORMETHOD(int h, int m, int s = 0, int ms = 0); there another method - with a more complex signature METH(int, int, ImplicitConv=DEFVALUE, ObjectType=0), - to produce an even worse scenario. - ''' - - def testConstructorWithoutParamers(self): - '''Constructor without parameters: Time()''' - time = Time() - self.assertTrue(time.isNull()) - - def testConstructorWithAllParamers(self): - '''Constructor with all parameters: Time(int h, int m, int s = 0, int ms = 0)''' - time = Time(1, 2, 3, 4) - self.assertTrue(time.toString(), '01:02:03.004') - - def testConstructorWithThreeParamers(self): - '''Constructor with 3 parameters: Time(int h, int m, int s = 0, int ms = 0)''' - time = Time(1, 2, 3) - self.assertTrue(time.toString(), '01:02:03.000') - - def testConstructorWithTwoParamers(self): - '''Constructor with 2 parameters: Time(int h, int m, int s = 0, int ms = 0)''' - time = Time(1, 2) - self.assertTrue(time.toString(), '01:02:00.000') - - def testSimpleMethodWithoutParamers(self): - '''Constructor without parameters: Time.setTime()''' - time = Time(1, 2, 3, 4) - time.setTime() - self.assertTrue(time.isNull()) - - def testSimpleMethodWithAllParamers(self): - '''Simple method with all parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' - time = Time() - time.setTime(1, 2, 3, 4) - self.assertTrue(time.toString(), '01:02:03.004') - - def testSimpleMethodWithThreeParamers(self): - '''Simple method with 3 parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' - time = Time() - time.setTime(1, 2, 3) - self.assertTrue(time.toString(), '01:02:03.000') - - def testSimpleMethodWithTwoParamers(self): - '''Simple method with 2 parameters: Time.setTime(int h, int m, int s = 0, int ms = 0)''' - time = Time() - time.setTime(1, 2) - self.assertTrue(time.toString(), '01:02:00.000') - - def testMethodWithoutParamers(self): - '''Method without parameters: Time.somethingCompletelyDifferent()''' - time = Time() - result = time.somethingCompletelyDifferent() - self.assertEqual(result, Time.ZeroArgs) - - def testMethodWithAllParamers(self): - '''Method with all parameters: - Time.somethingCompletelyDifferent( - int h, int m, ImplicitConv ic = ImplicitConv::CtorThree, ObjectType* type = 0 - ); - ''' - time = Time() - obj = ObjectType() - result = time.somethingCompletelyDifferent(1, 2, ImplicitConv(2), obj) - self.assertEqual(result, Time.FourArgs) - - def testMethodWithThreeParamers(self): - '''Method with 3 parameters: Time.somethingCompletelyDifferent(...)''' - time = Time() - result = time.somethingCompletelyDifferent(1, 2, ImplicitConv(ImplicitConv.CtorOne)) - self.assertEqual(result, Time.ThreeArgs) - - def testMethodWithTwoParamers(self): - '''Method with 2 parameters: Time.somethingCompletelyDifferent(...)''' - time = Time() - result = time.somethingCompletelyDifferent(1, 2) - self.assertEqual(result, Time.TwoArgs) - - def testMethodWithThreeParamersAndImplicitConversion(self): - '''Method with 3 parameters, the last one triggers an implicit conversion.''' - time = Time() - result = time.somethingCompletelyDifferent(1, 2, ImplicitConv.CtorOne) - self.assertEqual(result, Time.ThreeArgs) - - def testCompareWithPythonTime(self): - time = Time(12, 32, 5) - py = datetime.time(12, 32, 5) - self.assertEqual(time, py) - - def testNotEqual(self): - time = Time(12, 32, 6) - py = datetime.time(12, 32, 5) - self.assertNotEqual(time, py) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/transform_test.py b/tests/samplebinding/transform_test.py deleted file mode 100644 index f490945b8..000000000 --- a/tests/samplebinding/transform_test.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for argument modification with more than nine arguments.''' - -import unittest - -from sample import Point, applyHomogeneousTransform - -class TransformTest(unittest.TestCase): - '''Test cases for modifying a function with > 9 arguments.''' - - def testTransform_ValidMatrix(self): - '''Transform applies successfully.''' - p = Point(3, 4) - r = applyHomogeneousTransform(p, 0, 1, 0, -1, 0, 0, 0, 0, 1) - self.assertTrue(type(r) is Point) - self.assertEqual(r.x(), 4) - self.assertEqual(r.y(), -3) - - def testTransform_InvalidMatrix(self): - '''Transform does not apply successfully.''' - p = Point(3, 4) - 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/tests/samplebinding/typeconverters_test.py b/tests/samplebinding/typeconverters_test.py deleted file mode 100644 index b3b469c56..000000000 --- a/tests/samplebinding/typeconverters_test.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Tests various usages of the type converters.''' - -import unittest -import sample - -class GetPythonTypeByNameTest(unittest.TestCase): - - '''Uses an added function with inject code that uses the libshiboken - function "Shiboken::Conversions::getPythonTypeObject(typeName)".''' - - def testGetObjectType(self): - pyType1 = sample.getPythonType('ObjectType') - self.assertEqual(pyType1, sample.ObjectType) - pyType2 = sample.getPythonType('ObjectType*') - self.assertEqual(pyType2, sample.ObjectType) - self.assertEqual(pyType1, pyType2) - - def testGetValueType(self): - pyType1 = sample.getPythonType('Point') - self.assertEqual(pyType1, sample.Point) - pyType2 = sample.getPythonType('Point*') - self.assertEqual(pyType2, sample.Point) - self.assertEqual(pyType1, pyType2) - - def testGetUsersPrimitiveType(self): - pyType = sample.getPythonType('OddBool') - self.assertEqual(pyType, bool) - - def testGetUsersPrimitiveTypeWithoutTargetLangApiName(self): - '''If the primitive type attribute "target-lang-api-name" is not set - there'll be no Python type associated with the C++ type.''' - pyType = sample.getPythonType('PStr') - self.assertEqual(pyType, None) - - def testPrimitiveTypeAndTypedef(self): - pyType = sample.getPythonType('double') - self.assertEqual(pyType, float) - pyTypedef = sample.getPythonType('real') - self.assertEqual(pyType, pyTypedef) - - def testPairContainerType(self): - pyType = sample.getPythonType('std::pair') - self.assertEqual(pyType, list) - - def testListContainerType(self): - pyType = sample.getPythonType('std::list') - self.assertEqual(pyType, list) - - def testMapContainerType(self): - pyType = sample.getPythonType('std::map') - self.assertEqual(pyType, dict) - - def testGlobalEnumType(self): - pyType = sample.getPythonType('GlobalEnum') - self.assertEqual(pyType, sample.GlobalEnum) - - def testScopedEnumType(self): - pyType = sample.getPythonType('Abstract::Type') - self.assertEqual(pyType, sample.Abstract.Type) - - -class CheckValueAndObjectTypeByNameTest(unittest.TestCase): - - '''Uses an added function with inject code that uses the libshiboken - functions that check if a type is Object or Value, based on its converter.''' - - def testErrors(self): - '''not existent type''' - self.assertRaises(ValueError, sample.cppTypeIsValueType, 'NotExistentType') - self.assertRaises(ValueError, sample.cppTypeIsObjectType, 'NotExistentType') - - def testObjectType1(self): - self.assertTrue(sample.cppTypeIsObjectType('ObjectType')) - self.assertFalse(sample.cppTypeIsValueType('ObjectType')) - - def testObjectType2(self): - self.assertTrue(sample.cppTypeIsObjectType('ObjectType*')) - self.assertFalse(sample.cppTypeIsValueType('ObjectType*')) - - def testValueType1(self): - self.assertTrue(sample.cppTypeIsValueType('Point')) - self.assertFalse(sample.cppTypeIsObjectType('Point')) - - def testValueType2(self): - self.assertTrue(sample.cppTypeIsValueType('Point*')) - self.assertFalse(sample.cppTypeIsObjectType('Point*')) - - def testUsersPrimitiveType(self): - self.assertFalse(sample.cppTypeIsValueType('Complex')) - self.assertFalse(sample.cppTypeIsObjectType('Complex')) - - def testContainerType(self): - self.assertFalse(sample.cppTypeIsValueType('std::list')) - self.assertFalse(sample.cppTypeIsObjectType('std::list')) - - -class SpecificConverterTest(unittest.TestCase): - - '''Uses an added function with inject code that uses the libshiboken - adapter class "Shiboken::Conversions::SpecificConverter".''' - - def testNotExistentType(self): - conversion = sample.getConversionTypeString('NotExistentType') - self.assertEqual(conversion, 'Invalid conversion') - - def testObjectType(self): - conversion = sample.getConversionTypeString('ObjectType') - self.assertEqual(conversion, 'Pointer conversion') - conversion = sample.getConversionTypeString('ObjectType*') - self.assertEqual(conversion, 'Pointer conversion') - conversion = sample.getConversionTypeString('ObjectType&') - self.assertEqual(conversion, 'Reference conversion') - - def testValueType(self): - conversion = sample.getConversionTypeString('Point') - self.assertEqual(conversion, 'Copy conversion') - conversion = sample.getConversionTypeString('Point*') - self.assertEqual(conversion, 'Pointer conversion') - conversion = sample.getConversionTypeString('Point&') - self.assertEqual(conversion, 'Reference conversion') - - -class StringBasedConversionTest(unittest.TestCase): - - def testValueType(self): - pts = (sample.Point(1, 1), sample.Point(2, 2), sample.Point(3, 3)) - result = sample.convertValueTypeToCppAndThenToPython(pts[0], pts[1], pts[2]) - for orig, new in zip(pts, result): - self.assertEqual(orig, new) - self.assertFalse(pts[0] is result[0]) - self.assertTrue(pts[1] is result[1]) - self.assertTrue(pts[2] is result[2]) - - def testObjectType(self): - objs = (sample.ObjectType(), sample.ObjectType()) - objs[0].setObjectName('obj0') - objs[1].setObjectName('obj1') - result = sample.convertObjectTypeToCppAndThenToPython(objs[0], objs[1]) - for orig, new in zip(objs, result): - self.assertEqual(orig, new) - self.assertEqual(orig.objectName(), new.objectName()) - self.assertTrue(orig is new) - - def testContainerType(self): - lst = range(4) - result = sample.convertListOfIntegersToCppAndThenToPython(lst) - self.assertTrue(len(result), 1) - self.assertTrue(lst, result[0]) - - def testCppPrimitiveType(self): - integers = (12, 34) - result = sample.convertIntegersToCppAndThenToPython(integers[0], integers[1]) - for orig, new in zip(integers, result): - self.assertEqual(orig, new) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/typedealloc_test.py b/tests/samplebinding/typedealloc_test.py deleted file mode 100644 index b0fe763e0..000000000 --- a/tests/samplebinding/typedealloc_test.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test deallocation of type extended in Python.''' - -import gc -import weakref -import unittest - -from sample import Point - - -class TypeDeallocTest(unittest.TestCase): - - def setUp(self): - self.called = False - - def tearDown(self): - del self.called - - def callback(self, *args): - self.called = True - - def testScopeEnd(self): - ref = None - def scope(): - class Ext(Point): - pass - o = Ext() - global ref - ref = weakref.ref(Ext, self.callback) - scope() - gc.collect() - self.assertTrue(self.called) - - def testDeleteType(self): - class Ext(Point): - pass - ref = weakref.ref(Ext, self.callback) - del Ext - gc.collect() - self.assertTrue(self.called) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/typedtordoublefree_test.py b/tests/samplebinding/typedtordoublefree_test.py deleted file mode 100644 index 1106c8761..000000000 --- a/tests/samplebinding/typedtordoublefree_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import ObjectType - -class TestTypeDestructorDoubleFree(unittest.TestCase): - def testTypeDestructorDoubleFree(self): - '''Causes the type destructors of two derived classes to be called.''' - def scope(): - class ExtObj1(ObjectType): - def __init__(self): - ObjectType.__init__(self) - 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/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml deleted file mode 100644 index 089f835fc..000000000 --- a/tests/samplebinding/typesystem_sample.xml +++ /dev/null @@ -1,2426 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - return PyLong_FromSize_t(%in); - - - - %out = %OUTTYPE(PyLong_AsSsize_t(%in)); - - - - - - - static bool Check2TupleOfNumbers(PyObject* pyIn) { - if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2)) - return false; - Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0)); - if (!SbkNumber_Check(pyReal)) - return false; - Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1)); - if (!SbkNumber_Check(pyImag)) - return false; - return true; - } - - - - - - return PyComplex_FromDoubles(%in.real(), %in.imag()); - - - - - double real = PyComplex_RealAsDouble(%in); - double imag = PyComplex_ImagAsDouble(%in); - %out = %OUTTYPE(real, imag); - - - 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); - - - - - - - - - - SBK_UNUSED(%in); - Py_RETURN_NONE; - - - - %out = %OUTTYPE(%in == 0); - - - - - - - - - - if (!%in) - Py_RETURN_NONE; - #ifdef IS_PY3K - return PyCapsule_New(%in, 0, 0); - #else - return PyCObject_FromVoidPtr(%in, 0); - #endif - - - - %out = 0; - - - void* ptr; - #ifdef IS_PY3K - ptr = PyCapsule_GetPointer(%in, 0); - #else - ptr = PyCObject_AsVoidPtr(%in); - #endif - %out = (%OUTTYPE)ptr; - - - - - - - static bool checkPyCapsuleOrPyCObject(PyObject* pyObj) - { - #ifdef IS_PY3K - return PyCapsule_CheckExact(pyObj); - #else - return PyCObject_Check(pyObj); - #endif - } - - - - - - - #ifdef IS_PY3K - return PyCapsule_New(&%in, 0, 0); - #else - return PyCObject_FromVoidPtr(&%in, 0); - #endif - - - - void* ptr; - #ifdef IS_PY3K - ptr = PyCapsule_GetPointer(%in, 0); - #else - ptr = PyCObject_AsVoidPtr(%in); - #endif - %out = *((%OUTTYPE*)ptr); - - - - - - - - - - - return PyBool_FromLong(%in.value()); - - - - // Tests CONVERTTOCPP macro with C++ primitive type. - bool b = %CONVERTTOCPP[bool](%in); - %out = %OUTTYPE(b); - - - // Tests CONVERTTOCPP macro with user's primitive type. - Complex cpx = %CONVERTTOCPP[Complex](%in); - %out = %OUTTYPE(cpx.real() != 0.0 || cpx.imag() != 0.0); - - - - - - - - - - return Shiboken::String::fromCString(%in.cstring(), %in.size()); - - - - const char* str = %CONVERTTOCPP[const char*](%in); - %out = %OUTTYPE(str); - - - %out = %OUTTYPE(); - - - - - - - - - - - - - - - - %FUNCTION_NAME(&%1, %2); - %PYARG_0 = %CONVERTTOPYTHON[PStr](%1); - - - - - - - - - - - - - - - - %FUNCTION_NAME(&%1); - %PYARG_0 = %CONVERTTOPYTHON[PStr](%1); - - - - - - - - - PyObject* %out = PyList_New((int) %in.size()); - PStrList::const_iterator it = %in.begin(); - for (int idx = 0; it != %in.end(); ++it, ++idx) { - PStr cppItem(*it); - PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[PStr](cppItem)); - } - return %out; - - - - %OUTTYPE& list = %out; - Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0)); - for (int i = 0; i < PySequence_Fast_GET_SIZE(seq.object()); i++) { - PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), i); - PStr cppItem = %CONVERTTOCPP[PStr](pyItem); - list.push_back(cppItem); - } - - - - - - - - PStrList %0; - %0.push_back(%1); - %0.push_back(%2); - %PYARG_0 = %CONVERTTOPYTHON[PStrList](%0); - - - - - std::list<PStr> %0; - %0.push_back(%1); - %0.push_back(%2); - %PYARG_0 = %CONVERTTOPYTHON[std::list<PStr>](%0); - - - - - - %PYARG_0 = (PyObject*) Shiboken::Conversions::getPythonTypeObject(%1); - if (!%PYARG_0) - %PYARG_0 = Py_None; - Py_INCREF(%PYARG_0); - - - - - - - - - - - - - - - - - - - - - - Shiboken::Conversions::SpecificConverter converter(%1); - const char* %0 = 0; - switch (converter.conversionType()) { - case Shiboken::Conversions::SpecificConverter::CopyConversion: - %0 = "Copy conversion"; - break; - case Shiboken::Conversions::SpecificConverter::PointerConversion: - %0 = "Pointer conversion"; - break; - case Shiboken::Conversions::SpecificConverter::ReferenceConversion: - %0 = "Reference conversion"; - break; - default: - %0 = "Invalid conversion"; - } - %PYARG_0 = %CONVERTTOPYTHON[const char*](%0); - - - - - static PyObject* __convertCppValuesToPython(const char** typeName, void** values, int size) - { - PyObject* result = PyTuple_New(size); - for (int i = 0; i < size; ++i) { - Shiboken::Conversions::SpecificConverter converter(typeName[i]); - PyTuple_SET_ITEM(result, i, converter.toPython(values[i])); - } - return result; - } - - - - const char* typeNames[] = { "Point", "Point*", "Point&" }; - void* values[] = { &%1, &%2, &(%3) }; - %PYARG_0 = __convertCppValuesToPython(typeNames, values, 3); - - - - - const char* typeNames[] = { "ObjectType*", "ObjectType&" }; - void* values[] = { &%1, &(%2) }; - %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2); - - - - - const char* typeNames[] = { "std::list<int>" }; - void* values[] = { &%1 }; - %PYARG_0 = __convertCppValuesToPython(typeNames, values, 1); - - - - - const char* typeNames[] = { "int", "int" }; - void* values[] = { &%1, &%2 }; - %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2); - - - - - - - - PyObject* %out = PyTuple_New(2); - PyTuple_SET_ITEM(%out, 0, %CONVERTTOPYTHON[%INTYPE_0](%in.first)); - PyTuple_SET_ITEM(%out, 1, %CONVERTTOPYTHON[%INTYPE_1](%in.second)); - return %out; - - - - %out.first = %CONVERTTOCPP[%OUTTYPE_0](PySequence_Fast_GET_ITEM(%in, 0)); - %out.second = %CONVERTTOCPP[%OUTTYPE_1](PySequence_Fast_GET_ITEM(%in, 1)); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 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; - - - - PyObject* key; - PyObject* value; - Py_ssize_t pos = 0; - while (PyDict_Next(%in, &pos, &key, &value)) { - %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key); - %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value); - %out.insert(%OUTTYPE::value_type(cppKey, cppValue)); - } - - - - - - - - %RETURN_TYPE %0 = Shiboken::BindingManager::instance().getAllPyObjects().size(); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const unsigned char* %out = reinterpret_cast<const unsigned char*>(Shiboken::String::toCString(%PYARG_1)); - - - - - - unsigned int %out = static_cast<unsigned int>(Shiboken::String::len(%PYARG_1)); - - - - - - %RETURN_TYPE %0 = %1 + %2; - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - %RETURN_TYPE %0 = %1.x() + %1.y(); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - // The dot in "%1." must be replaced with a "->" by the generator. - %RETURN_TYPE %0 = %1.objectName().size(); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const char* tmpArg = %CONVERTTOCPP[const char*](%PYARG_1); - %0 = new %FUNCTION_NAME(atoi(tmpArg)); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - static void reparent_layout_items(PyObject* parent, PyObject* layout) - { - // CHECKTYPE and ISCONVERTIBLE are used here for test purposes, don't change them. - if (!%CHECKTYPE[ObjectTypeLayout*](layout) && !%ISCONVERTIBLE[ObjectTypeLayout*](layout)) - return; - // %CHECKTYPE[ObjectTypeLayout*](layout) - // %ISCONVERTIBLE[ObjectTypeLayout*](layout) - ObjectTypeLayout* var; - var = %CONVERTTOCPP[ObjectTypeLayout*](layout); - // TODO-CONVERTER: erase this - /* - ObjectTypeLayout* var2 = %CONVERTTOCPP[ObjectTypeLayout*](layout); - */ - const ObjectTypeList& objChildren = var->objects(); - ObjectTypeList::const_iterator it = objChildren.begin(); - for (; it != objChildren.end(); ++it) { - if ((*it)->isLayoutType()) { - ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(*it); - reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); - Shiboken::Object::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); - } else { - Shiboken::Object::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); - } - } - } - - - - - - - if (%PYARG_1 != Py_None) - reparent_layout_items(%PYSELF, %PYARG_1); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %2) * 10; - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%PYARG_1); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, true, %3, %4); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int %out = PySequence_Size(%PYARG_1); - - - - - - Shiboken::AutoArrayPointer<Point> %out(%1); - for (int i = 0; i < %1; ++i) - %out[i] = %CONVERTTOCPP[Point](PySequence_Fast_GET_ITEM(%PYARG_1, i)); - - - - - - - - - - - - int size = (%2 < 0) ? %1.size() : %2; - %BEGIN_ALLOW_THREADS - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME((const void*) %1.data(), size); - %END_ALLOW_THREADS - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); - Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); - *%2 = %CONVERTTOCPP[bool](_py_ok_); - %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ret_); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ObjectType* tmpObject = 0; - %BEGIN_ALLOW_THREADS - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(&tmpObject); - %END_ALLOW_THREADS - %PYARG_0 = PyTuple_New(2); - PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](%0)); - PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[ObjectType*](tmpObject)); - - - - - %RETURN_TYPE %0 = !%CPPSELF.%FUNCTION_NAME(%1); - %PYARG_0 = %CONVERTTOPYTHON[OddBool](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %1+%3, %3); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - PyObject* new_arg0 = PyInt_FromLong(PyInt_AS_LONG(%PYARG_1) - %2); - Py_DECREF(%PYARG_1); - %PYARG_1 = new_arg0; - - - - - %0.prepend(Str("Pimped")); - - - - - PyObject_Call(%PYTHON_METHOD_OVERRIDE, %PYTHON_ARGUMENTS, NULL); - - - - - - - - - - Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); - Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); - %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ok_); - %2 = %CONVERTTOCPP[Str*](_py_ret_); - - - - Str* _str_arg_ = 0; - %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, _str_arg_); - - - %PYARG_0 = PyTuple_New(2); - PyObject* _item_ = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - PyTuple_SET_ITEM(%PYARG_0, 0, _item_); - _item_ = %CONVERTTOPYTHON[Str*](_str_arg_); - PyTuple_SET_ITEM(%PYARG_0, 1, _item_); - - - - - - - - - - - Str* _str_arg_ = 0; - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, _str_arg_); - - - %PYARG_0 = PyTuple_New(2); - PyObject* _item_ = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - PyTuple_SET_ITEM(%PYARG_0, 0, _item_); - _item_ = %CONVERTTOPYTHON[Str*](_str_arg_); - PyTuple_SET_ITEM(%PYARG_0, 1, _item_); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %BEGIN_ALLOW_THREADS - // It's important for test purposes to use a constructor with parenthesis as argument. - %RETURN_TYPE %0 = %RETURN_TYPE(%CPPSELF.%FUNCTION_NAME(Str(%1))); - %END_ALLOW_THREADS - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - %0 = new %TYPE(%PYARG_1); - - - - - %PYARG_0 = reinterpret_cast<PyObject*>(%CPPSELF.%FUNCTION_NAME()); - if (!%PYARG_0) - %PYARG_0 = Py_None; - Py_INCREF(%PYARG_0); - - - - - - - - - - - - bool ok_; - %RETURN_TYPE retval_ = - %FUNCTION_NAME(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, &ok_); - if (!ok_) - %PYARG_0 = Py_None; - else - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](retval_); - - - - - - - - typedef std::list<int> Inner; - typedef std::list<Inner> Outer; - - int result = 0; - - Outer::const_iterator oiter, oend = %1.end(); - for (oiter = %1.begin(); oiter != oend; ++oiter) { - const Inner& inner = *oiter; - Inner::const_iterator iiter, iend = inner.end(); - for (iiter = inner.begin(); iiter != iend; ++iiter) - result += *iiter; - } - - %PYARG_0 = %CONVERTTOPYTHON[int](result); - - - - - - - typedef std::pair<int, int> Pair; - typedef std::list<Pair> List; - - int result = 0; - - List::const_iterator iter, end = %1.end(); - for (iter = %1.begin(); iter != end; ++iter) - result += iter->first * iter->second; - - %PYARG_0 = %CONVERTTOPYTHON[int](result); - - - - - - - - - - - - - int* array = NULL; - bool errorOccurred = false; - - if (PySequence_Check(%PYARG_1)) { - if((array = Shiboken::sequenceToIntArray(%PYARG_1, true)) == NULL && PyErr_Occurred()) { - PyErr_SetString(PyExc_TypeError, "Should be a sequence of ints"); - errorOccurred = true; - } - } else { - PyErr_SetString(PyExc_TypeError, "Should be a sequence of ints"); - errorOccurred = true; - } - - if (!errorOccurred) { - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(array); - if (array) - delete[] array; - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - } - - - - - - - - int %out = PySequence_Size(%PYARG_1); - - - - - - int numItems = PySequence_Size(%PYARG_1); - Shiboken::AutoArrayPointer<int> %out(numItems); - for (int i = 0; i < numItems; ++i) { - if (%CHECKTYPE[int](PySequence_Fast_GET_ITEM(%PYARG_1, i))) - %out[i] = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(%PYARG_1, i)); - else if (%ISCONVERTIBLE[int](PySequence_Fast_GET_ITEM(%PYARG_1, i))) - %out[i] = -1; - else - %out[i] = -2; - } - - - PyObject* %out = PyList_New(count); - for (int i = 0; i < count; ++i) - PyList_SET_ITEM(%out, i, %CONVERTTOPYTHON[int](%in[i])); - - - - - - - - - - - - - int numItems = PySequence_Size(%PYARG_1); - int *cppItems = new int[numItems]; - for (int i = 0; i < numItems; i++) - cppItems[i] = %CONVERTTOCPP[int](PySequence_GetItem(%PYARG_1, i)); - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(numItems, cppItems); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - delete[] cppItems; - - - - - - PyObject* InjectCode_tpstr(PyObject*) { return Shiboken::String::fromCString("Hi! I'm the inject code dummy class."); } - - - - %PYTHONTYPEOBJECT.tp_str = InjectCode_tpstr; - - - - - - %1 += 1; - - - PyObject* tmp = Shiboken::String::fromCString("end"); - Shiboken::String::concat(&%PYARG_0, tmp); - Py_DECREF(tmp); - - - - - - - PyObject* tmp = Shiboken::String::fromCString("end"); - Shiboken::String::concat(&%PYARG_0, tmp); - Py_DECREF(tmp); - - - - - - - - - - - - - int argc; - char** argv; - if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { - PyErr_SetString(PyExc_TypeError, "error"); - return 0; - } - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argc, argv); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - for (int i = 0; i < argc; ++i) - free(argv[i]); - delete[] argv; - - - - - - - - - - - - - int argc; - char** argv; - if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { - PyErr_SetString(PyExc_TypeError, "error"); - return 0; - } - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argc, argv); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - for (int i = 0; i < argc; ++i) - free(argv[i]); - delete[] argv; - - - - - - - - - return Shiboken::String::fromCString("PyObject"); - - - - - - return Shiboken::String::fromCString("PyObject"); - - - - - - - unsigned char* %out = 0; - - - - - - - - - - int x1 = (int) %CPPSELF.x(); - int x2 = ((int) (%CPPSELF.x() * 100)) - (x1 * 100); - int y1 = (int) %CPPSELF.y(); - int y2 = ((int) (%CPPSELF.y() * 100)) - (y1 * 100); - %PYARG_0 = Shiboken::String::fromFormat("Point(%d.%d, %d.%d)", x1, x2, y1, y2); - - - - - int x1 = (int) %CPPSELF.x(); - int x2 = ((int) (%CPPSELF.x() * 10)) - (x1 * 10); - int y1 = (int) %CPPSELF.y(); - int y2 = ((int) (%CPPSELF.y() * 10)) - (y1 * 10); - %PYARG_0 = Shiboken::String::fromFormat("<Point object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); - - - - - - PyObject* type = PyObject_Type(%PYSELF); - PyObject* args = NULL; - - args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); - - %PYARG_0 = Py_BuildValue("(OO)", type, args); - - - - - - - - - - - - Point _midpoint; - // The test consists in *NOT* using the ARGUMENT_NAMES type system variable. - %CPPSELF.%FUNCTION_NAME(%1, &_midpoint); - %PYARG_0 = %CONVERTTOPYTHON[Point](_midpoint); - - - - - - - - - - - - - - - - - - - - - int x1 = (int) %CPPSELF.x(); - int x2 = ((int) (%CPPSELF.x() * 100)) - (x1 * 100); - int y1 = (int) %CPPSELF.y(); - int y2 = ((int) (%CPPSELF.y() * 100)) - (y1 * 100); - %PYARG_0 = Shiboken::String::fromFormat("PointF(%d.%d, %d.%d)", x1, x2, y1, y2); - - - - - int x1 = (int) %CPPSELF.x(); - int x2 = ((int) (%CPPSELF.x() * 10)) - (x1 * 10); - int y1 = (int) %CPPSELF.y(); - int y2 = ((int) (%CPPSELF.y() * 10)) - (y1 * 10); - %PYARG_0 = Shiboken::String::fromFormat("<PointF object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); - - - - - - PyObject *type = PyObject_Type(%PYSELF); - PyObject *args = NULL; - - args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); - - %PYARG_0 = Py_BuildValue("(OO)", type, args); - - - - - - - - - - - - PointF _midpoint; - // The test consists in using the ARGUMENT_NAMES type system variable. - %CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, &_midpoint); - %PYARG_0 = %CONVERTTOPYTHON[PointF](_midpoint); - - - - - - - - - - - - - - - - - - - - - - - - - - - - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - if (PyTime_Check(%1)) { - int pyH = PyDateTime_TIME_GET_HOUR(%1); - int pyM = PyDateTime_TIME_GET_MINUTE(%1); - int pyS = PyDateTime_TIME_GET_SECOND(%1); - if ((pyH == %CPPSELF.hour()) && - (pyM == %CPPSELF.minute()) && - (pyS == %CPPSELF.second())) - %PYARG_0 = Py_False; - else - %PYARG_0 = Py_True; - } - - - - - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - if (PyTime_Check(%1)) { - int pyH = PyDateTime_TIME_GET_HOUR(%1); - int pyM = PyDateTime_TIME_GET_MINUTE(%1); - int pyS = PyDateTime_TIME_GET_SECOND(%1); - if ((pyH == %CPPSELF.hour()) && - (pyM == %CPPSELF.minute()) && - (pyS == %CPPSELF.second())) - %PYARG_0 = Py_True; - else - %PYARG_0 = Py_False; - } - - - - - - - - %0 = new %TYPE(); - - - Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF, const_cast<char*>("setHeight"), const_cast<char*>("i"), 2)); - - - - - - - - - - - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, 2, %3); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - { - Shiboken::AutoDecRef strList(PySequence_Fast(%PYARG_1, "The argument must be a sequence.")); - int lineCount = PySequence_Fast_GET_SIZE(strList.object()); - for (int line = 0; line < lineCount; ++line) { - if (!Shiboken::String::check(PySequence_Fast_GET_ITEM(strList.object(), line))) { - PyErr_SetString(PyExc_TypeError, "The argument must be a sequence of strings."); - break; - } - } - } - const char** %out = 0; - - - - - - - - void* %out = 0; - - - - - - - - - - - - - - - - - - - - - %BEGIN_ALLOW_THREADS - %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argOut, %2); - %END_ALLOW_THREADS - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - %PYARG_0 = Shiboken::String::fromCString(%CPPSELF.cstring()); - - - - - return %CPPSELF.size(); - - - - - if (_i < 0 || _i >= %CPPSELF.size()) { - PyErr_BadArgument(); - return 0; - } else { - char res[2]; - res[0] = %CPPSELF.get_char(_i); - res[1] = 0; - return Shiboken::String::fromCString(res); - } - - - - - PyObject* args = Py_BuildValue("(iO)", _i, _value); - PyObject* result = Sbk_StrFunc_set_char(self, args); - Py_DECREF(args); - int ok = result == Py_True; - if (result) { - Py_DECREF(result); - } - return !ok ? -1 : 0; - - - - - - - - - - - - - - - - - - - - - - - %out = %OUTTYPE(); - - - Py_ssize_t len; - const char* str = Shiboken::String::toCString(%in, &len); - %out = %OUTTYPE(str, len); - - - - - - - - - - - - PyObject* data = 0; - if (PyUnicode_CheckExact(%PYARG_1)) { - data = PyUnicode_AsASCIIString(%PYARG_1); - } else { - data = %PYARG_1; - Py_INCREF(data); - } - - %0 = new %TYPE(PyBytes_AsString(data), PyBytes_GET_SIZE(data)); - Py_DECREF(data); - - - - - - - #if PY_VERSION_HEX < 0x03000000 - Shiboken::SbkType<ByteArray>()->tp_as_buffer = &SbkByteArrayBufferProc; - Shiboken::SbkType<ByteArray>()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER; - #endif - - - - - %PYARG_0 = PyBytes_FromStringAndSize(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.size()); - - - - - - - - - - - - - - - - - - - Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); - if (!data.isNull()) { - ByteArray ba(*%CPPSELF); - ba.append(PyBytes_AsString(data.object()), PyBytes_GET_SIZE(data.object())); - %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); - } - - - - - Shiboken::AutoDecRef data(PyUnicode_AsASCIIString(%PYARG_1)); - if (!data.isNull()) { - ByteArray ba(PyBytes_AsString(data.object()), PyBytes_GET_SIZE(data.object())); - ba.append(*%CPPSELF); - %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); - } - - - - - ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1)); - ba = ba + *%CPPSELF; - %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); - - - - - ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1)); - ba.append(*%CPPSELF); - %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba); - - - - - ByteArray b(((PyObject*)%PYSELF)->ob_type->tp_name); - PyObject* aux = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); - if (PyUnicode_CheckExact(aux)) { - PyObject* tmp = PyUnicode_AsASCIIString(aux); - Py_DECREF(aux); - aux = tmp; - } - b += "('"; - b += ByteArray(PyBytes_AS_STRING(aux), PyBytes_GET_SIZE(aux)); - b += "')"; - %PYARG_0 = Shiboken::String::fromStringAndSize(b.data(), b.size()); - - - - - - %PYARG_0 = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size()); - - - - - - return %CPPSELF.size(); - - - - - if (_i < 0 || _i >= %CPPSELF.size()) { - PyErr_SetString(PyExc_IndexError, "index out of bounds"); - return 0; - } else { - char res[2]; - res[0] = %CPPSELF.at(_i); - res[1] = 0; - return PyBytes_FromStringAndSize(res, 1); - } - - - - - - - - - return %CPPSELF.size(); - - - - - if (_i < 0 || _i >= static_cast<Py_ssize_t>(%CPPSELF.size())) { - PyErr_BadArgument(); - return 0; - } else { - %TYPE::const_iterator it = %CPPSELF.begin(); - for (Py_ssize_t i = 1; i <= _i; i++) - ++it; - return %CONVERTTOPYTHON[Str](*it); - } - - - - - - - - - - - - - - - - - - - - %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); - %PYARG_0 = Shiboken::Object::newObject(&SbkObject_Type, %0, false, false); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %PYARG_0 = Shiboken::String::fromCString(%1); - - - - - // This should test if code injections works inside rich comparison operators - Py_INCREF(Py_True); - %PYARG_0 = Py_True; - - - - - - - - - - - - - - - // Does nothing really, just test the code generation - // of constructors whose arguments where - long %out = PyInt_AS_LONG(%PYARG_1) + 1; - - - - - - - - %PYARG_0 = Shiboken::String::fromCString(""); - for (unsigned int i = 0; i < %2; ++i) - Shiboken::String::concat(&%PYARG_0, %PYARG_1); - - - - - - %RETURN_TYPE %0 = PyTuple_GET_SIZE(%PYARG_2); - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - static bool PyDate_ImportAndCheck(PyObject* pyIn) { - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - return PyDate_Check(pyIn); - } - - - - - int day = PyDateTime_GET_DAY(%in); - int month = PyDateTime_GET_MONTH(%in); - int year = PyDateTime_GET_YEAR(%in); - %out = %OUTTYPE(day, month, year); - - - - - - if (!PyDateTimeAPI) - PyDateTime_IMPORT; - %PYARG_0 = PyDate_FromDate(%CPPSELF.day(), %CPPSELF.month(), %CPPSELF.year()); - - - - - - - - - - - %RETURN_TYPE %0 = %CPPSELF.key() != %1; - %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - %RETURN_TYPE %0 = *%CPPSELF & %1; - return %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - %RETURN_TYPE %0 = *%CPPSELF & %1; - return %CONVERTTOPYTHON[%RETURN_TYPE](%0); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/samplebinding/unsafe_parent_test.py b/tests/samplebinding/unsafe_parent_test.py deleted file mode 100644 index 18da16458..000000000 --- a/tests/samplebinding/unsafe_parent_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for ...''' - -import sys -import unittest - -from sample import ObjectType - -class DerivedObjectType(ObjectType): - def isPython(self): - return True - - 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/tests/samplebinding/useraddedctor_test.py b/tests/samplebinding/useraddedctor_test.py deleted file mode 100644 index ea9d1f878..000000000 --- a/tests/samplebinding/useraddedctor_test.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for user added constructors''' - -import unittest -from sample import * - -class PointTest(unittest.TestCase): - def testUsingSelfOnCtor(self): - # This is a user added ctor and no errors should happen! - s = Size("oi") - self.assertEqual(s.height(), 2) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/virtualdtor_test.py b/tests/samplebinding/virtualdtor_test.py deleted file mode 100644 index 46f29179c..000000000 --- a/tests/samplebinding/virtualdtor_test.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for virtual destructor.''' - -import sys -import unittest - -from sample import VirtualDtor - -class ExtendedVirtualDtor(VirtualDtor): - def __init__(self): - VirtualDtor.__init__(self) - -class VirtualDtorTest(unittest.TestCase): - '''Test case for virtual destructor.''' - - def setUp(self): - VirtualDtor.resetDtorCounter() - - def testVirtualDtor(self): - '''Original virtual destructor is being called.''' - dtor_called = VirtualDtor.dtorCalled() - for i in range(1, 10): - vd = VirtualDtor() - del vd - self.assertEqual(VirtualDtor.dtorCalled(), dtor_called + i) - - def testVirtualDtorOnCppCreatedObject(self): - '''Original virtual destructor is being called for a C++ created object.''' - dtor_called = VirtualDtor.dtorCalled() - for i in range(1, 10): - vd = VirtualDtor.create() - del vd - self.assertEqual(VirtualDtor.dtorCalled(), dtor_called + i) - - def testDtorOnDerivedClass(self): - '''Original virtual destructor is being called for a derived class.''' - dtor_called = ExtendedVirtualDtor.dtorCalled() - for i in range(1, 10): - evd = ExtendedVirtualDtor() - del evd - self.assertEqual(ExtendedVirtualDtor.dtorCalled(), dtor_called + i) - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/virtualmethods_test.py b/tests/samplebinding/virtualmethods_test.py deleted file mode 100644 index 8a361c9f9..000000000 --- a/tests/samplebinding/virtualmethods_test.py +++ /dev/null @@ -1,138 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test cases for virtual methods.''' - -import sys -import unittest - -from sample import * - -import warnings - -class ExtendedVirtualMethods(VirtualMethods): - def __init__(self): - VirtualMethods.__init__(self) - self.virtual_method0_called = False - - def virtualMethod0(self, pt, val, cpx, b): - self.virtual_method0_called = True - return VirtualMethods.virtualMethod0(self, pt, val, cpx, b) * -1.0 - - def strListToStdList(self, arg): - warnings.simplefilter('error') - # returning wrong type for test purposes. - return True - - def recursionOnModifiedVirtual(self, arg): - # 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) - self.grand_daughter_name_called = False - - def name(self): - self.grand_daughter_name_called = True - return VirtualDaughter.name(self).prepend('Extended') - -class ExtendedExtendedVirtualDaughter(ExtendedVirtualDaughter): - def __init__(self, name): - ExtendedVirtualDaughter.__init__(self, name) - self.grand_grand_daughter_name_called = False - - def name(self): - self.grand_grand_daughter_name_called = True - return ExtendedVirtualDaughter.name(self).prepend('Extended') - -class VirtualMethodsTest(unittest.TestCase): - '''Test case for virtual methods''' - - def setUp(self): - self.prefix_from_codeinjection = Str('Pimped') - - def tearDown(self): - del self.prefix_from_codeinjection - - def testReimplementedVirtualMethod0(self): - '''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) - val = 4 - cpx = complex(3.3, 4.4) - b = True - result0 = vm.callVirtualMethod0(pt, val, cpx, b) - result1 = evm.callVirtualMethod0(pt, val, cpx, b) - self.assertEqual(result0 * -1.0, result1) - - def testRecursionOnModifiedVirtual(self): - evm = ExtendedVirtualMethods() - self.assertEqual(evm.recursionOnModifiedVirtual(''), 10) - self.assertEqual(evm.callRecursionOnModifiedVirtual(''), 10) - - def testReimplementedVirtualMethodInheritedFromGrandParent(self): - '''Test Python override of a virtual method inherited from a grand parent.''' - original_name = 'Foo' - evd = ExtendedVirtualDaughter(original_name) - - self.assertEqual(VirtualDaughter.name(evd), original_name) - self.assertEqual(VirtualMethods.name(evd), original_name) - self.assertFalse(evd.grand_daughter_name_called) - - name = evd.callName() - self.assertTrue(evd.grand_daughter_name_called) - self.assertEqual(evd.name().prepend(self.prefix_from_codeinjection), name) - - def testReimplementedVirtualMethodInheritedFromGrandGrandParent(self): - '''Test Python override of a virtual method inherited from a grand grand parent.''' - original_name = 'Foo' - eevd = ExtendedExtendedVirtualDaughter(original_name) - - self.assertEqual(VirtualDaughter.name(eevd), original_name) - self.assertEqual(VirtualMethods.name(eevd), original_name) - self.assertFalse(eevd.grand_daughter_name_called) - self.assertFalse(eevd.grand_grand_daughter_name_called) - - name = eevd.callName() - self.assertTrue(eevd.grand_daughter_name_called) - self.assertTrue(eevd.grand_grand_daughter_name_called) - self.assertEqual(eevd.name().prepend(self.prefix_from_codeinjection), name) - -class PrettyErrorMessageTest(unittest.TestCase): - def testIt(self): - obj = ExtendedVirtualMethods() - self.assertRaises(RuntimeWarning, obj.callStrListToStdList, StrList()) - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/visibilitychange_test.py b/tests/samplebinding/visibilitychange_test.py deleted file mode 100644 index b89036a94..000000000 --- a/tests/samplebinding/visibilitychange_test.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest - -from sample import * - -class VisibilityChangeTest(unittest.TestCase): - - def testVisibilityChange(self): - b1 = Base1() - b1.publicMethod() # ok... - d1 = MDerived1() - self.assertRaises(TypeError, d1.publicMethod); - -if __name__ == '__main__': - unittest.main() - - diff --git a/tests/samplebinding/voidholder_test.py b/tests/samplebinding/voidholder_test.py deleted file mode 100644 index cb5cab6e5..000000000 --- a/tests/samplebinding/voidholder_test.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test case for a class that holds a void pointer.''' - -import unittest - -from sample import VoidHolder, Point - -class VoidHolderTest(unittest.TestCase): - '''Test case for void pointer manipulation.''' - - def testGetVoidPointerFromCppAndPutsOnVoidHolder(self): - '''Passes a void pointer created in C++ and to kept by VoidHolder.''' - voidptr = VoidHolder.gimmeMeSomeVoidPointer() - voidholder = VoidHolder(voidptr) - self.assertEqual(voidptr, voidholder.voidPointer()) - - def testPutRandomObjectInsideVoidHolder(self): - '''Passes a C++ pointer for an object created in Python to be kept by VoidHolder.''' - obj = Point(1, 2) - voidholder = VoidHolder(obj) - self.assertEqual(obj, voidholder.voidPointer()) - - def testGetNoneObjectFromVoidHolder(self): - '''A VoidHolder created without parameters returns a NULL pointer - that should be converted to a Python None.''' - voidholder = VoidHolder() - self.assertEqual(voidholder.voidPointer(), None) - - def testPutPythonObjectInsideVoidHolder(self): - '''Passes a native Python object to be kept by VoidHolder.''' - obj = 'Foo' - voidholder = VoidHolder(obj) - self.assertEqual(obj, voidholder.voidPointer()) - - - -if __name__ == '__main__': - unittest.main() - diff --git a/tests/samplebinding/weakref_test.py b/tests/samplebinding/weakref_test.py deleted file mode 100644 index 77be7ec9f..000000000 --- a/tests/samplebinding/weakref_test.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -'''Test weakref support''' - -import weakref -import unittest - -from sample import ObjectType, PrivateDtor - - -class WeakrefBasicTest(unittest.TestCase): - '''Simple test case of using a weakref''' - - def setUp(self): - self.called = False - - def cb(self, *args): - self.called = True - - def testBasic(self): - '''ObjectType weakref''' - obj = ObjectType() - ref = weakref.ref(obj, self.cb) - del obj - self.assertTrue(self.called) - - def testPrivateDtor(self): - '''PrivateDtor weakref''' - obj = PrivateDtor.instance() - ref = weakref.ref(obj, self.cb) - del obj - self.assertTrue(self.called) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/samplebinding/writableclassdict_test.py b/tests/samplebinding/writableclassdict_test.py deleted file mode 100644 index 828ac686a..000000000 --- a/tests/samplebinding/writableclassdict_test.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from sample import Point - -class ExtPoint(Point): pass - -class TestWritableClassDict(unittest.TestCase): - def testSetattrOnClass(self): - setattr(Point, 'foo', 123) - self.assertEqual(Point.foo, 123) - pt = Point() - self.assertEqual(pt.foo, 123) - - def testSetattrOnInheritingClass(self): - setattr(Point, 'bar', 321) - self.assertEqual(Point.bar, 321) - self.assertEqual(ExtPoint.bar, 321) - pt = ExtPoint() - self.assertEqual(pt.bar, 321) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/shibokenmodule/module_test.py b/tests/shibokenmodule/module_test.py deleted file mode 100644 index bc2931251..000000000 --- a/tests/shibokenmodule/module_test.py +++ /dev/null @@ -1,116 +0,0 @@ -############################################################################# -## -## Copyright (C) 2016 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import shiboken2 as shiboken -import unittest -from sample import * - -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())) - self.assertTrue(shiboken.isValid(None)) - - bb = BlackBox() - item = ObjectType() - ticket = bb.keepObjectType(item) - bb.disposeObjectType(ticket) - self.assertFalse(shiboken.isValid(item)) - - def testWrapInstance(self): - addr = ObjectType.createObjectType() - obj = shiboken.wrapInstance(addr, ObjectType) - self.assertFalse(shiboken.createdByPython(obj)) - obj.setObjectName("obj") - self.assertEqual(obj.objectName(), "obj") - self.assertEqual(addr, obj.identifier()) - self.assertFalse(shiboken.createdByPython(obj)) - - # avoid mem leak =] - bb = BlackBox() - self.assertTrue(shiboken.createdByPython(bb)) - bb.disposeObjectType(bb.keepObjectType(obj)) - - def testIsOwnedByPython(self): - obj = ObjectType() - self.assertTrue(shiboken.ownedByPython(obj)) - p = ObjectType() - obj.setParent(p) - self.assertFalse(shiboken.ownedByPython(obj)) - - def testDump(self): - """Just check if dump doesn't crash on certain use cases""" - p = ObjectType() - obj = ObjectType(p) - obj2 = ObjectType(obj) - obj3 = ObjectType(obj) - self.assertEqual(shiboken.dump(None), "Ordinary Python type.") - shiboken.dump(obj) - - model = ObjectModel(p) - v = ObjectView(model, p) - shiboken.dump(v) - - m = MultipleInherited() - shiboken.dump(m) - self.assertEqual(len(shiboken.getCppPointer(m)), 2) - - # 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 - - def testDelete(self): - obj = ObjectType() - child = ObjectType(obj) - self.assertTrue(shiboken.isValid(obj)) - self.assertTrue(shiboken.isValid(child)) - # Note: this test doesn't assure that the object dtor was really called - shiboken.delete(obj) - self.assertFalse(shiboken.isValid(obj)) - self.assertFalse(shiboken.isValid(child)) - - def testVersionAttr(self): - self.assertEqual(type(shiboken.__version__), str) - self.assertTrue(len(shiboken.__version__) >= 5) - self.assertEqual(type(shiboken.__version_info__), tuple) - self.assertEqual(len(shiboken.__version_info__), 5) - - def testAllWrappers(self): - obj = ObjectType() - self.assertTrue(obj in shiboken.getAllValidWrappers()) - shiboken.delete(obj) - self.assertFalse(obj in shiboken.getAllValidWrappers()) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/smartbinding/CMakeLists.txt b/tests/smartbinding/CMakeLists.txt deleted file mode 100644 index e9c52d447..000000000 --- a/tests/smartbinding/CMakeLists.txt +++ /dev/null @@ -1,39 +0,0 @@ -project(smart) - -set(smart_TYPESYSTEM -${CMAKE_CURRENT_SOURCE_DIR}/typesystem_smart.xml -) - -set(smart_SRC -${CMAKE_CURRENT_BINARY_DIR}/smart/smart_module_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/smart/obj_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/smart/integer_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/smart/sharedptr_obj_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/smart/sharedptr_integer_wrapper.cpp -${CMAKE_CURRENT_BINARY_DIR}/smart/registry_wrapper.cpp -) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/smart-binding.txt.in" - "${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt" @ONLY) - -add_custom_command(OUTPUT ${smart_SRC} -COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/smart-binding.txt ${GENERATOR_EXTRA_FLAGS} -DEPENDS ${smart_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2 -WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -COMMENT "Running generator for 'smart' test binding..." -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_SOURCE_DIR} - ${SBK_PYTHON_INCLUDE_DIR} - ${libsmart_SOURCE_DIR} - ${libshiboken_SOURCE_DIR}) -add_library(smart MODULE ${smart_SRC}) -set_property(TARGET smart PROPERTY PREFIX "") -if(WIN32) - set_property(TARGET smart PROPERTY SUFFIX ".pyd") -endif() -target_link_libraries(smart - libsmart - ${SBK_PYTHON_LIBRARIES} - libshiboken) diff --git a/tests/smartbinding/global.h b/tests/smartbinding/global.h deleted file mode 100644 index a72cd21a5..000000000 --- a/tests/smartbinding/global.h +++ /dev/null @@ -1,29 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "smart.h" diff --git a/tests/smartbinding/smart-binding.txt.in b/tests/smartbinding/smart-binding.txt.in deleted file mode 100644 index 699f0bfe6..000000000 --- a/tests/smartbinding/smart-binding.txt.in +++ /dev/null @@ -1,15 +0,0 @@ -[generator-project] - -generator-set = shiboken - -header-file = @CMAKE_CURRENT_SOURCE_DIR@/global.h -typesystem-file = @smart_TYPESYSTEM@ - -output-directory = @CMAKE_CURRENT_BINARY_DIR@ - -include-path = @libsmart_SOURCE_DIR@ - -typesystem-path = @CMAKE_CURRENT_SOURCE_DIR@ - -enable-parent-ctor-heuristic -use-isnull-as-nb_nonzero diff --git a/tests/smartbinding/smart_pointer_test.py b/tests/smartbinding/smart_pointer_test.py deleted file mode 100644 index c8eb1b2c5..000000000 --- a/tests/smartbinding/smart_pointer_test.py +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -############################################################################# -## -## Copyright (C) 2017 The Qt Company Ltd. -## Contact: https://www.qt.io/licensing/ -## -## This file is part of the test suite of PySide2. -## -## $QT_BEGIN_LICENSE:GPL-EXCEPT$ -## Commercial License Usage -## Licensees holding valid commercial Qt licenses may use this file in -## accordance with the commercial license agreement provided with the -## Software or, alternatively, in accordance with the terms contained in -## a written agreement between you and The Qt Company. For licensing terms -## and conditions see https://www.qt.io/terms-conditions. For further -## information use the contact form at https://www.qt.io/contact-us. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU -## General Public License version 3 as published by the Free Software -## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -## included in the packaging of this file. Please review the following -## information to ensure the GNU General Public License requirements will -## be met: https://www.gnu.org/licenses/gpl-3.0.html. -## -## $QT_END_LICENSE$ -## -############################################################################# - -import unittest -from copy import copy -from smart import Obj, Registry, Integer - -def objCount(): - return Registry.getInstance().countObjects() - -def integerCount(): - return Registry.getInstance().countIntegers() - -class SmartPointerTests(unittest.TestCase): - def testObjSmartPointer(self): - # Uncomment to see more debug info about creation of objects and ref counts. - # Registry.getInstance().setShouldPrint(True) - - # Create Obj. - o = Obj() - self.assertEqual(objCount(), 1) - - # Create a shared pointer to an Obj together with an Obj. - ptrToObj = o.giveSharedPtrToObj() - self.assertEqual(objCount(), 2) - - # Delete the old Obj. - o = None - self.assertEqual(objCount(), 1) - - # Get a wrapper to the Obj inside of the shared pointer, object count should not change. - obj = ptrToObj.data() - self.assertEqual(objCount(), 1) - obj.m_integer = 50 - self.assertEqual(obj.m_integer, 50) - - # Set and get a member value via shared pointer (like operator->). - ptrToObj.m_integer = 100 - self.assertEqual(ptrToObj.m_integer, 100) - - # Get inner PyObject via shared pointer (like operator->) and set value in it. - ptrToObj.m_internalInteger.m_int = 200 - self.assertEqual(ptrToObj.m_internalInteger.m_int, 200) - - # Pass smart pointer as argument to a method, return value is the value of m_integer of - # passed Obj inside the smart pointer. - result = ptrToObj.takeSharedPtrToObj(ptrToObj) - self.assertEqual(result, 100) - - # Pass an Integer as an argument that returns itself. - result = ptrToObj.takeInteger(ptrToObj.m_internalInteger) - self.assertEqual(integerCount(), 2) - result = None - self.assertEqual(integerCount(), 1) - - # Make a copy of the shared pointer, object count should not change. - ptrToObj2 = copy(ptrToObj) - self.assertEqual(objCount(), 1) - - # Delete the first shared pointer, object count should not change because the second - # one still has a reference. - del ptrToObj - self.assertEqual(objCount(), 1) - - # Delete the second smart pointer, object should be deleted. - del ptrToObj2 - self.assertEqual(objCount(), 0) - self.assertEqual(integerCount(), 0) - - def testIntegerSmartPointer(self): - # Uncomment to see more debug info about creation of objects and ref counts. - # Registry.getInstance().setShouldPrint(True) - - # Create Obj. - o = Obj() - self.assertEqual(objCount(), 1) - - # Create a shared pointer to an Integer together with an Integer. - ptrToInteger = o.giveSharedPtrToInteger() - self.assertEqual(objCount(), 1) - self.assertEqual(integerCount(), 2) - - # Get a wrapper to the Integer inside of the shared pointer, integer count should not - # change. - integer = ptrToInteger.data() - self.assertEqual(integerCount(), 2) - integer.m_int = 50 - self.assertEqual(integer.m_int, 50) - - # Set and get a member value via shared pointer (like operator->). - ptrToInteger.m_int = 100 - self.assertEqual(ptrToInteger.m_int, 100) - - # Pass smart pointer as argument to a method, return value is the value of m_int of - # passed Integer inside the smart pointer. - result = o.takeSharedPtrToInteger(ptrToInteger) - self.assertEqual(result, 100) - - # Make a copy of the shared pointer, integer count should not change. - ptrToInteger2 = copy(ptrToInteger) - self.assertEqual(integerCount(), 2) - - # Delete the first shared pointer, integer count should not change because the second - # one still has a reference. - del ptrToInteger - self.assertEqual(integerCount(), 2) - - # Delete the second smart pointer, integer should be deleted. - del ptrToInteger2 - self.assertEqual(objCount(), 1) - self.assertEqual(integerCount(), 1) - - # Delete the original object which was used to create the integer. - del o - self.assertEqual(objCount(), 0) - self.assertEqual(integerCount(), 0) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/smartbinding/typesystem_smart.xml b/tests/smartbinding/typesystem_smart.xml deleted file mode 100644 index a2654730d..000000000 --- a/tests/smartbinding/typesystem_smart.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/tests/sphinxtabletest.cpp b/tests/sphinxtabletest.cpp deleted file mode 100644 index 6a8ac7703..000000000 --- a/tests/sphinxtabletest.cpp +++ /dev/null @@ -1,332 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "sphinxtabletest.h" -#include "qtdocgenerator.h" -#include -#include - -QString SphinxTableTest::transformXml(const char* xml) -{ - return QtXmlToSphinx(m_generator, xml).result(); -} - -void SphinxTableTest::setUp() -{ - m_generator = new QtDocGenerator; -} - -void SphinxTableTest::tearDown() -{ - delete m_generator; -} - -void SphinxTableTest::testEmptyString() -{ - const char* xml = ""; - QCOMPARE(transformXml(xml), QString()); -} - -void SphinxTableTest::testSimpleTable() -{ - const char* xml = "\ -\ -
\ - \ - Header 1\ - \ - \ - Header 2\ - \ -
\ - \ - \ - 1 1\ - \ - \ - 1 2\ - \ - \ - \ - \ - 2 1\ - \ - \ - 2 2\ - \ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +--------+--------+\n\ - |Header 1|Header 2|\n\ - +--------+--------+\n\ - |1 1 |1 2 |\n\ - +--------+--------+\n\ - |2 1 |2 2 |\n\ - +--------+--------+\n\ -\n")); -} - -void SphinxTableTest::testColSpan() -{ - const char* xml = "\ -\ -
\ - \ - Header 1\ - \ - \ - Header 2\ - \ -
\ - \ - \ - I'm a big text!\ - \ - \ - \ - \ - 2 1\ - \ - \ - 2 2\ - \ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +---------------+--------+\n\ - |Header 1 |Header 2|\n\ - +---------------+--------+\n\ - |I'm a big text! |\n\ - +---------------+--------+\n\ - |2 1 |2 2 |\n\ - +---------------+--------+\n\ -\n")); -} - - -void SphinxTableTest::testRowSpan() -{ - const char* xml = "\ -\ -
\ - \ - Header 1\ - \ - \ - Header 2\ - \ -
\ - \ - \ - 1.1\ - \ - \ - 1.2\ - \ - \ - \ - \ - 2 2\ - \ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +--------+--------+\n\ - |Header 1|Header 2|\n\ - +--------+--------+\n\ - |1.1 |1.2 |\n\ - + +--------+\n\ - | |2 2 |\n\ - +--------+--------+\n\ -\n")); -} - - -void SphinxTableTest::testComplexTable() -{ - const char* xml = "\ -\ -
\ - \ - Header 1\ - \ - \ - Header 2\ - \ - \ - Header 3\ - \ -
\ - \ - \ - 1.1\ - \ - \ - 1.2\ - \ - \ - \ - \ - 2 2\ - \ - \ - 2 3\ - \ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +--------+--------+--------+\n\ - |Header 1|Header 2|Header 3|\n\ - +--------+--------+--------+\n\ - |1.1 |1.2 |\n\ - + +--------+--------+\n\ - | |2 2 |2 3 |\n\ - +--------+--------+--------+\n\ -\n")); -} - -void SphinxTableTest::testRowSpan2() -{ - const char* xml = "\ -\ -
\ - h1\ - h2\ - h3\ - h4\ -
\ - \ - A\ - B\ - C\ - D\ - \ - \ - E\ - F\ - \ - \ - E\ - F\ - \ - \ - E\ - F\ - \ - \ - E\ - F\ - \ - \ - E\ - F\ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +--+--+--+--+\n\ - |h1|h2|h3|h4|\n\ - +--+--+--+--+\n\ - |A |B |C |D |\n\ - + + +--+--+\n\ - | | |E |F |\n\ - + + +--+--+\n\ - | | |E |F |\n\ - + + +--+--+\n\ - | | |E |F |\n\ - + + +--+--+\n\ - | | |E |F |\n\ - + + +--+--+\n\ - | | |E |F |\n\ - +--+--+--+--+\n\ -\n")); -} - -void SphinxTableTest::testBrokenTable() -{ - const char* xml = "\ -\ -
\ - \ - Header 1\ - \ - \ - Header 2\ - \ -
\ - \ - \ - 1.1\ - \ - \ - 1.2\ - \ - \ - \ - \ - 2 2\ - \ - \ - 2 3\ - \ - \ - 2 4\ - \ - \ - 2 5\ - \ - \ - \ - \ - 3 1\ - \ - \ - 3 2\ - \ - \ - 3 3\ - \ - \ -
"; - QCOMPARE(transformXml(xml), QString("\ - +--------+------------+\n\ - |Header 1|Header 2 |\n\ - +--------+------------+\n\ - |1.1 |1.2 |\n\ - +--------+------------+\n\ - |2 2 2 3 2 4 2 5|\n\ - +--------+------------+\n\ - |3 1 |3 2 3 3 |\n\ - +--------+------------+\n\ -\n")); -} - - -QTEST_APPLESS_MAIN( SphinxTableTest ) - -#include "sphinxtabletest.moc" diff --git a/tests/sphinxtabletest.h b/tests/sphinxtabletest.h deleted file mode 100644 index 4779b75cd..000000000 --- a/tests/sphinxtabletest.h +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef SPHINXTABLETEST_H -#define SPHINXTABLETEST_H - -#include - -class QtDocGenerator; -class SphinxTableTest : public QObject { - Q_OBJECT - -private slots: - void setUp(); - void tearDown(); - void testEmptyString(); - void testSimpleTable(); - void testRowSpan(); - void testColSpan(); - void testComplexTable(); - void testRowSpan2(); - void testBrokenTable(); -private: - QtDocGenerator* m_generator; - - QString transformXml(const char* xml); -}; - -#endif diff --git a/tests/test_generator/CMakeLists.txt b/tests/test_generator/CMakeLists.txt deleted file mode 100644 index 5f5099897..000000000 --- a/tests/test_generator/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ -project(test_generator) - -set(dummy_generator_SRC dummygenerator.cpp) -add_library(dummy_generator SHARED ${dummy_generator_SRC}) -target_link_libraries(dummy_generator ${APIEXTRACTOR_LIBRARY} ${QT_QTCORE_LIBRARY} genrunner) -set_property(TARGET dummy_generator PROPERTY PREFIX "") - -add_executable(dummygenerator main.cpp) -set(DUMMYGENERATOR_EXECUTABLE dummygenerator${generator_SUFFIX}) -set_target_properties(dummygenerator PROPERTIES OUTPUT_NAME ${DUMMYGENERATOR_EXECUTABLE}) -target_link_libraries(dummygenerator ${Qt5Core_LIBRARIES}) - -configure_file(dummygentestconfig.h.in "${CMAKE_CURRENT_BINARY_DIR}/dummygentestconfig.h" @ONLY) - -get_filename_component(APIEXTRACTOR_LIBRARY_DIRS ${APIEXTRACTOR_LIBRARY} PATH) -if(WIN32) - set(PATH_SEP ";") - find_program(APIEXTRACTOR_BINARY apiextractor.dll HINTS ${APIEXTRACTOR_LIBRARY_DIRS}) - get_filename_component(APIEXTRACTOR_BINARY_DIR ${APIEXTRACTOR_BINARY} PATH) - set(APIEXTRACTOR_LIBRARY_DIRS "${APIEXTRACTOR_LIBRARY_DIRS}${PATH_SEP}${APIEXTRACTOR_BINARY_DIR}") -else() - set(PATH_SEP ":") -endif() - -set(ENV_PATH "${generatorrunner_BINARY_DIR}${PATH_SEP}${CMAKE_CURRENT_BINARY_DIR}${PATH_SEP}$ENV{PATH}${PATH_SEP}${APIEXTRACTOR_LIBRARY_DIRS}") -set(ENV_QT_PLUGIN_PATH "${CMAKE_CURRENT_BINARY_DIR}${PATH_SEP}$ENV{QT_PLUGIN_PATH}") -if(WIN32) - string(REPLACE "\\;" ";" ENV_PATH "${ENV_PATH}") - string(REPLACE ";" "\\;" ENV_PATH "${ENV_PATH}") - string(REPLACE "\\;" ";" ENV_QT_PLUGIN_PATH "${ENV_QT_PLUGIN_PATH}") - string(REPLACE ";" "\\;" ENV_QT_PLUGIN_PATH "${ENV_QT_PLUGIN_PATH}") -endif() - -macro(m_add_test testname) - if(CMAKE_VERSION VERSION_LESS 2.8) - add_test(${testname} ${CMAKE_COMMAND} -DTEST=${testname} - -DWORKDIR=${CMAKE_CURRENT_BINARY_DIR} - -DENV_PATH=${ENV_PATH} -DENV_QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH} - -P ${CMAKE_CURRENT_SOURCE_DIR}/run_test.cmake) - else() - add_test(${testname} ${testname}) - set_property(TEST ${testname} PROPERTY ENVIRONMENT "PATH=${ENV_PATH}" "QT_PLUGIN_PATH=${ENV_QT_PLUGIN_PATH}") - endif() -endmacro() - -macro(declare_test testname) - qt4_automoc("${testname}.cpp") - add_executable(${testname} "${testname}.cpp") - include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) - target_link_libraries(${testname} - ${QT_QTTEST_LIBRARY} - ${QT_QTCORE_LIBRARY} - ${Qt5Test_LIBRARIES} - ${Qt5Core_LIBRARIES} - ) - m_add_test(${testname}) -endmacro(declare_test testname) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/test_global.h" - "${CMAKE_CURRENT_BINARY_DIR}/test_global.h" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/test_typesystem.xml" - "${CMAKE_CURRENT_BINARY_DIR}/test_typesystem.xml" COPYONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/dummygentest-project.txt.in" - "${CMAKE_CURRENT_BINARY_DIR}/dummygentest-project.txt" @ONLY) -declare_test(dummygentest) - -add_dependencies(dummygenerator generatorrunner) - diff --git a/tests/test_generator/dummygenerator.cpp b/tests/test_generator/dummygenerator.cpp deleted file mode 100644 index 40d9fb771..000000000 --- a/tests/test_generator/dummygenerator.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include -#include "dummygenerator.h" - -EXPORT_GENERATOR_PLUGIN(new DummyGenerator) - -using namespace std; - -QString -DummyGenerator::fileNameForClass(const AbstractMetaClass* metaClass) const -{ - return QString("%1_generated.txt").arg(metaClass->name().toLower()); -} - -void -DummyGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass) -{ - s << "// Generated code for class: " << qPrintable(metaClass->name()) << endl; -} - -bool -DummyGenerator::doSetup(const QMap& args) -{ - if (args.contains("dump-arguments") && !args["dump-arguments"].isEmpty()) { - QFile logFile(args["dump-arguments"]); - logFile.open(QIODevice::WriteOnly | QIODevice::Text); - QTextStream out(&logFile); - for (QMap::const_iterator it = args.cbegin(), end = args.cend(); it != end; ++it) { - const QString& key = it.key(); - if (key == "arg-1") - out << "header-file"; - else if (key == "arg-2") - out << "typesystem-file"; - else - out << key; - if (!args[key].isEmpty()) - out << " = " << args[key]; - out << endl; - } - } - return true; -} - diff --git a/tests/test_generator/dummygenerator.h b/tests/test_generator/dummygenerator.h deleted file mode 100644 index 5ab95a925..000000000 --- a/tests/test_generator/dummygenerator.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef DUMMYGENERATOR_H -#define DUMMYGENERATOR_H - -#include "generator.h" - -class GENRUNNER_API DummyGenerator : public Generator -{ -public: - DummyGenerator() {} - ~DummyGenerator() {} - bool doSetup(const QMap& args); - const char* name() const { return "DummyGenerator"; } - -protected: - void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {} - void writeArgumentNames(QTextStream&, const AbstractMetaFunction*, Options) const {} - QString fileNameForClass(const AbstractMetaClass* metaClass) const; - void generateClass(QTextStream& s, const AbstractMetaClass* metaClass); - void finishGeneration() {} -}; - -#endif // DUMMYGENERATOR_H diff --git a/tests/test_generator/dummygentest-project.txt.in b/tests/test_generator/dummygentest-project.txt.in deleted file mode 100644 index 0a076d8bd..000000000 --- a/tests/test_generator/dummygentest-project.txt.in +++ /dev/null @@ -1,20 +0,0 @@ -[generator-project] - -generator-set = dummy -header-file = @CMAKE_CURRENT_BINARY_DIR@/test_global.h -typesystem-file = @CMAKE_CURRENT_BINARY_DIR@/test_typesystem.xml -output-directory = /tmp/output - -dump-arguments = @CMAKE_CURRENT_BINARY_DIR@/dummygen-args.log - -include-path = /include/path/location1 -include-path = /include/path/location2 - -typesystem-path = /typesystem/path/location1 -typesystem-path = /typesystem/path/location2 - -api-version = 1.2.3 -debug = sparse - -no-suppress-warnings - diff --git a/tests/test_generator/dummygentest.cpp b/tests/test_generator/dummygentest.cpp deleted file mode 100644 index ae028e2c8..000000000 --- a/tests/test_generator/dummygentest.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "dummygentest.h" -#include "dummygenerator.h" -#include "dummygentestconfig.h" -#include -#include -#include - -#define GENERATED_CONTENTS "// Generated code for class: Dummy" - -void DummyGenTest::initTestCase() -{ - int argc = 0; - char* argv[] = {NULL}; - QCoreApplication app(argc, argv); - workDir = QDir::currentPath(); - - headerFilePath = workDir + "/test_global.h"; - typesystemFilePath = workDir + "/test_typesystem.xml"; - projectFilePath = workDir + "/dummygentest-project.txt"; - generatedFilePath = QString("%1/dummy/dummy_generated.txt").arg(QDir::tempPath()); -} - -void DummyGenTest::testCallGenRunnerWithFullPathToDummyGenModule() -{ - QStringList args; - args.append("--generator-set=" DUMMYGENERATOR_BINARY_DIR "/dummy_generator" MODULE_EXTENSION); - args.append(QString("--output-directory=%1").arg(QDir::tempPath())); - args.append(headerFilePath); - args.append(typesystemFilePath); - int result = QProcess::execute("generatorrunner", args); - QCOMPARE(result, 0); - - QFile generatedFile(generatedFilePath); - generatedFile.open(QIODevice::ReadOnly); - QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); - generatedFile.close(); - - QVERIFY(generatedFile.remove()); -} - -void DummyGenTest::testCallGenRunnerWithNameOfDummyGenModule() -{ - QStringList args; - args.append("--generator-set=dummy"); - args.append(QString("--output-directory=%1").arg(QDir::tempPath())); - args.append(headerFilePath); - args.append(typesystemFilePath); - int result = QProcess::execute("generatorrunner", args); - QCOMPARE(result, 0); - - QFile generatedFile(generatedFilePath); - generatedFile.open(QIODevice::ReadOnly); - QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); - generatedFile.close(); - - QVERIFY(generatedFile.remove()); -} - -void DummyGenTest::testCallDummyGeneratorExecutable() -{ - QStringList args; - args.append(QString("--output-directory=%1").arg(QDir::tempPath())); - args.append(headerFilePath); - args.append(typesystemFilePath); - int result = QProcess::execute(DUMMYGENERATOR_BINARY, args); - QCOMPARE(result, 0); - - QFile generatedFile(generatedFilePath); - generatedFile.open(QIODevice::ReadOnly); - QCOMPARE(generatedFile.readAll().trimmed(), QByteArray(GENERATED_CONTENTS).trimmed()); - generatedFile.close(); - - QVERIFY(generatedFile.remove()); -} - -void DummyGenTest::testProjectFileArgumentsReading() -{ - QStringList args(QString("--project-file=%1/dummygentest-project.txt").arg(workDir)); - int result = QProcess::execute("generatorrunner", args); - QCOMPARE(result, 0); - - QFile logFile(workDir + "/dummygen-args.log"); - logFile.open(QIODevice::ReadOnly); - QStringList logContents; - while (!logFile.atEnd()) - logContents << logFile.readLine().trimmed(); - logContents.sort(); - QCOMPARE(logContents[0], QString("api-version = 1.2.3")); - QCOMPARE(logContents[1], QString("debug = sparse")); - QVERIFY(logContents[2].startsWith("dump-arguments = ")); - QVERIFY(logContents[2].endsWith("dummygen-args.log")); - QCOMPARE(logContents[3], QString("generator-set = dummy")); - QVERIFY(logContents[4].startsWith("header-file = ")); - QVERIFY(logContents[4].endsWith("test_global.h")); - QCOMPARE(logContents[5], - QDir::toNativeSeparators(QString("include-paths = /include/path/location1%1/include/path/location2").arg(PATH_SPLITTER))); - QCOMPARE(logContents[6], QString("no-suppress-warnings")); - QCOMPARE(logContents[7], QString("output-directory = /tmp/output")); - QVERIFY(logContents[8].startsWith("project-file = ")); - QVERIFY(logContents[8].endsWith("dummygentest-project.txt")); - QVERIFY(logContents[9].startsWith("typesystem-file = ")); - QVERIFY(logContents[9].endsWith("test_typesystem.xml")); - QCOMPARE(logContents[10], - QDir::toNativeSeparators(QString("typesystem-paths = /typesystem/path/location1%1/typesystem/path/location2").arg(PATH_SPLITTER))); -} - -QTEST_APPLESS_MAIN(DummyGenTest) - -#include "dummygentest.moc" - diff --git a/tests/test_generator/dummygentest.h b/tests/test_generator/dummygentest.h deleted file mode 100644 index be8ca42af..000000000 --- a/tests/test_generator/dummygentest.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef DUMMYGENTABLETEST_H -#define DUMMYGENTABLETEST_H - -#include - -class DummyGenerator; - -class DummyGenTest : public QObject -{ - Q_OBJECT - -private: - QString workDir; - QString headerFilePath; - QString typesystemFilePath; - QString generatedFilePath; - QString projectFilePath; - -private slots: - void initTestCase(); - void testCallGenRunnerWithFullPathToDummyGenModule(); - void testCallGenRunnerWithNameOfDummyGenModule(); - void testCallDummyGeneratorExecutable(); - void testProjectFileArgumentsReading(); -}; - -#endif - diff --git a/tests/test_generator/dummygentestconfig.h.in b/tests/test_generator/dummygentestconfig.h.in deleted file mode 100644 index 9da17dcd3..000000000 --- a/tests/test_generator/dummygentestconfig.h.in +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DUMMYGENTESTCONFIG_H -#define DUMMYGENTESTCONFIG_H - -#define MODULE_EXTENSION "@CMAKE_SHARED_LIBRARY_SUFFIX@" -#define DUMMYGENERATOR_BINARY "@DUMMYGENERATOR_EXECUTABLE@" -#define DUMMYGENERATOR_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@" - -#ifdef _WINDOWS - #define PATH_SPLITTER ";" -#else - #define PATH_SPLITTER ":" -#endif - -#endif // DUMMYGENTESTCONFIG_H - diff --git a/tests/test_generator/main.cpp b/tests/test_generator/main.cpp deleted file mode 100644 index 5c46ea006..000000000 --- a/tests/test_generator/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of PySide2. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -int main(int argc, char *argv[]) -{ - QStringList args; - args.append("--generator-set=dummy"); - for (int i = 1; i < argc; i++) - args.append(argv[i]); - return QProcess::execute("generatorrunner", args); -} - diff --git a/tests/test_generator/run_test.cmake b/tests/test_generator/run_test.cmake deleted file mode 100644 index 34a821d80..000000000 --- a/tests/test_generator/run_test.cmake +++ /dev/null @@ -1,11 +0,0 @@ -# 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. - -set(ENV{PATH} "${ENV_PATH}") -set(ENV{QT_PLUGIN_PATH} "${ENV_QT_PLUGIN_PATH}") -execute_process(COMMAND ${TEST} WORKING_DIRECTORY "${WORKDIR}" RESULT_VARIABLE OK) - -if(NOT OK EQUAL 0) - message(SEND_ERROR "${TEST} failed!") -endif() diff --git a/tests/test_generator/test_global.h b/tests/test_generator/test_global.h deleted file mode 100644 index 6a95200cf..000000000 --- a/tests/test_generator/test_global.h +++ /dev/null @@ -1 +0,0 @@ -struct Dummy {}; diff --git a/tests/test_generator/test_typesystem.xml b/tests/test_generator/test_typesystem.xml deleted file mode 100644 index c19a4e95e..000000000 --- a/tests/test_generator/test_typesystem.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - -- cgit v1.2.3