aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken2/.gitattributes2
-rw-r--r--sources/shiboken2/.gitignore8
-rw-r--r--sources/shiboken2/AUTHORS12
-rw-r--r--sources/shiboken2/ApiExtractor/AUTHORS8
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt102
-rw-r--r--sources/shiboken2/ApiExtractor/COPYING342
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp3381
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h106
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h194
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp2786
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h1983
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h49
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp356
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.h109
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractormacros.h41
-rw-r--r--sources/shiboken2/ApiExtractor/asttoxml.cpp160
-rw-r--r--sources/shiboken2/ApiExtractor/asttoxml.h46
-rw-r--r--sources/shiboken2/ApiExtractor/cmake_uninstall.cmake21
-rw-r--r--sources/shiboken2/ApiExtractor/dependency.h43
-rw-r--r--sources/shiboken2/ApiExtractor/doc/CMakeLists.txt10
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_templates/index.html27
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_templates/layout.html41
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/searchbox.html12
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.pngbin0 -> 36012 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpgbin0 -> 14237 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.pngbin0 -> 101 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpgbin0 -> 3138 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.pngbin0 -> 4702 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpgbin0 -> 2660 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.pngbin0 -> 4618 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidedocs.css409
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.pngbin0 -> 12969 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.pngbin0 -> 130 bytes
-rw-r--r--sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/theme.conf7
-rw-r--r--sources/shiboken2/ApiExtractor/doc/conf.py.in163
-rw-r--r--sources/shiboken2/ApiExtractor/doc/contents.rst9
-rw-r--r--sources/shiboken2/ApiExtractor/doc/dependency-apiextractor.svg360
-rw-r--r--sources/shiboken2/ApiExtractor/doc/overview.rst15
-rw-r--r--sources/shiboken2/ApiExtractor/doc/ownership.rst85
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem.rst29
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_arguments.rst192
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_conversionrule.rst113
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_documentation.rst43
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_manipulating_objects.rst132
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_modify_function.rst78
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_solving_compilation.rst70
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst371
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_templates.rst55
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.cpp174
-rw-r--r--sources/shiboken2/ApiExtractor/docparser.h127
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.cpp198
-rw-r--r--sources/shiboken2/ApiExtractor/doxygenparser.h43
-rw-r--r--sources/shiboken2/ApiExtractor/fileout.cpp231
-rw-r--r--sources/shiboken2/ApiExtractor/fileout.h62
-rw-r--r--sources/shiboken2/ApiExtractor/generator.qrc5
-rw-r--r--sources/shiboken2/ApiExtractor/graph.cpp135
-rw-r--r--sources/shiboken2/ApiExtractor/graph.h72
-rw-r--r--sources/shiboken2/ApiExtractor/icecc.cmake11
-rw-r--r--sources/shiboken2/ApiExtractor/include.cpp71
-rw-r--r--sources/shiboken2/ApiExtractor/include.h92
-rw-r--r--sources/shiboken2/ApiExtractor/merge.xsl82
-rw-r--r--sources/shiboken2/ApiExtractor/parser/ast.cpp38
-rw-r--r--sources/shiboken2/ApiExtractor/parser/ast.h884
-rw-r--r--sources/shiboken2/ApiExtractor/parser/binder.cpp866
-rw-r--r--sources/shiboken2/ApiExtractor/parser/binder.h133
-rw-r--r--sources/shiboken2/ApiExtractor/parser/class_compiler.cpp71
-rw-r--r--sources/shiboken2/ApiExtractor/parser/class_compiler.h77
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp1199
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h691
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_enums.h38
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp103
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_finder.h75
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h82
-rw-r--r--sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp55
-rw-r--r--sources/shiboken2/ApiExtractor/parser/compiler_utils.h50
-rw-r--r--sources/shiboken2/ApiExtractor/parser/control.cpp135
-rw-r--r--sources/shiboken2/ApiExtractor/parser/control.h165
-rw-r--r--sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp167
-rw-r--r--sources/shiboken2/ApiExtractor/parser/declarator_compiler.h101
-rw-r--r--sources/shiboken2/ApiExtractor/parser/default_visitor.cpp464
-rw-r--r--sources/shiboken2/ApiExtractor/parser/default_visitor.h123
-rw-r--r--sources/shiboken2/ApiExtractor/parser/dumptree.cpp131
-rw-r--r--sources/shiboken2/ApiExtractor/parser/dumptree.h51
-rw-r--r--sources/shiboken2/ApiExtractor/parser/lexer.cpp1726
-rw-r--r--sources/shiboken2/ApiExtractor/parser/lexer.h295
-rw-r--r--sources/shiboken2/ApiExtractor/parser/list.cpp33
-rw-r--r--sources/shiboken2/ApiExtractor/parser/list.h105
-rw-r--r--sources/shiboken2/ApiExtractor/parser/name_compiler.cpp139
-rw-r--r--sources/shiboken2/ApiExtractor/parser/name_compiler.h74
-rw-r--r--sources/shiboken2/ApiExtractor/parser/parser.cpp4075
-rw-r--r--sources/shiboken2/ApiExtractor/parser/parser.h204
-rw-r--r--sources/shiboken2/ApiExtractor/parser/r++.macros28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp-allocator.h29
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h62
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration86
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h1300
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h288
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h144
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h44
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h122
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h99
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h356
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h77
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration24
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h318
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h112
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h97
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/pp.h96
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp164
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h70
-rw-r--r--sources/shiboken2/ApiExtractor/parser/rxx_allocator.h146
-rw-r--r--sources/shiboken2/ApiExtractor/parser/smallobject.cpp33
-rw-r--r--sources/shiboken2/ApiExtractor/parser/smallobject.h58
-rw-r--r--sources/shiboken2/ApiExtractor/parser/symbol.h127
-rw-r--r--sources/shiboken2/ApiExtractor/parser/tokens.cpp256
-rw-r--r--sources/shiboken2/ApiExtractor/parser/tokens.h152
-rw-r--r--sources/shiboken2/ApiExtractor/parser/type_compiler.cpp134
-rw-r--r--sources/shiboken2/ApiExtractor/parser/type_compiler.h76
-rw-r--r--sources/shiboken2/ApiExtractor/parser/visitor.cpp127
-rw-r--r--sources/shiboken2/ApiExtractor/parser/visitor.h145
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.cpp188
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.h44
-rw-r--r--sources/shiboken2/ApiExtractor/reporthandler.cpp149
-rw-r--r--sources/shiboken2/ApiExtractor/reporthandler.h71
-rw-r--r--sources/shiboken2/ApiExtractor/symbols.filter7
-rw-r--r--sources/shiboken2/ApiExtractor/tests/CMakeLists.txt73
-rw-r--r--sources/shiboken2/ApiExtractor/tests/a.xml13
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp527
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.h55
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.cpp216
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testabstractmetatype.h47
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testaddfunction.cpp453
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testaddfunction.h54
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp129
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testcodeinjection.cpp106
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testcodeinjection.h45
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testcontainer.cpp105
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testcontainer.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testconversionoperator.cpp188
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testconversionoperator.h44
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testconversionruletag.cpp250
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testconversionruletag.h43
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testctorinformation.cpp76
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testctorinformation.h44
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testdroptypeentries.cpp145
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testdroptypeentries.h44
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testdtorinformation.cpp86
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testdtorinformation.h46
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testenum.cpp416
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testenum.h47
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testextrainclude.cpp85
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testextrainclude.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testfunctiontag.cpp97
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testfunctiontag.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testimplicitconversions.cpp163
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testimplicitconversions.h46
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testinserttemplate.cpp130
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testinserttemplate.h44
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.cpp80
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifydocumentation.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp249
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h45
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp74
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.h43
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnamespace.cpp96
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnamespace.h44
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnestedtypes.cpp128
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnestedtypes.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.cpp119
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testnumericaltypedef.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.cpp60
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testprimitivetypetag.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testrefcounttag.cpp100
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testrefcounttag.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreferencetopointer.cpp59
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreferencetopointer.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremovefield.cpp62
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremovefield.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremoveimplconv.cpp69
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremoveimplconv.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp116
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testresolvetype.cpp64
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testresolvetype.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreverseoperators.cpp138
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreverseoperators.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.cpp438
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.h51
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtoposort.cpp69
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtoposort.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtyperevision.cpp71
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtyperevision.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testutil.h66
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.cpp64
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testvaluetypedefaultctortag.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testvoidarg.cpp87
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testvoidarg.h42
-rw-r--r--sources/shiboken2/ApiExtractor/tests/utf8code.txt1
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.cpp699
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h179
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.cpp318
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.h59
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp2667
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h1947
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_enums.h86
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_p.h176
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem_typedefs.h58
-rw-r--r--sources/shiboken2/CMakeLists.txt244
-rw-r--r--sources/shiboken2/COPYING342
-rw-r--r--sources/shiboken2/COPYING.libsample501
-rw-r--r--sources/shiboken2/COPYING.libshiboken501
-rw-r--r--sources/shiboken2/Doxyfile311
-rw-r--r--sources/shiboken2/LICENSE.GPLv3686
-rw-r--r--sources/shiboken2/LICENSE.LGPLv21514
-rw-r--r--sources/shiboken2/LICENSE.LGPLv3175
-rw-r--r--sources/shiboken2/LICENSE.PREVIEW.COMMERCIAL630
-rw-r--r--sources/shiboken2/README.md19
-rw-r--r--sources/shiboken2/cmake_uninstall.cmake21
-rw-r--r--sources/shiboken2/data/CMakeLists.txt28
-rw-r--r--sources/shiboken2/data/GeneratorRunnerConfig.cmake.in17
-rw-r--r--sources/shiboken2/data/GeneratorRunnerConfigVersion.cmake.in10
-rw-r--r--sources/shiboken2/data/Shiboken2Config-spec.cmake.in29
-rw-r--r--sources/shiboken2/data/Shiboken2Config.cmake.in5
-rw-r--r--sources/shiboken2/data/Shiboken2ConfigVersion.cmake.in10
l---------sources/shiboken2/data/docgenerator.11
-rw-r--r--sources/shiboken2/data/generatorrunner.176
-rw-r--r--sources/shiboken2/data/generatorrunner.pc.in13
-rw-r--r--sources/shiboken2/data/shiboken2.pc.in13
-rw-r--r--sources/shiboken2/doc/CMakeLists.txt24
-rw-r--r--sources/shiboken2/doc/_templates/index.html35
-rw-r--r--sources/shiboken2/doc/_templates/layout.html29
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/searchbox.html12
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.pngbin0 -> 36012 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpgbin0 -> 14237 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.pngbin0 -> 101 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpgbin0 -> 2660 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.pngbin0 -> 1032 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/pysidedocs.css475
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.pngbin0 -> 12969 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.pngbin0 -> 130 bytes
-rw-r--r--sources/shiboken2/doc/_themes/pysidedocs/theme.conf7
-rw-r--r--sources/shiboken2/doc/codeinjectionsemantics.rst397
-rw-r--r--sources/shiboken2/doc/commandlineoptions.rst105
-rw-r--r--sources/shiboken2/doc/conf.py.in166
-rw-r--r--sources/shiboken2/doc/contents.rst17
-rw-r--r--sources/shiboken2/doc/dependency-pyqtb.svg600
-rw-r--r--sources/shiboken2/doc/dependency-pyside.svg527
-rw-r--r--sources/shiboken2/doc/faq.rst67
-rw-r--r--sources/shiboken2/doc/images/.directory3
-rw-r--r--sources/shiboken2/doc/images/bindinggen-development.pngbin0 -> 34333 bytes
-rw-r--r--sources/shiboken2/doc/images/bindinggen-development.svg543
-rw-r--r--sources/shiboken2/doc/images/boostgen.pngbin0 -> 153473 bytes
-rw-r--r--sources/shiboken2/doc/images/boostqtarch.pngbin0 -> 34257 bytes
-rw-r--r--sources/shiboken2/doc/images/boostqtarch.svg226
-rw-r--r--sources/shiboken2/doc/images/converter.dot14
-rw-r--r--sources/shiboken2/doc/images/converter.pngbin0 -> 37485 bytes
-rw-r--r--sources/shiboken2/doc/images/genrunnerarch.pngbin0 -> 68761 bytes
-rw-r--r--sources/shiboken2/doc/images/genrunnerarch.svg654
-rw-r--r--sources/shiboken2/doc/overview.rst46
-rw-r--r--sources/shiboken2/doc/ownership.rst153
-rw-r--r--sources/shiboken2/doc/projectfile.rst65
-rw-r--r--sources/shiboken2/doc/sequenceprotocol.rst23
-rw-r--r--sources/shiboken2/doc/shiboken2.173
-rw-r--r--sources/shiboken2/doc/shibokenmodule.rst79
-rw-r--r--sources/shiboken2/doc/typeconverters.rst288
-rw-r--r--sources/shiboken2/doc/typesystemvariables.rst336
-rw-r--r--sources/shiboken2/doc/wordsofadvice.rst109
-rw-r--r--sources/shiboken2/ext/sparsehash/AUTHORS2
-rw-r--r--sources/shiboken2/ext/sparsehash/COPYING28
-rw-r--r--sources/shiboken2/ext/sparsehash/google/dense_hash_map310
-rw-r--r--sources/shiboken2/ext/sparsehash/google/dense_hash_set287
-rw-r--r--sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h1062
-rw-r--r--sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h45
-rw-r--r--sources/shiboken2/ext/sparsehash/google/type_traits.h250
-rw-r--r--sources/shiboken2/generator/CMakeLists.txt40
-rw-r--r--sources/shiboken2/generator/generator.cpp854
-rw-r--r--sources/shiboken2/generator/generator.h447
-rw-r--r--sources/shiboken2/generator/main.cpp529
-rw-r--r--sources/shiboken2/generator/qtdoc/CMakeLists.txt21
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp1704
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.h235
-rw-r--r--sources/shiboken2/generator/shiboken2/CMakeLists.txt28
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp5689
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h370
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp558
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.h67
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.cpp1079
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.h161
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp2674
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h554
-rw-r--r--sources/shiboken2/generator/shibokenconfig.h.in6
-rw-r--r--sources/shiboken2/generatorrunnerconfig.h.in13
-rw-r--r--sources/shiboken2/generatorrunnermacros.h48
-rw-r--r--sources/shiboken2/generators/shiboken/shiboken.cpp32
-rw-r--r--sources/shiboken2/header.COMM20
-rw-r--r--sources/shiboken2/header.LGPL-ONLY22
-rw-r--r--sources/shiboken2/header.LGPL2133
-rw-r--r--sources/shiboken2/header.LGPL336
-rw-r--r--sources/shiboken2/header.LGPL3-COMM28
-rw-r--r--sources/shiboken2/icecc.cmake11
-rw-r--r--sources/shiboken2/libshiboken/CMakeLists.txt77
-rw-r--r--sources/shiboken2/libshiboken/autodecref.h115
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp1518
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h451
-rw-r--r--sources/shiboken2/libshiboken/basewrapper_p.h287
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp344
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.h109
-rw-r--r--sources/shiboken2/libshiboken/conversions.h731
-rw-r--r--sources/shiboken2/libshiboken/debugfreehook.cpp194
-rw-r--r--sources/shiboken2/libshiboken/debugfreehook.h61
-rw-r--r--sources/shiboken2/libshiboken/gilstate.cpp68
-rw-r--r--sources/shiboken2/libshiboken/gilstate.h63
-rw-r--r--sources/shiboken2/libshiboken/helper.cpp142
-rw-r--r--sources/shiboken2/libshiboken/helper.h136
-rw-r--r--sources/shiboken2/libshiboken/python25compat.h104
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.cpp572
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter.h367
-rw-r--r--sources/shiboken2/libshiboken/sbkconverter_p.h574
-rw-r--r--sources/shiboken2/libshiboken/sbkdbg.h124
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp623
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h118
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.cpp124
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.h115
-rw-r--r--sources/shiboken2/libshiboken/sbkpython.h74
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.cpp202
-rw-r--r--sources/shiboken2/libshiboken/sbkstring.h75
-rw-r--r--sources/shiboken2/libshiboken/sbkversion.h.in50
-rw-r--r--sources/shiboken2/libshiboken/shiboken.h60
-rw-r--r--sources/shiboken2/libshiboken/shibokenbuffer.cpp96
-rw-r--r--sources/shiboken2/libshiboken/shibokenbuffer.h85
-rw-r--r--sources/shiboken2/libshiboken/shibokenmacros.h63
-rw-r--r--sources/shiboken2/libshiboken/threadstatesaver.cpp69
-rw-r--r--sources/shiboken2/libshiboken/threadstatesaver.h66
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.cpp213
-rw-r--r--sources/shiboken2/libshiboken/tmp-referencetopython/sbkconverter.h191
-rw-r--r--sources/shiboken2/libshiboken/typeresolver.cpp162
-rw-r--r--sources/shiboken2/libshiboken/typeresolver.h139
-rw-r--r--sources/shiboken2/shibokenmodule/CMakeLists.txt40
-rw-r--r--sources/shiboken2/shibokenmodule/nothing.h0
-rw-r--r--sources/shiboken2/shibokenmodule/shibokenmodule.txt.in16
-rw-r--r--sources/shiboken2/shibokenmodule/typesystem_shiboken.xml120
-rw-r--r--sources/shiboken2/tests/CMakeLists.txt102
-rw-r--r--sources/shiboken2/tests/dumpcodemodel/CMakeLists.txt5
-rw-r--r--sources/shiboken2/tests/dumpcodemodel/main.cpp83
-rw-r--r--sources/shiboken2/tests/libminimal/CMakeLists.txt13
-rw-r--r--sources/shiboken2/tests/libminimal/libminimalmacros.h46
-rw-r--r--sources/shiboken2/tests/libminimal/listuser.cpp124
-rw-r--r--sources/shiboken2/tests/libminimal/listuser.h75
-rw-r--r--sources/shiboken2/tests/libminimal/minbool.h68
-rw-r--r--sources/shiboken2/tests/libminimal/obj.cpp44
-rw-r--r--sources/shiboken2/tests/libminimal/obj.h59
-rw-r--r--sources/shiboken2/tests/libminimal/typedef.cpp75
-rw-r--r--sources/shiboken2/tests/libminimal/typedef.h54
-rw-r--r--sources/shiboken2/tests/libminimal/val.h59
-rw-r--r--sources/shiboken2/tests/libother/CMakeLists.txt18
-rw-r--r--sources/shiboken2/tests/libother/extendsnoimplicitconversion.h45
-rw-r--r--sources/shiboken2/tests/libother/libothermacros.h46
-rw-r--r--sources/shiboken2/tests/libother/number.cpp59
-rw-r--r--sources/shiboken2/tests/libother/number.h57
-rw-r--r--sources/shiboken2/tests/libother/otherderived.cpp61
-rw-r--r--sources/shiboken2/tests/libother/otherderived.h65
-rw-r--r--sources/shiboken2/tests/libother/othermultiplederived.cpp50
-rw-r--r--sources/shiboken2/tests/libother/othermultiplederived.h46
-rw-r--r--sources/shiboken2/tests/libother/otherobjecttype.cpp36
-rw-r--r--sources/shiboken2/tests/libother/otherobjecttype.h49
-rw-r--r--sources/shiboken2/tests/libsample/CMakeLists.txt57
-rw-r--r--sources/shiboken2/tests/libsample/abstract.cpp97
-rw-r--r--sources/shiboken2/tests/libsample/abstract.h107
-rw-r--r--sources/shiboken2/tests/libsample/blackbox.cpp131
-rw-r--r--sources/shiboken2/tests/libsample/blackbox.h67
-rw-r--r--sources/shiboken2/tests/libsample/bucket.cpp86
-rw-r--r--sources/shiboken2/tests/libsample/bucket.h59
-rw-r--r--sources/shiboken2/tests/libsample/bytearray.cpp214
-rw-r--r--sources/shiboken2/tests/libsample/bytearray.h89
-rw-r--r--sources/shiboken2/tests/libsample/collector.cpp62
-rw-r--r--sources/shiboken2/tests/libsample/collector.h71
-rw-r--r--sources/shiboken2/tests/libsample/complex.cpp54
-rw-r--r--sources/shiboken2/tests/libsample/complex.h55
-rw-r--r--sources/shiboken2/tests/libsample/ctorconvrule.h45
-rw-r--r--sources/shiboken2/tests/libsample/cvlist.h53
-rw-r--r--sources/shiboken2/tests/libsample/derived.cpp119
-rw-r--r--sources/shiboken2/tests/libsample/derived.h92
-rw-r--r--sources/shiboken2/tests/libsample/echo.cpp29
-rw-r--r--sources/shiboken2/tests/libsample/echo.h55
-rw-r--r--sources/shiboken2/tests/libsample/expression.cpp137
-rw-r--r--sources/shiboken2/tests/libsample/expression.h64
-rw-r--r--sources/shiboken2/tests/libsample/filter.cpp73
-rw-r--r--sources/shiboken2/tests/libsample/filter.h99
-rw-r--r--sources/shiboken2/tests/libsample/functions.cpp214
-rw-r--r--sources/shiboken2/tests/libsample/functions.h93
-rw-r--r--sources/shiboken2/tests/libsample/handle.cpp44
-rw-r--r--sources/shiboken2/tests/libsample/handle.h72
-rw-r--r--sources/shiboken2/tests/libsample/implicitconv.cpp66
-rw-r--r--sources/shiboken2/tests/libsample/implicitconv.h83
-rw-r--r--sources/shiboken2/tests/libsample/injectcode.cpp108
-rw-r--r--sources/shiboken2/tests/libsample/injectcode.h65
-rw-r--r--sources/shiboken2/tests/libsample/libsamplemacros.h46
-rw-r--r--sources/shiboken2/tests/libsample/list.h106
-rw-r--r--sources/shiboken2/tests/libsample/listuser.cpp91
-rw-r--r--sources/shiboken2/tests/libsample/listuser.h74
-rw-r--r--sources/shiboken2/tests/libsample/main.cpp244
-rw-r--r--sources/shiboken2/tests/libsample/mapuser.cpp69
-rw-r--r--sources/shiboken2/tests/libsample/mapuser.h65
-rw-r--r--sources/shiboken2/tests/libsample/modelindex.h72
-rw-r--r--sources/shiboken2/tests/libsample/modifications.cpp151
-rw-r--r--sources/shiboken2/tests/libsample/modifications.h142
-rw-r--r--sources/shiboken2/tests/libsample/modified_constructor.cpp42
-rw-r--r--sources/shiboken2/tests/libsample/modified_constructor.h46
-rw-r--r--sources/shiboken2/tests/libsample/multiple_derived.cpp64
-rw-r--r--sources/shiboken2/tests/libsample/multiple_derived.h195
-rw-r--r--sources/shiboken2/tests/libsample/noimplicitconversion.h49
-rw-r--r--sources/shiboken2/tests/libsample/nondefaultctor.h75
-rw-r--r--sources/shiboken2/tests/libsample/null.h44
-rw-r--r--sources/shiboken2/tests/libsample/objectmodel.cpp42
-rw-r--r--sources/shiboken2/tests/libsample/objectmodel.h58
-rw-r--r--sources/shiboken2/tests/libsample/objecttype.cpp311
-rw-r--r--sources/shiboken2/tests/libsample/objecttype.h176
-rw-r--r--sources/shiboken2/tests/libsample/objecttypebyvalue.h46
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeholder.cpp52
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeholder.h51
-rw-r--r--sources/shiboken2/tests/libsample/objecttypelayout.cpp68
-rw-r--r--sources/shiboken2/tests/libsample/objecttypelayout.h56
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeoperators.cpp63
-rw-r--r--sources/shiboken2/tests/libsample/objecttypeoperators.h61
-rw-r--r--sources/shiboken2/tests/libsample/objectview.cpp54
-rw-r--r--sources/shiboken2/tests/libsample/objectview.h58
-rw-r--r--sources/shiboken2/tests/libsample/oddbool.h83
-rw-r--r--sources/shiboken2/tests/libsample/onlycopy.cpp57
-rw-r--r--sources/shiboken2/tests/libsample/onlycopy.h59
-rw-r--r--sources/shiboken2/tests/libsample/overload.cpp50
-rw-r--r--sources/shiboken2/tests/libsample/overload.h143
-rw-r--r--sources/shiboken2/tests/libsample/overloadsort.cpp30
-rw-r--r--sources/shiboken2/tests/libsample/overloadsort.h88
-rw-r--r--sources/shiboken2/tests/libsample/pairuser.cpp57
-rw-r--r--sources/shiboken2/tests/libsample/pairuser.h55
-rw-r--r--sources/shiboken2/tests/libsample/pen.cpp67
-rw-r--r--sources/shiboken2/tests/libsample/pen.h62
-rw-r--r--sources/shiboken2/tests/libsample/photon.cpp50
-rw-r--r--sources/shiboken2/tests/libsample/photon.h140
-rw-r--r--sources/shiboken2/tests/libsample/point.cpp155
-rw-r--r--sources/shiboken2/tests/libsample/point.h99
-rw-r--r--sources/shiboken2/tests/libsample/pointerholder.h45
-rw-r--r--sources/shiboken2/tests/libsample/pointf.cpp126
-rw-r--r--sources/shiboken2/tests/libsample/pointf.h88
-rw-r--r--sources/shiboken2/tests/libsample/polygon.cpp75
-rw-r--r--sources/shiboken2/tests/libsample/polygon.h66
-rw-r--r--sources/shiboken2/tests/libsample/privatector.h55
-rw-r--r--sources/shiboken2/tests/libsample/privatedtor.h60
-rw-r--r--sources/shiboken2/tests/libsample/protected.cpp32
-rw-r--r--sources/shiboken2/tests/libsample/protected.h151
-rw-r--r--sources/shiboken2/tests/libsample/rect.h86
-rw-r--r--sources/shiboken2/tests/libsample/reference.cpp78
-rw-r--r--sources/shiboken2/tests/libsample/reference.h81
-rw-r--r--sources/shiboken2/tests/libsample/removednamespaces.h68
-rw-r--r--sources/shiboken2/tests/libsample/sample.cpp39
-rw-r--r--sources/shiboken2/tests/libsample/sample.h48
-rw-r--r--sources/shiboken2/tests/libsample/samplenamespace.cpp128
-rw-r--r--sources/shiboken2/tests/libsample/samplenamespace.h162
-rw-r--r--sources/shiboken2/tests/libsample/sbkdate.cpp48
-rw-r--r--sources/shiboken2/tests/libsample/sbkdate.h50
-rw-r--r--sources/shiboken2/tests/libsample/simplefile.cpp108
-rw-r--r--sources/shiboken2/tests/libsample/simplefile.h56
-rw-r--r--sources/shiboken2/tests/libsample/size.cpp39
-rw-r--r--sources/shiboken2/tests/libsample/size.h206
-rw-r--r--sources/shiboken2/tests/libsample/sometime.cpp99
-rw-r--r--sources/shiboken2/tests/libsample/sometime.h92
-rw-r--r--sources/shiboken2/tests/libsample/str.cpp185
-rw-r--r--sources/shiboken2/tests/libsample/str.h78
-rw-r--r--sources/shiboken2/tests/libsample/strlist.cpp57
-rw-r--r--sources/shiboken2/tests/libsample/strlist.h65
-rw-r--r--sources/shiboken2/tests/libsample/templateptr.cpp33
-rw-r--r--sources/shiboken2/tests/libsample/templateptr.h43
-rw-r--r--sources/shiboken2/tests/libsample/transform.cpp65
-rw-r--r--sources/shiboken2/tests/libsample/transform.h45
-rw-r--r--sources/shiboken2/tests/libsample/valueandvirtual.h47
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.cpp59
-rw-r--r--sources/shiboken2/tests/libsample/virtualmethods.h139
-rw-r--r--sources/shiboken2/tests/libsample/voidholder.h50
-rw-r--r--sources/shiboken2/tests/libsmart/CMakeLists.txt11
-rw-r--r--sources/shiboken2/tests/libsmart/libsmartmacros.h46
-rw-r--r--sources/shiboken2/tests/libsmart/smart.cpp174
-rw-r--r--sources/shiboken2/tests/libsmart/smart.h210
-rw-r--r--sources/shiboken2/tests/minimalbinding/CMakeLists.txt38
-rw-r--r--sources/shiboken2/tests/minimalbinding/global.h33
-rw-r--r--sources/shiboken2/tests/minimalbinding/listuser_test.py323
-rw-r--r--sources/shiboken2/tests/minimalbinding/minbool_test.py64
-rw-r--r--sources/shiboken2/tests/minimalbinding/minimal-binding.txt.in15
-rw-r--r--sources/shiboken2/tests/minimalbinding/obj_test.py114
-rw-r--r--sources/shiboken2/tests/minimalbinding/typedef_test.py116
-rw-r--r--sources/shiboken2/tests/minimalbinding/typesystem_minimal.xml93
-rw-r--r--sources/shiboken2/tests/minimalbinding/val_test.py115
-rw-r--r--sources/shiboken2/tests/otherbinding/CMakeLists.txt48
-rw-r--r--sources/shiboken2/tests/otherbinding/collector_external_operator_test.py58
-rwxr-xr-xsources/shiboken2/tests/otherbinding/conversion_operator_for_class_without_implicit_conversions_test.py73
-rwxr-xr-xsources/shiboken2/tests/otherbinding/extended_multiply_operator_test.py64
-rw-r--r--sources/shiboken2/tests/otherbinding/global.h35
-rw-r--r--sources/shiboken2/tests/otherbinding/module_reload_test.py61
-rwxr-xr-xsources/shiboken2/tests/otherbinding/new_ctor_operator_test.py56
-rw-r--r--sources/shiboken2/tests/otherbinding/objtypehashes_test.py53
-rw-r--r--sources/shiboken2/tests/otherbinding/other-binding.txt.in18
-rw-r--r--sources/shiboken2/tests/otherbinding/otherderived_test.py120
-rw-r--r--sources/shiboken2/tests/otherbinding/test_module_template.py40
-rw-r--r--sources/shiboken2/tests/otherbinding/typediscovery_test.py64
-rw-r--r--sources/shiboken2/tests/otherbinding/typesystem_other.xml15
-rwxr-xr-xsources/shiboken2/tests/otherbinding/usersprimitivefromothermodule_test.py52
-rw-r--r--sources/shiboken2/tests/otherbinding/wrongctor_test.py53
-rw-r--r--sources/shiboken2/tests/py3k.py2
-rw-r--r--sources/shiboken2/tests/py3kcompat.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/CMakeLists.txt145
-rw-r--r--sources/shiboken2/tests/samplebinding/__del___test.py50
-rw-r--r--sources/shiboken2/tests/samplebinding/abstract_test.py111
-rw-r--r--sources/shiboken2/tests/samplebinding/addedfunction_test.py62
-rw-r--r--sources/shiboken2/tests/samplebinding/addedfunction_with_container_args_test.py51
-rw-r--r--sources/shiboken2/tests/samplebinding/argumentmodifications_test.py111
-rw-r--r--sources/shiboken2/tests/samplebinding/bug_554_test.py45
-rw-r--r--sources/shiboken2/tests/samplebinding/bug_704_test.py68
-rw-r--r--sources/shiboken2/tests/samplebinding/bytearray_bufferprotocol.cpp55
-rw-r--r--sources/shiboken2/tests/samplebinding/bytearray_test.py151
-rw-r--r--sources/shiboken2/tests/samplebinding/child_return_test.py58
-rw-r--r--sources/shiboken2/tests/samplebinding/class_fields_test.py168
-rw-r--r--sources/shiboken2/tests/samplebinding/collector_test.py81
-rw-r--r--sources/shiboken2/tests/samplebinding/complex_test.py84
-rw-r--r--sources/shiboken2/tests/samplebinding/conversion_operator_test.py55
-rw-r--r--sources/shiboken2/tests/samplebinding/copy_test.py86
-rw-r--r--sources/shiboken2/tests/samplebinding/ctorconvrule_test.py49
-rw-r--r--sources/shiboken2/tests/samplebinding/cyclic_test.py109
-rw-r--r--sources/shiboken2/tests/samplebinding/date_test.py58
-rw-r--r--sources/shiboken2/tests/samplebinding/decisor_test.py65
-rw-r--r--sources/shiboken2/tests/samplebinding/delete_test.py47
-rw-r--r--sources/shiboken2/tests/samplebinding/deprecated_test.py44
-rw-r--r--sources/shiboken2/tests/samplebinding/derived_test.py153
-rw-r--r--sources/shiboken2/tests/samplebinding/duck_punching_test.py176
-rw-r--r--sources/shiboken2/tests/samplebinding/echo_test.py52
-rw-r--r--sources/shiboken2/tests/samplebinding/enum_test.py168
-rw-r--r--sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py53
-rw-r--r--sources/shiboken2/tests/samplebinding/event_loop_call_virtual_test.py70
-rw-r--r--sources/shiboken2/tests/samplebinding/event_loop_thread_test.py96
-rw-r--r--sources/shiboken2/tests/samplebinding/filter_test.py45
-rw-r--r--sources/shiboken2/tests/samplebinding/global.h90
-rw-r--r--sources/shiboken2/tests/samplebinding/handleholder_test.py57
-rw-r--r--sources/shiboken2/tests/samplebinding/hashabletype_test.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/ignorederefop_test.py38
-rw-r--r--sources/shiboken2/tests/samplebinding/implicitconv_numerical_test.py151
-rw-r--r--sources/shiboken2/tests/samplebinding/implicitconv_test.py66
-rwxr-xr-xsources/shiboken2/tests/samplebinding/inheritanceandscope_test.py48
-rw-r--r--sources/shiboken2/tests/samplebinding/injectcode_test.py132
-rw-r--r--sources/shiboken2/tests/samplebinding/innerclass_test.py42
-rw-r--r--sources/shiboken2/tests/samplebinding/intlist_test.py98
-rw-r--r--sources/shiboken2/tests/samplebinding/invalid_virtual_return_test.py65
-rw-r--r--sources/shiboken2/tests/samplebinding/keep_reference_test.py81
-rw-r--r--sources/shiboken2/tests/samplebinding/list_test.py121
-rw-r--r--sources/shiboken2/tests/samplebinding/lock_test.py95
-rw-r--r--sources/shiboken2/tests/samplebinding/map_test.py80
-rw-r--r--sources/shiboken2/tests/samplebinding/metaclass_test.py61
-rw-r--r--sources/shiboken2/tests/samplebinding/mi_virtual_methods_test.py88
-rw-r--r--sources/shiboken2/tests/samplebinding/mixed_mi_test.py76
-rw-r--r--sources/shiboken2/tests/samplebinding/modelindex_test.py53
-rw-r--r--sources/shiboken2/tests/samplebinding/modelview_test.py78
-rw-r--r--sources/shiboken2/tests/samplebinding/modifications_test.py224
-rw-r--r--sources/shiboken2/tests/samplebinding/modified_constructor_test.py49
-rw-r--r--sources/shiboken2/tests/samplebinding/modifiedvirtualmethods_test.py248
-rw-r--r--sources/shiboken2/tests/samplebinding/multi_cpp_inheritance_test.py105
-rw-r--r--sources/shiboken2/tests/samplebinding/multiple_derived_test.py221
-rw-r--r--sources/shiboken2/tests/samplebinding/namespace_test.py69
-rw-r--r--sources/shiboken2/tests/samplebinding/newdivision_test.py42
-rw-r--r--sources/shiboken2/tests/samplebinding/nondefaultctor_test.py71
-rw-r--r--sources/shiboken2/tests/samplebinding/nonzero_test.py43
-rw-r--r--sources/shiboken2/tests/samplebinding/numericaltypedef_test.py56
-rw-r--r--sources/shiboken2/tests/samplebinding/numpy_test.py58
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttype_test.py122
-rwxr-xr-xsources/shiboken2/tests/samplebinding/objecttype_with_named_args_test.py72
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttypebyvalue_test.py42
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttypelayout_test.py302
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttypeoperators_test.py60
-rw-r--r--sources/shiboken2/tests/samplebinding/objecttypereferenceasvirtualmethodargument_test.py49
-rw-r--r--sources/shiboken2/tests/samplebinding/oddbool_test.py78
-rw-r--r--sources/shiboken2/tests/samplebinding/oldstyleclass_as_number_test.py82
-rw-r--r--sources/shiboken2/tests/samplebinding/onlycopyclass_test.py57
-rw-r--r--sources/shiboken2/tests/samplebinding/overflow_test.py87
-rw-r--r--sources/shiboken2/tests/samplebinding/overload_sorting_test.py92
-rw-r--r--sources/shiboken2/tests/samplebinding/overload_test.py209
-rw-r--r--sources/shiboken2/tests/samplebinding/overloadwithdefault_test.py64
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_argument_invalidation_test.py62
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_delete_child_in_cpp_test.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_delete_child_in_python_test.py60
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_delete_parent_test.py82
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_invalidate_after_use_test.py110
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_invalidate_child_test.py69
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_invalidate_nonpolymorphic_test.py53
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_invalidate_parent_test.py68
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_reparenting_test.py130
-rw-r--r--sources/shiboken2/tests/samplebinding/ownership_transference_test.py85
-rw-r--r--sources/shiboken2/tests/samplebinding/pair_test.py105
-rw-r--r--sources/shiboken2/tests/samplebinding/pen_test.py63
-rw-r--r--sources/shiboken2/tests/samplebinding/point_test.py109
-rw-r--r--sources/shiboken2/tests/samplebinding/pointerholder_test.py59
-rw-r--r--sources/shiboken2/tests/samplebinding/pointf_test.py69
-rw-r--r--sources/shiboken2/tests/samplebinding/primitivereferenceargument_test.py49
-rw-r--r--sources/shiboken2/tests/samplebinding/privatector_test.py84
-rw-r--r--sources/shiboken2/tests/samplebinding/privatedtor_test.py99
-rw-r--r--sources/shiboken2/tests/samplebinding/protected_test.py357
-rw-r--r--sources/shiboken2/tests/samplebinding/pstrlist_test.py50
-rw-r--r--sources/shiboken2/tests/samplebinding/pystr_test.py49
-rw-r--r--sources/shiboken2/tests/samplebinding/python_thread_test.py116
-rw-r--r--sources/shiboken2/tests/samplebinding/receive_null_cstring_test.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/reference_test.py122
-rw-r--r--sources/shiboken2/tests/samplebinding/referencetopointer_test.py97
-rw-r--r--sources/shiboken2/tests/samplebinding/return_null_test.py59
-rw-r--r--sources/shiboken2/tests/samplebinding/richcompare_test.py46
-rw-r--r--sources/shiboken2/tests/samplebinding/sample-binding.txt.in15
-rw-r--r--sources/shiboken2/tests/samplebinding/sample_test.py78
-rw-r--r--sources/shiboken2/tests/samplebinding/simplefile_glue.cpp34
-rw-r--r--sources/shiboken2/tests/samplebinding/simplefile_test.py81
-rw-r--r--sources/shiboken2/tests/samplebinding/size_test.py119
-rw-r--r--sources/shiboken2/tests/samplebinding/static_nonstatic_methods_test.py109
-rw-r--r--sources/shiboken2/tests/samplebinding/str_test.py115
-rw-r--r--sources/shiboken2/tests/samplebinding/strlist_test.py112
-rw-r--r--sources/shiboken2/tests/samplebinding/templateinheritingclass_test.py80
-rw-r--r--sources/shiboken2/tests/samplebinding/time_test.py139
-rw-r--r--sources/shiboken2/tests/samplebinding/transform_test.py56
-rw-r--r--sources/shiboken2/tests/samplebinding/typeconverters_test.py189
-rw-r--r--sources/shiboken2/tests/samplebinding/typedealloc_test.py75
-rw-r--r--sources/shiboken2/tests/samplebinding/typedtordoublefree_test.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml2426
-rw-r--r--sources/shiboken2/tests/samplebinding/unsafe_parent_test.py54
-rw-r--r--sources/shiboken2/tests/samplebinding/useraddedctor_test.py45
-rw-r--r--sources/shiboken2/tests/samplebinding/virtualdtor_test.py76
-rw-r--r--sources/shiboken2/tests/samplebinding/virtualmethods_test.py138
-rw-r--r--sources/shiboken2/tests/samplebinding/visibilitychange_test.py47
-rw-r--r--sources/shiboken2/tests/samplebinding/voidholder_test.py69
-rw-r--r--sources/shiboken2/tests/samplebinding/weakref_test.py65
-rw-r--r--sources/shiboken2/tests/samplebinding/writableclassdict_test.py52
-rw-r--r--sources/shiboken2/tests/shibokenmodule/module_test.py116
-rw-r--r--sources/shiboken2/tests/smartbinding/CMakeLists.txt39
-rw-r--r--sources/shiboken2/tests/smartbinding/global.h29
-rw-r--r--sources/shiboken2/tests/smartbinding/smart-binding.txt.in15
-rw-r--r--sources/shiboken2/tests/smartbinding/smart_pointer_test.py147
-rw-r--r--sources/shiboken2/tests/smartbinding/typesystem_smart.xml23
-rw-r--r--sources/shiboken2/tests/sphinxtabletest.cpp332
-rw-r--r--sources/shiboken2/tests/sphinxtabletest.h54
-rw-r--r--sources/shiboken2/tests/test_generator/CMakeLists.txt68
-rw-r--r--sources/shiboken2/tests/test_generator/dummygenerator.cpp69
-rw-r--r--sources/shiboken2/tests/test_generator/dummygenerator.h49
-rw-r--r--sources/shiboken2/tests/test_generator/dummygentest-project.txt.in20
-rw-r--r--sources/shiboken2/tests/test_generator/dummygentest.cpp138
-rw-r--r--sources/shiboken2/tests/test_generator/dummygentest.h56
-rw-r--r--sources/shiboken2/tests/test_generator/dummygentestconfig.h.in15
-rw-r--r--sources/shiboken2/tests/test_generator/main.cpp39
-rw-r--r--sources/shiboken2/tests/test_generator/run_test.cmake11
-rw-r--r--sources/shiboken2/tests/test_generator/test_global.h1
-rw-r--r--sources/shiboken2/tests/test_generator/test_typesystem.xml3
653 files changed, 106755 insertions, 0 deletions
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 <jcummings2@users.sf.net>
+John Ehresman <jpe@wingware.com>
+Roman Lacko <backup.rlacko@gmail.com>
+Matthew Woehlke <matthew.woehlke@kitware.com>
+Anderson Lizardo <anderson.lizardo@openbossa.org>
+Bruno Araujo <bruno.araujo@openbossa.org>
+Hugo Parente Lima <hugo.lima@openbossa.org>
+Lauro Moura <lauro.neto@openbossa.org>
+Luciano Wolf <luciano.wolf@openbossa.org>
+Marcelo Lira <marcelo.lira@openbossa.org>
+Renato Araujo Oliveira Filho <renato.filho@openbossa.org>
+
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 <anderson.lizardo@openbossa.org>
+Bruno Araujo <bruno.araujo@openbossa.org>
+Hugo Parente Lima <hugo.lima@openbossa.org>
+Lauro Moura <lauro.neto@openbossa.org>
+Luciano Wolf <luciano.wolf@openbossa.org>
+Marcelo Lira <marcelo.lira@openbossa.org>
+Renato Araujo Oliveira Filho <renato.filho@openbossa.org>
+
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt
new file mode 100644
index 000000000..26ae03173
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -0,0 +1,102 @@
+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
+asttoxml.cpp
+fileout.cpp
+graph.cpp
+reporthandler.cpp
+typeparser.cpp
+typesystem.cpp
+include.cpp
+typedatabase.cpp
+parser/ast.cpp
+parser/binder.cpp
+parser/class_compiler.cpp
+parser/codemodel.cpp
+parser/codemodel_finder.cpp
+parser/compiler_utils.cpp
+parser/control.cpp
+parser/declarator_compiler.cpp
+parser/default_visitor.cpp
+parser/dumptree.cpp
+parser/lexer.cpp
+parser/list.cpp
+parser/name_compiler.cpp
+parser/parser.cpp
+parser/smallobject.cpp
+parser/tokens.cpp
+parser/type_compiler.cpp
+parser/visitor.cpp
+parser/rpp/builtin-macros.cpp
+parser/rpp/preprocessor.cpp
+)
+
+if (NOT DISABLE_DOCSTRINGS)
+ set(apiextractor_SRC
+ ${apiextractor_SRC}
+ docparser.cpp
+ doxygenparser.cpp
+ qtdocparser.cpp
+ )
+ set(APIEXTRACTOR_EXTRA_INCLUDES ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+ set(APIEXTRACTOR_EXTRA_LIBRARIES ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES})
+else()
+ set(APIEXTRACTOR_EXTRA_INCLUDES "")
+ set(APIEXTRACTOR_EXTRA_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)
+
+qt5_add_resources(apiextractor_RCCS_SRC generator.qrc)
+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}
+ )
+
+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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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..e71841ec3
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -0,0 +1,3381 @@
+/****************************************************************************
+**
+** 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 "parser/ast.h"
+#include "parser/binder.h"
+#include "parser/control.h"
+#include "parser/default_visitor.h"
+#include "parser/dumptree.h"
+#include "parser/lexer.h"
+#include "parser/parser.h"
+#include "parser/tokens.h"
+
+#include <QDebug>
+#include <QFile>
+#include <QFileInfo>
+#include <QTextCodec>
+#include <QTextStream>
+#include <QVariant>
+#include <QTime>
+#include <QQueue>
+#include <QDir>
+
+#include <cstdio>
+#include <algorithm>
+#include "graph.h"
+#include <QTemporaryFile>
+
+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<A, bar<B, C>, D>" -> ( "foo", "A", "bar<B, C>", "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<QString> AbstractMetaBuilder::qtMetaTypeDeclaredTypeNames() const
+{
+ return d->m_qmetatypeDeclaredTypenames;
+}
+
+void AbstractMetaBuilderPrivate::checkFunctionModifications()
+{
+ TypeDatabase *types = TypeDatabase::instance();
+ SingleTypeEntryHash entryHash = types->entries();
+ QList<TypeEntry*> entries = entryHash.values();
+
+ foreach (TypeEntry* entry, entries) {
+ if (!entry)
+ continue;
+ if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
+ continue;
+
+ ComplexTypeEntry* centry = static_cast<ComplexTypeEntry*>(entry);
+ FunctionModificationList modifications = centry->functionModifications();
+
+ foreach (const FunctionModification &modification, 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;
+
+ AbstractMetaFunctionList functions = clazz->functions();
+ bool found = false;
+ QStringList possibleSignatures;
+ foreach (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)
+{
+ foreach (const ClassModelItem &item, scope->classes()) {
+ 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();
+ foreach (const NamespaceModelItem &n, namespaces) {
+ if (scope != n)
+ fixQObjectForScope(dom, types, n);
+ }
+}
+
+void AbstractMetaBuilderPrivate::sortLists()
+{
+ foreach (AbstractMetaClass *cls, m_metaClasses)
+ cls->sortFunctions();
+}
+
+FileModelItem AbstractMetaBuilderPrivate::buildDom(QIODevice *input)
+{
+ Q_ASSERT(input);
+
+ if (!input->isOpen() && !input->open(QIODevice::ReadOnly))
+ return FileModelItem();
+
+ QByteArray contents = input->readAll();
+ input->close();
+
+ Control control;
+ Parser p(&control);
+ pool __pool;
+
+ TranslationUnitAST* ast = p.parse(contents, contents.size(), &__pool);
+
+ CodeModel model;
+ Binder binder(&model, p.location());
+ return binder.run(ast);
+}
+
+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);
+ foreach (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
+ ReportHandler::setProgressReference(dom->enums());
+ foreach (const EnumModelItem &item, dom->enums()) {
+ ReportHandler::progress(QLatin1String("Generating enum model..."));
+ AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>());
+ if (metaEnum) {
+ if (metaEnum->typeEntry()->generateCode())
+ m_globalEnums << metaEnum;
+ }
+ }
+
+ const QSet<NamespaceModelItem> &namespaceTypeValues = dom->uniqueNamespaces();
+ ReportHandler::setProgressReference(namespaceTypeValues);
+ foreach (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.
+ TypeDefList typeDefs = dom->typeDefs();
+ ReportHandler::setProgressReference(typeDefs);
+ foreach (const TypeDefModelItem &typeDef, typeDefs) {
+ ReportHandler::progress(QLatin1String("Resolving typedefs..."));
+ AbstractMetaClass* cls = traverseTypeDef(dom, typeDef);
+ addAbstractMetaClass(cls);
+ }
+
+ figureOutEnumValues();
+
+ foreach (const ClassModelItem &item, typeValues)
+ traverseClassMembers(item);
+
+ foreach (const NamespaceModelItem &item, namespaceTypeValues)
+ traverseNamespaceMembers(item);
+
+ // Global functions
+ foreach (const FunctionModelItem &func, dom->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);
+ foreach (AbstractMetaClass* cls, m_metaClasses) {
+ ReportHandler::progress(QLatin1String("Fixing class inheritance..."));
+ if (!cls->isInterface() && !cls->isNamespace())
+ setupInheritance(cls);
+ }
+
+ ReportHandler::setProgressReference(m_metaClasses);
+ foreach (AbstractMetaClass* cls, 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"));
+ }
+ TypeEntryHash allEntries = types->allEntries();
+ ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem..."));
+ foreach (QList<TypeEntry*> entries, allEntries) {
+ foreach (TypeEntry* entry, entries) {
+
+ 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<const FunctionTypeEntry*>(entry);
+ foreach (const QString &signature, fte->signatures()) {
+ bool ok = false;
+ foreach (AbstractMetaFunction* func, 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
+ foreach (AbstractMetaEnum* metaEnum, 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());
+ }
+
+ }
+ }
+ }
+
+ {
+ FunctionList hashFunctions = dom->findFunctions(QLatin1String("qHash"));
+ foreach (const FunctionModelItem &item, hashFunctions)
+ registerHashFunction(item);
+ }
+
+ {
+ FunctionList hashFunctions = dom->findFunctions(QLatin1String("operator<<"));
+ foreach (const FunctionModelItem &item, hashFunctions)
+ 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&"));
+ foreach (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>")));
+
+ foreach (const FunctionModelItem &item, binaryOperators)
+ traverseOperatorFunction(item);
+ }
+
+ {
+ FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<"))
+ + dom->findFunctions(QLatin1String("operator>>"));
+ foreach (const FunctionModelItem &item, streamOperators)
+ traverseStreamOperator(item);
+ }
+
+ figureOutDefaultEnumArguments();
+ checkFunctionModifications();
+
+ // sort all classes topologically
+ m_metaClasses = classesTopologicalSorted();
+
+ foreach (AbstractMetaClass* cls, 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.
+ foreach (const AddedFunction &addedFunc, types->globalUserFunctions()) {
+ AbstractMetaFunction* metaFunc = traverseFunction(addedFunc);
+ metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction);
+ m_globalFunctions << metaFunc;
+ }
+
+ std::puts("");
+}
+
+bool AbstractMetaBuilder::build(QIODevice *input)
+{
+ FileModelItem dom = d->buildDom(input);
+ const bool result = dom.data() != Q_NULLPTR;
+ if (result)
+ d->traverseDom(dom);
+ return result;
+}
+
+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());
+
+ ClassList classes = namespaceItem->classes();
+ foreach (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();
+ foreach (const TypeDefModelItem &typeDef, typeDefs) {
+ AbstractMetaClass *cls = traverseTypeDef(dom, typeDef);
+ if (cls) {
+ metaClass->addInnerClass(cls);
+ cls->setEnclosingClass(metaClass);
+ addAbstractMetaClass(cls);
+ }
+ }
+
+ // Traverse namespaces recursively
+ const QSet<NamespaceModelItem> &innerNamespaces = namespaceItem->uniqueNamespaces();
+ foreach (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<AbstractMetaClass *> *classes)
+{
+ AbstractMetaClass* base = metaClass->baseClass();
+
+ if (base && !classes->contains(base))
+ figureOutEnumValuesForClass(base, classes);
+
+ if (classes->contains(metaClass))
+ return;
+
+ AbstractMetaEnumList enums = metaClass->enums();
+ foreach (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<AbstractMetaClass*> classes;
+ foreach (AbstractMetaClass *c, m_metaClasses)
+ figureOutEnumValuesForClass(c, &classes);
+
+ foreach (AbstractMetaEnum* metaEnum, 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()
+{
+ foreach (AbstractMetaClass* metaClass, m_metaClasses) {
+ foreach (AbstractMetaFunction* metaFunction, metaClass->functions()) {
+ foreach (AbstractMetaArgument *arg, metaFunction->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<QString> &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();
+ foreach (const EnumeratorModelItem& enumValue, enumItem->enumerators()) {
+ 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();
+
+ if (TypeDatabase::instance()->isEnumRejected(className, enumName)) {
+ if (typeEntry)
+ typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
+ m_rejectedEnums.insert(qualifiedName, 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();
+
+ foreach (const EnumeratorModelItem &value, enumItem->enumerators()) {
+
+ 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
+ foreach(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<EnumTypeEntry*>(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<ObjectTypeEntry *>(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();
+ QList<TypeEntry *> template_args;
+ template_args.clear();
+ for (int i = 0; i < template_parameters.size(); ++i) {
+ const TemplateParameterModelItem &param = 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();
+ foreach (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();
+ foreach (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();
+ foreach (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<NamespaceModelItem> &innerNamespaces = item->uniqueNamespaces();
+ foreach (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;
+
+ if (TypeDatabase::instance()->isFieldRejected(className, fieldName)) {
+ m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field),
+ 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)
+{
+ foreach (const VariableModelItem &field, scope_item->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();
+ QString castTo = metaFunction->name().remove(QRegExp(QLatin1String("^operator "))).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<T> &)".
+static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass)
+{
+ const QList<TypeEntry *> &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());
+ foreach (const FunctionModelItem &function, scopeItem->functions()) {
+ 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<T> Vector { public:
+// Vector(const Vector &rhs);
+// };
+// template class<T>
+// Vector<T>::Vector(const Vector<T>&) {} // More specific, remove declaration.
+
+class DuplicatingFunctionPredicate : public std::unary_function<bool, const AbstractMetaFunction *> {
+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());
+ foreach (FunctionModelItem function, scopeItem->functions()) {
+ // 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);
+
+ foreach (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 "<type> 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(<type>)"
+ // 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
+ foreach (const AddedFunction &addedFunc, metaClass->typeEntry()->addedFunctions())
+ traverseFunction(addedFunc, metaClass);
+}
+
+void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func)
+{
+ FunctionModificationList mods = func->modifications(func->implementingClass());
+ AbstractMetaFunction& funcRef = *func;
+ foreach (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);
+
+ AbstractMetaClassList interfaces = iface->interfaces();
+ foreach (AbstractMetaClass* iface, interfaces)
+ metaClass->addInterface(iface);
+ }
+ }
+
+ return true;
+}
+
+void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem,
+ AbstractMetaClass *metaClass,
+ const QStringList &enumsDeclarations)
+{
+ EnumList enums = scopeItem->enums();
+ foreach (const EnumModelItem &enumItem, enums) {
+ AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet<QString>::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()));
+
+
+ QList<AddedFunction::TypeInfo> 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<AbstractMetaArgument*, AbstractMetaFunction*>(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;
+ foreach (const FunctionModification &mod, func->modifications(m_currentClass)) {
+ foreach (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);
+ }
+ }
+ }
+
+ int i = 1;
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ if (arg->name().isEmpty())
+ arg->setName(QLatin1String("arg__") + QString::number(i), false);
+ ++i;
+ }
+}
+
+static QString functionSignature(FunctionModelItem functionItem)
+{
+ QStringList args;
+ foreach (const ArgumentModelItem &arg, functionItem->arguments())
+ args << arg->type().toString();
+ return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')');
+}
+
+static inline QString functionSignatureWithReturnType(FunctionModelItem functionItem)
+{
+ return functionSignature(functionItem)
+ + QStringLiteral(" -> ") + functionItem->type().toString();
+}
+
+static inline QString qualifiedFunctionSignatureWithType(const QString &className,
+ FunctionModelItem functionItem)
+{
+ return className + colonColon() + functionSignatureWithReturnType(functionItem);
+}
+
+AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem)
+{
+ QString functionName = functionItem->name();
+ QString className;
+ QString rejectedFunctionSignature;
+ if (m_currentClass)
+ className = m_currentClass->typeEntry()->qualifiedCppName();
+
+ if (TypeDatabase::instance()->isFunctionRejected(className, functionName)) {
+ rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem);
+ m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+ else if (TypeDatabase::instance()->isFunctionRejected(className,
+ functionSignature(functionItem))) {
+ rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem);
+ m_rejectedFunctions.insert(rejectedFunctionSignature, 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 (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::%2', unmatched return type '%3'")
+ .arg(className, functionItem->name(),
+ functionItem->type().toString());
+ rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem);
+ m_rejectedFunctions.insert(rejectedFunctionSignature, 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);
+
+ bool ok;
+ AbstractMetaType* metaType = translateType(arg->type(), &ok);
+ if (!ok) {
+ Q_ASSERT(metaType == 0);
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("skipping function '%1::%2', unmatched parameter type '%3'")
+ .arg(className, functionItem->name(), arg->type().toString());
+ rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem);
+ m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
+ metaFunction->setInvalid(true);
+ return metaFunction;
+ }
+
+ if (metaType == Q_NULLPTR) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QString::fromLatin1("skipping function '%1::%2', 'void' encountered at parameter "
+ "position %3, but it can only be the the first and only "
+ "parameter")
+ .arg(className, functionItem->name()).arg(i);
+ rejectedFunctionSignature = qualifiedFunctionSignatureWithType(className, functionItem);
+ 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()) {
+ QList<ArgumentModification> 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<AbstractMetaArgument *, AbstractMetaFunction *>(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();
+ foreach (const QString& candidate, 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) {
+ foreach (const QString& templateArg, 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()) {
+ foreach (const AbstractMetaClass* cls, getBaseClasses(m_currentClass)) {
+ 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) {
+ QList<TypeEntry *> template_args = m_currentClass->templateArguments();
+ foreach (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());
+
+ foreach (const TypeParser::Info &ta, 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 QRegExp variableNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ if (!variableNameRegExp.exactMatch(stringValue)) {
+ ok = true;
+ return 0;
+ }
+
+ AbstractMetaEnumValue *enumValue = AbstractMetaClass::findEnumValue(m_metaClasses, stringValue);
+ if (enumValue) {
+ ok = true;
+ return enumValue->value();
+ }
+
+ foreach (AbstractMetaEnum* metaEnum, m_globalEnums) {
+ foreach (AbstractMetaEnumValue* ev, metaEnum->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
+ QRegExp typeRegEx(QLatin1String("[^<]*[<]([^:]*::).*"));
+ typeRegEx.indexIn(type->minimalSignature());
+ expr = typeRegEx.cap(1) + expr;
+ }
+ } else if (type->isContainer() && expr.contains(QLatin1Char('<'))) {
+ QRegExp typeRegEx(QLatin1String("[^<]*<(.*)>"));
+ typeRegEx.indexIn(type->minimalSignature());
+ QRegExp defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)"));
+ defaultRegEx.indexIn(expr);
+ expr = defaultRegEx.cap(1) + typeRegEx.cap(1) + defaultRegEx.cap(2);
+ } else {
+ // Here the default value is supposed to be a constructor,
+ // a class field, or a constructor receiving a class field
+ QRegExp defaultRegEx(QLatin1String("([^\\(]*\\(|)([^\\)]*)(\\)|)"));
+ defaultRegEx.indexIn(expr);
+
+ QString defaultValueCtorName = defaultRegEx.cap(1);
+ 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.
+ QRegExp typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$"));
+ typeRegEx.indexIn(type->minimalSignature());
+
+ QString typeNamespace = typeRegEx.cap(1);
+ QString typeCtorName = typeRegEx.cap(2);
+ if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName)
+ expr.prepend(typeNamespace);
+
+ // Fix scope if the parameter is a field of the current class
+ if (implementingClass) {
+ foreach (const AbstractMetaField* field, implementingClass->fields()) {
+ if (defaultRegEx.cap(2) == field->name()) {
+ expr = defaultRegEx.cap(1) + implementingClass->name()
+ + colonColon() + defaultRegEx.cap(2) + defaultRegEx.cap(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;
+ foreach (AbstractMetaClass *c, 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;
+ foreach (const QString& parent, metaClass->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;
+ foreach (const AbstractMetaClass* cls, getBaseClasses(metaClass)) {
+ if (ancestorHasPrivateCopyConstructor(cls))
+ return true;
+ }
+ return false;
+}
+
+AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QList<AbstractMetaType *> &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<const TemplateArgumentEntry*>(returned->typeEntry());
+
+ // If the template is intantiated with void we special case this as rejecting the functions that use this
+ // parameter from the instantiation.
+ 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)
+{
+ QList<TypeParser::Info> targs = info.template_instantiations;
+ QList<AbstractMetaType*> 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());
+ }
+
+ foreach (const TypeParser::Info &i, 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;
+ foreach (const QString &possibleName, 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();
+ foreach (const AbstractMetaFunction* function, templateClass->functions()) {
+ 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;
+ }
+
+ foreach (AbstractMetaArgument* argument, function->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);
+
+ foreach (AbstractMetaFunction* f, 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<AbstractMetaClass*> baseClasses;
+ if (cls->baseClass())
+ baseClasses.enqueue(cls->baseClass());
+ baseClasses << cls->interfaces();
+
+ while (!baseClasses.isEmpty()) {
+ AbstractMetaClass* currentClass = baseClasses.dequeue();
+ baseClasses << currentClass->interfaces();
+ if (currentClass->baseClass())
+ baseClasses.enqueue(currentClass->baseClass());
+
+ copyCtor = findCopyCtor(currentClass);
+ if (copyCtor) {
+ result = copyCtor->isPublic();
+ break;
+ }
+ }
+ }
+ cls->setHasCloneOperator(result);
+}
+
+void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls)
+{
+ AbstractMetaFunctionList convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp);
+ foreach (AbstractMetaFunction* func, convOps) {
+ if (func->isModifiedRemoved())
+ continue;
+ AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type()->typeEntry());
+ if (!metaClass)
+ continue;
+ metaClass->addExternalConversionOperator(func);
+ }
+ foreach (AbstractMetaClass* innerClass, cls->innerClasses())
+ setupExternalConversion(innerClass);
+}
+
+static void writeRejectLogFile(const QString &name,
+ const QMap<QString, AbstractMetaBuilder::RejectReason> &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<QString, AbstractMetaBuilder::RejectReason>::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<int> unmappedResult;
+ QHash<QString, int> map;
+ QHash<int, AbstractMetaClass*> reverseMap;
+
+ const AbstractMetaClassList& classList = cppClass ? cppClass->innerClasses() : m_metaClasses;
+
+ int i = 0;
+ foreach (AbstractMetaClass* clazz, classList) {
+ if (map.contains(clazz->qualifiedCppName()))
+ continue;
+ map[clazz->qualifiedCppName()] = i;
+ reverseMap[i] = clazz;
+ i++;
+ }
+
+ Graph graph(map.count());
+
+ foreach (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
+ QRegExp regex1(QLatin1String("\\(.*\\)"));
+ QRegExp regex2(QLatin1String("::.*"));
+ foreach (AbstractMetaClass* clazz, classList) {
+ if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName()))
+ graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]);
+
+ AbstractMetaClassList bases = getBaseClasses(clazz);
+ foreach(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()]);
+ }
+
+ foreach (AbstractMetaFunction* func, clazz->functions()) {
+ foreach (AbstractMetaArgument* arg, func->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;
+ foreach(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<int, QString> hash;
+ QHash<QString, int>::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 {
+ foreach (int i, 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();
+ foreach (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 <class Container>
+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..b4a36a1b6
--- /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<QString> 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(QIODevice* input);
+ 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..f9eb4bb46
--- /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 <QSet>
+#include <QFileInfo>
+
+class TypeDatabase;
+
+class AbstractMetaBuilderPrivate
+{
+public:
+ AbstractMetaBuilderPrivate();
+ ~AbstractMetaBuilderPrivate();
+
+ static FileModelItem buildDom(QIODevice *input);
+ 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<AbstractMetaClass *> *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<QString> &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 QList<AbstractMetaType *> &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<const TypeEntry *> m_usedTypes;
+
+ typedef QMap<QString, AbstractMetaBuilder::RejectReason> RejectMap;
+
+ RejectMap m_rejectedClasses;
+ RejectMap m_rejectedEnums;
+ RejectMap m_rejectedFunctions;
+ RejectMap m_rejectedFields;
+
+ QList<AbstractMetaEnum *> m_enums;
+
+ QList<QPair<AbstractMetaArgument *, AbstractMetaFunction *> > m_enumDefaultArguments;
+
+ QHash<QString, AbstractMetaEnumValue *> m_enumValues;
+
+ AbstractMetaClass *m_currentClass;
+ QList<ScopeModelItem> m_scopes;
+ QString m_namespacePrefix;
+
+ QSet<AbstractMetaClass *> m_setupInheritanceDone;
+
+ // QtScript
+ QSet<QString> 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..b861f1b2f
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -0,0 +1,2786 @@
+/****************************************************************************
+**
+** 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 <QStack>
+
+#include "abstractmetalang.h"
+#include "reporthandler.h"
+#include "typedatabase.h"
+#include "typesystem.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+# include <QtCore/QMetaEnum>
+# include <QtCore/QMetaObject>
+#endif
+
+#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<const ComplexTypeEntry *>(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<const ComplexTypeEntry *>(m_typeEntry)->isQObject()
+ ? QObjectPattern : ObjectPattern;
+ }
+ setTypeUsagePattern(pattern);
+}
+
+bool AbstractMetaType::hasTemplateChildren() const
+{
+ QStack<AbstractMetaType *> children;
+ children << m_children.toVector();
+
+ // 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.toVector();
+ }
+
+ 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
+{
+ FunctionModificationList mods = modifications(implementingClass());
+ foreach (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;
+
+ foreach (const AbstractMetaArgument *arg, 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) {
+ QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i);
+ foreach (const ReferenceCount &referenceCount, referenceCounts) {
+ if (referenceCount.action != ReferenceCount::Set)
+ return true;
+ }
+ }
+ return false;
+}
+
+QString AbstractMetaFunction::marshalledName() const
+{
+ QString returned = QLatin1String("__qt_") + name();
+ AbstractMetaArgumentList arguments = this->arguments();
+ foreach (const AbstractMetaArgument *arg, 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());
+
+ foreach (AbstractMetaArgument *arg, 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;
+ foreach (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
+QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
+{
+ QList<ReferenceCount> returned;
+
+ FunctionModificationList mods = this->modifications(cls);
+ foreach (const FunctionModification &mod, mods) {
+ foreach (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
+{
+ FunctionModificationList mods = this->modifications(cls);
+ foreach (const FunctionModification &mod, mods) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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();
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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 {
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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 {
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (const ArgumentModification &argumentModification, modification.argument_mods) {
+ if (argumentModification.index != key)
+ continue;
+
+ foreach (const CodeSnip &snip, argumentModification.conversion_rules) {
+ if (snip.language == language && !snip.code().isEmpty())
+ return snip.code();
+ }
+ }
+ }
+
+ return QString();
+}
+
+QString AbstractMetaFunction::argumentReplaced(int key) const
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (const ArgumentModification &argumentModification, modification.argument_mods) {
+ if (argumentModification.index == key) {
+ if (argumentModification.removed)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::isVirtualSlot() const
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ if (modification.isVirtualSlot())
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
+{
+ typedef QHash<TypeSystem::Language, TypeSystem::Ownership>::const_iterator OwnershipMapIt;
+
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ if (modification.isDeprecated())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaFunction::isThread() const
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ if (modification.isThread())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaFunction::allowThread() const
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ if (modification.allowThread())
+ return true;
+ }
+ return false;
+}
+
+
+TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
+{
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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
+{
+ FunctionModificationList modifications = this->modifications(cls);
+ foreach (const FunctionModification &modification, modifications) {
+ if ((modification.removal & language) == language)
+ return true;
+ }
+
+ return false;
+
+}
+
+QString AbstractMetaFunction::typeReplaced(int key) const
+{
+ FunctionModificationList modifications = this->modifications(declaringClass());
+ foreach (const FunctionModification &modification, modifications) {
+ foreach (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;
+ foreach (const AbstractMetaClass* interface, implementor->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
+{
+ foreach (const FunctionModification &mod, modifications(ownerClass())) {
+ if (mod.isCodeInjection())
+ return true;
+ }
+ return false;
+}
+
+CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const
+{
+ CodeSnipList result;
+ foreach (const FunctionModification &mod, modifications(ownerClass())) {
+ if (mod.isCodeInjection()) {
+ QList<CodeSnip>::const_iterator it = mod.snips.constBegin();
+ for (;it != mod.snips.constEnd(); ++it) {
+ if ((it->language & language) && (it->position == position || position == TypeSystem::CodeSnipPositionAny))
+ result << *it;
+ }
+ }
+ }
+ return result;
+}
+
+bool AbstractMetaFunction::hasSignatureModifications() const
+{
+ foreach (const FunctionModification &mod, modifications()) {
+ if (mod.isRenameModifier())
+ return true;
+ foreach (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 QRegExp opRegEx(QLatin1String("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$"));
+ return opRegEx.indexIn(funcName) > -1;
+}
+
+bool AbstractMetaFunction::isOperatorOverload(QString funcName)
+{
+ if (isConversionOperator(funcName))
+ return true;
+
+ static QRegExp opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?"
+ "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~"
+ "|\\[\\]|\\s+delete\\[?\\]?"
+ "|\\(\\)"
+ "|\\s+new\\[?\\]?)$"));
+ return opRegEx.indexIn(funcName) > -1;
+}
+
+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()) {
+ FunctionModificationList mods = modifications(implementingClass());
+ foreach (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()) {
+ foreach (AbstractMetaType* inst, templateBaseClassInstantiations())
+ delete inst;
+ }
+}
+
+/*******************************************************************************
+ * 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());
+
+ foreach (AbstractMetaFunction *function, functions()) {
+ if (!function->isConstructor())
+ iface->addFunction(function->copy());
+ }
+
+// iface->setEnums(enums());
+// setEnums(AbstractMetaEnumList());
+
+ foreach (const AbstractMetaField *field, 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;
+ AbstractMetaFunctionList functions = this->functions();
+ foreach (AbstractMetaFunction *function, 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
+{
+ AbstractMetaFunctionList list = functionsInShellClass();
+
+ AbstractMetaFunctionList returned;
+ foreach (AbstractMetaFunction *f, list) {
+ if (!f->isFinalInCpp() || f->isVirtualSlot())
+ returned += f;
+ }
+
+ return returned;
+}
+
+AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const
+{
+ if (!hasCloneOperator() && !hasExternalConversionOperators())
+ return AbstractMetaFunctionList();
+
+ AbstractMetaFunctionList returned;
+ AbstractMetaFunctionList list = queryFunctions(Constructors);
+
+ list.append(externalConversionOperators());
+
+ // Exclude anything that uses rvalue references, be it a move
+ // constructor "QPolygon(QPolygon &&)" or something else like
+ // "QPolygon(QVector<QPoint> &&)".
+ foreach (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
+{
+ AbstractMetaFunctionList list = queryFunctions(OperatorOverloads | Visible);
+ AbstractMetaFunctionList returned;
+ foreach (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
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isOperatorOverload() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasArithmeticOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasBitwiseOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasComparisonOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasLogicalOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasSubscriptOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isSubscriptOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasAssignmentOperatorOverload() const
+{
+ foreach (const AbstractMetaFunction *f, m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isAssignmentOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasConversionOperatorOverload() const
+{
+ foreach (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;
+ foreach (AbstractMetaFunction *f, 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) {
+ foreach (AbstractMetaFunction *final_function, 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
+{
+ foreach (const AbstractMetaField *field, fields()) {
+ if (field->getter() || field->setter())
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaClass::hasDefaultToStringFunction() const
+{
+ foreach (AbstractMetaFunction *f, queryFunctionsByName(QLatin1String("toString"))) {
+ 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;
+
+ foreach (const AbstractMetaFunction *f, 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
+{
+ foreach (const AbstractMetaFunction *f, functions()) {
+ if (f->name() == functionName)
+ return f;
+ }
+ return 0;
+}
+
+bool AbstractMetaClass::hasProtectedFunctions() const
+{
+ foreach (AbstractMetaFunction *func, m_functions) {
+ if (func->isProtected())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasProtectedFields() const
+{
+ foreach (const AbstractMetaField *field, 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<const AbstractMetaClass*, AbstractMetaTypeList> 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)
+{
+ foreach (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
+{
+ FieldModificationList mods = modifications();
+ foreach (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);
+
+ FieldModificationList mods = g->modifications();
+ foreach (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
+{
+ FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications();
+ FieldModificationList returned;
+
+ foreach (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
+{
+ foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) {
+ if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction)
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasPrivateCopyConstructor() const
+{
+ foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) {
+ 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;
+
+ foreach (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
+ foreach (AbstractMetaFunction *function, interface->functions())
+ 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.
+ FunctionModificationList mods = function->modifications(interface);
+ foreach (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;
+ foreach (const AbstractMetaClass* interface, interfaces) {
+ if (interface)
+ m_isPolymorphic |= interface->isPolymorphic();
+ }
+}
+
+
+AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
+{
+ foreach (AbstractMetaEnum *e, 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)
+{
+ foreach (AbstractMetaEnum *e, m_enums) {
+ if (e != meta_enum)
+ continue;
+ foreach (AbstractMetaEnumValue *v, e->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)
+{
+ foreach (AbstractMetaEnum *e, m_enums) {
+ foreach (AbstractMetaEnumValue *v, e->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<const ComplexTypeEntry *>(entry);
+ ComplexTypeEntry *class_entry = metaClass->typeEntry();
+ if (class_entry && centry->include().isValid())
+ class_entry->addExtraInclude(centry->include());
+ }
+
+ if (type->hasInstantiations()) {
+ AbstractMetaTypeList instantiations = type->instantiations();
+ foreach (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());
+
+ AbstractMetaArgumentList arguments = meta_function->arguments();
+ foreach (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<AbstractMetaFunction *> 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;
+ FunctionModificationList mods = sf->modifications(sf->implementingClass());
+ foreach (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; i<arguments.size(); ++i)
+ // arguments[i]->setDefaultValueExpression("<#>" + 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;
+ }
+
+ foreach (AbstractMetaFunction *f, funcsToAdd)
+ funcs << f->copy();
+
+ if (superClass)
+ superClass = superClass->baseClass();
+ else
+ iface_idx++;
+ }
+
+ bool hasPrivateConstructors = false;
+ bool hasPublicConstructors = false;
+ foreach (AbstractMetaFunction *func, funcs) {
+ FunctionModificationList mods = func->modifications(this);
+ foreach (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;
+ }
+
+ foreach (AbstractMetaFunction *f1, funcs) {
+ foreach (AbstractMetaFunction *f2, 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<const EnumTypeEntry *>(typeEntry())->forceInteger();
+}
+
+bool AbstractMetaType::isTargetLangFlags() const
+{
+ return isFlags() && !static_cast<const FlagsTypeEntry *>(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 *AbstractMetaEnumValueList::find(const QString &name) const
+{
+ for (int i = 0; i < size(); ++i) {
+ if (name == at(i)->name())
+ return at(i);
+ }
+ return 0;
+}
+
+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);
+ }
+
+ foreach (AbstractMetaClass* metaClass, classes) {
+ foreach(AbstractMetaEnum* metaEnum, metaClass->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;
+
+ foreach (AbstractMetaClass *c, classes) {
+ if (c->qualifiedCppName() == name)
+ return c;
+ }
+
+ foreach (AbstractMetaClass *c, classes) {
+ if (c->fullName() == name)
+ return c;
+ }
+
+ foreach (AbstractMetaClass *c, classes) {
+ if (c->name() == name)
+ return c;
+ }
+
+ return 0;
+}
+
+AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
+ const TypeEntry* typeEntry)
+{
+ foreach (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..26702d3a2
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -0,0 +1,1983 @@
+/****************************************************************************
+**
+** 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 <QtCore/qobjectdefs.h>
+#include <QtCore/QStringList>
+
+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
+ {
+ foreach (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;
+ QList<ReferenceCount> 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 AbstractMetaEnumValueList : public QList<AbstractMetaEnumValue *>
+{
+public:
+ AbstractMetaEnumValue *find(const QString &name) const;
+};
+
+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;
+
+
+ QList<TypeEntry *> templateArguments() const
+ {
+ return m_templateArgs;
+ }
+
+ void setTemplateArguments(const QList<TypeEntry *> &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;
+ }
+
+ QList<QPropertySpec *> 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;
+ QList<QPropertySpec *> m_propertySpecs;
+ AbstractMetaClassList m_innerClasses;
+
+ AbstractMetaFunctionList m_externalConversionOperators;
+
+ QStringList m_baseClassNames;
+ QList<TypeEntry *> 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..dd6573b78
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang_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 ABSTRACTMETALANG_TYPEDEFS_H
+#define ABSTRACTMETALANG_TYPEDEFS_H
+
+#include <QtCore/QList>
+
+class AbstractMetaClass;
+class AbstractMetaField;
+class AbstractMetaArgument;
+class AbstractMetaEnum;
+class AbstractMetaEnumValueList;
+class AbstractMetaFunction;
+class AbstractMetaType;
+
+typedef QList<AbstractMetaArgument *> AbstractMetaArgumentList;
+typedef QList<AbstractMetaClass *> AbstractMetaClassList;
+typedef QList<AbstractMetaEnum *> AbstractMetaEnumList;
+typedef QList<AbstractMetaField *> AbstractMetaFieldList;
+typedef QList<AbstractMetaFunction *> AbstractMetaFunctionList;
+typedef QList<AbstractMetaType *> 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..371ccf559
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** 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 <QDir>
+#include <QDebug>
+#include <QTemporaryFile>
+#include <iostream>
+
+#include "reporthandler.h"
+#include "typesystem.h"
+#include "fileout.h"
+#include "parser/rpp/pp.h"
+#include "abstractmetabuilder.h"
+#include "typedatabase.h"
+#include "typesystem.h"
+
+static bool preprocess(const QString& sourceFile,
+ QFile& targetFile,
+ const QStringList& includes);
+
+ApiExtractor::ApiExtractor() : m_builder(0)
+{
+ static bool qrcInitialized = false;
+ if (!qrcInitialized)
+ Q_INIT_RESOURCE(generator);
+ // 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)
+{
+ foreach (const QString &path, paths)
+ addTypesystemSearchPath(path);
+}
+
+void ApiExtractor::addIncludePath(const QString& path)
+{
+ m_includePaths << path;
+}
+
+void ApiExtractor::addIncludePath(const QStringList& 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<QString> ApiExtractor::qtMetaTypeDeclaredTypeNames() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->qtMetaTypeDeclaredTypeNames();
+}
+
+static const AbstractMetaEnum* findEnumOnClasses(AbstractMetaClassList metaClasses, const EnumTypeEntry* typeEntry)
+{
+ const AbstractMetaEnum* result = 0;
+ foreach (const AbstractMetaClass* metaClass, metaClasses) {
+ foreach (const AbstractMetaEnum* metaEnum, metaClass->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;
+ foreach (AbstractMetaEnum* metaEnum, m_builder->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<const FlagsTypeEntry*>(typeEntry));
+ if (typeEntry->isEnum())
+ return findAbstractMetaEnum(reinterpret_cast<const EnumTypeEntry*>(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;
+ }
+
+ QTemporaryFile ppFile;
+#ifndef NDEBUG
+ ppFile.setAutoRemove(false);
+#endif
+ // make sure that a tempfile can be written
+ if (!ppFile.open()) {
+ std::cerr << "could not create tempfile in " << qPrintable(QDir::tempPath());
+ return false;
+ }
+
+ // run rpp pre-processor
+ if (!preprocess(m_cppFileName, ppFile, m_includePaths)) {
+ std::cerr << "Preprocessor failed on file: " << qPrintable(m_cppFileName);
+ return false;
+ }
+ ppFile.seek(0);
+ m_builder = new AbstractMetaBuilder;
+ m_builder->setLogDirectory(m_logDirectory);
+ m_builder->setGlobalHeader(m_cppFileName);
+ m_builder->build(&ppFile);
+
+ return true;
+}
+
+static bool preprocess(const QString& sourceFile,
+ QFile& targetFile,
+ const QStringList& includes)
+{
+ rpp::pp_environment env;
+ rpp::pp preprocess(env);
+
+ rpp::pp_null_output_iterator null_out;
+
+ const char *ppconfig = ":/trolltech/generator/pp-qt-configuration";
+
+ const QString fileName = QLatin1String(ppconfig);
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ std::cerr << "Preprocessor configuration file not found " << ppconfig << std::endl;
+ return false;
+ }
+
+ QByteArray ba = file.readAll();
+ file.close();
+ preprocess.operator()(ba.constData(), ba.constData() + ba.size(), null_out);
+
+ preprocess.push_include_path(".");
+ foreach (const QString &include, includes)
+ preprocess.push_include_path(QDir::toNativeSeparators(include).toStdString());
+ preprocess.push_include_path("/usr/include");
+
+ QString currentDir = QDir::current().absolutePath();
+ QFileInfo sourceInfo(sourceFile);
+ if (!sourceInfo.exists()) {
+ std::cerr << "File not found " << qPrintable(sourceFile) << std::endl;
+ return false;
+ }
+ QDir::setCurrent(sourceInfo.absolutePath());
+
+ std::string result;
+ result.reserve(20 * 1024); // 20K
+
+ result += "# 1 \"builtins\"\n";
+ result += "# 1 \"";
+ result += sourceFile.toStdString();
+ result += "\"\n";
+
+ preprocess.file(sourceInfo.fileName().toStdString(),
+ rpp::pp_output_iterator<std::string> (result));
+
+ QDir::setCurrent(currentDir);
+
+ if (!targetFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
+ std::cerr << "Failed to write preprocessed file: " << qPrintable(targetFile.fileName()) << std::endl;
+ return false;
+ }
+
+ targetFile.write(result.c_str(), result.length());
+ return true;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+template <class Container>
+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..1080ff507
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/apiextractor.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:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information 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 "typesystem_typedefs.h"
+#include <QStringList>
+
+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 QString& path);
+ void addIncludePath(const QStringList& paths);
+ QStringList 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<QString> 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;
+ QStringList 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/asttoxml.cpp b/sources/shiboken2/ApiExtractor/asttoxml.cpp
new file mode 100644
index 000000000..7a2f1261e
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/asttoxml.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:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 "asttoxml.h"
+#include "parser/control.h"
+#include "parser/parser.h"
+#include "parser/binder.h"
+
+
+#include <QtCore/QXmlStreamWriter>
+#include <QtCore/QTextStream>
+#include <QtCore/QTextCodec>
+#include <QtCore/QFile>
+
+typedef QHash<QString, EnumModelItem> EnumMap;
+typedef QHash<QString, FunctionModelItem> FunctionModelItemMap;
+typedef QHash<QString, ClassModelItem> ClassModelItemMap;
+typedef QHash<QString, NamespaceModelItem> NamespaceModelItemMap;
+
+void astToXML(QString name)
+{
+ QFile file(name);
+
+ if (!file.open(QFile::ReadOnly))
+ return;
+
+ QTextStream stream(&file);
+ stream.setCodec(QTextCodec::codecForName("UTF-8"));
+ QByteArray contents = stream.readAll().toUtf8();
+ file.close();
+
+ Control control;
+ Parser p(&control);
+ pool __pool;
+
+ TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
+
+ CodeModel model;
+ Binder binder(&model, p.location());
+ FileModelItem dom = binder.run(ast);
+
+ QFile outputFile;
+ if (!outputFile.open(stdout, QIODevice::WriteOnly))
+ return;
+
+ QXmlStreamWriter s(&outputFile);
+ s.setAutoFormatting(true);
+
+ s.writeStartElement(QLatin1String("code"));
+
+ const NamespaceList &namespaces = dom->namespaces();
+ foreach (const NamespaceModelItem &n, namespaces)
+ writeOutNamespace(s, n);
+
+ const ClassList &classList = dom->classes();
+ foreach (const ClassModelItem &c, classList)
+ writeOutClass(s, c);
+
+ s.writeEndElement();
+}
+
+void writeOutNamespace(QXmlStreamWriter &s, const NamespaceModelItem &item)
+{
+ s.writeStartElement(QLatin1String("namespace"));
+ s.writeAttribute(QLatin1String("name"), item->name());
+
+ const NamespaceList &namespaces = item->namespaces();
+ foreach (const NamespaceModelItem &n, namespaces)
+ writeOutNamespace(s, n);
+
+ const ClassList &classList = item->classes();
+ foreach (const ClassModelItem &c, classList)
+ writeOutClass(s, c);
+
+ const EnumList &enums = item->enums();
+ foreach (const EnumModelItem &e, enums)
+ writeOutEnum(s, e);
+
+ s.writeEndElement();
+}
+
+void writeOutEnum(QXmlStreamWriter &s, const EnumModelItem &item)
+{
+ QString qualifiedName = item->qualifiedName().join(QLatin1String("::"));
+ s.writeStartElement(QLatin1String("enum"));
+ s.writeAttribute(QLatin1String("name"), qualifiedName);
+
+ EnumeratorList enumList = item->enumerators();
+ for (int i = 0; i < enumList.size() ; i++) {
+ s.writeStartElement(QLatin1String("enumerator"));
+ if (!enumList[i]->value().isEmpty())
+ s.writeAttribute(QLatin1String("value"), enumList[i]->value());
+ s.writeCharacters(enumList[i]->name());
+
+ s.writeEndElement();
+ }
+ s.writeEndElement();
+}
+
+void writeOutFunction(QXmlStreamWriter &s, const FunctionModelItem &item)
+{
+ QString qualifiedName = item->qualifiedName().join(QLatin1String("::"));
+ s.writeStartElement(QLatin1String("function"));
+ s.writeAttribute(QLatin1String("name"), qualifiedName);
+
+ ArgumentList arguments = item->arguments();
+ for (int i = 0; i < arguments.size() ; i++) {
+ s.writeStartElement(QLatin1String("argument"));
+ s.writeAttribute(QLatin1String("type"), arguments[i]->type().qualifiedName().join(QLatin1String("::")));
+ s.writeEndElement();
+ }
+ s.writeEndElement();
+}
+
+void writeOutClass(QXmlStreamWriter &s, const ClassModelItem &item)
+{
+ QString qualifiedName = item->qualifiedName().join(QLatin1String("::"));
+ s.writeStartElement(QLatin1String("class"));
+ s.writeAttribute(QLatin1String("name"), qualifiedName);
+
+ const EnumList &enums = item->enums();
+ foreach (const EnumModelItem &e, enums)
+ writeOutEnum(s, e);
+
+ const FunctionList &functionList = item->functions();
+ foreach (const FunctionModelItem &func, functionList)
+ writeOutFunction(s, func);
+
+ const ClassList &classList = item->classes();
+ foreach (const ClassModelItem &c, classList)
+ writeOutClass(s, c);
+
+ s.writeEndElement();
+}
+
diff --git a/sources/shiboken2/ApiExtractor/asttoxml.h b/sources/shiboken2/ApiExtractor/asttoxml.h
new file mode 100644
index 000000000..ed2a04833
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/asttoxml.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+**
+** 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 ASTTOXML
+#define ASTTOXML
+
+#include "parser/codemodel_fwd.h"
+
+#include <QtCore/QString>
+
+QT_FORWARD_DECLARE_CLASS(QXmlStreamWriter)
+
+void astToXML(const QString name);
+void writeOutNamespace(QXmlStreamWriter &s, const NamespaceModelItem &item);
+void writeOutEnum(QXmlStreamWriter &s, const EnumModelItem &item);
+void writeOutFunction(QXmlStreamWriter &s, const FunctionModelItem &item);
+void writeOutClass(QXmlStreamWriter &s, const ClassModelItem &item);
+
+
+#endif // ASTTOXML
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 <QtCore/QString>
+#include <QtCore/QVector>
+
+// Dependencies for topologically sorting classes
+struct Dependency {
+ QString parent;
+ QString child;
+};
+
+typedef QVector<Dependency> 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 %}
+<div class="section">
+ <h1>API Extractor {{ version }}</h1>
+
+ <p>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.
+
+ <p>API Extractor is based on the
+ <a href="http://labs.trolltech.com/page/Projects/QtScript/Generator">QtScriptGenerator</a> project.</p>
+
+ <h2>Documentation</h2>
+ <table class="contentstable"><tr>
+ <td width="50%">
+ <p class="biglink"><a href="{{ pathto("overview") }}">Overview</a><br/>
+ <span class="linkdescr">how API Extractor works</span></p>
+ <p class="biglink"><a href="{{ pathto("typesystem") }}">Typesystem reference</a><br/>
+ <span class="linkdescr">reference for all typesystem tags</span></p>
+ </td>
+ <td width="50%">
+ <p class="biglink"><a href="{{ pathto("contents") }}">Contents</a><br/>
+ <span class="linkdescr">for a complete overview</span></p>
+ </td></tr>
+ </table>
+</div>
+{% 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 %}
+<div id="container">
+<div class="header">
+ <div class="header_container">
+ <div class="logo"><a href="http://www.pyside.org"><img alt="PySide" src="{{ pathto('_static/pysidelogo.png', 1) }}" width="199" height="102" /></a></div>
+ <div class="related">
+ <ul>
+ {%- block rootrellink %}
+ <li><a href="{{ pathto( 'index' ) }}">{{ shorttitle|e }}</a></li>
+ {%- endblock %}
+ {%- for parent in parents %}
+ <li>{{ reldelim1 }} <a href="{{ parent.link|e }}" {% if loop.last %}{{ accesskey("U") }}{% endif %}>{{ parent.title }}</a></li>
+ {%- endfor %}
+ {%- block relbaritems %} {% endblock %}
+ </ul>
+ </div>
+ </div>
+</div>
+{%- endblock -%}
+
+{%- block footer %}
+ <div class="footer">
+ <a href="http://www.indt.org.br"><img src="{{ pathto('_static/logo_indt.jpg', 1) }}" alt="Indt" border="0" /></a>
+ <a href="http://www.openbossa.org"><img src="{{ pathto('_static/logo_openbossa.png', 1) }}" alt="Openbossa" border="0" /></a>
+ <a href="http://qt.nokia.com/"><img src="{{ pathto('_static/logo_qt.png', 1) }}" alt="Qt" border="0" /></a>
+ <a href="http://www.python.org"><img src="{{ pathto('_static/logo_python.jpg', 1) }}" alt="Python" border="0" /></a>
+ </div>
+</div>
+{%- 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" %}
+<div id="searchbox" style="display: none">
+ <h3>{{ _('Quick search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" id="q" size="18" />
+ <input type="submit" value="{{ _('Go') }}" id="search_button" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+{%- 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_header.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/bg_topo.jpg
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/fakebar.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_indt.jpg
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_openbossa.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_python.jpg
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/logo_qt.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/pysidelogo.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/doc/_themes/pysidedocs/static/relbar_bg.png
Binary files 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
+# "<project> v<release> 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 <link> 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="750"
+ height="230"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="dependency-apiextractor.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/tmp/dependency-pyside.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3270"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3679"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.6315754"
+ inkscape:cx="375"
+ inkscape:cy="115"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg2"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1278"
+ inkscape:window-height="949"
+ inkscape:window-x="1330"
+ inkscape:window-y="25">
+ <sodipodi:guide
+ orientation="1,0"
+ position="384.28571,590"
+ id="guide2601" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="678.57143,491.42857"
+ id="guide2603" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="78.571429,257.14286"
+ id="guide2605" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="93.571429,280.71429"
+ id="guide7565" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="148.57143,216.42857"
+ id="guide7567" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-250.44576,-308.53365)" />
+ <g
+ id="g2664"
+ transform="translate(-162.03535,-115.53321)">
+ <path
+ inkscape:connector-type="polyline"
+ id="path2869"
+ d="M 439.27375,270.21407 L 594.99083,193.03351"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <g
+ transform="translate(166.24286,-190.07976)"
+ id="g2606">
+ <rect
+ style="fill:#e3e2db;stroke:#000000;stroke-opacity:1"
+ id="rect7541"
+ width="211.42857"
+ height="124.28571"
+ x="6.6142678"
+ y="308.16089"
+ ry="17.142857" />
+ <text
+ xml:space="preserve"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="76.614265"
+ y="339.74512"
+ id="text7543"><tspan
+ sodipodi:role="line"
+ id="tspan7545"
+ x="76.614265"
+ y="339.74512">Boost</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="76.614265"
+ y="372.67505"
+ id="text7547"><tspan
+ sodipodi:role="line"
+ id="tspan7549"
+ x="76.614265"
+ y="372.67505">Qt Software</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="76.614265"
+ y="408.38055"
+ id="text7551"><tspan
+ sodipodi:role="line"
+ id="tspan7553"
+ x="76.614265"
+ y="408.38055">INdT/Nokia</tspan></text>
+ <rect
+ style="fill:#aaeeff;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1"
+ id="rect7555"
+ width="43.163269"
+ height="22.5"
+ x="21.614267"
+ y="321.55374"
+ ry="6.4285707" />
+ <rect
+ style="fill:#b3ff80;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1"
+ id="rect7561"
+ width="43.163269"
+ height="22.5"
+ x="21.614267"
+ y="355.4823"
+ ry="6.4285707" />
+ <rect
+ style="fill:#e9ddaf;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1"
+ id="rect7563"
+ width="43.163269"
+ height="22.5"
+ x="21.614267"
+ y="390.4823"
+ ry="6.4285707" />
+ </g>
+ <path
+ inkscape:connector-type="polyline"
+ id="path2604"
+ d="M 782.79015,270.0418 L 627.07307,192.86124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <g
+ transform="translate(234.84929,-73.143707)"
+ id="g5193">
+ <rect
+ ry="9.2689295"
+ style="fill:#b3ff80;fill-rule:evenodd;stroke:#2a7800;stroke-width:0.96558368px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2417"
+ width="274.18781"
+ height="73.282379"
+ x="78.571426"
+ y="342.86383"
+ rx="8.3239012" />
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="88.822823"
+ y="359.67014"
+ id="text2419"><tspan
+ sodipodi:role="line"
+ id="tspan2421"
+ x="88.822823"
+ y="359.67014">Qt 4.5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="88.822823"
+ y="375.33484"
+ id="text2423"><tspan
+ sodipodi:role="line"
+ id="tspan2425"
+ x="88.822823"
+ y="375.33484">4.5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="88.822823"
+ y="390.87479"
+ id="text2427"><tspan
+ sodipodi:role="line"
+ id="tspan2429"
+ x="88.822823"
+ y="390.87479">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="88.822823"
+ y="400.84058"
+ id="text2431"><tspan
+ sodipodi:role="line"
+ id="tspan2433"
+ x="88.822823"
+ y="400.84058">GNU General Public License v3 /</tspan><tspan
+ id="tspan2472"
+ sodipodi:role="line"
+ x="88.822823"
+ y="411.1687">GNU Lesser General Public Licence v2.1</tspan></text>
+ </g>
+ <g
+ transform="translate(101.41581,-378.37135)"
+ id="g5120">
+ <rect
+ rx="10.404889"
+ ry="13.104635"
+ style="fill:#e9ddaf;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2441"
+ width="274.54263"
+ height="73.281754"
+ x="384.28571"
+ y="496.43558" />
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="513.59869"
+ id="text2443"><tspan
+ sodipodi:role="line"
+ id="tspan2445"
+ x="389.17969"
+ y="513.59869">libapiextractor</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="529.26337"
+ id="text2447"><tspan
+ sodipodi:role="line"
+ id="tspan2449"
+ x="389.17969"
+ y="529.26337">0.2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="544.80334"
+ id="text2451"><tspan
+ sodipodi:role="line"
+ x="389.17969"
+ y="544.80334"
+ id="tspan2453">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="560.12628"
+ id="text2455"><tspan
+ sodipodi:role="line"
+ id="tspan2457"
+ x="389.17969"
+ y="560.12628">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ transform="translate(242.40213,-378.858)"
+ id="g5182">
+ <rect
+ ry="11.287985"
+ style="fill:#aaeeff;fill-rule:evenodd;stroke:#006078;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ id="rect2563"
+ width="274.54263"
+ height="73.281754"
+ x="384.28571"
+ y="648.57843"
+ rx="10.404877" />
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="665.74158"
+ id="text2565"><tspan
+ sodipodi:role="line"
+ id="tspan2567"
+ x="389.17969"
+ y="665.74158">boost::graph</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="681.40625"
+ id="text2569"><tspan
+ sodipodi:role="line"
+ id="tspan2571"
+ x="389.17969"
+ y="681.40625">1.38.0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="696.94623"
+ id="text2573"><tspan
+ sodipodi:role="line"
+ x="389.17969"
+ y="696.94623"
+ id="tspan2575">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="389.17969"
+ y="712.26917"
+ id="text2577"><tspan
+ sodipodi:role="line"
+ id="tspan2579"
+ x="389.17969"
+ y="712.26917">Boost Software License 1.0</tspan></text>
+ </g>
+ </g>
+</svg>
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
+
+ <modify-argument index="1">
+ <define-ownership class="target" owner="target" />
+ </modify-argument>
+
+
+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
+
+ <modify-argument index="1">
+ <define-ownership class="target" owner="c++" />
+ </modify-argument>
+
+
+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
+
+ <modify-argument index="this">
+ <parent index="1" action="add">
+ </modify-argument>
+
+In this example, the instance with the method that is being invoked (indicated by 'index="this"' on
+modify-argument) will be marked as a child
+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
+
+ <modify-argument index="2" invalidate-after-use="yes"/>
+
+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/<QT_MODULE_NAME> 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
+
+ <modify-argument ...>
+ <conversion-rule class="target | native">
+ // the code
+ </conversion-rule>
+ </modify-argument>
+
+ 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
+
+ <conversion-rule class="native">
+ bool %out = (bool) %in;
+ </conversion-rule>
+
+ .. note:: You can also use the conversion-rule node to specify :ref:`a conversion code which will be used instead of the generator's conversion code everywhere for a given type <conversion-rule-on-types>`.
+
+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
+
+ <modify-argument>
+ <remove-argument />
+ </modify-argument>
+
+rename to
+^^^^^^^^^
+
+ The 'rename to' node is used to rename a argument and use this new name in the generated code.
+
+ .. code-block:: xml
+
+ <modify-argument>
+ <rename to='...' />
+ </modify-argument>
+
+
+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
+
+ <modify-argument...>
+ <remove-default-expression />
+ </modify-argument>
+
+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
+
+ <modify-argument>
+ <replace-default-expression with="..." />
+ </modify-argument>
+
+
+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
+
+ <modify-argument>
+ <replace-type modified-type="..." />
+ </modify-argument>
+
+ If the new type is a class, the ``modified-type`` attribute must be set to
+ the fully qualified name (including name of the package as well as the class
+ name).
+
+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
+
+ <modify-argument>
+ <define-ownership class="target | native"
+ owner="target | c++ | default" />
+ </modify-argument>
+
+
+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
+
+ <modify-argument>
+ <reference-count action="add|add-all|remove|set|ignore" variable-name="..." />
+ </modify-argument>
+
+
+ The variable-name attribute specifies the name used for the variable that
+ holds the reference(s).
+
+
+replace-value
+^^^^^^^^^^^^^
+
+ 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
+
+ <modify-argument index="0" replace-value="this"/>
+
+
+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
+
+ <modify-argument index="1">
+ <parent index="this" action="add | remove" />
+ </modify-argument>
+
+ In the ``index`` argument you must specify the parent argument. The action
+ *add* creates a parent link between objects, while *remove* will undo the
+ parentage relationship.
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
+
+ <value-type>
+ <conversion-rule>
+ <native-to-target>
+ // Code to convert a native value to a target language object.
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type='TARGETTYPEA' check='TARGETTYPEA_CHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPEA
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ <add-conversion type='TARGETTYPEB' check='TARGETTYPEB_CHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPEB
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </value-type>
+
+ The 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
+
+ <conversion-rule>
+ <native-to-target>
+ // Code to convert a native value to a target language object.
+ </native-to-target>
+ </conversion-rule>
+
+ Use the replace node to modify the template code.
+ Notice that the generator must provide type system variables for the input
+ and output values and types, namely **%in**, **%out**, **%INTYPE** and
+ **%OUTTYPE**. In the case of container types, **%INTYPE** refers to the
+ full container type (e.g. **"list<int>"**) and **%INTYPE_0**, **%INTYPE_1**,
+ **%INTYPE_#**, should be replaced by the types used in the container template
+ (e.g. **%INTYPE_0** correspondes to **"int"** for **"list<int>"**).
+
+
+.. _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
+
+ <conversion-rule>
+ <target-to-native replace='yes|no'>\
+ // List of target to native conversions meant to replace or expand
+ // the already existing implicit conversions.
+ </target-to-native>
+ </conversion-rule>
+
+
+.. _add-conversion:
+
+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
+
+ <target-to-native>
+ <add-conversion type='TARGETTYPE' check='TARGETTYPECHECK(%in)'>
+ // Code to convert target language type object of type TARGETTYPE_A
+ // to the C++ native type represented by the value/primitive/container-type.
+ </add-conversion>
+ <target-to-native>
+
+ The ``check`` attribute tells how a target value should be checked to see if it belongs to
+ the type expected. This attribute is *optional*, for it can be derived from the ``type``
+ attribute, but it isn't unusual that some special check is needed. The variables
+ **%in**, **%out**, **%INTYPE**, **%INTYPE_#**, and **%OUTTYPE**, must be provided by
+ the generator as in the ``native-to-target`` tag.
+
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
+
+ <value-type>
+ <inject-documentation mode="append | prepend | replace" format="native | target" >
+ // the documentation
+ </inject-code>
+ </value-type>
+
+ 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
+
+ <modify-documentation xpath="...">
+ <!-- new documentation -->
+ </modify-documentation>
+
+ 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
+
+ <value-type>
+ <inject-code class="native | target | target-declaration"
+ position="beginning | end" since="...">
+ // the code
+ </inject-code>
+ </value-type>
+
+ 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
+
+ <object-type>
+ <modify-field name="..."
+ write="true | false"
+ read="true | false" />
+ </object-type>
+
+ The ``name`` attribute is the name of the field, the *optional* ``write``
+ and ``read`` attributes specify the field's access privileges in the target
+ language API (both are set to true by default).
+ The ``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
+
+ <object-type>
+ <modify-function signature="..."
+ since="..."
+ remove="all | c++"
+ access="public | private | protected"
+ rename="..." />
+ </object-type>
+
+ 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
+
+ <object-type>
+ <add-function signature="..." return-type="..." access="public | protected" static="yes | no" since="..."/>
+ </object-type>
+
+ 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
+
+ <value-type name="Foo">
+ <convertion-rule file="my_converter_implementation.h" since="..."/>
+ </value-type>
+
+ 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 <conversion-rule>`.
+
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
+
+ <modify-function>
+ <modify-argument index="return | this | 1 ..." >
+ // modifications
+ </modify-argument>
+ </modify-function>
+
+ Set the ``index`` attribute to "1" for the first argument, "2" for the second
+ one and so on. Alternatively, set it to "return" or "this" if you want to
+ modify the function's return value or the object the function is called upon,
+ respectively.
+
+.. _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
+
+ <modify-function>
+ <remove class="all" />
+ </modify-function>
+
+ .. 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
+
+ <modify-function>
+ <access modifier="public | protected | private"/>
+ </modify-function>
+
+ .. 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
+
+ <modify-function>
+ <rename to="..." />
+ </modify-function>
+
+ 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
+
+ <typesystem>
+ <suppress-warning text="..." />
+ </typesystem>
+
+ The **text** attribute is the warning text to suppress, and may contain the *
+ wildcard (use "" to escape regular expression matching if the warning contain
+ a regular "*").
+
+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
+
+ <value-type>
+ <extra-includes>
+ <include file-name="..." location="global | local"/>
+ </extra-includes>
+ </value-type>
+
+ The **file-name** attribute is the file to include, such as "QStringList".
+ The **location** attribute is where the file is located: *global* means that
+ the file is located in $INCLUDEPATH and will be included using #include <...>,
+ *local* means that the file is in a local directory and will be included
+ using #include "...".
+
+
+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
+
+ <value-type>
+ <include file-name="..."
+ location="global | local"/>
+ </value-type>
+
+ The **file-name** attribute is the file to include, such as "QStringList".
+ The **location** attribute is where the file is located: *global* means that
+ the file is located in $INCLUDEPATH and will be included using #include <...>,
+ *local* means that the file is in a local directory and will be included
+ using #include "...".
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
+
+ <typesystem package="..." default-superclass="...">
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <load-typesystem name="..." generate="yes | no" />
+ </typesystem>
+
+ The **name** attribute is the filename of the typesystem to load, the
+ **generate** attribute specifies whether code should be generated or not. The
+ later must be specified when basing one library on another, making the generator
+ able to understand inheritance hierarchies, primitive mapping, parameter types
+ in functions, etc.
+
+ 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
+
+ <typesystem>
+ <rejection class="..."
+ function-name="..."
+ field-name="..." />
+ </typesystem>
+
+ The **class** attribute is the C++ class name of the class to reject. Use the
+ *optional* **function-name** or **field-name** attributes to reject a particular
+ function or field. Note that the **field-name** and **function-name** cannot
+ be specified at the same time. To remove all occurrences of a given field or
+ function, set the class attribute to \*.
+
+.. _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
+
+ <typesystem>
+ <primitive-type name="..."
+ since="..."
+ target-name="..."
+ default-constructor="..."
+ preferred-conversion="yes | no" />
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <namespace-type name="..."
+ generate="yes | no"
+ package="..."
+ since="..."
+ revision="..." />
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <enum-type name="..."
+ identified-by-value="..."
+ since="..."
+ flags="yes | no"
+ flags-revision="..."
+ lower-bound="..."
+ upper-bound="..."
+ force-integer="yes | no"
+ extensible="yes | no"
+ revision="..." />
+ </typesystem>
+
+ The **name** attribute is the fully qualified C++ name of the enum
+ (e.g.,"Qt::FillRule"). If the *optional* **flags** attribute is set to *yes*
+ (the default is *no*), the generator will expect an existing QFlags<T> for the
+ given enum type. The **lower-bound** and **upper-bound** attributes are used
+ to specify runtime bounds checking for the enum value. The value must be a
+ compilable target language statement, such as "QGradient.Spread.PadSpread"
+ (taking again Python as an example). If the **force-integer** attribute is
+ set to *yes* (the default is *no*), the generated target language code will
+ use the target language integers instead of enums. And finally, the
+ **extensible** attribute specifies whether the given enum can be extended
+ with user values (the default is *no*).
+
+ The *optional* **since** value is used to specify the API version of this type.
+
+ The attribute **identified-by-value** helps to specify anonymous enums using the
+ name of one of their values, which is unique for the anonymous enum scope.
+ Notice that the **enum-type** tag can either have **name** or **identified-by-value**
+ but not both.
+
+ The **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
+
+ <enum-type>
+ <reject-enum-value name="..."/>
+ </enum-type>
+
+ This node is used when a C++ enum implementation has several identical numeric
+ values, some of which are typically obsolete.
+
+.. _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
+
+ <typesystem>
+ <value-type name="..." since="..."
+ copyable="yes | no"
+ hash-function="..."
+ stream="yes | no"
+ default-constructor="..."
+ revision="..." />
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <object-type name="..."
+ since="..."
+ copyable="yes | no"
+ hash-function="..."
+ stream="yes | no"
+ revision="..." />
+ </typesystem>
+
+ The **name** attribute is the fully qualified C++ class name. If there is no
+ C++ base class, the default-superclass attribute can be used to specify a
+ superclass for the given type, in the generated target language API. The
+ **copyable** and **hash-function** attributes are the same as described for
+ :ref:`value-type`.
+
+ The *optional* 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
+
+ <typesystem>
+ <interface-type name="..."
+ since="..."
+ package ="..."
+ default-superclass ="..."
+ revision="..." />
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <container-type name="..."
+ since="..."
+ type ="..." />
+ </typesystem>
+
+ The **name** attribute is the fully qualified C++ class name. The **type**
+ attribute is used to indicate what conversion rule will be applied to the
+ container. It can be: *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
+
+ <typesystem>
+ <custom-type name="..." />
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <function signature="..." rename="..." since="..."/>
+ </typesystem>
+
+ 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
+
+ <typesystem>
+ <template name="my_template">
+ // the code
+ </template>
+ </typesystem>
+
+ Use the insert-template node to insert the template code (identified by the
+ template's ``name`` attribute) into the generated code base.
+
+
+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
+
+ <inject-code class="target" position="beginning">
+ <insert-template name="my_template" />
+ </inject-code>
+
+ Use the replace node to modify the template code.
+
+
+replace
+^^^^^^^
+
+ The replace node allows you to modify template code before inserting it into
+ the generated code, and it can be a child of the insert-template node.
+
+ .. code-block:: xml
+
+ <insert-template name="my_template">
+ <replace from="..." to="..." />
+ </insert-template>
+
+ 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..4ec1da299
--- /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 <QtCore/QDebug>
+#include <QtXmlPatterns/QXmlQuery>
+#include <QBuffer>
+
+#include <cstdlib>
+#include <libxslt/xsltutils.h>
+#include <libxslt/transform.h>
+
+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("&amp;"));
+ escapedQuery.replace(QLatin1Char('<'), QLatin1String("&lt;"));
+ 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;
+ foreach (DocModification mod, mods) {
+ if (mod.mode() == TypeSystem::DocModificationXPathReplace) {
+ hasXPathBasedModification = true;
+ break;
+ }
+ }
+
+ if (!hasXPathBasedModification)
+ return xml;
+
+ QString xsl = QLatin1String("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
+ "<xsl:transform version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
+ "<xsl:template match=\"/\">\n"
+ " <xsl:apply-templates />\n"
+ "</xsl:template>\n"
+ "<xsl:template match=\"*\">\n"
+ "<xsl:copy>\n"
+ " <xsl:copy-of select=\"@*\"/>\n"
+ " <xsl:apply-templates/>\n"
+ "</xsl:copy>\n"
+ "</xsl:template>\n"
+ );
+ foreach (DocModification mod, mods) {
+ if (mod.mode() == TypeSystem::DocModificationXPathReplace) {
+ QString xpath = mod.xpath();
+ xpath.replace(QLatin1Char('"'), QLatin1String("&quot;"));
+ xsl += QLatin1String("<xsl:template match=\"")
+ + xpath + QLatin1String("\">")
+ + mod.code() + QLatin1String("</xsl:template>\n");
+ }
+ }
+ xsl += QLatin1String("</xsl:transform>");
+
+ 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<char*>(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 <QtCore/QString>
+
+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..f7d868f8d
--- /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 <QtXmlPatterns/QXmlQuery>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+
+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
+ AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang();
+ foreach (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;
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ QString type;
+ 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
+ AbstractMetaFieldList fields = metaClass->fields();
+ foreach (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
+ AbstractMetaEnumList enums = metaClass->enums();
+ foreach (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..7314cfe3b
--- /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() {}
+ virtual void fillDocumentation(AbstractMetaClass *metaClass);
+ virtual Documentation retrieveModuleDocumentation();
+ virtual Documentation retrieveModuleDocumentation(const QString& name);
+};
+
+#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 <QtCore/QTextCodec>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+
+#include <cstdio>
+
+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<QByteArray> a, QList<QByteArray> 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<QByteArray> a, QList<QByteArray> 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<Unit*> *unitAppend(QList<Unit*> *res, Type type, int pos)
+{
+ if (!res) {
+ res = new QList<Unit*>;
+ 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<Unit*> *diffHelper(int *lcs, QList<QByteArray> a, QList<QByteArray> 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<QByteArray> a, QList<QByteArray> b)
+{
+ QList<Unit*> *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 <QtCore/QObject>
+#include <QtCore/QTextStream>
+
+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/generator.qrc b/sources/shiboken2/ApiExtractor/generator.qrc
new file mode 100644
index 000000000..2d82b37cb
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/generator.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource prefix="/trolltech/generator/">
+<file alias="pp-qt-configuration">parser/rpp/pp-qt-configuration</file>
+</qresource>
+</RCC>
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 <QVector>
+#include <QDebug>
+#include <QLinkedList>
+#include <QSet>
+#include <iterator>
+#include <algorithm>
+#include <iostream>
+#include <QFile>
+
+struct Graph::GraphPrivate
+{
+ enum Color { WHITE, GRAY, BLACK };
+ typedef QVector<QSet<int> > Edges;
+ typedef QSet<int>::const_iterator EdgeIterator;
+
+ Edges edges;
+
+ GraphPrivate(int numNodes) : edges(numNodes)
+ {
+ }
+
+ void dfsVisit(int node, QLinkedList<int>& result, QVector<Color>& 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<int> Graph::topologicalSort() const
+{
+ int nodeCount = Graph::nodeCount();
+ QLinkedList<int> result;
+ QVector<GraphPrivate::Color> 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<int>();
+ 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<int>(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 <QLinkedList>
+#include <QHash>
+#include <QString>
+
+/// 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<int, QString>& 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<int> topologicalSort() const;
+private:
+
+ struct GraphPrivate;
+ GraphPrivate* m_d;
+};
+
+#endif
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 <QDebug>
+#include <QDir>
+#include <QTextStream>
+#include <QHash>
+
+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..e4ff5b309
--- /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 <QString>
+#include <QList>
+
+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 QList<Include> 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 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ version="1.0">
+ <xsl:output method="xml" indent="yes"/>
+ <xsl:param name="lang" />
+ <xsl:param name="source" />
+
+ <xsl:template match="processing-instruction()" />
+
+ <xsl:template match="/typesystem">
+ <xsl:copy>
+ <xsl:for-each select="@*">
+ <xsl:copy>
+ <xsl:value-of select="." />
+ </xsl:copy>
+ </xsl:for-each>
+
+ <xsl:for-each select="document($source)/typesystem/@*">
+ <xsl:copy>
+ <xsl:value-of select="." />
+ </xsl:copy>
+ </xsl:for-each>
+
+ <xsl:variable name="other" select="document($source)/typesystem/*[not(self::object-type | self::value-type | self::interface-type | self::namespace-type)]" />
+ <xsl:if test="$other">
+ <xsl:choose>
+ <xsl:when test="$lang != ''">
+ <xsl:element name="language">
+ <xsl:attribute name="name" ><xsl:value-of select="$lang" /></xsl:attribute>
+ <xsl:copy-of select="$other" />
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$other" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+
+ <xsl:apply-templates select="node()" />
+
+ </xsl:copy>
+ </xsl:template>
+
+
+
+ <xsl:template match="/typesystem/*[self::object-type | self::value-type | self::interface-type | self::namespace-type]">
+ <xsl:variable name="name" select="name()" />
+ <xsl:copy>
+ <xsl:for-each select="@*">
+ <xsl:copy>
+ <xsl:value-of select="." />
+ </xsl:copy>
+ </xsl:for-each>
+
+ <xsl:apply-templates select="node()" />
+
+ <xsl:variable name="other" select="document($source)/typesystem/*[name() = $name][@name = current()/@name]" />
+ <xsl:if test="$other">
+ <xsl:choose>
+ <xsl:when test="$lang != ''">
+ <xsl:element name="language">
+ <xsl:attribute name="name" ><xsl:value-of select="$lang" /></xsl:attribute>
+ <xsl:copy-of select="$other/node()" />
+ </xsl:element>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:copy-of select="$other/node()" />
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:if>
+ </xsl:copy>
+ </xsl:template>
+
+ <!-- Plain identity transform. -->
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
diff --git a/sources/shiboken2/ApiExtractor/parser/ast.cpp b/sources/shiboken2/ApiExtractor/parser/ast.cpp
new file mode 100644
index 000000000..a744704fe
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/ast.cpp
@@ -0,0 +1,38 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "ast.h"
+#include "lexer.h"
+
+QString AST::toString(TokenStream *stream) const
+{
+ const Token &tk = stream->token((int) start_token);
+ const Token &end_tk = stream->token((int) end_token);
+ return QString::fromLatin1(tk.text + tk.position, end_tk.position - tk.position);
+}
diff --git a/sources/shiboken2/ApiExtractor/parser/ast.h b/sources/shiboken2/ApiExtractor/parser/ast.h
new file mode 100644
index 000000000..7640b7c38
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/ast.h
@@ -0,0 +1,884 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 AST_H
+#define AST_H
+
+#include "smallobject.h"
+#include "list.h"
+
+#include <QString>
+
+#define DECLARE_AST_NODE(k) \
+ enum { __node_kind = Kind_##k };
+
+class TokenStream;
+
+struct AccessSpecifierAST;
+struct AsmDefinitionAST;
+struct BaseClauseAST;
+struct BaseSpecifierAST;
+struct BinaryExpressionAST;
+struct CastExpressionAST;
+struct ClassMemberAccessAST;
+struct ClassSpecifierAST;
+struct CompoundStatementAST;
+struct ConditionAST;
+struct ConditionalExpressionAST;
+struct CppCastExpressionAST;
+struct CtorInitializerAST;
+struct DeclarationAST;
+struct DeclarationStatementAST;
+struct DeclaratorAST;
+struct DeleteExpressionAST;
+struct DoStatementAST;
+struct ElaboratedTypeSpecifierAST;
+struct EnumSpecifierAST;
+struct EnumeratorAST;
+struct ExceptionSpecificationAST;
+struct ExpressionAST;
+struct ExpressionOrDeclarationStatementAST;
+struct ExpressionStatementAST;
+struct ForStatementAST;
+struct FunctionCallAST;
+struct FunctionDefinitionAST;
+struct IfStatementAST;
+struct IncrDecrExpressionAST;
+struct InitDeclaratorAST;
+struct InitializerAST;
+struct InitializerClauseAST;
+struct LabeledStatementAST;
+struct LinkageBodyAST;
+struct LinkageSpecificationAST;
+struct MemInitializerAST;
+struct NameAST;
+struct NamespaceAST;
+struct NamespaceAliasDefinitionAST;
+struct NewDeclaratorAST;
+struct NewExpressionAST;
+struct NewInitializerAST;
+struct NewTypeIdAST;
+struct OperatorAST;
+struct OperatorFunctionIdAST;
+struct ParameterDeclarationAST;
+struct ParameterDeclarationClauseAST;
+struct PostfixExpressionAST;
+struct PrimaryExpressionAST;
+struct PtrOperatorAST;
+struct PtrToMemberAST;
+struct ReturnStatementAST;
+struct SimpleDeclarationAST;
+struct SimpleTypeSpecifierAST;
+struct SizeofExpressionAST;
+struct StatementAST;
+struct StringLiteralAST;
+struct SubscriptExpressionAST;
+struct SwitchStatementAST;
+struct TemplateArgumentAST;
+struct TemplateDeclarationAST;
+struct TemplateParameterAST;
+struct ThrowExpressionAST;
+struct TranslationUnitAST;
+struct TryBlockStatementAST;
+struct TypeIdAST;
+struct TypeIdentificationAST;
+struct TypeParameterAST;
+struct TypeSpecifierAST;
+struct TypedefAST;
+struct UnaryExpressionAST;
+struct UnqualifiedNameAST;
+struct UsingAST;
+struct UsingDirectiveAST;
+struct WhileStatementAST;
+struct WinDeclSpecAST;
+struct QPropertyAST;
+struct QEnumsAST;
+
+struct AST
+{
+ enum NODE_KIND {
+ Kind_UNKNOWN = 0,
+
+ Kind_AccessSpecifier,
+ Kind_AsmDefinition,
+ Kind_BaseClause,
+ Kind_BaseSpecifier,
+ Kind_BinaryExpression,
+ Kind_CastExpression,
+ Kind_ClassMemberAccess,
+ Kind_ClassSpecifier,
+ Kind_CompoundStatement,
+ Kind_Condition,
+ Kind_ConditionalExpression,
+ Kind_CppCastExpression,
+ Kind_CtorInitializer,
+ Kind_DeclarationStatement,
+ Kind_Declarator,
+ Kind_DeleteExpression,
+ Kind_DoStatement,
+ Kind_ElaboratedTypeSpecifier,
+ Kind_EnumSpecifier,
+ Kind_Enumerator,
+ Kind_ExceptionSpecification,
+ Kind_ExpressionOrDeclarationStatement,
+ Kind_ExpressionStatement,
+ Kind_ForStatement,
+ Kind_FunctionCall,
+ Kind_FunctionDefinition,
+ Kind_IfStatement,
+ Kind_IncrDecrExpression,
+ Kind_InitDeclarator,
+ Kind_Initializer,
+ Kind_InitializerClause,
+ Kind_LabeledStatement,
+ Kind_LinkageBody,
+ Kind_LinkageSpecification,
+ Kind_MemInitializer,
+ Kind_Name,
+ Kind_Namespace,
+ Kind_NamespaceAliasDefinition,
+ Kind_NewDeclarator,
+ Kind_NewExpression,
+ Kind_NewInitializer,
+ Kind_NewTypeId,
+ Kind_Operator,
+ Kind_OperatorFunctionId,
+ Kind_ParameterDeclaration,
+ Kind_ParameterDeclarationClause,
+ Kind_PostfixExpression,
+ Kind_PrimaryExpression,
+ Kind_PtrOperator,
+ Kind_PtrToMember,
+ Kind_ReturnStatement,
+ Kind_SimpleDeclaration,
+ Kind_SimpleTypeSpecifier,
+ Kind_SizeofExpression,
+ Kind_StringLiteral,
+ Kind_SubscriptExpression,
+ Kind_SwitchStatement,
+ Kind_TemplateArgument,
+ Kind_TemplateDeclaration,
+ Kind_TemplateParameter,
+ Kind_ThrowExpression,
+ Kind_TranslationUnit,
+ Kind_TryBlockStatement,
+ Kind_TypeId,
+ Kind_TypeIdentification,
+ Kind_TypeParameter,
+ Kind_Typedef,
+ Kind_UnaryExpression,
+ Kind_UnqualifiedName,
+ Kind_Using,
+ Kind_UsingDirective,
+ Kind_WhileStatement,
+ Kind_WinDeclSpec,
+ Kind_QPropertyAST,
+ Kind_ForwardDeclarationSpecifier,
+ Kind_QEnumsAST,
+
+ NODE_KIND_COUNT
+ };
+
+ QString toString(TokenStream *stream) const;
+
+ int kind;
+
+ std::size_t start_token;
+ std::size_t end_token;
+};
+
+struct TypeSpecifierAST: public AST
+{
+ const ListNode<std::size_t> *cv;
+};
+
+struct StatementAST: public AST
+{
+};
+
+struct ExpressionAST: public AST
+{
+};
+
+struct DeclarationAST: public AST
+{
+};
+
+struct AccessSpecifierAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(AccessSpecifier)
+
+ const ListNode<std::size_t> *specs;
+};
+
+struct AsmDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(AsmDefinition)
+
+ const ListNode<std::size_t> *cv;
+};
+
+struct BaseClauseAST: public AST
+{ // ### kill me
+ DECLARE_AST_NODE(BaseClause)
+
+ const ListNode<BaseSpecifierAST*> *base_specifiers;
+};
+
+struct BaseSpecifierAST: public AST
+{
+ DECLARE_AST_NODE(BaseSpecifier)
+
+ std::size_t virt;
+ std::size_t access_specifier;
+ NameAST *name;
+};
+
+struct BinaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(BinaryExpression)
+
+ std::size_t op;
+ ExpressionAST *left_expression;
+ ExpressionAST *right_expression;
+};
+
+struct CastExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(CastExpression)
+
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct ClassMemberAccessAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ClassMemberAccess)
+
+ std::size_t op;
+ NameAST *name;
+};
+
+struct ClassSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ClassSpecifier)
+
+ WinDeclSpecAST *win_decl_specifiers;
+ std::size_t class_key;
+ NameAST *name;
+ BaseClauseAST *base_clause;
+ const ListNode<DeclarationAST*> *member_specs;
+};
+
+struct ForwardDeclarationSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ForwardDeclarationSpecifier)
+
+ std::size_t class_key;
+ NameAST *name;
+ BaseClauseAST *base_clause;
+};
+
+struct CompoundStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(CompoundStatement)
+
+ const ListNode<StatementAST*> *statements;
+};
+
+struct ConditionAST: public AST
+{
+ DECLARE_AST_NODE(Condition)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ ExpressionAST *expression;
+};
+
+struct ConditionalExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ConditionalExpression)
+
+ ExpressionAST *condition;
+ ExpressionAST *left_expression;
+ ExpressionAST *right_expression;
+};
+
+struct CppCastExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(CppCastExpression)
+
+ std::size_t op;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+ const ListNode<ExpressionAST*> *sub_expressions;
+};
+
+struct CtorInitializerAST: public AST
+{
+ DECLARE_AST_NODE(CtorInitializer)
+
+ std::size_t colon;
+ const ListNode<MemInitializerAST*> *member_initializers;
+};
+
+struct DeclarationStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(DeclarationStatement)
+
+ DeclarationAST *declaration;
+};
+
+struct DeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(Declarator)
+
+ const ListNode<PtrOperatorAST*> *ptr_ops;
+ DeclaratorAST *sub_declarator;
+ NameAST *id;
+ ExpressionAST *bit_expression;
+ const ListNode<ExpressionAST*> *array_dimensions;
+ ParameterDeclarationClauseAST *parameter_declaration_clause;
+ const ListNode<std::size_t> *fun_cv;
+ ExceptionSpecificationAST *exception_spec;
+};
+
+struct DeleteExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(DeleteExpression)
+
+ std::size_t scope_token;
+ std::size_t delete_token;
+ std::size_t lbracket_token;
+ std::size_t rbracket_token;
+ ExpressionAST *expression;
+};
+
+struct DoStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(DoStatement)
+
+ StatementAST *statement;
+ ExpressionAST *expression;
+};
+
+struct ElaboratedTypeSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(ElaboratedTypeSpecifier)
+
+ std::size_t type;
+ NameAST *name;
+};
+
+struct EnumSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(EnumSpecifier)
+
+ NameAST *name;
+ const ListNode<EnumeratorAST*> *enumerators;
+};
+
+struct EnumeratorAST: public AST
+{
+ DECLARE_AST_NODE(Enumerator)
+
+ std::size_t id;
+ ExpressionAST *expression;
+};
+
+struct ExceptionSpecificationAST: public AST
+{
+ DECLARE_AST_NODE(ExceptionSpecification)
+
+ std::size_t ellipsis;
+ const ListNode<TypeIdAST*> *type_ids;
+};
+
+struct ExpressionOrDeclarationStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ExpressionOrDeclarationStatement)
+
+ StatementAST *expression;
+ StatementAST *declaration;
+};
+
+struct ExpressionStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ExpressionStatement)
+
+ ExpressionAST *expression;
+};
+
+struct FunctionCallAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(FunctionCall)
+
+ ExpressionAST *arguments;
+};
+
+struct FunctionDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(FunctionDefinition)
+
+ const ListNode<std::size_t> *storage_specifiers;
+ const ListNode<std::size_t> *function_specifiers;
+ TypeSpecifierAST *type_specifier;
+ InitDeclaratorAST *init_declarator;
+ StatementAST *function_body;
+ WinDeclSpecAST *win_decl_specifiers;
+};
+
+struct ForStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ForStatement)
+
+ StatementAST *init_statement;
+ ConditionAST *condition;
+ ExpressionAST *expression;
+ StatementAST *statement;
+};
+
+struct IfStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(IfStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+ StatementAST *else_statement;
+};
+
+struct IncrDecrExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(IncrDecrExpression)
+
+ std::size_t op;
+};
+
+struct InitDeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(InitDeclarator)
+
+ DeclaratorAST *declarator;
+ InitializerAST *initializer;
+};
+
+struct InitializerAST: public AST
+{
+ DECLARE_AST_NODE(Initializer)
+
+ InitializerClauseAST *initializer_clause;
+ ExpressionAST *expression;
+};
+
+struct InitializerClauseAST: public AST
+{
+ DECLARE_AST_NODE(InitializerClause)
+
+ ExpressionAST *expression;
+};
+
+struct LabeledStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(LabeledStatement)
+};
+
+struct LinkageBodyAST: public AST
+{
+ DECLARE_AST_NODE(LinkageBody)
+
+ const ListNode<DeclarationAST*> *declarations;
+};
+
+struct LinkageSpecificationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(LinkageSpecification)
+
+ std::size_t extern_type;
+ LinkageBodyAST *linkage_body;
+ DeclarationAST *declaration;
+};
+
+struct MemInitializerAST: public AST
+{
+ DECLARE_AST_NODE(MemInitializer)
+
+ NameAST *initializer_id;
+ ExpressionAST *expression;
+};
+
+struct NameAST: public AST
+{
+ DECLARE_AST_NODE(Name)
+
+ bool global;
+ const ListNode<UnqualifiedNameAST*> *qualified_names;
+ UnqualifiedNameAST *unqualified_name;
+};
+
+struct NamespaceAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Namespace)
+
+ std::size_t namespace_name;
+ LinkageBodyAST *linkage_body;
+};
+
+struct NamespaceAliasDefinitionAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(NamespaceAliasDefinition)
+
+ std::size_t namespace_name;
+ NameAST *alias_name;
+};
+
+struct NewDeclaratorAST: public AST
+{
+ DECLARE_AST_NODE(NewDeclarator)
+
+ PtrOperatorAST *ptr_op;
+ NewDeclaratorAST *sub_declarator;
+ const ListNode<ExpressionAST*> *expressions;
+};
+
+struct NewExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(NewExpression)
+
+ std::size_t scope_token;
+ std::size_t new_token;
+ ExpressionAST *expression;
+ TypeIdAST *type_id;
+ NewTypeIdAST *new_type_id;
+ NewInitializerAST *new_initializer;
+};
+
+struct NewInitializerAST: public AST
+{
+ DECLARE_AST_NODE(NewInitializer)
+
+ ExpressionAST *expression;
+};
+
+struct NewTypeIdAST: public AST
+{
+ DECLARE_AST_NODE(NewTypeId)
+
+ TypeSpecifierAST *type_specifier;
+ NewInitializerAST *new_initializer;
+ NewDeclaratorAST *new_declarator;
+};
+
+struct OperatorAST: public AST
+{
+ DECLARE_AST_NODE(Operator)
+
+ std::size_t op;
+ std::size_t open;
+ std::size_t close;
+};
+
+struct OperatorFunctionIdAST: public AST
+{
+ DECLARE_AST_NODE(OperatorFunctionId)
+
+ OperatorAST *op;
+ TypeSpecifierAST *type_specifier;
+ const ListNode<PtrOperatorAST*> *ptr_ops;
+};
+
+struct ParameterDeclarationAST: public AST
+{
+ DECLARE_AST_NODE(ParameterDeclaration)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+ ExpressionAST *expression;
+};
+
+struct ParameterDeclarationClauseAST: public AST
+{
+ DECLARE_AST_NODE(ParameterDeclarationClause)
+
+ const ListNode<ParameterDeclarationAST*> *parameter_declarations;
+ std::size_t ellipsis;
+};
+
+struct PostfixExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(PostfixExpression)
+
+ TypeSpecifierAST *type_specifier;
+ ExpressionAST *expression;
+ const ListNode<ExpressionAST*> *sub_expressions;
+};
+
+struct PrimaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(PrimaryExpression)
+
+ StringLiteralAST *literal;
+ std::size_t token;
+ StatementAST *expression_statement;
+ ExpressionAST *sub_expression;
+ NameAST *name;
+};
+
+struct PtrOperatorAST: public AST
+{
+ DECLARE_AST_NODE(PtrOperator)
+
+ const ListNode<std::size_t> *cv;
+ std::size_t op;
+ PtrToMemberAST *mem_ptr;
+};
+
+struct PtrToMemberAST: public AST
+{
+ DECLARE_AST_NODE(PtrToMember)
+};
+
+struct ReturnStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(ReturnStatement)
+
+ ExpressionAST *expression;
+};
+
+struct SimpleDeclarationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(SimpleDeclaration)
+
+ const ListNode<std::size_t> *storage_specifiers;
+ const ListNode<std::size_t> *function_specifiers;
+ TypeSpecifierAST *type_specifier;
+ const ListNode<InitDeclaratorAST*> *init_declarators;
+ WinDeclSpecAST *win_decl_specifiers;
+};
+
+struct SimpleTypeSpecifierAST: public TypeSpecifierAST
+{
+ DECLARE_AST_NODE(SimpleTypeSpecifier)
+
+ const ListNode<std::size_t> *integrals;
+ std::size_t type_of;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+ NameAST *name;
+};
+
+struct SizeofExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(SizeofExpression)
+
+ std::size_t sizeof_token;
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct StringLiteralAST: public AST
+{
+ DECLARE_AST_NODE(StringLiteral)
+
+ const ListNode<std::size_t> *literals;
+};
+
+struct SubscriptExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(SubscriptExpression)
+
+ ExpressionAST *subscript;
+};
+
+struct SwitchStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(SwitchStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+};
+
+struct TemplateArgumentAST: public AST
+{
+ DECLARE_AST_NODE(TemplateArgument)
+
+ TypeIdAST *type_id;
+ ExpressionAST *expression;
+};
+
+struct TemplateDeclarationAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(TemplateDeclaration)
+
+ std::size_t exported;
+ const ListNode<TemplateParameterAST*> *template_parameters;
+ DeclarationAST* declaration;
+};
+
+struct TemplateParameterAST: public AST
+{
+ DECLARE_AST_NODE(TemplateParameter)
+
+ TypeParameterAST *type_parameter;
+ ParameterDeclarationAST *parameter_declaration;
+};
+
+struct ThrowExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(ThrowExpression)
+
+ std::size_t throw_token;
+ ExpressionAST *expression;
+};
+
+struct TranslationUnitAST: public AST
+{
+ DECLARE_AST_NODE(TranslationUnit)
+
+ const ListNode<DeclarationAST*> *declarations;
+};
+
+struct TryBlockStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(TryBlockStatement)
+};
+
+struct TypeIdAST: public AST
+{
+ DECLARE_AST_NODE(TypeId)
+
+ TypeSpecifierAST *type_specifier;
+ DeclaratorAST *declarator;
+};
+
+struct TypeIdentificationAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(TypeIdentification)
+
+ std::size_t typename_token;
+ NameAST *name;
+ ExpressionAST *expression;
+};
+
+struct TypeParameterAST: public AST
+{
+ DECLARE_AST_NODE(TypeParameter)
+
+ std::size_t type;
+ NameAST *name;
+ TypeIdAST *type_id;
+ const ListNode<TemplateParameterAST*> *template_parameters;
+ NameAST *template_name;
+};
+
+struct TypedefAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Typedef)
+
+ TypeSpecifierAST *type_specifier;
+ const ListNode<InitDeclaratorAST*> *init_declarators;
+};
+
+struct UnaryExpressionAST: public ExpressionAST
+{
+ DECLARE_AST_NODE(UnaryExpression)
+
+ std::size_t op;
+ ExpressionAST *expression;
+};
+
+struct UnqualifiedNameAST: public AST
+{
+ DECLARE_AST_NODE(UnqualifiedName)
+
+ std::size_t tilde;
+ std::size_t id;
+ OperatorFunctionIdAST *operator_id;
+ const ListNode<TemplateArgumentAST*> *template_arguments;
+};
+
+struct UsingAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(Using)
+
+ std::size_t type_name;
+ NameAST *name;
+};
+
+struct UsingDirectiveAST: public DeclarationAST
+{
+ DECLARE_AST_NODE(UsingDirective)
+
+ NameAST *name;
+};
+
+struct WhileStatementAST: public StatementAST
+{
+ DECLARE_AST_NODE(WhileStatement)
+
+ ConditionAST *condition;
+ StatementAST *statement;
+};
+
+struct WinDeclSpecAST: public AST
+{
+ DECLARE_AST_NODE(WinDeclSpec)
+
+ std::size_t specifier;
+ std::size_t modifier;
+};
+
+struct QPropertyAST : public DeclarationAST
+{
+ DECLARE_AST_NODE(QPropertyAST)
+};
+
+struct QEnumsAST : public DeclarationAST
+{
+ DECLARE_AST_NODE(QEnumsAST)
+};
+
+template <class _Tp>
+_Tp *CreateNode(pool *memory_pool)
+{
+ _Tp *node = reinterpret_cast<_Tp*>(memory_pool->allocate(sizeof(_Tp), strideof(_Tp)));
+ node->kind = _Tp::__node_kind;
+ return node;
+}
+
+template <class _Tp>
+_Tp ast_cast(AST *item)
+{
+ if (item && static_cast<_Tp>(0)->__node_kind == item->kind)
+ return static_cast<_Tp>(item);
+
+ return 0;
+}
+
+#endif // AST_H
diff --git a/sources/shiboken2/ApiExtractor/parser/binder.cpp b/sources/shiboken2/ApiExtractor/parser/binder.cpp
new file mode 100644
index 000000000..709f86c56
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/binder.cpp
@@ -0,0 +1,866 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "binder.h"
+#include "lexer.h"
+#include "control.h"
+#include "symbol.h"
+#include "codemodel_finder.h"
+#include "class_compiler.h"
+#include "compiler_utils.h"
+#include "tokens.h"
+#include "dumptree.h"
+
+#include <iostream>
+#include <QDebug>
+
+Binder::Binder(CodeModel *__model, LocationManager &__location, Control *__control)
+ : _M_model(__model),
+ _M_location(__location),
+ _M_token_stream(&_M_location.token_stream),
+ _M_control(__control),
+ _M_current_function_type(CodeModel::Normal),
+ type_cc(this),
+ name_cc(this),
+ decl_cc(this)
+{
+ _M_qualified_types.insert(QLatin1String("char"), QString());
+ _M_qualified_types.insert(QLatin1String("double"), QString());
+ _M_qualified_types.insert(QLatin1String("float"), QString());
+ _M_qualified_types.insert(QLatin1String("int"), QString());
+ _M_qualified_types.insert(QLatin1String("long"), QString());
+ _M_qualified_types.insert(QLatin1String("short"), QString());
+ _M_qualified_types.insert(QLatin1String("void"), QString());
+}
+
+Binder::~Binder()
+{
+}
+
+FileModelItem Binder::run(AST *node)
+{
+ FileModelItem old = _M_current_file;
+ _M_current_access = CodeModel::Public;
+
+ _M_current_file.reset(new _FileModelItem(model()));
+ updateItemPosition(_M_current_file, node);
+ visit(node);
+ FileModelItem result = _M_current_file;
+
+ _M_current_file = old; // restore
+
+ return result;
+}
+
+ScopeModelItem Binder::currentScope()
+{
+ if (_M_current_class)
+ return _M_current_class;
+ else if (_M_current_namespace)
+ return _M_current_namespace;
+
+ return _M_current_file;
+}
+
+TemplateParameterList Binder::changeTemplateParameters(TemplateParameterList templateParameters)
+{
+ TemplateParameterList old = _M_current_template_parameters;
+ _M_current_template_parameters = templateParameters;
+ return old;
+}
+
+CodeModel::FunctionType Binder::changeCurrentFunctionType(CodeModel::FunctionType functionType)
+{
+ CodeModel::FunctionType old = _M_current_function_type;
+ _M_current_function_type = functionType;
+ return old;
+}
+
+CodeModel::AccessPolicy Binder::changeCurrentAccess(CodeModel::AccessPolicy accessPolicy)
+{
+ CodeModel::AccessPolicy old = _M_current_access;
+ _M_current_access = accessPolicy;
+ return old;
+}
+
+NamespaceModelItem Binder::changeCurrentNamespace(NamespaceModelItem item)
+{
+ NamespaceModelItem old = _M_current_namespace;
+ _M_current_namespace = item;
+ return old;
+}
+
+ClassModelItem Binder::changeCurrentClass(ClassModelItem item)
+{
+ ClassModelItem old = _M_current_class;
+ _M_current_class = item;
+ return old;
+}
+
+FunctionModelItem Binder::changeCurrentFunction(FunctionModelItem item)
+{
+ FunctionModelItem old = _M_current_function;
+ _M_current_function = item;
+ return old;
+}
+
+int Binder::decode_token(std::size_t index) const
+{
+ return _M_token_stream->kind(index);
+}
+
+CodeModel::AccessPolicy Binder::decode_access_policy(std::size_t index) const
+{
+ switch (decode_token(index)) {
+ case Token_class:
+ return CodeModel::Private;
+
+ case Token_struct:
+ case Token_union:
+ return CodeModel::Public;
+
+ default:
+ return CodeModel::Public;
+ }
+}
+
+CodeModel::ClassType Binder::decode_class_type(std::size_t index) const
+{
+ switch (decode_token(index)) {
+ case Token_class:
+ return CodeModel::Class;
+ case Token_struct:
+ return CodeModel::Struct;
+ case Token_union:
+ return CodeModel::Union;
+ default:
+ std::cerr << "** WARNING unrecognized class type" << std::endl;
+ }
+ return CodeModel::Class;
+}
+
+const NameSymbol *Binder::decode_symbol(std::size_t index) const
+{
+ return _M_token_stream->symbol(index);
+}
+
+void Binder::visitAccessSpecifier(AccessSpecifierAST *node)
+{
+ const ListNode<std::size_t> *it = node->specs;
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_public:
+ changeCurrentAccess(CodeModel::Public);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_protected:
+ changeCurrentAccess(CodeModel::Protected);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_private:
+ changeCurrentAccess(CodeModel::Private);
+ changeCurrentFunctionType(CodeModel::Normal);
+ break;
+ case Token_signals:
+ changeCurrentAccess(CodeModel::Protected);
+ changeCurrentFunctionType(CodeModel::Signal);
+ break;
+ case Token_slots:
+ changeCurrentFunctionType(CodeModel::Slot);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+void Binder::visitSimpleDeclaration(SimpleDeclarationAST *node)
+{
+ visit(node->type_specifier);
+
+ if (const ListNode<InitDeclaratorAST*> *it = node->init_declarators) {
+ it = it->toFront();
+ const ListNode<InitDeclaratorAST*> *end = it;
+ do {
+ InitDeclaratorAST *init_declarator = it->element;
+ declare_symbol(node, init_declarator);
+ it = it->next;
+ } while (it != end);
+ }
+}
+
+void Binder::declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator)
+{
+ DeclaratorAST *declarator = init_declarator->declarator;
+
+ while (declarator && declarator->sub_declarator)
+ declarator = declarator->sub_declarator;
+
+ NameAST *id = declarator->id;
+ if (!declarator->id) {
+ std::cerr << "** WARNING expected a declarator id" << std::endl;
+ return;
+ }
+
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem symbolScope = finder.resolveScope(id, currentScope());
+ if (!symbolScope) {
+ name_cc.run(id);
+ std::cerr << "** WARNING scope not found for symbol:"
+ << qPrintable(name_cc.name()) << std::endl;
+ return;
+ }
+
+ decl_cc.run(declarator);
+
+ if (decl_cc.isFunction()) {
+ name_cc.run(id->unqualified_name);
+
+ FunctionModelItem fun(new _FunctionModelItem(model(), name_cc.name()));
+ updateItemPosition(fun, node);
+ fun->setAccessPolicy(_M_current_access);
+ fun->setFunctionType(_M_current_function_type);
+ fun->setAbstract(init_declarator->initializer != 0);
+ fun->setConstant(declarator->fun_cv != 0);
+ fun->setTemplateParameters(_M_current_template_parameters);
+ applyStorageSpecifiers(node->storage_specifiers, fun);
+ applyFunctionSpecifiers(node->function_specifiers, fun);
+
+ // build the type
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ declarator,
+ this);
+
+ fun->setType(qualifyType(typeInfo, symbolScope->qualifiedName()));
+
+
+ fun->setVariadics(decl_cc.isVariadics());
+
+ // ... and the signature
+ foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) {
+ ArgumentModelItem arg(new _ArgumentModelItem(model(), p.name));
+ arg->setType(qualifyType(p.type, _M_context));
+ arg->setDefaultValue(p.defaultValue);
+ if (p.defaultValue)
+ arg->setDefaultValueExpression(p.defaultValueExpression);
+ fun->addArgument(arg);
+ }
+
+ fun->setScope(symbolScope->qualifiedName());
+ symbolScope->addFunction(fun);
+ } else {
+ VariableModelItem var(new _VariableModelItem(model()));
+ updateItemPosition(var, node);
+ var->setTemplateParameters(_M_current_template_parameters);
+ var->setAccessPolicy(_M_current_access);
+ name_cc.run(id->unqualified_name);
+ var->setName(name_cc.name());
+ // Possible bug, because second parameter uses declarator instead of
+ // init_declarator->declarator like in DeclaratorCompiler::visitParameterDeclaration,
+ // but it doesn't seem to affect anything because the generator doesn't currently use
+ // variable declarations, only function declarations (because it cares about the API only,
+ // variable declarations are not exposed to the target language).
+ // See PYSIDE-455.
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ declarator,
+ this);
+ if (declarator != init_declarator->declarator
+ && init_declarator->declarator->parameter_declaration_clause) {
+ typeInfo.setFunctionPointer(true);
+ decl_cc.run(init_declarator->declarator);
+ foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters())
+ typeInfo.addArgument(p.type);
+ }
+
+ var->setType(qualifyType(typeInfo, _M_context));
+ applyStorageSpecifiers(node->storage_specifiers, var);
+
+ var->setScope(symbolScope->qualifiedName());
+ symbolScope->addVariable(var);
+ }
+}
+
+void Binder::visitFunctionDefinition(FunctionDefinitionAST *node)
+{
+ Q_ASSERT(node->init_declarator);
+
+ ScopeModelItem scope = currentScope();
+
+ InitDeclaratorAST *init_declarator = node->init_declarator;
+ DeclaratorAST *declarator = init_declarator->declarator;
+
+ // in the case of "void (func)()" or "void ((func))()" we need to
+ // skip to the inner most. This is in line with how the declarator
+ // node is generated in 'parser.cpp'
+ while (declarator && declarator->sub_declarator)
+ declarator = declarator->sub_declarator;
+ if (!declarator->id) {
+ std::cerr << "** WARNING temp hack for Qt 5.6.0: "
+ << "skipped a class that inherits from a private class"
+ << std::endl;
+ return;
+ }
+ Q_ASSERT(declarator->id);
+
+ CodeModelFinder finder(model(), this);
+
+ ScopeModelItem functionScope = finder.resolveScope(declarator->id, scope);
+ if (!functionScope) {
+ name_cc.run(declarator->id);
+ std::cerr << "** WARNING scope not found for function definition:"
+ << qPrintable(name_cc.name()) << std::endl
+ << "\tdefinition *ignored*"
+ << std::endl;
+ return;
+ }
+
+ decl_cc.run(declarator);
+
+ Q_ASSERT(!decl_cc.id().isEmpty());
+
+ FunctionModelItem
+ old = changeCurrentFunction(FunctionModelItem(new _FunctionModelItem(_M_model)));
+ _M_current_function->setScope(functionScope->qualifiedName());
+ updateItemPosition(_M_current_function, node);
+
+ Q_ASSERT(declarator->id->unqualified_name);
+ name_cc.run(declarator->id->unqualified_name);
+ QString unqualified_name = name_cc.name();
+
+ _M_current_function->setName(unqualified_name);
+ TypeInfo tmp_type = CompilerUtils::typeDescription(node->type_specifier,
+ declarator, this);
+
+ _M_current_function->setType(qualifyType(tmp_type, _M_context));
+ _M_current_function->setAccessPolicy(_M_current_access);
+ _M_current_function->setFunctionType(_M_current_function_type);
+ _M_current_function->setConstant(declarator->fun_cv);
+ _M_current_function->setTemplateParameters(_M_current_template_parameters);
+
+ applyStorageSpecifiers(node->storage_specifiers,
+ _M_current_function);
+ applyFunctionSpecifiers(node->function_specifiers,
+ _M_current_function);
+
+ _M_current_function->setVariadics(decl_cc.isVariadics());
+
+ foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters()) {
+ ArgumentModelItem arg(new _ArgumentModelItem(model(), p.name));
+ arg->setType(qualifyType(p.type, functionScope->qualifiedName()));
+ arg->setDefaultValue(p.defaultValue);
+ if (p.defaultValue)
+ arg->setDefaultValueExpression(p.defaultValueExpression);
+ _M_current_function->addArgument(arg);
+ }
+
+ FunctionModelItem prototype = _M_current_function;
+ FunctionModelItem declared = functionScope->declaredFunction(prototype);
+
+ // try to find a function declaration for this definition..
+ if (!declared) {
+ functionScope->addFunction(prototype);
+ } else {
+ applyFunctionSpecifiers(node->function_specifiers, declared);
+
+ // fix the function type and the access policy
+ _M_current_function->setAccessPolicy(declared->accessPolicy());
+ _M_current_function->setFunctionType(declared->functionType());
+ }
+
+ changeCurrentFunction(old);
+}
+
+void Binder::visitTemplateDeclaration(TemplateDeclarationAST *node)
+{
+ const ListNode<TemplateParameterAST*> *it = node->template_parameters;
+ if (!it) {
+ // QtScript: we want to visit the declaration still, so that
+ // e.g. QMetaTypeId<Foo> is added to the code model
+ visit(node->declaration);
+ return;
+ }
+
+ TemplateParameterList savedTemplateParameters = changeTemplateParameters(TemplateParameterList());
+
+ it = it->toFront();
+ const ListNode<TemplateParameterAST*> *end = it;
+
+ TemplateParameterList templateParameters;
+ do {
+ TemplateParameterAST *parameter = it->element;
+ TypeParameterAST *type_parameter = parameter->type_parameter;
+
+ NameAST *name;
+ if (!type_parameter) {
+ // A hacky hack to work around missing support for parameter declarations in
+ // templates. We just need the to get the name of the variable, since we
+ // aren't actually compiling these anyway. We are still not supporting much
+ // more, but we are refusing to fail for a few more declarations
+ if (!parameter->parameter_declaration ||
+ !parameter->parameter_declaration->declarator ||
+ !parameter->parameter_declaration->declarator->id) {
+
+ /*std::cerr << "** WARNING template declaration not supported ``";
+ Token const &tk = _M_token_stream->token ((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
+
+ std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
+ << std::endl << std::endl;*/
+
+ changeTemplateParameters(savedTemplateParameters);
+ return;
+
+ }
+
+ name = parameter->parameter_declaration->declarator->id;
+ } else {
+ int tk = decode_token(type_parameter->type);
+ if (tk != Token_typename && tk != Token_class) {
+ /*std::cerr << "** WARNING template declaration not supported ``";
+ Token const &tk = _M_token_stream->token ((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token ((int) node->declaration->start_token);
+
+ std::cerr << std::string (&tk.text[tk.position], (end_tk.position) - tk.position) << "''"
+ << std::endl << std::endl;*/
+
+ changeTemplateParameters(savedTemplateParameters);
+ return;
+ }
+ assert(tk == Token_typename || tk == Token_class);
+
+ name = type_parameter->name;
+ }
+
+
+ name_cc.run(name);
+ const TemplateParameterModelItem p(new _TemplateParameterModelItem(model(), name_cc.name()));
+ _M_current_template_parameters.append(p);
+ it = it->next;
+ } while (it != end);
+
+ visit(node->declaration);
+
+ changeTemplateParameters(savedTemplateParameters);
+}
+
+void Binder::visitTypedef(TypedefAST *node)
+{
+ const ListNode<InitDeclaratorAST*> *it = node->init_declarators;
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<InitDeclaratorAST*> *end = it;
+
+ do {
+ InitDeclaratorAST *init_declarator = it->element;
+ it = it->next;
+
+ Q_ASSERT(init_declarator->declarator);
+
+ // the name
+ decl_cc.run(init_declarator->declarator);
+ QString alias_name = decl_cc.id();
+
+ if (alias_name.isEmpty()) {
+ std::cerr << "** WARNING anonymous typedef not supported! ``";
+ Token const &tk = _M_token_stream->token((int) node->start_token);
+ Token const &end_tk = _M_token_stream->token((int) node->end_token);
+
+ std::cerr << std::string(&tk.text[tk.position], end_tk.position - tk.position) << "''"
+ << std::endl << std::endl;
+ continue;
+ }
+
+ // build the type
+ TypeInfo typeInfo = CompilerUtils::typeDescription(node->type_specifier,
+ init_declarator->declarator,
+ this);
+ DeclaratorAST *decl = init_declarator->declarator;
+ while (decl && decl->sub_declarator)
+ decl = decl->sub_declarator;
+
+ if (decl != init_declarator->declarator
+ && init_declarator->declarator->parameter_declaration_clause) {
+ typeInfo.setFunctionPointer(true);
+ decl_cc.run(init_declarator->declarator);
+ foreach (const DeclaratorCompiler::Parameter &p, decl_cc.parameters())
+ typeInfo.addArgument(p.type);
+ }
+
+ ScopeModelItem scope = currentScope();
+ DeclaratorAST *declarator = init_declarator->declarator;
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem typedefScope = finder.resolveScope(declarator->id, scope);
+
+ TypeDefModelItem typeDef(new _TypeDefModelItem(model()));
+ updateItemPosition(typeDef, node);
+ typeDef->setName(alias_name);
+ typeDef->setType(qualifyType(typeInfo, currentScope()->qualifiedName()));
+ typeDef->setScope(typedefScope->qualifiedName());
+ _M_qualified_types[typeDef->qualifiedName().join(QLatin1Char('.'))] = QString();
+ currentScope()->addTypeDef(typeDef);
+ } while (it != end);
+}
+
+void Binder::visitNamespace(NamespaceAST *node)
+{
+ bool anonymous = (node->namespace_name == 0);
+
+ ScopeModelItem scope = currentScope();
+
+ NamespaceModelItem old;
+ if (!anonymous) {
+ QString name = decode_symbol(node->namespace_name)->as_string();
+
+ QStringList qualified_name = scope->qualifiedName();
+ qualified_name += name;
+ const CodeModelItem nsI = _M_model->findItem(qualified_name, _M_current_file);
+ NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(nsI);
+ if (!ns) {
+ ns.reset(new _NamespaceModelItem(_M_model));
+ updateItemPosition(ns, node);
+ ns->setName(name);
+ ns->setScope(scope->qualifiedName());
+ }
+ old = changeCurrentNamespace(ns);
+
+ _M_context.append(name);
+ }
+
+ DefaultVisitor::visitNamespace(node);
+
+ if (!anonymous) {
+ Q_ASSERT(scope->kind() == _CodeModelItem::Kind_Namespace
+ || scope->kind() == _CodeModelItem::Kind_File);
+
+ _M_context.removeLast();
+
+ if (const NamespaceModelItem ns = qSharedPointerDynamicCast<_NamespaceModelItem>(scope))
+ ns->addNamespace(_M_current_namespace);
+
+ changeCurrentNamespace(old);
+ }
+}
+
+void Binder::visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ if (name_cc.name().isEmpty())
+ return;
+
+ ScopeModelItem scope = currentScope();
+ _M_qualified_types[(scope->qualifiedName() + name_cc.qualifiedName()).join(QLatin1Char('.'))] = QString();
+}
+
+void Binder::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ ClassCompiler class_cc(this);
+ class_cc.run(node);
+
+ if (class_cc.name().isEmpty()) {
+ // anonymous not supported
+ return;
+ }
+
+ Q_ASSERT(node->name && node->name->unqualified_name);
+
+ ScopeModelItem scope = currentScope();
+
+ ClassModelItem old = changeCurrentClass(ClassModelItem(new _ClassModelItem(_M_model)));
+ updateItemPosition(_M_current_class, node);
+ _M_current_class->setName(class_cc.name());
+
+ QStringList baseClasses = class_cc.baseClasses();
+ TypeInfo info;
+ for (int i = 0; i < baseClasses.size(); ++i) {
+ info.setQualifiedName(baseClasses.at(i).split(QLatin1String("::")));
+ baseClasses[i] = qualifyType(info, scope->qualifiedName()).qualifiedName().join(QLatin1String("::"));
+ }
+
+ _M_current_class->setBaseClasses(baseClasses);
+ _M_current_class->setClassType(decode_class_type(node->class_key));
+ _M_current_class->setTemplateParameters(_M_current_template_parameters);
+
+ if (!_M_current_template_parameters.isEmpty()) {
+ QString name = _M_current_class->name();
+ name += QLatin1Char('<');
+ for (int i = 0; i < _M_current_template_parameters.size(); ++i) {
+ if (i > 0)
+ name += QLatin1Char(',');
+
+ name += _M_current_template_parameters.at(i)->name();
+ }
+
+ name += QLatin1Char('>');
+ _M_current_class->setName(name);
+ }
+
+ CodeModel::AccessPolicy oldAccessPolicy = changeCurrentAccess(decode_access_policy(node->class_key));
+ CodeModel::FunctionType oldFunctionType = changeCurrentFunctionType(CodeModel::Normal);
+
+ _M_current_class->setScope(scope->qualifiedName());
+ _M_qualified_types[_M_current_class->qualifiedName().join(QLatin1Char('.'))] = QString();
+
+ scope->addClass(_M_current_class);
+
+ name_cc.run(node->name->unqualified_name);
+ _M_context.append(name_cc.name());
+ visitNodes(this, node->member_specs);
+ _M_context.removeLast();
+
+ changeCurrentClass(old);
+ changeCurrentAccess(oldAccessPolicy);
+ changeCurrentFunctionType(oldFunctionType);
+}
+
+void Binder::visitLinkageSpecification(LinkageSpecificationAST *node)
+{
+ DefaultVisitor::visitLinkageSpecification(node);
+}
+
+void Binder::visitUsing(UsingAST *node)
+{
+ DefaultVisitor::visitUsing(node);
+}
+
+void Binder::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ CodeModelFinder finder(model(), this);
+ ScopeModelItem scope = currentScope();
+ ScopeModelItem enumScope = finder.resolveScope(node->name, scope);
+
+ name_cc.run(node->name);
+ QString name = name_cc.name();
+
+ bool isAnonymous = name.isEmpty();
+ if (isAnonymous) {
+ // anonymous enum
+ QString key = _M_context.join(QLatin1String("::"));
+ int current = ++_M_anonymous_enums[key];
+ name += QLatin1String("enum_");
+ name += QString::number(current);
+ }
+
+ _M_current_enum.reset(new _EnumModelItem(model()));
+ _M_current_enum->setAccessPolicy(_M_current_access);
+ updateItemPosition(_M_current_enum, node);
+ _M_current_enum->setName(name);
+ _M_current_enum->setAnonymous(isAnonymous);
+ _M_current_enum->setScope(enumScope->qualifiedName());
+
+ _M_qualified_types[_M_current_enum->qualifiedName().join(QLatin1Char('.'))] = QString();
+
+ enumScope->addEnum(_M_current_enum);
+
+ DefaultVisitor::visitEnumSpecifier(node);
+
+ _M_current_enum.clear();
+}
+
+static QString strip_preprocessor_lines(const QString &name)
+{
+ QStringList lst = name.split(QLatin1Char('\n'));
+ QString s;
+ for (int i = 0; i < lst.size(); ++i) {
+ if (!lst.at(i).startsWith(QLatin1Char('#')))
+ s += lst.at(i);
+ }
+ return s.trimmed();
+}
+
+void Binder::visitEnumerator(EnumeratorAST *node)
+{
+ Q_ASSERT(_M_current_enum);
+ EnumeratorModelItem e(new _EnumeratorModelItem(model()));
+ updateItemPosition(e, node);
+ e->setName(decode_symbol(node->id)->as_string());
+
+ if (ExpressionAST *expr = node->expression) {
+ const Token &start_token = _M_token_stream->token((int) expr->start_token);
+ const Token &end_token = _M_token_stream->token((int) expr->end_token);
+ const QString token = QString::fromUtf8(&start_token.text[start_token.position],
+ (int)(end_token.position - start_token.position));
+ QString lines = strip_preprocessor_lines(token.trimmed());
+ lines.remove(QLatin1Char(' '));
+ e->setValue(lines);
+ }
+
+ _M_current_enum->addEnumerator(e);
+}
+
+void Binder::visitUsingDirective(UsingDirectiveAST *node)
+{
+ DefaultVisitor::visitUsingDirective(node);
+}
+
+void Binder::visitQEnums(QEnumsAST *node)
+{
+ const Token &start = _M_token_stream->token((int) node->start_token);
+ const Token &end = _M_token_stream->token((int) node->end_token);
+ QStringList enum_list = QString::fromLatin1(start.text + start.position,
+ end.position - start.position).split(QLatin1Char(' '));
+
+ ScopeModelItem scope = currentScope();
+ for (int i = 0; i < enum_list.size(); ++i)
+ scope->addEnumsDeclaration(enum_list.at(i));
+}
+
+void Binder::visitQProperty(QPropertyAST *node)
+{
+ const Token &start = _M_token_stream->token((int) node->start_token);
+ const Token &end = _M_token_stream->token((int) node->end_token);
+ QString property = QString::fromLatin1(start.text + start.position,
+ end.position - start.position);
+ _M_current_class->addPropertyDeclaration(property);
+}
+
+void Binder::applyStorageSpecifiers(const ListNode<std::size_t> *it, MemberModelItem item)
+{
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_friend:
+ item->setFriend(true);
+ break;
+ case Token_auto:
+ item->setAuto(true);
+ break;
+ case Token_register:
+ item->setRegister(true);
+ break;
+ case Token_static:
+ item->setStatic(true);
+ break;
+ case Token_extern:
+ item->setExtern(true);
+ break;
+ case Token_mutable:
+ item->setMutable(true);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+void Binder::applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item)
+{
+ if (!it)
+ return;
+
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+
+ do {
+ switch (decode_token(it->element)) {
+ default:
+ break;
+
+ case Token_inline:
+ item->setInline(true);
+ break;
+
+ case Token_virtual:
+ item->setVirtual(true);
+ break;
+
+ case Token_explicit:
+ item->setExplicit(true);
+ break;
+
+ case Token_Q_INVOKABLE:
+ item->setInvokable(true);
+ break;
+ }
+ it = it->next;
+ } while (it != end);
+}
+
+TypeInfo Binder::qualifyType(const TypeInfo &type, const QStringList &context) const
+{
+ // ### Potentially improve to use string list in the name table to
+ if (!context.size()) {
+ // ### We can assume that this means global namespace for now...
+ return type;
+ } else if (_M_qualified_types.contains(type.qualifiedName().join(QLatin1Char('.')))) {
+ return type;
+ } else {
+ QStringList expanded = context;
+ expanded << type.qualifiedName();
+ if (_M_qualified_types.contains(expanded.join(QLatin1Char('.')))) {
+ TypeInfo modified_type = type;
+ modified_type.setQualifiedName(expanded);
+ return modified_type;
+ } else {
+ CodeModelItem scope = model()->findItem(context, _M_current_file);
+
+ if (ClassModelItem klass = qSharedPointerDynamicCast<_ClassModelItem>(scope)) {
+ foreach (const QString &base, klass->baseClasses()) {
+ QStringList ctx = context;
+ ctx.removeLast();
+ ctx.append(base);
+
+ TypeInfo qualified = qualifyType(type, ctx);
+ if (qualified != type)
+ return qualified;
+ }
+ }
+
+ QStringList copy = context;
+ copy.removeLast();
+ return qualifyType(type, copy);
+ }
+ }
+}
+
+void Binder::updateItemPosition(CodeModelItem item, AST *node)
+{
+ QString filename;
+ int line, column;
+
+ assert(node);
+ _M_location.positionAt(_M_token_stream->position(node->start_token), &line, &column, &filename);
+ item->setFileName(filename);
+}
diff --git a/sources/shiboken2/ApiExtractor/parser/binder.h b/sources/shiboken2/ApiExtractor/parser/binder.h
new file mode 100644
index 000000000..cd8d93a95
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/binder.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 BINDER_H
+#define BINDER_H
+
+#include "default_visitor.h"
+#include "codemodel.h"
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "declarator_compiler.h"
+
+class TokenStream;
+class LocationManager;
+class Control;
+struct NameSymbol;
+
+class Binder: protected DefaultVisitor
+{
+public:
+ Binder(CodeModel *__model, LocationManager &__location, Control *__control = 0);
+ virtual ~Binder();
+
+ inline TokenStream *tokenStream() const
+ {
+ return _M_token_stream;
+ }
+
+ inline CodeModel *model() const
+ {
+ return _M_model;
+ }
+
+ ScopeModelItem currentScope();
+
+ FileModelItem run(AST *node);
+
+// utils
+ TypeInfo qualifyType(const TypeInfo &type, const QStringList &context) const;
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *);
+ virtual void visitClassSpecifier(ClassSpecifierAST *);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *);
+ virtual void visitEnumerator(EnumeratorAST *);
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *);
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *);
+ virtual void visitNamespace(NamespaceAST *);
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *);
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *);
+ virtual void visitTypedef(TypedefAST *);
+ virtual void visitUsing(UsingAST *);
+ virtual void visitUsingDirective(UsingDirectiveAST *);
+ virtual void visitQProperty(QPropertyAST *);
+ virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *);
+ virtual void visitQEnums(QEnumsAST *);
+
+private:
+
+ int decode_token(std::size_t index) const;
+ const NameSymbol *decode_symbol(std::size_t index) const;
+ CodeModel::AccessPolicy decode_access_policy(std::size_t index) const;
+ CodeModel::ClassType decode_class_type(std::size_t index) const;
+
+ CodeModel::FunctionType changeCurrentFunctionType(CodeModel::FunctionType functionType);
+ CodeModel::AccessPolicy changeCurrentAccess(CodeModel::AccessPolicy accessPolicy);
+ NamespaceModelItem changeCurrentNamespace(NamespaceModelItem item);
+ ClassModelItem changeCurrentClass(ClassModelItem item);
+ FunctionModelItem changeCurrentFunction(FunctionModelItem item);
+ TemplateParameterList changeTemplateParameters(TemplateParameterList templateParameters);
+
+ void declare_symbol(SimpleDeclarationAST *node, InitDeclaratorAST *init_declarator);
+
+ void applyStorageSpecifiers(const ListNode<std::size_t> *storage_specifiers, MemberModelItem item);
+ void applyFunctionSpecifiers(const ListNode<std::size_t> *it, FunctionModelItem item);
+
+ void updateItemPosition(CodeModelItem item, AST *node);
+
+private:
+ CodeModel *_M_model;
+ LocationManager &_M_location;
+ TokenStream *_M_token_stream;
+ Control *_M_control;
+
+ CodeModel::FunctionType _M_current_function_type;
+ CodeModel::AccessPolicy _M_current_access;
+ FileModelItem _M_current_file;
+ NamespaceModelItem _M_current_namespace;
+ ClassModelItem _M_current_class;
+ FunctionModelItem _M_current_function;
+ EnumModelItem _M_current_enum;
+ QStringList _M_context;
+ TemplateParameterList _M_current_template_parameters; // ### check me
+ QHash<QString, QString> _M_qualified_types;
+ QHash<QString, int> _M_anonymous_enums;
+ void dummy() {
+ _M_control=0;
+ }
+
+protected:
+ TypeCompiler type_cc;
+ NameCompiler name_cc;
+ DeclaratorCompiler decl_cc;
+};
+
+#endif // BINDER_H
diff --git a/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp
new file mode 100644
index 000000000..3387412ff
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/class_compiler.cpp
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "class_compiler.h"
+#include "lexer.h"
+#include "binder.h"
+
+ClassCompiler::ClassCompiler(Binder *binder)
+ : _M_binder(binder),
+ _M_token_stream(binder->tokenStream()),
+ name_cc(_M_binder),
+ type_cc(_M_binder)
+{
+}
+
+ClassCompiler::~ClassCompiler()
+{
+}
+
+void ClassCompiler::run(ClassSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ _M_name = name_cc.name();
+ _M_base_classes.clear();
+
+ visit(node);
+}
+
+void ClassCompiler::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->base_clause);
+}
+
+void ClassCompiler::visitBaseSpecifier(BaseSpecifierAST *node)
+{
+ name_cc.run(node->name);
+ QString name = name_cc.name();
+
+ if (!name.isEmpty())
+ _M_base_classes.append(name);
+}
+
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/class_compiler.h b/sources/shiboken2/ApiExtractor/parser/class_compiler.h
new file mode 100644
index 000000000..09b727fe6
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/class_compiler.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 CLASS_COMPILER_H
+#define CLASS_COMPILER_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/QStringList>
+
+#include <default_visitor.h>
+#include <name_compiler.h>
+#include <type_compiler.h>
+
+class TokenStream;
+class Binder;
+
+class ClassCompiler: protected DefaultVisitor
+{
+public:
+ ClassCompiler(Binder *binder);
+ virtual ~ClassCompiler();
+
+ inline QString name() const
+ {
+ return _M_name;
+ }
+
+ inline QStringList baseClasses() const
+ {
+ return _M_base_classes;
+ }
+
+ void run(ClassSpecifierAST *node);
+
+protected:
+ virtual void visitClassSpecifier(ClassSpecifierAST *node);
+ virtual void visitBaseSpecifier(BaseSpecifierAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QString _M_name;
+ QStringList _M_base_classes;
+ NameCompiler name_cc;
+ TypeCompiler type_cc;
+};
+
+#endif // CLASS_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
new file mode 100644
index 000000000..a5024c4a3
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp
@@ -0,0 +1,1199 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 <algorithm>
+#include <functional>
+#include <iostream>
+#include <QDebug>
+#include <QDir>
+
+// Predicate to find an item by name in a list of QSharedPointer<Item>
+template <class T> class ModelItemNamePredicate : public std::unary_function<bool, QSharedPointer<T> >
+{
+public:
+ explicit ModelItemNamePredicate(const QString &name) : m_name(name) {}
+ bool operator()(const QSharedPointer<T> &item) const { return item->name() == m_name; }
+
+private:
+ const QString m_name;
+};
+
+template <class T>
+static QSharedPointer<T> findModelItem(const QList<QSharedPointer<T> > &list, const QString &name)
+{
+ typedef typename QList<QSharedPointer<T> >::const_iterator It;
+ const It it = std::find_if(list.begin(), list.end(), ModelItemNamePredicate<T>(name));
+ return it != list.end() ? *it : QSharedPointer<T>();
+}
+
+// ---------------------------------------------------------------------------
+
+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(')');
+ }
+
+ foreach(QString elt, arrayElements()) {
+ tmp += QLatin1Char('[');
+ tmp += elt;
+ tmp += QLatin1Char(']');
+ }
+
+ return tmp;
+}
+
+bool TypeInfo::operator==(const TypeInfo &other)
+{
+ 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 <class It>
+void formatSequence(QDebug &d, It i1, It i2, const char *separator=", ")
+{
+ for (It i = i1; i != i2; ++i) {
+ if (i != i1)
+ d << separator;
+ d << *i;
+ }
+}
+
+void TypeInfo::formatDebug(QDebug &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 <class It>
+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 <class List>
+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)
+{
+ foreach (const FunctionModelItem &fun, 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 <class Hash>
+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 <class List>
+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<T>" (as seen for methods
+// from within the class "Vector").
+class ClassNamePredicate : public std::unary_function<bool, ClassModelItem>
+{
+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;
+ foreach (const FunctionModelItem &func, m_functions) {
+ if (func->name() == name)
+ result.append(func);
+ }
+ return result;
+}
+
+// ---------------------------------------------------------------------------
+_NamespaceModelItem::~_NamespaceModelItem()
+{
+}
+
+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..811cfec3e
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h
@@ -0,0 +1,691 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 <QtCore/QHash>
+#include <QtCore/QList>
+#include <QtCore/QSet>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVector>
+
+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;
+ }
+
+ QList<TypeInfo> arguments() const
+ {
+ return m_arguments;
+ }
+
+ void setArguments(const QList<TypeInfo> &arguments);
+
+ void addArgument(const TypeInfo &arg)
+ {
+ m_arguments.append(arg);
+ }
+
+ bool operator==(const TypeInfo &other);
+
+ bool operator!=(const TypeInfo &other)
+ {
+ 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;
+ QList<TypeInfo> 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 Q_DECL_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 Q_DECL_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<NamespaceModelItem> uniqueNamespaces() const { return m_namespaces.toSet(); }
+
+ void addNamespace(NamespaceModelItem item);
+
+ NamespaceModelItem findNamespace(const QString &name) const;
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const Q_DECL_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 Q_DECL_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 Q_DECL_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 Q_DECL_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 Q_DECL_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 Q_DECL_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 Q_DECL_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 Q_DECL_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_finder.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp
new file mode 100644
index 000000000..57f8ae0cf
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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_finder.h"
+#include "codemodel.h"
+#include "binder.h"
+
+CodeModelFinder::CodeModelFinder(CodeModel *model, Binder *binder)
+ : _M_model(model),
+ _M_binder(binder),
+ _M_token_stream(binder->tokenStream()),
+ name_cc(_M_binder),
+ _M_resolve_policy(ResolveItem)
+{
+}
+
+CodeModelFinder::~CodeModelFinder()
+{
+}
+
+ScopeModelItem CodeModelFinder::resolveScope(NameAST *name, ScopeModelItem scope)
+{
+ Q_ASSERT(scope);
+
+ ResolvePolicy saved_resolve_policy = _M_resolve_policy;
+ _M_resolve_policy = ResolveScope;
+
+ ScopeModelItem old = changeCurrentScope(scope);
+
+ visit(name);
+ ScopeModelItem result = _M_current_scope;
+
+ changeCurrentScope(old); // restore
+
+ _M_resolve_policy = saved_resolve_policy;
+
+ return result;
+}
+
+ScopeModelItem CodeModelFinder::changeCurrentScope(ScopeModelItem scope)
+{
+ ScopeModelItem old = _M_current_scope;
+ _M_current_scope = scope;
+ return old;
+}
+
+void CodeModelFinder::visitName(NameAST *node)
+{
+ visitNodes(this, node->qualified_names);
+
+ if (_M_resolve_policy == ResolveItem)
+ visit(node->unqualified_name);
+}
+
+void CodeModelFinder::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ if (!_M_current_scope) {
+ // nothing to do
+ return;
+ }
+
+ name_cc.run(node);
+ QString id = name_cc.name();
+
+ if (ClassModelItem klass = _M_current_scope->findClass(id)) {
+ _M_current_scope = klass;
+ } else if (NamespaceModelItem parentNamespace = qSharedPointerDynamicCast<_NamespaceModelItem>(_M_current_scope)) {
+ NamespaceModelItem ns = parentNamespace->findNamespace(id);
+ _M_current_scope = ns;
+ } else if (FileModelItem file = qSharedPointerDynamicCast<_FileModelItem>(_M_current_scope)) {
+ NamespaceModelItem ns = file->findNamespace(id);
+ _M_current_scope = ns;
+ }
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h
new file mode 100644
index 000000000..0217cbac6
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/codemodel_finder.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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_FINDER_H
+#define CODEMODEL_FINDER_H
+
+#include <default_visitor.h>
+#include <codemodel_fwd.h>
+#include <name_compiler.h>
+
+class TokenStream;
+class Binder;
+
+class CodeModelFinder: protected DefaultVisitor
+{
+ enum ResolvePolicy {
+ ResolveScope,
+ ResolveItem
+ };
+
+public:
+ CodeModelFinder(CodeModel *model, Binder *binder);
+ virtual ~CodeModelFinder();
+
+ ScopeModelItem resolveScope(NameAST *name, ScopeModelItem scope);
+
+ inline CodeModel *model() const
+ {
+ return _M_model;
+ }
+
+protected:
+ virtual void visitName(NameAST *node);
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *node);
+
+ ScopeModelItem changeCurrentScope(ScopeModelItem scope);
+
+private:
+ CodeModel *_M_model;
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ NameCompiler name_cc;
+
+ ScopeModelItem _M_current_scope;
+ ResolvePolicy _M_resolve_policy;
+};
+
+#endif // CODEMODEL_FINDER_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..676bda872
--- /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 <roberto@kdevelop.org>
+** 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 <QtCore/QList>
+#include <QtCore/QSharedPointer>
+
+// 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 QList<ArgumentModelItem> ArgumentList;
+typedef QList<ClassModelItem> ClassList;
+typedef QList<CodeModelItem> ItemList;
+typedef QList<EnumModelItem> EnumList;
+typedef QList<EnumeratorModelItem> EnumeratorList;
+typedef QList<FileModelItem> FileList;
+typedef QList<FunctionModelItem> FunctionList;
+typedef QList<NamespaceModelItem> NamespaceList;
+typedef QList<ScopeModelItem> ScopeList;
+typedef QList<TemplateParameterModelItem> TemplateParameterList;
+typedef QList<TypeDefModelItem> TypeDefList;
+typedef QList<VariableModelItem> VariableList;
+typedef QList<MemberModelItem> MemberList;
+
+#endif // CODEMODEL_FWD_H
diff --git a/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp b/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp
new file mode 100644
index 000000000..95a9db6c3
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/compiler_utils.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "compiler_utils.h"
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "declarator_compiler.h"
+#include "ast.h"
+#include "binder.h"
+
+TypeInfo CompilerUtils::typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder)
+{
+ TypeCompiler type_cc(binder);
+ DeclaratorCompiler decl_cc(binder);
+
+ type_cc.run(type_specifier);
+ decl_cc.run(declarator);
+
+ TypeInfo typeInfo;
+ typeInfo.setQualifiedName(type_cc.qualifiedName());
+ typeInfo.setConstant(type_cc.isConstant());
+ typeInfo.setVolatile(type_cc.isVolatile());
+ typeInfo.setReferenceType(decl_cc.isReference() ? LValueReference : NoReference);
+ typeInfo.setIndirections(decl_cc.indirection());
+ typeInfo.setArrayElements(decl_cc.arrayElements());
+
+ return typeInfo;
+}
diff --git a/sources/shiboken2/ApiExtractor/parser/compiler_utils.h b/sources/shiboken2/ApiExtractor/parser/compiler_utils.h
new file mode 100644
index 000000000..849baf5aa
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/compiler_utils.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 COMPILER_UTILS_H
+#define COMPILER_UTILS_H
+
+#include <utility>
+
+#include "codemodel.h"
+
+struct TypeSpecifierAST;
+struct DeclaratorAST;
+class TokenStream;
+class Binder;
+
+namespace CompilerUtils
+{
+
+TypeInfo typeDescription(TypeSpecifierAST *type_specifier, DeclaratorAST *declarator, Binder *binder);
+
+} // namespace CompilerUtils
+
+#endif // COMPILER_UTILS_H
diff --git a/sources/shiboken2/ApiExtractor/parser/control.cpp b/sources/shiboken2/ApiExtractor/parser/control.cpp
new file mode 100644
index 000000000..f86fa16bb
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/control.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "control.h"
+#include "lexer.h"
+
+Control::Control()
+ : current_context(0),
+ _M_skipFunctionBody(false),
+ _M_lexer(0),
+ _M_parser(0)
+{
+ pushContext();
+
+ declareTypedef(findOrInsertName("__builtin_va_list",
+ strlen("__builtin_va_list")), 0);
+}
+
+Control::~Control()
+{
+ popContext();
+
+ Q_ASSERT(current_context == 0);
+}
+
+Lexer *Control::changeLexer(Lexer *lexer)
+{
+ Lexer *old = _M_lexer;
+ _M_lexer = lexer;
+ return old;
+}
+
+Parser *Control::changeParser(Parser *parser)
+{
+ Parser *old = _M_parser;
+ _M_parser = parser;
+ return old;
+}
+
+Type *Control::lookupType(const NameSymbol *name) const
+{
+ Q_ASSERT(current_context != 0);
+
+ return current_context->resolve(name);
+}
+
+void Control::declare(const NameSymbol *name, Type *type)
+{
+ //printf("*** Declare:");
+ //printSymbol(name);
+ //putchar('\n');
+ Q_ASSERT(current_context != 0);
+
+ current_context->bind(name, type);
+}
+
+void Control::pushContext()
+{
+ // printf("+Context\n");
+ Context *new_context = new Context;
+ new_context->parent = current_context;
+ current_context = new_context;
+}
+
+void Control::popContext()
+{
+ // printf("-Context\n");
+ Q_ASSERT(current_context != 0);
+
+ Context *old_context = current_context;
+ current_context = current_context->parent;
+
+ delete old_context;
+}
+
+void Control::declareTypedef(const NameSymbol *name, Declarator *d)
+{
+ // printf("declared typedef:");
+ // printSymbol(name);
+ // printf("\n");
+ stl_typedef_table.insert(name, d);
+}
+
+bool Control::isTypedef(const NameSymbol *name) const
+{
+ // printf("is typedef:");
+ // printSymbol(name);
+ // printf("= %d\n", (stl_typedef_table.find(name) != stl_typedef_table.end()));
+
+ return stl_typedef_table.contains(name);
+}
+
+QList<Control::ErrorMessage> Control::errorMessages() const
+{
+ return _M_error_messages;
+}
+
+void Control::clearErrorMessages()
+{
+ _M_error_messages.clear();
+}
+
+void Control::reportError(const ErrorMessage &errmsg)
+{
+ _M_error_messages.append(errmsg);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/control.h b/sources/shiboken2/ApiExtractor/parser/control.h
new file mode 100644
index 000000000..92635299e
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/control.h
@@ -0,0 +1,165 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 CONTROL_H
+#define CONTROL_H
+
+#include "symbol.h"
+#include "smallobject.h"
+
+#include <QtCore/QHash>
+
+struct Declarator;
+struct Type;
+class Lexer;
+class Parser;
+
+struct Context {
+ Context *parent;
+
+ inline void bind(const NameSymbol *name, Type *type) {
+ symbol_table.insert(name, type);
+ }
+
+ inline Type *resolve(const NameSymbol *name) const {
+ if (Type *type = symbol_table.value(name))
+ return type;
+ else if (parent)
+ return parent->resolve(name);
+
+ return 0;
+ }
+
+ typedef QHash<const NameSymbol*, Type*> symbol_table_t;
+
+ symbol_table_t symbol_table;
+};
+
+class Control
+{
+public:
+ class ErrorMessage
+ {
+ public:
+ ErrorMessage():
+ _M_line(0),
+ _M_column(0) {}
+
+ inline int line() const {
+ return _M_line;
+ }
+ inline void setLine(int line) {
+ _M_line = line;
+ }
+
+ inline int column() const {
+ return _M_column;
+ }
+ inline void setColumn(int column) {
+ _M_column = column;
+ }
+
+ inline QString fileName() const {
+ return _M_fileName;
+ }
+ inline void setFileName(const QString &fileName) {
+ _M_fileName = fileName;
+ }
+
+ inline QString message() const {
+ return _M_message;
+ }
+ inline void setMessage(const QString &message) {
+ _M_message = message;
+ }
+
+ private:
+ int _M_line;
+ int _M_column;
+ QString _M_fileName;
+ QString _M_message;
+ };
+
+ Control();
+ ~Control();
+
+ inline bool skipFunctionBody() const {
+ return _M_skipFunctionBody;
+ }
+ inline void setSkipFunctionBody(bool skip) {
+ _M_skipFunctionBody = skip;
+ }
+
+ Lexer *changeLexer(Lexer *lexer);
+ Parser *changeParser(Parser *parser);
+
+ Lexer *currentLexer() const {
+ return _M_lexer;
+ }
+ Parser *currentParser() const {
+ return _M_parser;
+ }
+
+ Context *current_context;
+
+ inline Context *currentContext() const {
+ return current_context;
+ }
+
+ void pushContext();
+ void popContext();
+
+ Type *lookupType(const NameSymbol *name) const;
+ void declare(const NameSymbol *name, Type *type);
+
+ inline const NameSymbol *findOrInsertName(const char *data, size_t count) {
+ return name_table.findOrInsert(data, count);
+ }
+
+ void declareTypedef(const NameSymbol *name, Declarator *d);
+ bool isTypedef(const NameSymbol *name) const;
+
+ void reportError(const ErrorMessage &errmsg);
+ QList<ErrorMessage> errorMessages() const;
+ void clearErrorMessages();
+
+private:
+ NameTable name_table;
+ QHash<const NameSymbol*, Declarator*> stl_typedef_table;
+ bool _M_skipFunctionBody;
+ Lexer *_M_lexer;
+ Parser *_M_parser;
+
+ QList<ErrorMessage> _M_error_messages;
+};
+
+#endif // CONTROL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp
new file mode 100644
index 000000000..e27ea5842
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "declarator_compiler.h"
+#include "name_compiler.h"
+#include "type_compiler.h"
+#include "compiler_utils.h"
+#include "lexer.h"
+#include "binder.h"
+#include "tokens.h"
+
+#include <qdebug.h>
+
+DeclaratorCompiler::DeclaratorCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+void DeclaratorCompiler::run(DeclaratorAST *node)
+{
+ _M_id.clear();
+ _M_parameters.clear();
+ _M_array.clear();
+ _M_function = false;
+ _M_reference = false;
+ _M_variadics = false;
+ _M_indirection = 0;
+
+ if (node) {
+ NameCompiler name_cc(_M_binder);
+
+ DeclaratorAST *decl = node;
+ while (decl && decl->sub_declarator)
+ decl = decl->sub_declarator;
+
+ Q_ASSERT(decl != 0);
+
+ name_cc.run(decl->id);
+ _M_id = name_cc.name();
+ _M_function = (node->parameter_declaration_clause != 0);
+ if (node->parameter_declaration_clause && node->parameter_declaration_clause->ellipsis)
+ _M_variadics = true;
+
+ visitNodes(this, node->ptr_ops);
+ visit(node->parameter_declaration_clause);
+
+ if (const ListNode<ExpressionAST*> *it = node->array_dimensions) {
+ it->toFront();
+ const ListNode<ExpressionAST*> *end = it;
+
+ do {
+ QString elt;
+ if (ExpressionAST *expr = it->element) {
+ const Token &start_token = _M_token_stream->token((int) expr->start_token);
+ const Token &end_token = _M_token_stream->token((int) expr->end_token);
+
+ elt += QString::fromUtf8(&start_token.text[start_token.position],
+ (int)(end_token.position - start_token.position)).trimmed();
+ }
+
+ _M_array.append(elt);
+
+ it = it->next;
+ } while (it != end);
+ }
+ }
+}
+
+void DeclaratorCompiler::visitPtrOperator(PtrOperatorAST *node)
+{
+ std::size_t op = _M_token_stream->kind(node->op);
+
+ switch (op) {
+ case '&':
+ _M_reference = true;
+ break;
+ case '*':
+ ++_M_indirection;
+ break;
+
+ default:
+ break;
+ }
+
+ if (node->mem_ptr) {
+#if defined(__GNUC__)
+#warning "ptr to mem -- not implemented"
+#endif
+ }
+}
+
+void DeclaratorCompiler::visitParameterDeclaration(ParameterDeclarationAST *node)
+{
+ Parameter p;
+ DeclaratorCompiler decl_cc(_M_binder);
+
+ // Find the innermost declarator, to extract the name / id of the declaration.
+ DeclaratorAST *declarator = node->declarator;
+ while (declarator && declarator->sub_declarator)
+ declarator = declarator->sub_declarator;
+ decl_cc.run(declarator);
+ p.name = decl_cc.id();
+
+ // Use the original declarator to extract the type.
+ p.type = CompilerUtils::typeDescription(node->type_specifier, node->declarator, _M_binder);
+
+ // In case if the declarator is a function pointer, extract the arguments of the declarator
+ // parameter clause. This only works for top-declarator function pointers, it will fail to
+ // determine nested function pointers.
+ if (declarator != node->declarator
+ && node->declarator->parameter_declaration_clause) {
+ p.type.setFunctionPointer(true);
+ decl_cc.run(node->declarator);
+ foreach (const DeclaratorCompiler::Parameter &innerParam, decl_cc.parameters())
+ p.type.addArgument(innerParam.type);
+ }
+
+ if (node->expression != 0) {
+ const Token &start = _M_token_stream->token((int) node->expression->start_token);
+ const Token &end = _M_token_stream->token((int) node->expression->end_token);
+ int length = (int)(end.position - start.position);
+
+ p.defaultValueExpression = QString();
+ QString source = QString::fromUtf8(&start.text[start.position], length).trimmed();
+ QStringList list = source.split(QLatin1Char('\n'));
+
+
+ for (int i = 0; i < list.size(); ++i) {
+ if (!list.at(i).startsWith(QLatin1Char('#')))
+ p.defaultValueExpression += list.at(i).trimmed();
+ }
+
+ p.defaultValue = p.defaultValueExpression.size() > 0;
+
+ }
+
+ _M_parameters.append(p);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h
new file mode 100644
index 000000000..f67bd4672
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/declarator_compiler.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 DECLARATOR_COMPILER_H
+#define DECLARATOR_COMPILER_H
+
+#include "default_visitor.h"
+#include "codemodel.h"
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+class TokenStream;
+class Binder;
+
+class DeclaratorCompiler: protected DefaultVisitor
+{
+public:
+ struct Parameter {
+ TypeInfo type;
+ QString name;
+ QString defaultValueExpression;
+ bool defaultValue;
+
+ Parameter(): defaultValue(false) {}
+ };
+
+public:
+ DeclaratorCompiler(Binder *binder);
+
+ void run(DeclaratorAST *node);
+
+ inline QString id() const {
+ return _M_id;
+ }
+ inline QStringList arrayElements() const {
+ return _M_array;
+ }
+ inline bool isFunction() const {
+ return _M_function;
+ }
+ inline bool isVariadics() const {
+ return _M_variadics;
+ }
+ inline bool isReference() const {
+ return _M_reference;
+ }
+ inline int indirection() const {
+ return _M_indirection;
+ }
+ inline QList<Parameter> parameters() const {
+ return _M_parameters;
+ }
+
+protected:
+ virtual void visitPtrOperator(PtrOperatorAST *node);
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+
+ bool _M_function;
+ bool _M_reference;
+ bool _M_variadics;
+ int _M_indirection;
+ QString _M_id;
+ QStringList _M_array;
+ QList<Parameter> _M_parameters;
+};
+
+#endif // DECLARATOR_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp b/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp
new file mode 100644
index 000000000..e330abcbb
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/default_visitor.cpp
@@ -0,0 +1,464 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "default_visitor.h"
+
+void DefaultVisitor::visitAccessSpecifier(AccessSpecifierAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitAsmDefinition(AsmDefinitionAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitBaseClause(BaseClauseAST *node)
+{
+ visitNodes(this, node->base_specifiers);
+}
+
+void DefaultVisitor::visitBaseSpecifier(BaseSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitBinaryExpression(BinaryExpressionAST *node)
+{
+ visit(node->left_expression);
+ visit(node->right_expression);
+}
+
+void DefaultVisitor::visitCastExpression(CastExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitClassMemberAccess(ClassMemberAccessAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->win_decl_specifiers);
+ visit(node->name);
+ visit(node->base_clause);
+ visitNodes(this, node->member_specs);
+}
+
+void DefaultVisitor::visitCompoundStatement(CompoundStatementAST *node)
+{
+ visitNodes(this, node->statements);
+}
+
+void DefaultVisitor::visitCondition(ConditionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitConditionalExpression(ConditionalExpressionAST *node)
+{
+ visit(node->condition);
+ visit(node->left_expression);
+ visit(node->right_expression);
+}
+
+void DefaultVisitor::visitCppCastExpression(CppCastExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+ visitNodes(this, node->sub_expressions);
+}
+
+void DefaultVisitor::visitCtorInitializer(CtorInitializerAST *node)
+{
+ visitNodes(this, node->member_initializers);
+}
+
+void DefaultVisitor::visitDeclarationStatement(DeclarationStatementAST *node)
+{
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitDeclarator(DeclaratorAST *node)
+{
+ visit(node->sub_declarator);
+ visitNodes(this, node->ptr_ops);
+ visit(node->id);
+ visit(node->bit_expression);
+ visitNodes(this, node->array_dimensions);
+ visit(node->parameter_declaration_clause);
+ visit(node->exception_spec);
+}
+
+void DefaultVisitor::visitDeleteExpression(DeleteExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitDoStatement(DoStatementAST *node)
+{
+ visit(node->statement);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ visit(node->name);
+ visitNodes(this, node->enumerators);
+}
+
+void DefaultVisitor::visitEnumerator(EnumeratorAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitExceptionSpecification(ExceptionSpecificationAST *node)
+{
+ visitNodes(this, node->type_ids);
+}
+
+void DefaultVisitor::visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *node)
+{
+ visit(node->expression);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitExpressionStatement(ExpressionStatementAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitForStatement(ForStatementAST *node)
+{
+ visit(node->init_statement);
+ visit(node->condition);
+ visit(node->expression);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitFunctionCall(FunctionCallAST *node)
+{
+ visit(node->arguments);
+}
+
+void DefaultVisitor::visitFunctionDefinition(FunctionDefinitionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->init_declarator);
+ visit(node->function_body);
+ visit(node->win_decl_specifiers);
+}
+
+void DefaultVisitor::visitIfStatement(IfStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+ visit(node->else_statement);
+}
+
+void DefaultVisitor::visitIncrDecrExpression(IncrDecrExpressionAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitInitDeclarator(InitDeclaratorAST *node)
+{
+ visit(node->declarator);
+ visit(node->initializer);
+}
+
+void DefaultVisitor::visitInitializer(InitializerAST *node)
+{
+ visit(node->initializer_clause);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitInitializerClause(InitializerClauseAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitLabeledStatement(LabeledStatementAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitLinkageBody(LinkageBodyAST *node)
+{
+ visitNodes(this, node->declarations);
+}
+
+void DefaultVisitor::visitLinkageSpecification(LinkageSpecificationAST *node)
+{
+ visit(node->linkage_body);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitMemInitializer(MemInitializerAST *node)
+{
+ visit(node->initializer_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitName(NameAST *node)
+{
+ visitNodes(this, node->qualified_names);
+ visit(node->unqualified_name);
+}
+
+void DefaultVisitor::visitNamespace(NamespaceAST *node)
+{
+ visit(node->linkage_body);
+}
+
+void DefaultVisitor::visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *node)
+{
+ visit(node->alias_name);
+}
+
+void DefaultVisitor::visitNewDeclarator(NewDeclaratorAST *node)
+{
+ visit(node->ptr_op);
+ visit(node->sub_declarator);
+ visitNodes(this, node->expressions);
+}
+
+void DefaultVisitor::visitNewExpression(NewExpressionAST *node)
+{
+ visit(node->expression);
+ visit(node->type_id);
+ visit(node->new_type_id);
+ visit(node->new_initializer);
+}
+
+void DefaultVisitor::visitNewInitializer(NewInitializerAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitNewTypeId(NewTypeIdAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->new_initializer);
+ visit(node->new_declarator);
+}
+
+void DefaultVisitor::visitOperator(OperatorAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitOperatorFunctionId(OperatorFunctionIdAST *node)
+{
+ visit(node->op);
+ visit(node->type_specifier);
+ visitNodes(this, node->ptr_ops);
+}
+
+void DefaultVisitor::visitParameterDeclaration(ParameterDeclarationAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitParameterDeclarationClause(ParameterDeclarationClauseAST *node)
+{
+ visitNodes(this, node->parameter_declarations);
+}
+
+void DefaultVisitor::visitPostfixExpression(PostfixExpressionAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->expression);
+ visitNodes(this, node->sub_expressions);
+}
+
+void DefaultVisitor::visitPrimaryExpression(PrimaryExpressionAST *node)
+{
+ visit(node->literal);
+ visit(node->expression_statement);
+ visit(node->sub_expression);
+ visit(node->name);
+}
+
+void DefaultVisitor::visitPtrOperator(PtrOperatorAST *node)
+{
+ visit(node->mem_ptr);
+}
+
+void DefaultVisitor::visitPtrToMember(PtrToMemberAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitReturnStatement(ReturnStatementAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitSimpleDeclaration(SimpleDeclarationAST *node)
+{
+ visit(node->type_specifier);
+ visitNodes(this, node->init_declarators);
+ visit(node->win_decl_specifiers);
+}
+
+void DefaultVisitor::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
+{
+ visit(node->name);
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitSizeofExpression(SizeofExpressionAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitStringLiteral(StringLiteralAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitSubscriptExpression(SubscriptExpressionAST *node)
+{
+ visit(node->subscript);
+}
+
+void DefaultVisitor::visitSwitchStatement(SwitchStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitTemplateArgument(TemplateArgumentAST *node)
+{
+ visit(node->type_id);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTemplateDeclaration(TemplateDeclarationAST *node)
+{
+ visitNodes(this, node->template_parameters);
+ visit(node->declaration);
+}
+
+void DefaultVisitor::visitTemplateParameter(TemplateParameterAST *node)
+{
+ visit(node->type_parameter);
+ visit(node->parameter_declaration);
+}
+
+void DefaultVisitor::visitThrowExpression(ThrowExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTranslationUnit(TranslationUnitAST *node)
+{
+ visitNodes(this, node->declarations);
+}
+
+void DefaultVisitor::visitTryBlockStatement(TryBlockStatementAST *)
+{
+ // nothing to do
+}
+
+void DefaultVisitor::visitTypeId(TypeIdAST *node)
+{
+ visit(node->type_specifier);
+ visit(node->declarator);
+}
+
+void DefaultVisitor::visitTypeIdentification(TypeIdentificationAST *node)
+{
+ visit(node->name);
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitTypeParameter(TypeParameterAST *node)
+{
+ visit(node->name);
+ visit(node->type_id);
+ visitNodes(this, node->template_parameters);
+ visit(node->template_name);
+}
+
+void DefaultVisitor::visitTypedef(TypedefAST *node)
+{
+ visit(node->type_specifier);
+ visitNodes(this, node->init_declarators);
+}
+
+void DefaultVisitor::visitUnaryExpression(UnaryExpressionAST *node)
+{
+ visit(node->expression);
+}
+
+void DefaultVisitor::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ visit(node->operator_id);
+ visitNodes(this, node->template_arguments);
+}
+
+void DefaultVisitor::visitUsing(UsingAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitUsingDirective(UsingDirectiveAST *node)
+{
+ visit(node->name);
+}
+
+void DefaultVisitor::visitWhileStatement(WhileStatementAST *node)
+{
+ visit(node->condition);
+ visit(node->statement);
+}
+
+void DefaultVisitor::visitWinDeclSpec(WinDeclSpecAST *)
+{
+ // nothing to do
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/default_visitor.h b/sources/shiboken2/ApiExtractor/parser/default_visitor.h
new file mode 100644
index 000000000..1eef8cc85
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/default_visitor.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 DEFAULT_VISITOR_H
+#define DEFAULT_VISITOR_H
+
+#include "visitor.h"
+
+class DefaultVisitor: public Visitor
+{
+public:
+ DefaultVisitor() {}
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *);
+ virtual void visitAsmDefinition(AsmDefinitionAST *);
+ virtual void visitBaseClause(BaseClauseAST *);
+ virtual void visitBaseSpecifier(BaseSpecifierAST *);
+ virtual void visitBinaryExpression(BinaryExpressionAST *);
+ virtual void visitCastExpression(CastExpressionAST *);
+ virtual void visitClassMemberAccess(ClassMemberAccessAST *);
+ virtual void visitClassSpecifier(ClassSpecifierAST *);
+ virtual void visitCompoundStatement(CompoundStatementAST *);
+ virtual void visitCondition(ConditionAST *);
+ virtual void visitConditionalExpression(ConditionalExpressionAST *);
+ virtual void visitCppCastExpression(CppCastExpressionAST *);
+ virtual void visitCtorInitializer(CtorInitializerAST *);
+ virtual void visitDeclarationStatement(DeclarationStatementAST *);
+ virtual void visitDeclarator(DeclaratorAST *);
+ virtual void visitDeleteExpression(DeleteExpressionAST *);
+ virtual void visitDoStatement(DoStatementAST *);
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *);
+ virtual void visitEnumerator(EnumeratorAST *);
+ virtual void visitExceptionSpecification(ExceptionSpecificationAST *);
+ virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *);
+ virtual void visitExpressionStatement(ExpressionStatementAST *);
+ virtual void visitForStatement(ForStatementAST *);
+ virtual void visitFunctionCall(FunctionCallAST *);
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *);
+ virtual void visitIfStatement(IfStatementAST *);
+ virtual void visitIncrDecrExpression(IncrDecrExpressionAST *);
+ virtual void visitInitDeclarator(InitDeclaratorAST *);
+ virtual void visitInitializer(InitializerAST *);
+ virtual void visitInitializerClause(InitializerClauseAST *);
+ virtual void visitLabeledStatement(LabeledStatementAST *);
+ virtual void visitLinkageBody(LinkageBodyAST *);
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *);
+ virtual void visitMemInitializer(MemInitializerAST *);
+ virtual void visitName(NameAST *);
+ virtual void visitNamespace(NamespaceAST *);
+ virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *);
+ virtual void visitNewDeclarator(NewDeclaratorAST *);
+ virtual void visitNewExpression(NewExpressionAST *);
+ virtual void visitNewInitializer(NewInitializerAST *);
+ virtual void visitNewTypeId(NewTypeIdAST *);
+ virtual void visitOperator(OperatorAST *);
+ virtual void visitOperatorFunctionId(OperatorFunctionIdAST *);
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *);
+ virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *);
+ virtual void visitPostfixExpression(PostfixExpressionAST *);
+ virtual void visitPrimaryExpression(PrimaryExpressionAST *);
+ virtual void visitPtrOperator(PtrOperatorAST *);
+ virtual void visitPtrToMember(PtrToMemberAST *);
+ virtual void visitReturnStatement(ReturnStatementAST *);
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *);
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *);
+ virtual void visitSizeofExpression(SizeofExpressionAST *);
+ virtual void visitStringLiteral(StringLiteralAST *);
+ virtual void visitSubscriptExpression(SubscriptExpressionAST *);
+ virtual void visitSwitchStatement(SwitchStatementAST *);
+ virtual void visitTemplateArgument(TemplateArgumentAST *);
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *);
+ virtual void visitTemplateParameter(TemplateParameterAST *);
+ virtual void visitThrowExpression(ThrowExpressionAST *);
+ virtual void visitTranslationUnit(TranslationUnitAST *);
+ virtual void visitTryBlockStatement(TryBlockStatementAST *);
+ virtual void visitTypeId(TypeIdAST *);
+ virtual void visitTypeIdentification(TypeIdentificationAST *);
+ virtual void visitTypeParameter(TypeParameterAST *);
+ virtual void visitTypedef(TypedefAST *);
+ virtual void visitUnaryExpression(UnaryExpressionAST *);
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *);
+ virtual void visitUsing(UsingAST *);
+ virtual void visitUsingDirective(UsingDirectiveAST *);
+ virtual void visitWhileStatement(WhileStatementAST *);
+ virtual void visitWinDeclSpec(WinDeclSpecAST *);
+
+private:
+ typedef void (Visitor::*visitor_fun_ptr)(AST *);
+ static visitor_fun_ptr _S_table[];
+};
+
+#endif // VISITOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/dumptree.cpp b/sources/shiboken2/ApiExtractor/parser/dumptree.cpp
new file mode 100644
index 000000000..0a7444c14
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/dumptree.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "dumptree.h"
+
+#include <QtCore/QString>
+#include <QtCore/qdebug.h>
+
+static char const * const names[] = {
+ 0,
+ "AccessSpecifier",
+ "AsmDefinition",
+ "BaseClause",
+ "BaseSpecifier",
+ "BinaryExpression",
+ "CastExpression",
+ "ClassMemberAccess",
+ "ClassSpecifier",
+ "CompoundStatement",
+ "Condition",
+ "ConditionalExpression",
+ "CppCastExpression",
+ "CtorInitializer",
+ "DeclarationStatement",
+ "Declarator",
+ "DeleteExpression",
+ "DoStatement",
+ "ElaboratedTypeSpecifier",
+ "EnumSpecifier",
+ "Enumerator",
+ "ExceptionSpecification",
+ "ExpressionOrDeclarationStatement",
+ "ExpressionStatement",
+ "ForStatement",
+ "FunctionCall",
+ "FunctionDefinition",
+ "IfStatement",
+ "IncrDecrExpression",
+ "InitDeclarator",
+ "Initializer",
+ "InitializerClause",
+ "LabeledStatement",
+ "LinkageBody",
+ "LinkageSpecification",
+ "MemInitializer",
+ "Name",
+ "Namespace",
+ "NamespaceAliasDefinition",
+ "NewDeclarator",
+ "NewExpression",
+ "NewInitializer",
+ "NewTypeId",
+ "Operator",
+ "OperatorFunctionId",
+ "ParameterDeclaration",
+ "ParameterDeclarationClause",
+ "PostfixExpression",
+ "PrimaryExpression",
+ "PtrOperator",
+ "PtrToMember",
+ "ReturnStatement",
+ "SimpleDeclaration",
+ "SimpleTypeSpecifier",
+ "SizeofExpression",
+ "StringLiteral",
+ "SubscriptExpression",
+ "SwitchStatement",
+ "TemplateArgument",
+ "TemplateDeclaration",
+ "TemplateParameter",
+ "ThrowExpression",
+ "TranslationUnit",
+ "TryBlockStatement",
+ "TypeId",
+ "TypeIdentification",
+ "TypeParameter",
+ "Typedef",
+ "UnaryExpression",
+ "UnqualifiedName",
+ "Using",
+ "UsingDirective",
+ "WhileStatement",
+ "WinDeclSpec"
+};
+
+DumpTree::DumpTree()
+{
+}
+
+void DumpTree::visit(AST *node)
+{
+ static int indent = 0;
+
+
+ if (node)
+ qDebug() << QByteArray(indent * 2, ' ').constData() << names[node->kind]
+ << '[' << node->start_token << ", " << node->end_token << ']';
+
+ ++indent;
+ DefaultVisitor::visit(node);
+ --indent;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/dumptree.h b/sources/shiboken2/ApiExtractor/parser/dumptree.h
new file mode 100644
index 000000000..5d91c6ef1
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/dumptree.h
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 DUMPTREE_H
+#define DUMPTREE_H
+
+#include "default_visitor.h"
+
+class DumpTree: protected DefaultVisitor
+{
+public:
+ DumpTree();
+
+ void dump(AST *node) {
+ visit(node);
+ }
+
+protected:
+ virtual void visit(AST *node);
+};
+
+#endif // DUMPTREE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/lexer.cpp b/sources/shiboken2/ApiExtractor/parser/lexer.cpp
new file mode 100644
index 000000000..3fcf3b561
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/lexer.cpp
@@ -0,0 +1,1726 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "lexer.h"
+#include "tokens.h"
+#include "control.h"
+
+#include <cctype>
+#include <iostream>
+
+scan_fun_ptr Lexer::s_scan_keyword_table[] = {
+ &Lexer::scanKeyword0, &Lexer::scanKeyword0,
+ &Lexer::scanKeyword2, &Lexer::scanKeyword3,
+ &Lexer::scanKeyword4, &Lexer::scanKeyword5,
+ &Lexer::scanKeyword6, &Lexer::scanKeyword7,
+ &Lexer::scanKeyword8, &Lexer::scanKeyword9,
+ &Lexer::scanKeyword10, &Lexer::scanKeyword11,
+ &Lexer::scanKeyword12, &Lexer::scanKeyword13,
+ &Lexer::scanKeyword14, &Lexer::scanKeyword0,
+ &Lexer::scanKeyword16
+};
+
+void LocationManager::extract_line(int offset, int *line, QString *filename) const
+{
+ *line = 0;
+ if (token_stream.size() < 1)
+ return;
+
+ const unsigned char *begin_buffer = reinterpret_cast<const unsigned char *>(token_stream[0].text);
+ const unsigned char *cursor = begin_buffer + offset;
+
+ ++cursor; // skip '#'
+ if (std::isspace(*cursor) && std::isdigit(*(cursor + 1))) {
+ ++cursor;
+ char buffer[1024], *cp = buffer;
+ do {
+ *cp++ = *cursor++;
+ } while (std::isdigit(*cursor));
+ *cp = '\0';
+ int l = strtol(buffer, 0, 0);
+
+ Q_ASSERT(std::isspace(*cursor));
+ ++cursor;
+
+ Q_ASSERT(*cursor == '"');
+ ++cursor;
+
+ cp = buffer;
+ while (*cursor && *cursor != '"') {
+ *cp++ = *cursor++;
+ }
+ *cp = '\0';
+ Q_ASSERT(*cursor == '"');
+ ++cursor;
+
+ *filename = QLatin1String(buffer);
+ *line = l;
+ // printf("filename: %s line: %d\n", buffer, line);
+ }
+}
+
+void LocationManager::positionAt(std::size_t offset, int *line, int *column,
+ QString *filename) const
+{
+ int ppline = 0;
+ int ppcolumn = 0;
+ line_table.positionAt(offset, &ppline, &ppcolumn);
+
+ int base_line = 0;
+ extract_line((int) line_table[ppline-1], &base_line, filename);
+
+ int line2 = 0;
+ int column2 = 0;
+ location_table.positionAt((int) line_table[ppline-1], &line2, &column2);
+
+ location_table.positionAt(offset, line, column);
+ *line = base_line + *line - line2 - 1;
+}
+
+scan_fun_ptr Lexer::s_scan_table[256];
+bool Lexer::s_initialized = false;
+
+void Lexer::tokenize(const char *contents, std::size_t size)
+{
+ if (!s_initialized)
+ initialize_scan_table();
+
+ token_stream.resize(1024);
+ token_stream[0].kind = Token_EOF;
+ token_stream[0].text = contents;
+
+ index = 1;
+
+ cursor = (const unsigned char *) contents;
+ begin_buffer = (const unsigned char *) contents;
+ end_buffer = cursor + size;
+
+ location_table.resize(1024);
+ location_table[0] = 0;
+ location_table.current_line = 1;
+
+ line_table.resize(1024);
+ line_table[0] = 0;
+ line_table.current_line = 1;
+
+ do {
+ if (index == token_stream.size())
+ token_stream.resize(token_stream.size() * 2);
+
+ Token *current_token = &token_stream[(int) index];
+ current_token->text = reinterpret_cast<const char*>(begin_buffer);
+ current_token->position = cursor - begin_buffer;
+ (this->*s_scan_table[*cursor])();
+ current_token->size = cursor - begin_buffer - current_token->position;
+ } while (cursor < end_buffer);
+
+ if (index == token_stream.size())
+ token_stream.resize(token_stream.size() * 2);
+
+ Q_ASSERT(index < token_stream.size());
+ token_stream[(int) index].position = cursor - begin_buffer;
+ token_stream[(int) index].kind = Token_EOF;
+}
+
+void Lexer::reportError(const QString& msg)
+{
+ int line = 0;
+ int column = 0;
+ QString fileName;
+
+ std::size_t tok = token_stream.cursor();
+ _M_location.positionAt(token_stream.position(tok),
+ &line, &column, &fileName);
+
+ Control::ErrorMessage errmsg;
+ errmsg.setLine(line + 1);
+ errmsg.setColumn(column);
+ errmsg.setFileName(fileName);
+ errmsg.setMessage(QLatin1String("** LEXER ERROR ") + msg);
+ control->reportError(errmsg);
+}
+
+void Lexer::initialize_scan_table()
+{
+ s_initialized = true;
+
+ for (int i = 0; i < 256; ++i) {
+ if (isspace(i))
+ s_scan_table[i] = &Lexer::scan_white_spaces;
+ else if (isalpha(i) || i == '_')
+ s_scan_table[i] = &Lexer::scan_identifier_or_keyword;
+ else if (isdigit(i))
+ s_scan_table[i] = &Lexer::scan_int_constant;
+ else
+ s_scan_table[i] = &Lexer::scan_invalid_input;
+ }
+
+ s_scan_table[int('L')] = &Lexer::scan_identifier_or_literal;
+ s_scan_table[int('\n')] = &Lexer::scan_newline;
+ s_scan_table[int('#')] = &Lexer::scan_preprocessor;
+
+ s_scan_table[int('\'')] = &Lexer::scan_char_constant;
+ s_scan_table[int('"')] = &Lexer::scan_string_constant;
+
+ s_scan_table[int('.')] = &Lexer::scan_int_constant;
+
+ s_scan_table[int('!')] = &Lexer::scan_not;
+ s_scan_table[int('%')] = &Lexer::scan_remainder;
+ s_scan_table[int('&')] = &Lexer::scan_and;
+ s_scan_table[int('(')] = &Lexer::scan_left_paren;
+ s_scan_table[int(')')] = &Lexer::scan_right_paren;
+ s_scan_table[int('*')] = &Lexer::scan_star;
+ s_scan_table[int('+')] = &Lexer::scan_plus;
+ s_scan_table[int(',')] = &Lexer::scan_comma;
+ s_scan_table[int('-')] = &Lexer::scan_minus;
+ s_scan_table[int('/')] = &Lexer::scan_divide;
+ s_scan_table[int(':')] = &Lexer::scan_colon;
+ s_scan_table[int(';')] = &Lexer::scan_semicolon;
+ s_scan_table[int('<')] = &Lexer::scan_less;
+ s_scan_table[int('=')] = &Lexer::scan_equal;
+ s_scan_table[int('>')] = &Lexer::scan_greater;
+ s_scan_table[int('?')] = &Lexer::scan_question;
+ s_scan_table[int('[')] = &Lexer::scan_left_bracket;
+ s_scan_table[int(']')] = &Lexer::scan_right_bracket;
+ s_scan_table[int('^')] = &Lexer::scan_xor;
+ s_scan_table[int('{')] = &Lexer::scan_left_brace;
+ s_scan_table[int('|')] = &Lexer::scan_or;
+ s_scan_table[int('}')] = &Lexer::scan_right_brace;
+ s_scan_table[int('~')] = &Lexer::scan_tilde;
+
+ s_scan_table[0] = &Lexer::scan_EOF;
+}
+
+void Lexer::scan_preprocessor()
+{
+ if (line_table.current_line == line_table.size())
+ line_table.resize(line_table.current_line * 2);
+
+ line_table[(int) line_table.current_line++] = (cursor - begin_buffer);
+
+ while (*cursor && *cursor != '\n')
+ ++cursor;
+
+ if (*cursor != '\n')
+ reportError(QLatin1String("expected newline"));
+}
+
+void Lexer::scan_char_constant()
+{
+ const unsigned char *begin = cursor;
+
+ ++cursor;
+ while (*cursor && *cursor != '\'') {
+ if (*cursor == '\n')
+ reportError(QLatin1String("did not expect newline"));
+
+ if (*cursor == '\\')
+ ++cursor;
+ ++cursor;
+ }
+
+ if (*cursor != '\'')
+ reportError(QLatin1String("expected \'"));
+
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_char_literal;
+}
+
+void Lexer::scan_string_constant()
+{
+ const unsigned char *begin = cursor;
+
+ ++cursor;
+ while (*cursor && *cursor != '"') {
+ if (*cursor == '\n')
+ reportError(QLatin1String("did not expect newline"));
+
+ if (*cursor == '\\')
+ ++cursor;
+ ++cursor;
+ }
+
+ if (*cursor != '"')
+ reportError(QLatin1String("expected \""));
+
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_string_literal;
+}
+
+void Lexer::scan_newline()
+{
+ if (location_table.current_line == location_table.size())
+ location_table.resize(location_table.current_line * 2);
+
+ location_table[(int) location_table.current_line++] = (cursor - begin_buffer);
+ ++cursor;
+}
+
+void Lexer::scan_white_spaces()
+{
+ while (isspace(*cursor)) {
+ if (*cursor == '\n')
+ scan_newline();
+ else
+ ++cursor;
+ }
+}
+
+void Lexer::scan_identifier_or_literal()
+{
+ switch (*(cursor + 1)) {
+ case '\'':
+ ++cursor;
+ scan_char_constant();
+ break;
+
+ case '\"':
+ ++cursor;
+ scan_string_constant();
+ break;
+
+ default:
+ scan_identifier_or_keyword();
+ break;
+ }
+}
+
+void Lexer::scan_identifier_or_keyword()
+{
+ const unsigned char *skip = cursor;
+ while (isalnum(*skip) || *skip == '_')
+ ++skip;
+
+ int n = skip - cursor;
+ Token *current_token = &token_stream[(int) index];
+ (this->*s_scan_keyword_table[n < 17 ? n : 0])();
+
+ if (current_token->kind == Token_identifier) {
+ current_token->extra.symbol =
+ control->findOrInsertName((const char*) cursor, n);
+ }
+
+ cursor = skip;
+}
+
+void Lexer::scan_int_constant()
+{
+ if (*cursor == '.' && !std::isdigit(*(cursor + 1))) {
+ scan_dot();
+ return;
+ }
+
+ const unsigned char *begin = cursor;
+
+ while (isalnum(*cursor) || *cursor == '.')
+ ++cursor;
+
+ token_stream[(int) index].extra.symbol =
+ control->findOrInsertName((const char*) begin, cursor - begin);
+
+ token_stream[(int) index++].kind = Token_number_literal;
+}
+
+void Lexer::scan_not()
+{
+ /*
+ '!' ::= not
+ '!=' ::= not_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_not_eq;
+ } else {
+ token_stream[(int) index++].kind = '!';
+ }
+}
+
+void Lexer::scan_remainder()
+{
+ /*
+ '%' ::= remainder
+ '%=' ::= remainder_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '%';
+ }
+}
+
+void Lexer::scan_and()
+{
+ /*
+ '&&' ::= and_and
+ '&' ::= and
+ '&=' ::= and_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '&') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_and;
+ } else {
+ token_stream[(int) index++].kind = '&';
+ }
+}
+
+void Lexer::scan_left_paren()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '(';
+}
+
+void Lexer::scan_right_paren()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ')';
+}
+
+void Lexer::scan_star()
+{
+ /*
+ '*' ::= star
+ '*=' ::= star_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '*';
+ }
+}
+
+void Lexer::scan_plus()
+{
+ /*
+ '+' ::= plus
+ '++' ::= incr
+ '+=' ::= plus_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '+') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_incr;
+ } else {
+ token_stream[(int) index++].kind = '+';
+ }
+}
+
+void Lexer::scan_comma()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ',';
+}
+
+void Lexer::scan_minus()
+{
+ /*
+ '-' ::= minus
+ '--' ::= decr
+ '-=' ::= minus_equal
+ '->' ::= left_arrow
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '-') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_decr;
+ } else if (*cursor == '>') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_arrow;
+ if (*cursor == '*') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_ptrmem;
+ }
+ } else {
+ token_stream[(int) index++].kind = '-';
+ }
+}
+
+void Lexer::scan_dot()
+{
+ /*
+ '.' ::= dot
+ '...' ::= ellipsis
+ */
+
+ ++cursor;
+ if (*cursor == '.' && *(cursor + 1) == '.') {
+ cursor += 2;
+ token_stream[(int) index++].kind = Token_ellipsis;
+ } else if (*cursor == '.' && *(cursor + 1) == '*') {
+ cursor += 2;
+ token_stream[(int) index++].kind = Token_ptrmem;
+ } else
+ token_stream[(int) index++].kind = '.';
+}
+
+void Lexer::scan_divide()
+{
+ /*
+ '/' ::= divide
+ '/=' ::= divide_equal
+ */
+
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '/';
+ }
+}
+
+void Lexer::scan_colon()
+{
+ ++cursor;
+ if (*cursor == ':') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_scope;
+ } else {
+ token_stream[(int) index++].kind = ':';
+ }
+}
+
+void Lexer::scan_semicolon()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ';';
+}
+
+void Lexer::scan_less()
+{
+ /*
+ '<' ::= less
+ '<<' ::= left_shift
+ '<<=' ::= left_shift_equal
+ '<=' ::= less_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_leq;
+ } else if (*cursor == '<') {
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = Token_shift;
+ }
+ } else {
+ token_stream[(int) index++].kind = '<';
+ }
+}
+
+void Lexer::scan_equal()
+{
+ /*
+ '=' ::= equal
+ '==' ::= equal_equal
+ */
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_eq;
+ } else {
+ token_stream[(int) index++].kind = '=';
+ }
+}
+
+void Lexer::scan_greater()
+{
+ /*
+ '>' ::= greater
+ '>=' ::= greater_equal
+ '>>' ::= right_shift
+ '>>=' ::= right_shift_equal
+ */
+
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_geq;
+ } else if (*cursor == '>') {
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = Token_shift;
+ }
+ } else {
+ token_stream[(int) index++].kind = '>';
+ }
+}
+
+void Lexer::scan_question()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '?';
+}
+
+void Lexer::scan_left_bracket()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '[';
+}
+
+void Lexer::scan_right_bracket()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = ']';
+}
+
+void Lexer::scan_xor()
+{
+ /*
+ '^' ::= xor
+ '^=' ::= xor_equal
+ */
+ ++cursor;
+
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else {
+ token_stream[(int) index++].kind = '^';
+ }
+}
+
+void Lexer::scan_left_brace()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '{';
+}
+
+void Lexer::scan_or()
+{
+ /*
+ '|' ::= or
+ '|=' ::= or_equal
+ '||' ::= or_or
+ */
+ ++cursor;
+ if (*cursor == '=') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_assign;
+ } else if (*cursor == '|') {
+ ++cursor;
+ token_stream[(int) index++].kind = Token_or;
+ } else {
+ token_stream[(int) index++].kind = '|';
+ }
+}
+
+void Lexer::scan_right_brace()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '}';
+}
+
+void Lexer::scan_tilde()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = '~';
+}
+
+void Lexer::scan_EOF()
+{
+ ++cursor;
+ token_stream[(int) index++].kind = Token_EOF;
+}
+
+void Lexer::scan_invalid_input()
+{
+ QString errmsg(QLatin1String("invalid input: %1"));
+ reportError(errmsg);
+ ++cursor;
+}
+
+void LocationTable::positionAt(std::size_t offset, int max_line,
+ int *line, int *column) const
+{
+ if (!(line && column && max_line != 0))
+ return;
+
+ int first = 0;
+ int len = max_line;
+ int half;
+ int middle;
+
+ while (len > 0) {
+ half = len >> 1;
+ middle = first;
+
+ middle += half;
+
+ if (lines[middle] < offset) {
+ first = middle;
+ ++first;
+ len = len - half - 1;
+ } else
+ len = half;
+ }
+
+ *line = std::max(first, 1);
+ *column = (int)(offset - lines[*line - 1] - 1);
+
+ if (*column < 0) {
+ *column = 0;
+ }
+}
+
+void Lexer::scanKeyword0()
+{
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword2()
+{
+ switch (*cursor) {
+ case 'i':
+ if (*(cursor + 1) == 'f') {
+ token_stream[(int) index++].kind = Token_if;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (*(cursor + 1) == 'o') {
+ token_stream[(int) index++].kind = Token_do;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'r') {
+ token_stream[(int) index++].kind = Token_or;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword3()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'd') {
+ token_stream[(int) index++].kind = Token_and;
+ return;
+ }
+ if (*(cursor + 1) == 's' &&
+ *(cursor + 2) == 'm') {
+ token_stream[(int) index++].kind = Token_asm;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r') {
+ token_stream[(int) index++].kind = Token_for;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 't') {
+ token_stream[(int) index++].kind = Token_int;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'w') {
+ token_stream[(int) index++].kind = Token_new;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't') {
+ token_stream[(int) index++].kind = Token_not;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'y') {
+ token_stream[(int) index++].kind = Token_try;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r') {
+ token_stream[(int) index++].kind = Token_xor;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword4()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o') {
+ token_stream[(int) index++].kind = Token_auto;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'e') {
+ token_stream[(int) index++].kind = Token_case;
+ return;
+ }
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 'r') {
+ token_stream[(int) index++].kind = Token_char;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'l') {
+ token_stream[(int) index++].kind = Token_bool;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'e') {
+ token_stream[(int) index++].kind = Token_else;
+ return;
+ }
+ if (*(cursor + 1) == 'm' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 't') {
+ token_stream[(int) index++].kind = Token_emit;
+ return;
+ }
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'u' &&
+ *(cursor + 3) == 'm') {
+ token_stream[(int) index++].kind = Token_enum;
+ return;
+ }
+ break;
+
+ case 'g':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o') {
+ token_stream[(int) index++].kind = Token_goto;
+ return;
+ }
+ break;
+
+ case 'l':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 'g') {
+ token_stream[(int) index++].kind = Token_long;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 's') {
+ token_stream[(int) index++].kind = Token_this;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'd') {
+ token_stream[(int) index++].kind = Token_void;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword5()
+{
+ switch (*cursor) {
+ case 'c':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'h') {
+ token_stream[(int) index++].kind = Token_catch;
+ return;
+ }
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 's') {
+ token_stream[(int) index++].kind = Token_class;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'p' &&
+ *(cursor + 4) == 'l') {
+ token_stream[(int) index++].kind = Token_compl;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_const;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'r') {
+ token_stream[(int) index++].kind = Token_bitor;
+ return;
+ }
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'e' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'k') {
+ token_stream[(int) index++].kind = Token_break;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_float;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == '_' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'q') {
+ token_stream[(int) index++].kind = Token_or_eq;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 'r' &&
+ *(cursor + 4) == 't') {
+ token_stream[(int) index++].kind = Token_short;
+ return;
+ }
+ if (*(cursor + 1) == 'l' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 's') {
+ token_stream[(int) index++].kind = Token_slots;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'n') {
+ token_stream[(int) index++].kind = Token_union;
+ return;
+ }
+ if (*(cursor + 1) == 's' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'g') {
+ token_stream[(int) index++].kind = Token_using;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'w') {
+ token_stream[(int) index++].kind = Token_throw;
+ return;
+ }
+ break;
+
+ case 'w':
+ if (*(cursor + 1) == 'h' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'e') {
+ token_stream[(int) index++].kind = Token_while;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword6()
+{
+ switch (*cursor) {
+ case 'a':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_and_eq;
+ return;
+ }
+ break;
+
+ case 'b':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_bitand;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'o' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 't') {
+ token_stream[(int) index++].kind = Token_export;
+ return;
+ }
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 'n') {
+ token_stream[(int) index++].kind = Token_extern;
+ return;
+ }
+ break;
+
+ case 'd':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_delete;
+ return;
+ }
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'u' &&
+ *(cursor + 3) == 'b' &&
+ *(cursor + 4) == 'l' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_double;
+ return;
+ }
+ break;
+
+ case 'f':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_friend;
+ return;
+ }
+ break;
+
+ case 'i':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'e') {
+ token_stream[(int) index++].kind = Token_inline;
+ return;
+ }
+ break;
+
+ case 'K':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'D' &&
+ *(cursor + 3) == 'C' &&
+ *(cursor + 4) == 'O' &&
+ *(cursor + 5) == 'P') {
+ token_stream[(int) index++].kind = Token_K_DCOP;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_not_eq;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 'b' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c') {
+ token_stream[(int) index++].kind = Token_public;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_signed;
+ return;
+ }
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'z' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'f') {
+ token_stream[(int) index++].kind = Token_sizeof;
+ return;
+ }
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c') {
+ token_stream[(int) index++].kind = Token_static;
+ return;
+ }
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 'u' &&
+ *(cursor + 4) == 'c' &&
+ *(cursor + 5) == 't') {
+ token_stream[(int) index++].kind = Token_struct;
+ return;
+ }
+ if (*(cursor + 1) == 'w' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'c' &&
+ *(cursor + 5) == 'h') {
+ token_stream[(int) index++].kind = Token_switch;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'u' &&
+ *(cursor + 4) == 'r' &&
+ *(cursor + 5) == 'n') {
+ token_stream[(int) index++].kind = Token_return;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'd') {
+ token_stream[(int) index++].kind = Token_typeid;
+ return;
+ }
+ break;
+
+ case 'x':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == '_' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'q') {
+ token_stream[(int) index++].kind = Token_xor_eq;
+ return;
+ }
+ break;
+
+ case 'k':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'p') {
+ token_stream[(int) index++].kind = Token_k_dcop;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'E' &&
+ *(cursor + 3) == 'N' &&
+ *(cursor + 4) == 'U' &&
+ *(cursor + 5) == 'M') { // Qt5.5
+ token_stream[(int) index++].kind = Token_Q_ENUM;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword7()
+{
+ switch (*cursor) {
+ case 'd':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'f' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'u' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 't') {
+ token_stream[(int) index++].kind = Token_default;
+ return;
+ }
+ break;
+
+ case 'm':
+ if (*(cursor + 1) == 'u' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'b' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 'e') {
+ token_stream[(int) index++].kind = Token_mutable;
+ return;
+ }
+ break;
+
+ case 'p':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'v' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'e') {
+ token_stream[(int) index++].kind = Token_private;
+ return;
+ }
+ break;
+ case 's':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 'l' &&
+ *(cursor + 6) == 's') {
+ token_stream[(int) index++].kind = Token_signals;
+ return;
+ }
+ break;
+ case 't':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'd' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'f') {
+ token_stream[(int) index++].kind = Token_typedef;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'i' &&
+ *(cursor + 2) == 'r' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'u' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 'l') {
+ token_stream[(int) index++].kind = Token_virtual;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'E' &&
+ *(cursor + 3) == 'N' &&
+ *(cursor + 4) == 'U' &&
+ *(cursor + 5) == 'M' &&
+ *(cursor + 6) == 'S') {
+ token_stream[(int) index++].kind = Token_Q_ENUMS;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword8()
+{
+ switch (*cursor) {
+ case '_':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 't' &&
+ *(cursor + 3) == 'y' &&
+ *(cursor + 4) == 'p' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'o' &&
+ *(cursor + 7) == 'f') {
+ token_stream[(int) index++].kind = Token___typeof;
+ return;
+ }
+ break;
+
+ case 'c':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'n' &&
+ *(cursor + 6) == 'u' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_continue;
+ return;
+ }
+ break;
+
+ case 'e':
+ if (*(cursor + 1) == 'x' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'l' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == 'i' &&
+ *(cursor + 7) == 't') {
+ token_stream[(int) index++].kind = Token_explicit;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'e' &&
+ *(cursor + 3) == 'x' &&
+ *(cursor + 4) == 'c' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'p' &&
+ *(cursor + 7) == 't') {
+ token_stream[(int) index++].kind = Token_noexcept;
+ return;
+ }
+ break;
+
+ case 'o':
+ if (*(cursor + 1) == 'p' &&
+ *(cursor + 2) == 'e' &&
+ *(cursor + 3) == 'r' &&
+ *(cursor + 4) == 'a' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'o' &&
+ *(cursor + 7) == 'r') {
+ token_stream[(int) index++].kind = Token_operator;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'O' &&
+ *(cursor + 3) == 'B' &&
+ *(cursor + 4) == 'J' &&
+ *(cursor + 5) == 'E' &&
+ *(cursor + 6) == 'C' &&
+ *(cursor + 7) == 'T') {
+ token_stream[(int) index++].kind = Token_Q_OBJECT;
+ return;
+ }
+ break;
+
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'g' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 's' &&
+ *(cursor + 5) == 't' &&
+ *(cursor + 6) == 'e' &&
+ *(cursor + 7) == 'r') {
+ token_stream[(int) index++].kind = Token_register;
+ return;
+ }
+ break;
+
+ case 'u':
+ if (*(cursor + 1) == 'n' &&
+ *(cursor + 2) == 's' &&
+ *(cursor + 3) == 'i' &&
+ *(cursor + 4) == 'g' &&
+ *(cursor + 5) == 'n' &&
+ *(cursor + 6) == 'e' &&
+ *(cursor + 7) == 'd') {
+ token_stream[(int) index++].kind = Token_unsigned;
+ return;
+ }
+ break;
+
+ case 't':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'p' &&
+ *(cursor + 4) == 'l' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 't' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_template;
+ return;
+ }
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'p' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 'n' &&
+ *(cursor + 5) == 'a' &&
+ *(cursor + 6) == 'm' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_typename;
+ return;
+ }
+ break;
+
+ case 'v':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'l' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'i' &&
+ *(cursor + 6) == 'l' &&
+ *(cursor + 7) == 'e') {
+ token_stream[(int) index++].kind = Token_volatile;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword9()
+{
+ switch (*cursor) {
+ case 'p':
+ if (*(cursor + 1) == 'r' &&
+ *(cursor + 2) == 'o' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'e' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == 't' &&
+ *(cursor + 7) == 'e' &&
+ *(cursor + 8) == 'd') {
+ token_stream[(int) index++].kind = Token_protected;
+ return;
+ }
+ break;
+
+ case 'n':
+ if (*(cursor + 1) == 'a' &&
+ *(cursor + 2) == 'm' &&
+ *(cursor + 3) == 'e' &&
+ *(cursor + 4) == 's' &&
+ *(cursor + 5) == 'p' &&
+ *(cursor + 6) == 'a' &&
+ *(cursor + 7) == 'c' &&
+ *(cursor + 8) == 'e') {
+ token_stream[(int) index++].kind = Token_namespace;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword10()
+{
+ switch (*cursor) {
+ case 'c':
+ if (*(cursor + 1) == 'o' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 's' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == '_' &&
+ *(cursor + 6) == 'c' &&
+ *(cursor + 7) == 'a' &&
+ *(cursor + 8) == 's' &&
+ *(cursor + 9) == 't') {
+ token_stream[(int) index++].kind = Token_const_cast;
+ return;
+ }
+ break;
+
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'P' &&
+ *(cursor + 3) == 'R' &&
+ *(cursor + 4) == 'O' &&
+ *(cursor + 5) == 'P' &&
+ *(cursor + 6) == 'E' &&
+ *(cursor + 7) == 'R' &&
+ *(cursor + 8) == 'T' &&
+ *(cursor + 9) == 'Y') {
+ token_stream[(int) index++].kind = Token_Q_PROPERTY;
+ return;
+ }
+
+ break;
+ }
+
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword11()
+{
+ switch (*cursor) {
+ case 'Q':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'I' &&
+ *(cursor + 3) == 'N' &&
+ *(cursor + 4) == 'V' &&
+ *(cursor + 5) == 'O' &&
+ *(cursor + 6) == 'K' &&
+ *(cursor + 7) == 'A' &&
+ *(cursor + 8) == 'B' &&
+ *(cursor + 9) == 'L' &&
+ *(cursor + 10) == 'E') {
+ token_stream[(int) index++].kind = Token_Q_INVOKABLE;
+ return;
+ }
+ break;
+
+ case 's':
+ if (*(cursor + 1) == 't' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 'i' &&
+ *(cursor + 5) == 'c' &&
+ *(cursor + 6) == '_' &&
+ *(cursor + 7) == 'c' &&
+ *(cursor + 8) == 'a' &&
+ *(cursor + 9) == 's' &&
+ *(cursor + 10) == 't') {
+ token_stream[(int) index++].kind = Token_static_cast;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword12()
+{
+ switch (*cursor) {
+ case 'd':
+ if (*(cursor + 1) == 'y' &&
+ *(cursor + 2) == 'n' &&
+ *(cursor + 3) == 'a' &&
+ *(cursor + 4) == 'm' &&
+ *(cursor + 5) == 'i' &&
+ *(cursor + 6) == 'c' &&
+ *(cursor + 7) == '_' &&
+ *(cursor + 8) == 'c' &&
+ *(cursor + 9) == 'a' &&
+ *(cursor + 10) == 's' &&
+ *(cursor + 11) == 't') {
+ token_stream[(int) index++].kind = Token_dynamic_cast;
+ return;
+ }
+ break;
+
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword13()
+{
+ switch (*cursor) {
+ case '_':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'a' &&
+ *(cursor + 3) == 't' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'r' &&
+ *(cursor + 6) == 'i' &&
+ *(cursor + 7) == 'b' &&
+ *(cursor + 8) == 'u' &&
+ *(cursor + 9) == 't' &&
+ *(cursor + 10) == 'e' &&
+ *(cursor + 11) == '_' &&
+ *(cursor + 12) == '_') {
+ token_stream[(int) index++].kind = Token___attribute__;
+ return;
+ }
+ break;
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword14()
+{
+ switch (*cursor) {
+ case 'k':
+ if (*(cursor + 1) == '_' &&
+ *(cursor + 2) == 'd' &&
+ *(cursor + 3) == 'c' &&
+ *(cursor + 4) == 'o' &&
+ *(cursor + 5) == 'p' &&
+ *(cursor + 6) == '_' &&
+ *(cursor + 7) == 's' &&
+ *(cursor + 8) == 'i' &&
+ *(cursor + 9) == 'g' &&
+ *(cursor + 10) == 'n' &&
+ *(cursor + 11) == 'a' &&
+ *(cursor + 12) == 'l' &&
+ *(cursor + 13) == 's') {
+ token_stream[(int) index++].kind = Token_k_dcop_signals;
+ return;
+ }
+ break;
+ }
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+void Lexer::scanKeyword16()
+{
+ switch (*cursor) {
+ case 'r':
+ if (*(cursor + 1) == 'e' &&
+ *(cursor + 2) == 'i' &&
+ *(cursor + 3) == 'n' &&
+ *(cursor + 4) == 't' &&
+ *(cursor + 5) == 'e' &&
+ *(cursor + 6) == 'r' &&
+ *(cursor + 7) == 'p' &&
+ *(cursor + 8) == 'r' &&
+ *(cursor + 9) == 'e' &&
+ *(cursor + 10) == 't' &&
+ *(cursor + 11) == '_' &&
+ *(cursor + 12) == 'c' &&
+ *(cursor + 13) == 'a' &&
+ *(cursor + 14) == 's' &&
+ *(cursor + 15) == 't') {
+ token_stream[(int) index++].kind = Token_reinterpret_cast;
+ return;
+ }
+ break;
+ }
+
+ token_stream[(int) index++].kind = Token_identifier;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/lexer.h b/sources/shiboken2/ApiExtractor/parser/lexer.h
new file mode 100644
index 000000000..7144355e4
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/lexer.h
@@ -0,0 +1,295 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 LEXER_H
+#define LEXER_H
+
+#include "symbol.h"
+
+#include <QtCore/QString>
+#include <cstdlib>
+#include <cassert>
+
+struct NameSymbol;
+class Lexer;
+class Control;
+
+typedef void (Lexer::*scan_fun_ptr)();
+
+class Token
+{
+public:
+ int kind;
+ std::size_t position;
+ std::size_t size;
+ char const *text;
+
+ union {
+ const NameSymbol *symbol;
+ std::size_t right_brace;
+ } extra;
+};
+
+class LocationTable
+{
+private:
+ LocationTable(const LocationTable &source);
+ void operator = (const LocationTable &source);
+
+public:
+ inline LocationTable(std::size_t size = 1024)
+ : lines(0),
+ line_count(0),
+ current_line(0) {
+ resize(size);
+ }
+
+ inline ~LocationTable() {
+ free(lines);
+ }
+
+ inline std::size_t size() const {
+ return line_count;
+ }
+
+ void resize(std::size_t size) {
+ Q_ASSERT(size > 0);
+ lines = (std::size_t*) ::realloc(lines, sizeof(std::size_t) * size);
+ line_count = size;
+ }
+
+ void positionAt(std::size_t offset, int *line, int *column) const {
+ positionAt(offset, (int) current_line, line, column);
+ }
+
+ void positionAt(std::size_t offset, int max_line, int *line, int *column) const;
+
+ inline std::size_t &operator[](int index) {
+ return lines[index];
+ }
+
+private:
+ std::size_t *lines;
+ std::size_t line_count;
+ std::size_t current_line;
+
+ friend class Lexer;
+};
+
+class TokenStream
+{
+private:
+ TokenStream(const TokenStream &);
+ void operator = (const TokenStream &);
+
+public:
+ inline TokenStream(std::size_t size = 1024)
+ : tokens(0),
+ index(0),
+ token_count(0) {
+ resize(size);
+ }
+
+ inline ~TokenStream() {
+ ::free(tokens);
+ }
+
+ inline std::size_t size() const {
+ return token_count;
+ }
+
+ inline std::size_t cursor() const {
+ return index;
+ }
+
+ inline void rewind(int i) {
+ index = i;
+ }
+
+ void resize(std::size_t size) {
+ Q_ASSERT(size > 0);
+ tokens = (Token*) ::realloc(tokens, sizeof(Token) * size);
+ token_count = size;
+ }
+
+ inline std::size_t nextToken() {
+ return index++;
+ }
+
+ inline int lookAhead(std::size_t i = 0) const {
+ return tokens[index + i].kind;
+ }
+
+ inline int kind(std::size_t i) const {
+ return tokens[i].kind;
+ }
+
+ inline std::size_t position(std::size_t i) const {
+ return tokens[i].position;
+ }
+
+ inline const NameSymbol *symbol(std::size_t i) const {
+ return tokens[i].extra.symbol;
+ }
+
+ inline std::size_t matchingBrace(std::size_t i) const {
+ return tokens[i].extra.right_brace;
+ }
+
+ inline Token &operator[](int index) {
+ return tokens[index];
+ }
+
+ inline const Token &token(int index) const {
+ return tokens[index];
+ }
+
+private:
+ Token *tokens;
+ std::size_t index;
+ std::size_t token_count;
+
+private:
+ friend class Lexer;
+};
+
+class LocationManager
+{
+ LocationManager(LocationManager const &__other);
+ void operator = (LocationManager const &__other);
+
+public:
+ LocationManager(TokenStream &__token_stream,
+ LocationTable &__location_table,
+ LocationTable &__line_table):
+ token_stream(__token_stream),
+ location_table(__location_table),
+ line_table(__line_table) {}
+
+ void positionAt(std::size_t offset, int *line, int *column,
+ QString *filename) const;
+
+ void extract_line(int offset, int *line, QString *filename) const;
+
+ TokenStream &token_stream;
+ LocationTable &location_table;
+ LocationTable &line_table;
+};
+
+class Lexer
+{
+public:
+ Lexer(LocationManager &__location, Control *__control):
+ _M_location(__location),
+ token_stream(_M_location.token_stream),
+ location_table(_M_location.location_table),
+ line_table(_M_location.line_table),
+ control(__control) {}
+
+ void tokenize(const char *contents, std::size_t size);
+
+ LocationManager &_M_location;
+ TokenStream &token_stream;
+ LocationTable &location_table;
+ LocationTable &line_table;
+
+private:
+ void reportError(const QString& msg);
+
+ void initialize_scan_table();
+ void scan_newline();
+ void scan_white_spaces();
+ void scan_identifier_or_keyword();
+ void scan_identifier_or_literal();
+ void scan_int_constant();
+ void scan_char_constant();
+ void scan_string_constant();
+ void scan_invalid_input();
+ void scan_preprocessor();
+
+ // keywords
+ void scanKeyword0();
+ void scanKeyword2();
+ void scanKeyword3();
+ void scanKeyword4();
+ void scanKeyword5();
+ void scanKeyword6();
+ void scanKeyword7();
+ void scanKeyword8();
+ void scanKeyword9();
+ void scanKeyword10();
+ void scanKeyword11();
+ void scanKeyword12();
+ void scanKeyword13();
+ void scanKeyword14();
+ void scanKeyword16();
+
+ // operators
+ void scan_not();
+ void scan_remainder();
+ void scan_and();
+ void scan_left_paren();
+ void scan_right_paren();
+ void scan_star();
+ void scan_plus();
+ void scan_comma();
+ void scan_minus();
+ void scan_dot();
+ void scan_divide();
+ void scan_colon();
+ void scan_semicolon();
+ void scan_less();
+ void scan_equal();
+ void scan_greater();
+ void scan_question();
+ void scan_left_bracket();
+ void scan_right_bracket();
+ void scan_xor();
+ void scan_left_brace();
+ void scan_or();
+ void scan_right_brace();
+ void scan_tilde();
+ void scan_EOF();
+
+private:
+ Control *control;
+ const unsigned char *cursor;
+ const unsigned char *begin_buffer;
+ const unsigned char *end_buffer;
+ std::size_t index;
+
+ static scan_fun_ptr s_scan_table[];
+ static scan_fun_ptr s_scan_keyword_table[];
+ static bool s_initialized;
+};
+
+#endif // LEXER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/list.cpp b/sources/shiboken2/ApiExtractor/parser/list.cpp
new file mode 100644
index 000000000..2d2a78700
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/list.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "list.h"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/list.h b/sources/shiboken2/ApiExtractor/parser/list.h
new file mode 100644
index 000000000..764fafffd
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/list.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 FASTLIST_H
+#define FASTLIST_H
+
+#include "smallobject.h"
+
+template <typename Tp>
+struct ListNode {
+ Tp element;
+ int index;
+ mutable const ListNode<Tp> *next;
+
+ static ListNode *create(const Tp &element, pool *p) {
+ ListNode<Tp> *node = new(p->allocate(sizeof(ListNode), strideof(ListNode))) ListNode();
+ node->element = element;
+ node->index = 0;
+ node->next = node;
+
+ return node;
+ }
+
+ static ListNode *create(const ListNode *n1, const Tp &element, pool *p) {
+ ListNode<Tp> *n2 = ListNode::create(element, p);
+
+ n2->index = n1->index + 1;
+ n2->next = n1->next;
+ n1->next = n2;
+
+ return n2;
+ }
+
+ inline ListNode<Tp>() { }
+
+ inline const ListNode<Tp> *at(int index) const {
+ const ListNode<Tp> *node = this;
+ while (index != node->index)
+ node = node->next;
+
+ return node;
+ }
+
+ inline bool hasNext() const {
+ return index < next->index;
+ }
+
+ inline int count() const {
+ return 1 + toBack()->index;
+ }
+
+ inline const ListNode<Tp> *toFront() const {
+ return toBack()->next;
+ }
+
+ inline const ListNode<Tp> *toBack() const {
+ const ListNode<Tp> *node = this;
+ while (node->hasNext())
+ node = node->next;
+
+ return node;
+ }
+};
+
+template <class Tp>
+inline const ListNode<Tp> *snoc(const ListNode<Tp> *list,
+ const Tp &element, pool *p)
+{
+ if (!list)
+ return ListNode<Tp>::create(element, p);
+
+ return ListNode<Tp>::create(list->toBack(), element, p);
+}
+
+#endif // FASTLIST_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp
new file mode 100644
index 000000000..338d81c25
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/name_compiler.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "name_compiler.h"
+#include "type_compiler.h"
+#include "declarator_compiler.h"
+#include "lexer.h"
+#include "symbol.h"
+#include "binder.h"
+
+#include <QtCore/qdebug.h>
+
+NameCompiler::NameCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+QString NameCompiler::decode_operator(std::size_t index) const
+{
+ const Token &tk = _M_token_stream->token((int) index);
+ return QString::fromUtf8(&tk.text[tk.position], (int) tk.size);
+}
+
+QString NameCompiler::internal_run(AST *node)
+{
+ _M_name.clear();
+ visit(node);
+ return name();
+}
+
+void NameCompiler::visitUnqualifiedName(UnqualifiedNameAST *node)
+{
+ QString tmp_name;
+
+ if (node->tilde)
+ tmp_name += QLatin1String("~");
+
+ if (node->id)
+ tmp_name += _M_token_stream->symbol(node->id)->as_string();
+
+ if (OperatorFunctionIdAST *op_id = node->operator_id) {
+#if defined(__GNUC__)
+#warning "NameCompiler::visitUnqualifiedName() -- implement me"
+#endif
+
+ if (op_id->op && op_id->op->op) {
+ tmp_name += QLatin1String("operator");
+ tmp_name += decode_operator(op_id->op->op);
+ if (op_id->op->close)
+ tmp_name += decode_operator(op_id->op->close);
+ } else if (op_id->type_specifier) {
+#if defined(__GNUC__)
+#warning "don't use an hardcoded string as cast' name"
+#endif
+ Token const &tk = _M_token_stream->token((int) op_id->start_token);
+ Token const &end_tk = _M_token_stream->token((int) op_id->end_token);
+ tmp_name += QString::fromLatin1(&tk.text[tk.position],
+ (int)(end_tk.position - tk.position)).trimmed();
+ }
+ }
+
+ _M_name += tmp_name;
+ if (node->template_arguments) {
+ // ### cleanup
+ _M_name.last() += QLatin1String("<");
+ visitNodes(this, node->template_arguments);
+ _M_name.last().truncate(_M_name.last().count() - 1); // remove the last ','
+ _M_name.last() += QLatin1String(">");
+ }
+
+}
+
+void NameCompiler::visitTemplateArgument(TemplateArgumentAST *node)
+{
+ if (node->type_id && node->type_id->type_specifier) {
+ TypeCompiler type_cc(_M_binder);
+ type_cc.run(node->type_id->type_specifier);
+
+ DeclaratorCompiler decl_cc(_M_binder);
+ decl_cc.run(node->type_id->declarator);
+
+ if (type_cc.isConstant())
+ _M_name.last() += QLatin1String("const ");
+
+ QStringList q = type_cc.qualifiedName();
+
+ if (q.count() == 1) {
+#if defined (RXX_RESOLVE_TYPEDEF) // ### it'll break :(
+ TypeInfo tp;
+ tp.setQualifiedName(q);
+ tp = TypeInfo::resolveType(tp, _M_binder->currentScope()->toItem());
+ q = tp.qualifiedName();
+#endif
+
+ if (CodeModelItem item = _M_binder->model()->findItem(q, _M_binder->currentScope())) {
+ if (item->name() == q.last())
+ q = item->qualifiedName();
+ }
+ }
+
+ _M_name.last() += q.join(QLatin1String("::"));
+
+ if (decl_cc.isReference())
+ _M_name.last() += QLatin1Char('&');
+ if (decl_cc.indirection())
+ _M_name.last() += QString(decl_cc.indirection(), QLatin1Char('*'));
+
+ _M_name.last() += QLatin1Char(',');
+ }
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/name_compiler.h b/sources/shiboken2/ApiExtractor/parser/name_compiler.h
new file mode 100644
index 000000000..431d401f8
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/name_compiler.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 NAME_COMPILER_H
+#define NAME_COMPILER_H
+
+#include "default_visitor.h"
+#include <QtCore/QStringList>
+
+class TokenStream;
+class Binder;
+
+class NameCompiler: protected DefaultVisitor
+{
+public:
+ NameCompiler(Binder *binder);
+
+ void run(NameAST *node) {
+ internal_run(node);
+ }
+ void run(UnqualifiedNameAST *node) {
+ internal_run(node);
+ }
+
+ QString name() const {
+ return _M_name.join(QLatin1String("::"));
+ }
+ QStringList qualifiedName() const {
+ return _M_name;
+ }
+
+protected:
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *node);
+ virtual void visitTemplateArgument(TemplateArgumentAST *node);
+
+ QString internal_run(AST *node);
+ QString decode_operator(std::size_t index) const;
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QStringList _M_name;
+};
+
+#endif // NAME_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/parser.cpp b/sources/shiboken2/ApiExtractor/parser/parser.cpp
new file mode 100644
index 000000000..60d034e83
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/parser.cpp
@@ -0,0 +1,4075 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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$
+**
+****************************************************************************/
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+
+// c++ support
+#include "parser.h"
+#include "tokens.h"
+#include "lexer.h"
+#include "control.h"
+
+#include <cstdlib>
+
+#define ADVANCE(tk, descr) \
+ { \
+ if (token_stream.lookAhead() != tk) { \
+ tokenRequiredError(tk); \
+ return false; \
+ } \
+ token_stream.nextToken(); \
+ }
+
+#define ADVANCE_NR(tk, descr) \
+ do { \
+ if (token_stream.lookAhead() != tk) { \
+ tokenRequiredError(tk); \
+ } \
+ else \
+ token_stream.nextToken(); \
+ } while (0)
+
+#define CHECK(tk) \
+ do { \
+ if (token_stream.lookAhead() != tk) { \
+ return false; \
+ } \
+ token_stream.nextToken(); \
+ } while (0)
+
+#define UPDATE_POS(_node, start, end) \
+ do { \
+ (_node)->start_token = start; \
+ (_node)->end_token = end; \
+ } while (0)
+
+Parser::Parser(Control *c)
+ : _M_location(token_stream, location_table, line_table),
+ control(c),
+ lexer(_M_location, control)
+{
+ _M_block_errors = false;
+}
+
+Parser::~Parser()
+{
+}
+
+void Parser::advance()
+{
+ token_stream.nextToken();
+}
+
+TranslationUnitAST *Parser::parse(const char *contents,
+ std::size_t size, pool *p)
+{
+ _M_block_errors = false;
+ _M_pool = p;
+ lexer.tokenize(contents, size);
+ token_stream.nextToken(); // skip the first token
+
+ Lexer *oldLexer = control->changeLexer(&lexer);
+ Parser *oldParser = control->changeParser(this);
+
+ TranslationUnitAST *ast = 0;
+ parseTranslationUnit(ast);
+
+ control->changeLexer(oldLexer);
+ control->changeParser(oldParser);
+
+ return ast;
+}
+
+bool Parser::parseWinDeclSpec(WinDeclSpecAST *&node)
+{
+ if (token_stream.lookAhead() != Token_identifier)
+ return false;
+
+ std::size_t start = token_stream.cursor();
+
+ const NameSymbol *name_symbol = token_stream.symbol(token_stream.cursor());
+ QString name = name_symbol->as_string();
+ if (name != QLatin1String("__declspec"))
+ return false;
+ std::size_t specifier = token_stream.cursor();
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != '(')
+ return false;
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != Token_identifier)
+ return false;
+ std::size_t modifier = token_stream.cursor();
+
+ token_stream.nextToken();
+ if (token_stream.lookAhead() != ')')
+ return false;
+
+ token_stream.nextToken();
+
+ node = CreateNode<WinDeclSpecAST>(_M_pool);
+ node->specifier = specifier;
+ node->modifier = modifier;
+
+ UPDATE_POS(node, start, token_stream.cursor());
+
+ return true;
+}
+
+void Parser::tokenRequiredError(int token)
+{
+ QString err;
+
+ err += QLatin1String("expected token ");
+ err += QLatin1String("``");
+ err += QLatin1String(token_name(token));
+ err += QLatin1String("'' found ``");
+ err += QLatin1String(token_name(token_stream.lookAhead()));
+ err += QLatin1String("''");
+
+ reportError(err);
+}
+
+void Parser::syntaxError()
+{
+ QString err;
+
+ err += QLatin1String("unexpected token ");
+ err += QLatin1String("``");
+ err += QLatin1String(token_name(token_stream.lookAhead()));
+ err += QLatin1String("''");
+
+ reportError(err);
+}
+
+void Parser::reportError(const QString& msg)
+{
+ if (!_M_block_errors) {
+ int line, column;
+ QString fileName;
+
+ std::size_t tok = token_stream.cursor();
+ location().positionAt(token_stream.position(tok),
+ &line, &column, &fileName);
+
+ Control::ErrorMessage errmsg;
+ errmsg.setLine(line + 1);
+ errmsg.setColumn(column);
+ errmsg.setFileName(fileName);
+ errmsg.setMessage(QLatin1String("** PARSER ERROR ") + msg);
+ control->reportError(errmsg);
+ }
+}
+
+bool Parser::skipUntil(int token)
+{
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == token)
+ return true;
+
+ token_stream.nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilDeclaration()
+{
+ while (token_stream.lookAhead()) {
+
+ switch (token_stream.lookAhead()) {
+ case ';':
+ case '~':
+ case Token_scope:
+ case Token_identifier:
+ case Token_operator:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_extern:
+ case Token_namespace:
+ case Token_using:
+ case Token_typedef:
+ case Token_asm:
+ case Token_template:
+ case Token_export:
+
+ case Token_const: // cv
+ case Token_volatile: // cv
+
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ case Token_signals: // Qt
+ case Token_slots: // Qt
+ return true;
+
+ default:
+ token_stream.nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skipUntilStatement()
+{
+ while (token_stream.lookAhead()) {
+ switch (token_stream.lookAhead()) {
+ case ';':
+ case '{':
+ case '}':
+ case Token_const:
+ case Token_volatile:
+ case Token_identifier:
+ case Token_case:
+ case Token_default:
+ case Token_if:
+ case Token_switch:
+ case Token_while:
+ case Token_do:
+ case Token_for:
+ case Token_break:
+ case Token_continue:
+ case Token_return:
+ case Token_goto:
+ case Token_try:
+ case Token_catch:
+ case Token_throw:
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ case Token_class:
+ case Token_struct:
+ case Token_union:
+ case Token_enum:
+ case Token_scope:
+ case Token_template:
+ case Token_using:
+ return true;
+
+ default:
+ token_stream.nextToken();
+ }
+ }
+
+ return false;
+}
+
+bool Parser::skip(int l, int r)
+{
+ int count = 0;
+ while (token_stream.lookAhead()) {
+ int tk = token_stream.lookAhead();
+
+ if (tk == l)
+ ++count;
+ else if (tk == r)
+ --count;
+ else if (l != '{' && (tk == '{' || tk == '}' || tk == ';'))
+ return false;
+
+ if (!count)
+ return true;
+
+ token_stream.nextToken();
+ }
+
+ return false;
+}
+
+bool Parser::parseName(NameAST *&node, bool acceptTemplateId)
+{
+ std::size_t start = token_stream.cursor();
+
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ NameAST *ast = CreateNode<NameAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope) {
+ ast->global = true;
+ token_stream.nextToken();
+ }
+
+ std::size_t idx = token_stream.cursor();
+
+ while (true) {
+ UnqualifiedNameAST *n = 0;
+ if (!parseUnqualifiedName(n))
+ return false;
+
+ if (token_stream.lookAhead() == Token_scope) {
+ token_stream.nextToken();
+
+ ast->qualified_names
+ = snoc(ast->qualified_names, n, _M_pool);
+
+ if (token_stream.lookAhead() == Token_template) {
+ /// skip optional template #### @todo CHECK
+ token_stream.nextToken();
+ }
+ } else {
+ Q_ASSERT(n);
+ if (!acceptTemplateId) {
+ token_stream.rewind((int) n->start_token);
+ parseUnqualifiedName(n, false);
+ }
+
+ ast->unqualified_name = n;
+ break;
+ }
+ }
+
+ if (idx == token_stream.cursor())
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTranslationUnit(TranslationUnitAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ TranslationUnitAST *ast = CreateNode<TranslationUnitAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *declaration = 0;
+ if (parseDeclaration(declaration)) {
+ ast->declarations =
+ snoc(ast->declarations, declaration, _M_pool);
+ } else {
+ // error recovery
+ if (startDecl == token_stream.cursor()) {
+ // skip at least one token
+ token_stream.nextToken();
+ }
+
+ skipUntilDeclaration();
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclaration(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case ';':
+ token_stream.nextToken();
+ return true;
+
+ case Token_extern:
+ return parseLinkageSpecification(node);
+
+ case Token_namespace:
+ return parseNamespace(node);
+
+ case Token_using:
+ return parseUsing(node);
+
+ case Token_typedef:
+ return parseTypedef(node);
+
+ case Token_asm:
+ return parseAsmDefinition(node);
+
+ case Token_Q_ENUMS:
+ case Token_Q_ENUM:
+ // Qt5:
+ // These two Q_ENUM tokens map to the same handler.
+ // If that turns out to be wrong, then write a new one
+ // named parseQ_ENUM
+ return parseQ_ENUMS(node);
+
+ case Token_template:
+ case Token_export:
+ return parseTemplateDeclaration(node);
+
+ default: {
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec)
+ || parseClassSpecifier(spec)
+ || parseForwardDeclarationSpecifier(spec)) {
+ parseCvQualify(cv);
+
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast =
+ CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ } // end switch
+
+ token_stream.rewind((int) start);
+ return parseDeclarationInternal(node);
+}
+
+bool Parser::parseLinkageSpecification(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_extern);
+
+ LinkageSpecificationAST *ast = CreateNode<LinkageSpecificationAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_string_literal) {
+ ast->extern_type = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == '{')
+ parseLinkageBody(ast->linkage_body);
+ else if (!parseDeclaration(ast->declaration))
+ reportError(QLatin1String("Declaration syntax error"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLinkageBody(LinkageBodyAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('{');
+
+ LinkageBodyAST *ast = CreateNode<LinkageBodyAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ int tk = token_stream.lookAhead();
+
+ if (tk == '}')
+ break;
+
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *declaration = 0;
+ if (parseDeclaration(declaration)) {
+ ast->declarations = snoc(ast->declarations, declaration, _M_pool);
+ } else {
+ // error recovery
+ if (startDecl == token_stream.cursor()) {
+ // skip at least one token
+ token_stream.nextToken();
+ }
+
+ skipUntilDeclaration();
+ }
+ }
+
+ if (token_stream.lookAhead() != '}')
+ reportError(QLatin1String("} expected"));
+ else
+ token_stream.nextToken();
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespace(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ std::size_t namespace_name = 0;
+ if (token_stream.lookAhead() == Token_identifier) {
+ namespace_name = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == '=') {
+ // namespace alias
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (parseName(name)) {
+ ADVANCE(';', ";");
+
+ NamespaceAliasDefinitionAST *ast
+ = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+ ast->namespace_name = namespace_name;
+ ast->alias_name = name;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ } else {
+ reportError(QLatin1String("namespace expected"));
+ return false;
+ }
+ } else if (token_stream.lookAhead() != '{') {
+ reportError(QLatin1String("{ expected"));
+ return false;
+ }
+
+ NamespaceAST *ast = CreateNode<NamespaceAST>(_M_pool);
+ ast->namespace_name = namespace_name;
+ parseLinkageBody(ast->linkage_body);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsing(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_using);
+
+ if (token_stream.lookAhead() == Token_namespace)
+ return parseUsingDirective(node);
+
+ UsingAST *ast = CreateNode<UsingAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_typename) {
+ ast->type_name = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (!parseName(ast->name))
+ return false;
+
+ ADVANCE(';', ";");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseUsingDirective(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ NameAST *name = 0;
+ if (!parseName(name)) {
+ reportError(QLatin1String("Namespace name expected"));
+ return false;
+ }
+
+ ADVANCE(';', ";");
+
+ UsingDirectiveAST *ast = CreateNode<UsingDirectiveAST>(_M_pool);
+ ast->name = name;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseOperatorFunctionId(OperatorFunctionIdAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_operator);
+
+ OperatorFunctionIdAST *ast = CreateNode<OperatorFunctionIdAST>(_M_pool);
+
+ if (!parseOperator(ast->op)) {
+ ast->op = 0;
+
+ // parse cast operator
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ if (!parseSimpleTypeSpecifier(ast->type_specifier)) {
+ syntaxError();
+ return false;
+ }
+
+ parseCvQualify(cv);
+ ast->type_specifier->cv = cv;
+
+ PtrOperatorAST *ptr_op = 0;
+ while (parsePtrOperator(ptr_op))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptr_op, _M_pool);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
+ bool reportError)
+{
+ TemplateArgumentAST *templArg = 0;
+ if (!parseTemplateArgument(templArg))
+ return false;
+
+ node = snoc(node, templArg, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseTemplateArgument(templArg)) {
+ if (reportError) {
+ syntaxError();
+ break;
+ }
+
+ node = 0;
+ return false;
+ }
+
+ node = snoc(node, templArg, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseTypedef(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_typedef);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) {
+ reportError(QLatin1String("Need a type specifier to declare"));
+ return false;
+ }
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ if (!parseInitDeclaratorList(declarators)) {
+ //reportError(("Need an identifier to declare"));
+ //return false;
+ }
+
+ ADVANCE(';', ";");
+
+ TypedefAST *ast = CreateNode<TypedefAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAsmDefinition(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_asm, "asm");
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ skip('(', ')');
+ token_stream.nextToken();
+ ADVANCE(';', ";");
+
+ AsmDefinitionAST *ast = CreateNode<AsmDefinitionAST>(_M_pool);
+ ast->cv = cv;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateDeclaration(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ std::size_t exported = 0;
+ if (token_stream.lookAhead() == Token_export) {
+ exported = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_template);
+
+ const ListNode<TemplateParameterAST*> *params = 0;
+ if (token_stream.lookAhead() == '<') {
+ token_stream.nextToken();
+ parseTemplateParameterList(params);
+
+ ADVANCE('>', ">");
+ }
+
+ DeclarationAST *declaration = 0;
+ if (!parseDeclaration(declaration))
+ reportError(QLatin1String("expected a declaration"));
+
+ TemplateDeclarationAST *ast = CreateNode<TemplateDeclarationAST>(_M_pool);
+ ast->exported = exported;
+ ast->template_parameters = params;
+ ast->declaration = declaration;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseOperator(OperatorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ OperatorAST *ast = CreateNode<OperatorAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case Token_new:
+ case Token_delete: {
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '['
+ && token_stream.lookAhead(1) == ']') {
+ ast->open = token_stream.cursor();
+ token_stream.nextToken();
+
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ }
+ break;
+
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case '^':
+ case '&':
+ case '|':
+ case '~':
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ case ',':
+ case Token_assign:
+ case Token_shift:
+ case Token_eq:
+ case Token_not_eq:
+ case Token_leq:
+ case Token_geq:
+ case Token_and:
+ case Token_or:
+ case Token_incr:
+ case Token_decr:
+ case Token_ptrmem:
+ case Token_arrow:
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ default:
+ if (token_stream.lookAhead() == '('
+ && token_stream.lookAhead(1) == ')') {
+ ast->op = ast->open = token_stream.cursor();
+ token_stream.nextToken();
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == '['
+ && token_stream.lookAhead(1) == ']') {
+ ast->op = ast->open = token_stream.cursor();
+ token_stream.nextToken();
+ ast->close = token_stream.cursor();
+ token_stream.nextToken();
+ } else {
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseCvQualify(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_const || tk == Token_volatile)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
+ bool onlyIntegral)
+{
+ std::size_t start = token_stream.cursor();
+ bool isIntegral = false;
+ bool done = false;
+
+ const ListNode<std::size_t> *integrals = 0;
+
+ while (!done) {
+ switch (token_stream.lookAhead()) {
+ case Token_char:
+ case Token_wchar_t:
+ case Token_bool:
+ case Token_short:
+ case Token_int:
+ case Token_long:
+ case Token_signed:
+ case Token_unsigned:
+ case Token_float:
+ case Token_double:
+ case Token_void:
+ integrals = snoc(integrals, token_stream.cursor(), _M_pool);
+ isIntegral = true;
+ token_stream.nextToken();
+ break;
+
+ default:
+ done = true;
+ }
+ }
+
+ SimpleTypeSpecifierAST *ast = CreateNode<SimpleTypeSpecifierAST>(_M_pool);
+ if (isIntegral) {
+ ast->integrals = integrals;
+ } else if (token_stream.lookAhead() == Token___typeof) {
+ ast->type_of = token_stream.cursor();
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ std::size_t saved = token_stream.cursor();
+ parseTypeId(ast->type_id);
+ if (token_stream.lookAhead() != ')') {
+ ast->type_id = 0;
+ token_stream.rewind((int) saved);
+ parseUnaryExpression(ast->expression);
+ }
+ ADVANCE(')', ")");
+ } else {
+ parseUnaryExpression(ast->expression);
+ }
+ } else if (onlyIntegral) {
+ token_stream.rewind((int) start);
+ return false;
+ } else {
+ if (!parseName(ast->name, true)) {
+ ast->name = 0;
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parsePtrOperator(PtrOperatorAST *&node)
+{
+ int tk = token_stream.lookAhead();
+
+ if (tk != '&' && tk != '*'
+ && tk != Token_scope && tk != Token_identifier) {
+ return false;
+ }
+
+ std::size_t start = token_stream.cursor();
+
+ PtrOperatorAST *ast = CreateNode<PtrOperatorAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case '&':
+ case '*':
+ ast->op = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ case Token_scope:
+ case Token_identifier: {
+ if (!parsePtrToMember(ast->mem_ptr)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+ break;
+
+ default:
+ Q_ASSERT(0);
+ break;
+ }
+
+ parseCvQualify(ast->cv);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateArgument(TemplateArgumentAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeIdAST *typeId = 0;
+ ExpressionAST *expr = 0;
+
+ if (!parseTypeId(typeId) || (token_stream.lookAhead() != ','
+ && token_stream.lookAhead() != '>')) {
+ token_stream.rewind((int) start);
+
+ if (!parseLogicalOrExpression(expr, true))
+ return false;
+ }
+
+ TemplateArgumentAST *ast = CreateNode<TemplateArgumentAST>(_M_pool);
+ ast->type_id = typeId;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *ast = 0;
+ if (!parseElaboratedTypeSpecifier(ast) && !parseSimpleTypeSpecifier(ast)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ parseCvQualify(cv);
+ ast->cv = cv;
+
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarator(DeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+
+ //fprintf(stderr, "[%s-%s] ast->ptr_ops: %p\n", __FILE__, __FUNCTION__, ast->ptr_ops);
+
+ DeclaratorAST *decl = 0;
+ NameAST *declId = 0;
+
+ PtrOperatorAST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ if (!parseDeclarator(decl))
+ return false;
+
+ ast->sub_declarator = decl;
+
+ CHECK(')');
+ } else {
+ if (token_stream.lookAhead() == ':') {
+ // unnamed bitfield
+ } else if (parseName(declId, true)) {
+ ast->id = declId;
+ } else {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ if (token_stream.lookAhead() == ':') {
+ token_stream.nextToken();
+
+ if (!parseConstantExpression(ast->bit_expression))
+ reportError(QLatin1String("Constant expression expected"));
+
+ goto update_pos;
+ }
+ }
+
+ {
+ bool isVector = true;
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+
+ ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+ isVector = true;
+ }
+
+ bool skipParen = false;
+ if (token_stream.lookAhead() == Token_identifier
+ && token_stream.lookAhead(1) == '('
+ && token_stream.lookAhead(2) == '(') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+ skipParen = true;
+ }
+
+ int tok = token_stream.lookAhead();
+ if (ast->sub_declarator
+ && !(isVector || tok == '(' || tok == ','
+ || tok == ';' || tok == '=')) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ std::size_t index = token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ ast->parameter_declaration_clause = params;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ token_stream.nextToken(); // skip ')'
+
+ parseCvQualify(ast->fun_cv);
+ parseNoExcept();
+ parseExceptionSpecification(ast->exception_spec);
+
+ if (token_stream.lookAhead() == Token___attribute__)
+ parse_Attribute__();
+ }
+
+ if (skipParen) {
+ if (token_stream.lookAhead() != ')')
+ reportError(QLatin1String("')' expected"));
+ else
+ token_stream.nextToken();
+ }
+ }
+
+update_pos:
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAbstractDeclarator(DeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *ast = CreateNode<DeclaratorAST>(_M_pool);
+ DeclaratorAST *decl = 0;
+
+ PtrOperatorAST *ptrOp = 0;
+ while (parsePtrOperator(ptrOp))
+ ast->ptr_ops = snoc(ast->ptr_ops, ptrOp, _M_pool);
+
+ int index = (int) token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ if (!parseAbstractDeclarator(decl)) {
+ token_stream.rewind((int) index);
+ goto label1;
+ }
+
+ ast->sub_declarator = decl;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == ':') {
+ token_stream.nextToken();
+ if (!parseConstantExpression(ast->bit_expression)) {
+ ast->bit_expression = 0;
+ reportError(QLatin1String("Constant expression expected"));
+ }
+ goto update_pos;
+ }
+
+label1: {
+ bool isVector = true;
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(']', "]");
+
+ ast->array_dimensions = snoc(ast->array_dimensions, expr, _M_pool);
+ isVector = true;
+ }
+
+ int tok = token_stream.lookAhead();
+ if (ast->sub_declarator
+ && !(isVector || tok == '(' || tok == ','
+ || tok == ';' || tok == '=')) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ int index = (int) token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ ParameterDeclarationClauseAST *params = 0;
+ if (!parseParameterDeclarationClause(params)) {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ ast->parameter_declaration_clause = params;
+
+ if (token_stream.lookAhead() != ')') {
+ token_stream.rewind((int) index);
+ goto update_pos;
+ }
+
+ token_stream.nextToken(); // skip ')'
+
+ parseCvQualify(ast->fun_cv);
+ parseExceptionSpecification(ast->exception_spec);
+ }
+ }
+
+update_pos:
+ if (token_stream.cursor() == start)
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseEnumSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_enum);
+
+ NameAST *name = 0;
+ parseName(name);
+
+ if (token_stream.lookAhead() != '{') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+
+ EnumSpecifierAST *ast = CreateNode<EnumSpecifierAST>(_M_pool);
+ ast->name = name;
+
+ EnumeratorAST *enumerator = 0;
+ if (parseEnumerator(enumerator)) {
+ ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseEnumerator(enumerator)) {
+ //reportError(("Enumerator expected"));
+ break;
+ }
+
+ ast->enumerators = snoc(ast->enumerators, enumerator, _M_pool);
+ }
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node)
+{
+ TemplateParameterAST *param = 0;
+ if (!parseTemplateParameter(param))
+ return false;
+
+ node = snoc(node, param, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseTemplateParameter(param)) {
+ syntaxError();
+ break;
+ } else {
+ node = snoc(node, param, _M_pool);
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseTemplateParameter(TemplateParameterAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ TemplateParameterAST *ast = CreateNode<TemplateParameterAST>(_M_pool);
+
+ int tk = token_stream.lookAhead();
+
+ if ((tk == Token_class || tk == Token_typename || tk == Token_template)
+ && parseTypeParameter(ast->type_parameter)) {
+ // nothing to do
+ } else if (!parseParameterDeclaration(ast->parameter_declaration))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeParameter(TypeParameterAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeParameterAST *ast = CreateNode<TypeParameterAST>(_M_pool);
+ ast->type = start;
+
+ switch (token_stream.lookAhead()) {
+ case Token_class:
+ case Token_typename: {
+ token_stream.nextToken(); // skip class
+
+ // parse optional name
+ if (parseName(ast->name, true)) {
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseTypeId(ast->type_id)) {
+ //syntaxError();
+ token_stream.rewind((int) start);
+ return false;
+ }
+ } else if (token_stream.lookAhead() != ','
+ && token_stream.lookAhead() != '>') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+ }
+ break;
+
+ case Token_template: {
+ token_stream.nextToken(); // skip template
+ ADVANCE('<', "<");
+
+ if (!parseTemplateParameterList(ast->template_parameters))
+ return false;
+
+ ADVANCE('>', ">");
+
+ if (token_stream.lookAhead() == Token_class)
+ token_stream.nextToken();
+
+ // parse optional name
+ if (parseName(ast->name, true)) {
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseTypeId(ast->type_id)) {
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ parseName(ast->template_name, true);
+ }
+ }
+ break;
+
+ default:
+ return false;
+
+ } // end switch
+
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+}
+
+bool Parser::parseStorageClassSpecifier(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_friend || tk == Token_auto
+ || tk == Token_register || tk == Token_static
+ || tk == Token_extern || tk == Token_mutable)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseFunctionSpecifier(const ListNode<std::size_t> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk;
+ while (0 != (tk = token_stream.lookAhead())
+ && (tk == Token_inline || tk == Token_virtual
+ || tk == Token_explicit || tk == Token_Q_INVOKABLE)) {
+ node = snoc(node, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ return start != token_stream.cursor();
+}
+
+bool Parser::parseTypeId(TypeIdAST *&node)
+{
+ /// @todo implement the AST for typeId
+ std::size_t start = token_stream.cursor();
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ DeclaratorAST *decl = 0;
+ parseAbstractDeclarator(decl);
+
+ TypeIdAST *ast = CreateNode<TypeIdAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->declarator = decl;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node)
+{
+ InitDeclaratorAST *decl = 0;
+ if (!parseInitDeclarator(decl))
+ return false;
+
+ node = snoc(node, decl, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseInitDeclarator(decl)) {
+ syntaxError();
+ break;
+ }
+ node = snoc(node, decl, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ParameterDeclarationClauseAST *ast
+ = CreateNode<ParameterDeclarationClauseAST>(_M_pool);
+
+ if (!parseParameterDeclarationList(ast->parameter_declarations)) {
+ if (token_stream.lookAhead() == ')')
+ goto good;
+
+ if (token_stream.lookAhead() == Token_ellipsis
+ && token_stream.lookAhead(1) == ')') {
+ ast->ellipsis = token_stream.cursor();
+ goto good;
+ }
+
+ return false;
+ }
+
+good:
+
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ ast->ellipsis = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ /// @todo add ellipsis
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ParameterDeclarationAST *param = 0;
+ if (!parseParameterDeclaration(param)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ node = snoc(node, param, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == Token_ellipsis)
+ break;
+
+ if (!parseParameterDeclaration(param)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ node = snoc(node, param, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseParameterDeclaration(ParameterDeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *storage = 0;
+ parseStorageClassSpecifier(storage);
+
+ // parse decl spec
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifier(spec)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ int index = (int) token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl)) {
+ token_stream.rewind((int) index);
+
+ // try with abstract declarator
+ parseAbstractDeclarator(decl);
+ }
+
+ ExpressionAST *expr = 0;
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+ if (!parseLogicalOrExpression(expr, true))
+ reportError(QLatin1String("Expression expected"));
+ }
+
+ ParameterDeclarationAST *ast = CreateNode<ParameterDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->declarator = decl;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parse_Attribute__()
+{
+ token_stream.nextToken();
+
+ ADVANCE('(', "(");
+
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+
+ if (token_stream.lookAhead() != ')') {
+ reportError(QLatin1String("')' expected"));
+ return false;
+ } else {
+ token_stream.nextToken();
+ }
+ return true;
+}
+
+QString Parser::tokenText(AST *ast) const
+{
+ if (!ast)
+ return QString();
+
+ int start_token = ast->start_token;
+ int end_token = ast->end_token;
+
+ Token const &tk = token_stream.token(start_token);
+ Token const &end_tk = token_stream.token(end_token);
+
+ return QString::fromLatin1(&tk.text[tk.position],
+ (int)(end_tk.position - tk.position)).trimmed();
+}
+
+bool Parser::parseForwardDeclarationSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int kind = token_stream.lookAhead();
+ if (kind != Token_class && kind != Token_struct && kind != Token_union)
+ return false;
+
+ std::size_t class_key = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (!parseName(name, false)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ BaseClauseAST *bases = 0;
+ if (token_stream.lookAhead() == ':') {
+ if (!parseBaseClause(bases)) {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ }
+
+ if (token_stream.lookAhead() != ';') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ ForwardDeclarationSpecifierAST *ast = CreateNode<ForwardDeclarationSpecifierAST>(_M_pool);
+ ast->class_key = class_key;
+ ast->name = name;
+ ast->base_clause = bases;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseClassSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int kind = token_stream.lookAhead();
+ if (kind != Token_class && kind != Token_struct && kind != Token_union)
+ return false;
+
+ std::size_t class_key = token_stream.cursor();
+ token_stream.nextToken();
+
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ if (token_stream.lookAhead() == Token___attribute__)
+ parse_Attribute__();
+
+ while (token_stream.lookAhead() == Token_identifier
+ && token_stream.lookAhead(1) == Token_identifier)
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ parseName(name, true);
+
+ BaseClauseAST *bases = 0;
+
+ if (token_stream.lookAhead() == ':') {
+ if (!parseBaseClause(bases))
+ skipUntil('{');
+ }
+
+ if (token_stream.lookAhead() != '{') {
+
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ ADVANCE('{', "{");
+
+ ClassSpecifierAST *ast = CreateNode<ClassSpecifierAST>(_M_pool);
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->class_key = class_key;
+ ast->name = name;
+ ast->base_clause = bases;
+
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == '}')
+ break;
+
+ std::size_t startDecl = token_stream.cursor();
+
+ DeclarationAST *memSpec = 0;
+ if (!parseMemberSpecification(memSpec)) {
+ if (startDecl == token_stream.cursor())
+ token_stream.nextToken(); // skip at least one token
+ skipUntilDeclaration();
+ } else
+ ast->member_specs = snoc(ast->member_specs, memSpec, _M_pool);
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseAccessSpecifier(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *specs = 0;
+
+ bool done = false;
+ while (!done) {
+ switch (token_stream.lookAhead()) {
+ case Token_signals:
+ case Token_slots:
+ case Token_k_dcop:
+ case Token_k_dcop_signals:
+ case Token_public:
+ case Token_protected:
+ case Token_private:
+ specs = snoc(specs, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ break;
+
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ if (!specs)
+ return false;
+
+ ADVANCE(':', ":");
+
+ AccessSpecifierAST *ast = CreateNode<AccessSpecifierAST>(_M_pool);
+ ast->specs = specs;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseMemberSpecification(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == ';') {
+ token_stream.nextToken();
+ return true;
+ } else if (token_stream.lookAhead() == Token_Q_OBJECT
+ || token_stream.lookAhead() == Token_K_DCOP) {
+ token_stream.nextToken();
+ return true;
+ } else if (parseTypedef(node)) {
+ return true;
+ } else if (parseUsing(node)) {
+ return true;
+ } else if (parseTemplateDeclaration(node)) {
+ return true;
+ } else if (parseAccessSpecifier(node)) {
+ return true;
+ } else if (parseQ_PROPERTY(node)) {
+ return true;
+ } else if (parseQ_ENUMS(node)) {
+ return true;
+ }
+
+ token_stream.rewind((int) start);
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (parseEnumSpecifier(spec) || parseClassSpecifier(spec)) {
+ parseCvQualify(cv);
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+ ADVANCE(';', ";");
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ token_stream.rewind((int) start);
+ return parseDeclarationInternal(node);
+}
+
+bool Parser::parseCtorInitializer(CtorInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(':');
+
+ CtorInitializerAST *ast = CreateNode<CtorInitializerAST>(_M_pool);
+ ast->colon = start;
+
+ if (!parseMemInitializerList(ast->member_initializers))
+ reportError(QLatin1String("Member initializers expected"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseElaboratedTypeSpecifier(TypeSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk = token_stream.lookAhead();
+ if (tk == Token_class
+ || tk == Token_struct
+ || tk == Token_union
+ || tk == Token_enum
+ || tk == Token_typename) {
+ std::size_t type = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST *name = 0;
+ if (parseName(name, true)) {
+ ElaboratedTypeSpecifierAST *ast
+ = CreateNode<ElaboratedTypeSpecifierAST>(_M_pool);
+
+ ast->type = type;
+ ast->name = name;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+
+ token_stream.rewind((int) start);
+ return false;
+}
+
+bool Parser::parseNoExcept()
+{
+ // right now we only accept 'noexcept' with no conditional
+ CHECK(Token_noexcept);
+
+ return true;
+}
+
+bool Parser::parseExceptionSpecification(ExceptionSpecificationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_throw);
+ ADVANCE('(', "(");
+
+ ExceptionSpecificationAST *ast = CreateNode<ExceptionSpecificationAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ ast->ellipsis = token_stream.cursor();
+ token_stream.nextToken();
+ } else {
+ parseTypeIdList(ast->type_ids);
+ }
+
+ ADVANCE(')', ")");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseEnumerator(EnumeratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_identifier);
+ std::size_t id = token_stream.cursor() - 1;
+
+ EnumeratorAST *ast = CreateNode<EnumeratorAST>(_M_pool);
+ ast->id = id;
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ if (!parseConstantExpression(ast->expression))
+ reportError(QLatin1String("Constant expression expected"));
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitDeclarator(InitDeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl))
+ return false;
+
+ if (token_stream.lookAhead(0) == Token_asm) {
+ token_stream.nextToken();
+ skip('(', ')');
+ token_stream.nextToken();
+ }
+
+ InitializerAST *init = 0;
+ parseInitializer(init);
+
+ InitDeclaratorAST *ast = CreateNode<InitDeclaratorAST>(_M_pool);
+ ast->declarator = decl;
+ ast->initializer = init;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseBaseClause(BaseClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(':');
+
+ BaseSpecifierAST *baseSpec = 0;
+ if (!parseBaseSpecifier(baseSpec))
+ return false;
+
+ BaseClauseAST *ast = CreateNode<BaseClauseAST>(_M_pool);
+ ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseBaseSpecifier(baseSpec)) {
+ reportError(QLatin1String("Base class specifier expected"));
+ break;
+ }
+ ast->base_specifiers = snoc(ast->base_specifiers, baseSpec, _M_pool);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitializer(InitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ int tk = token_stream.lookAhead();
+ if (tk != '=' && tk != '(')
+ return false;
+
+ InitializerAST *ast = CreateNode<InitializerAST>(_M_pool);
+
+ if (tk == '=') {
+ token_stream.nextToken();
+
+ if (!parseInitializerClause(ast->initializer_clause))
+ reportError(QLatin1String("Initializer clause expected"));
+
+ } else if (tk == '(') {
+ token_stream.nextToken();
+ parseCommaExpression(ast->expression);
+ CHECK(')');
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseMemInitializerList(const ListNode<MemInitializerAST*> *&node)
+{
+ MemInitializerAST *init = 0;
+
+ if (!parseMemInitializer(init))
+ return false;
+
+ node = snoc(node, init, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+
+ if (!parseMemInitializer(init))
+ break;
+
+ node = snoc(node, init, _M_pool);
+ }
+
+ return true;
+}
+
+bool Parser::parseMemInitializer(MemInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NameAST *initId = 0;
+ if (!parseName(initId, true)) {
+ reportError(QLatin1String("Identifier expected"));
+ return false;
+ }
+
+ ADVANCE('(', "(");
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ MemInitializerAST *ast = CreateNode<MemInitializerAST>(_M_pool);
+ ast->initializer_id = initId;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseTypeIdList(const ListNode<TypeIdAST*> *&node)
+{
+ TypeIdAST *typeId = 0;
+ if (!parseTypeId(typeId))
+ return false;
+
+ node = snoc(node, typeId, _M_pool);
+
+ while (token_stream.lookAhead() == ',') {
+ token_stream.nextToken();
+ if (parseTypeId(typeId)) {
+ node = snoc(node, typeId, _M_pool);
+ } else {
+ reportError(QLatin1String("Type id expected"));
+ break;
+ }
+ }
+
+ return true;
+}
+
+bool Parser::parseBaseSpecifier(BaseSpecifierAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ BaseSpecifierAST *ast = CreateNode<BaseSpecifierAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_virtual) {
+ ast->virt = token_stream.cursor();
+ token_stream.nextToken();
+
+ int tk = token_stream.lookAhead();
+ if (tk == Token_public || tk == Token_protected
+ || tk == Token_private) {
+ ast->access_specifier = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ } else {
+ int tk = token_stream.lookAhead();
+ if (tk == Token_public || tk == Token_protected
+ || tk == Token_private) {
+ ast->access_specifier = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ if (token_stream.lookAhead() == Token_virtual) {
+ ast->virt = token_stream.cursor();
+ token_stream.nextToken();
+ }
+ }
+
+ if (!parseName(ast->name, true))
+ reportError(QLatin1String("Class name expected"));
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseInitializerClause(InitializerClauseAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ InitializerClauseAST *ast = CreateNode<InitializerClauseAST>(_M_pool);
+
+ if (token_stream.lookAhead() == '{') {
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ if (skip('{', '}'))
+ token_stream.nextToken();
+ else
+ reportError(QLatin1String("} missing"));
+ } else {
+ if (!parseAssignmentExpression(ast->expression))
+ reportError(QLatin1String("Expression expected"));
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parsePtrToMember(PtrToMemberAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implemente me (AST)"
+#endif
+
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == Token_scope) {
+ token_stream.nextToken();
+ }
+
+ UnqualifiedNameAST *name = 0;
+ while (token_stream.lookAhead() == Token_identifier) {
+ if (!parseUnqualifiedName(name))
+ break;
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == '*') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ PtrToMemberAST *ast = CreateNode<PtrToMemberAST>(_M_pool);
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ if (token_stream.lookAhead() == Token_scope)
+ token_stream.nextToken();
+ }
+
+ token_stream.rewind((int) start);
+ return false;
+}
+
+bool Parser::parseUnqualifiedName(UnqualifiedNameAST *&node,
+ bool parseTemplateId)
+{
+ std::size_t start = token_stream.cursor();
+
+ std::size_t tilde = 0;
+ std::size_t id = 0;
+ OperatorFunctionIdAST *operator_id = 0;
+
+ if (token_stream.lookAhead() == Token_identifier) {
+ id = token_stream.cursor();
+ token_stream.nextToken();
+ } else if (token_stream.lookAhead() == '~'
+ && token_stream.lookAhead(1) == Token_identifier) {
+ tilde = token_stream.cursor();
+ token_stream.nextToken(); // skip ~
+
+ id = token_stream.cursor();
+ token_stream.nextToken(); // skip classname
+ } else if (token_stream.lookAhead() == Token_operator) {
+ if (!parseOperatorFunctionId(operator_id))
+ return false;
+ } else {
+ return false;
+ }
+
+ UnqualifiedNameAST *ast = CreateNode<UnqualifiedNameAST>(_M_pool);
+ ast->tilde = tilde;
+ ast->id = id;
+ ast->operator_id = operator_id;
+
+ if (parseTemplateId && !tilde) {
+ std::size_t index = token_stream.cursor();
+
+ if (token_stream.lookAhead() == '<') {
+ token_stream.nextToken();
+
+ // optional template arguments
+ parseTemplateArgumentList(ast->template_arguments);
+
+ if (token_stream.lookAhead() == '>') {
+ token_stream.nextToken();
+ } else {
+ ast->template_arguments = 0;
+ token_stream.rewind((int) index);
+ }
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStringLiteral(StringLiteralAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() != Token_string_literal)
+ return false;
+
+ StringLiteralAST *ast = CreateNode<StringLiteralAST>(_M_pool);
+
+ while (token_stream.lookAhead() == Token_string_literal) {
+ ast->literals = snoc(ast->literals, token_stream.cursor(), _M_pool);
+ token_stream.nextToken();
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseExpressionStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ExpressionStatementAST *ast = CreateNode<ExpressionStatementAST>(_M_pool);
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_while:
+ return parseWhileStatement(node);
+
+ case Token_do:
+ return parseDoStatement(node);
+
+ case Token_for:
+ return parseForStatement(node);
+
+ case Token_if:
+ return parseIfStatement(node);
+
+ case Token_switch:
+ return parseSwitchStatement(node);
+
+ case Token_try:
+ return parseTryBlockStatement(node);
+
+ case Token_case:
+ case Token_default:
+ return parseLabeledStatement(node);
+
+ case Token_break:
+ case Token_continue:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ token_stream.nextToken();
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_goto:
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ token_stream.nextToken();
+ ADVANCE(Token_identifier, "identifier");
+ ADVANCE(';', ";");
+ return true;
+
+ case Token_return: {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+
+ ADVANCE(';', ";");
+
+ ReturnStatementAST *ast = CreateNode<ReturnStatementAST>(_M_pool);
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '{':
+ return parseCompoundStatement(node);
+
+ case Token_identifier:
+ if (parseLabeledStatement(node))
+ return true;
+ break;
+ }
+
+ return parseExpressionOrDeclarationStatement(node);
+}
+
+bool Parser::parseExpressionOrDeclarationStatement(StatementAST *&node)
+{
+ bool blocked = block_errors(true);
+
+ std::size_t start = token_stream.cursor();
+
+ StatementAST *decl_ast = 0;
+ bool maybe_amb = parseDeclarationStatement(decl_ast);
+ maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+ std::size_t end = token_stream.cursor();
+
+ token_stream.rewind((int) start);
+ StatementAST *expr_ast = 0;
+ maybe_amb &= parseExpressionStatement(expr_ast);
+ maybe_amb &= token_stream.kind(token_stream.cursor() - 1) == ';';
+
+ if (maybe_amb) {
+ Q_ASSERT(decl_ast && expr_ast);
+ ExpressionOrDeclarationStatementAST *ast =
+ CreateNode<ExpressionOrDeclarationStatementAST>(_M_pool);
+ ast->declaration = decl_ast;
+ ast->expression = expr_ast;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ } else {
+ token_stream.rewind((int) std::max(end, token_stream.cursor()));
+
+ node = decl_ast;
+ if (!node)
+ node = expr_ast;
+ }
+
+ block_errors(blocked);
+
+ if (!node)
+ syntaxError();
+
+ return node != 0;
+}
+
+bool Parser::parseCondition(ConditionAST *&node, bool initRequired)
+{
+ std::size_t start = token_stream.cursor();
+
+ ConditionAST *ast = CreateNode<ConditionAST>(_M_pool);
+ TypeSpecifierAST *spec = 0;
+
+ if (parseTypeSpecifier(spec)) {
+ ast->type_specifier = spec;
+
+ std::size_t declarator_start = token_stream.cursor();
+
+ DeclaratorAST *decl = 0;
+ if (!parseDeclarator(decl)) {
+ token_stream.rewind((int) declarator_start);
+ if (!initRequired && !parseAbstractDeclarator(decl))
+ decl = 0;
+ }
+
+ if (decl && (!initRequired || token_stream.lookAhead() == '=')) {
+ ast->declarator = decl;
+
+ if (token_stream.lookAhead() == '=') {
+ token_stream.nextToken();
+
+ parseExpression(ast->expression);
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+
+ token_stream.rewind((int) start);
+
+ if (!parseCommaExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+bool Parser::parseWhileStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_while, "while");
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(QLatin1String("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(QLatin1String("statement expected"));
+ return false;
+ }
+
+ WhileStatementAST *ast = CreateNode<WhileStatementAST>(_M_pool);
+ ast->condition = cond;
+ ast->statement = body;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDoStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_do, "do");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body)) {
+ reportError(QLatin1String("statement expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(Token_while, "while");
+ ADVANCE_NR('(' , "(");
+
+ ExpressionAST *expr = 0;
+ if (!parseCommaExpression(expr)) {
+ reportError(QLatin1String("expression expected"));
+ //return false;
+ }
+
+ ADVANCE_NR(')', ")");
+ ADVANCE_NR(';', ";");
+
+ DoStatementAST *ast = CreateNode<DoStatementAST>(_M_pool);
+ ast->statement = body;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_for, "for");
+ ADVANCE('(', "(");
+
+ StatementAST *init = 0;
+ if (!parseForInitStatement(init)) {
+ reportError(QLatin1String("for initialization expected"));
+ return false;
+ }
+
+ ConditionAST *cond = 0;
+ parseCondition(cond);
+ ADVANCE(';', ";");
+
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseStatement(body))
+ return false;
+
+ ForStatementAST *ast = CreateNode<ForStatementAST>(_M_pool);
+ ast->init_statement = init;
+ ast->condition = cond;
+ ast->expression = expr;
+ ast->statement = body;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseForInitStatement(StatementAST *&node)
+{
+ if (parseDeclarationStatement(node))
+ return true;
+
+ return parseExpressionStatement(node);
+}
+
+bool Parser::parseCompoundStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('{');
+
+ CompoundStatementAST *ast = CreateNode<CompoundStatementAST>(_M_pool);
+
+ while (token_stream.lookAhead()) {
+ if (token_stream.lookAhead() == '}')
+ break;
+
+ std::size_t startStmt = token_stream.cursor();
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ if (startStmt == token_stream.cursor())
+ token_stream.nextToken();
+
+ skipUntilStatement();
+ } else {
+ ast->statements = snoc(ast->statements, stmt, _M_pool);
+ }
+ }
+
+ ADVANCE_NR('}', "}");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseIfStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ ADVANCE(Token_if, "if");
+
+ ADVANCE('(' , "(");
+
+ IfStatementAST *ast = CreateNode<IfStatementAST>(_M_pool);
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(QLatin1String("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseStatement(stmt)) {
+ reportError(QLatin1String("statement expected"));
+ return false;
+ }
+
+ ast->condition = cond;
+ ast->statement = stmt;
+
+ if (token_stream.lookAhead() == Token_else) {
+ token_stream.nextToken();
+
+ if (!parseStatement(ast->else_statement)) {
+ reportError(QLatin1String("statement expected"));
+ return false;
+ }
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseSwitchStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+ ADVANCE(Token_switch, "switch");
+
+ ADVANCE('(' , "(");
+
+ ConditionAST *cond = 0;
+ if (!parseCondition(cond)) {
+ reportError(QLatin1String("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ SwitchStatementAST *ast = CreateNode<SwitchStatementAST>(_M_pool);
+ ast->condition = cond;
+ ast->statement = stmt;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseLabeledStatement(StatementAST *&node)
+{
+ switch (token_stream.lookAhead()) {
+ case Token_identifier:
+ case Token_default:
+ if (token_stream.lookAhead(1) == ':') {
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ StatementAST *stmt = 0;
+ if (parseStatement(stmt)) {
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ case Token_case: {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ if (!parseConstantExpression(expr)) {
+ reportError(QLatin1String("expression expected"));
+ } else if (token_stream.lookAhead() == Token_ellipsis) {
+ token_stream.nextToken();
+
+ ExpressionAST *expr2 = 0;
+ if (!parseConstantExpression(expr2))
+ reportError(QLatin1String("expression expected"));
+ }
+ ADVANCE(':', ":");
+
+ StatementAST *stmt = 0;
+ if (parseStatement(stmt)) {
+ node = stmt;
+ return true;
+ }
+ }
+ break;
+
+ }
+
+ return false;
+}
+
+bool Parser::parseBlockDeclaration(DeclarationAST *&node)
+{
+ switch (token_stream.lookAhead()) {
+ case Token_typedef:
+ return parseTypedef(node);
+ case Token_using:
+ return parseUsing(node);
+ case Token_asm:
+ return parseAsmDefinition(node);
+ case Token_namespace:
+ return parseNamespaceAliasDefinition(node);
+ }
+
+ std::size_t start = token_stream.cursor();
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ parseStorageClassSpecifier(storageSpec);
+
+ parseCvQualify(cv);
+
+ TypeSpecifierAST *spec = 0;
+ if (!parseTypeSpecifierOrClassSpec(spec)) { // replace with simpleTypeSpecifier?!?!
+ token_stream.rewind((int) start);
+ return false;
+ }
+
+ parseCvQualify(cv);
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ parseInitDeclaratorList(declarators);
+
+ if (token_stream.lookAhead() != ';') {
+ token_stream.rewind((int) start);
+ return false;
+ }
+ token_stream.nextToken();
+
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->type_specifier = spec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNamespaceAliasDefinition(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_namespace);
+
+ NamespaceAliasDefinitionAST *ast
+ = CreateNode<NamespaceAliasDefinitionAST>(_M_pool);
+
+ ADVANCE(Token_identifier, "identifier");
+ ast->namespace_name = token_stream.cursor() - 1;
+
+ ADVANCE('=', "=");
+
+ if (!parseName(ast->alias_name))
+ reportError(QLatin1String("Namespace name expected"));
+
+ ADVANCE(';', ";");
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarationStatement(StatementAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeclarationAST *decl = 0;
+ if (!parseBlockDeclaration(decl))
+ return false;
+
+ DeclarationStatementAST *ast = CreateNode<DeclarationStatementAST>(_M_pool);
+ ast->declaration = decl;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeclarationInternal(DeclarationAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ // that is for the case '__declspec(dllexport) int ...' or
+ // '__declspec(dllexport) inline int ...', etc.
+ WinDeclSpecAST *winDeclSpec = 0;
+ parseWinDeclSpec(winDeclSpec);
+
+ const ListNode<std::size_t> *funSpec = 0;
+ bool hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ const ListNode<std::size_t> *cv = 0;
+ parseCvQualify(cv);
+
+ const ListNode<std::size_t> *storageSpec = 0;
+ bool hasStorageSpec = parseStorageClassSpecifier(storageSpec);
+
+ if (hasStorageSpec && !hasFunSpec)
+ hasFunSpec = parseFunctionSpecifier(funSpec);
+
+ // that is for the case 'friend __declspec(dllexport) ....'
+ parseWinDeclSpec(winDeclSpec);
+
+ if (!cv)
+ parseCvQualify(cv);
+
+ int index = (int) token_stream.cursor();
+ NameAST *name = 0;
+ if (parseName(name, true) && token_stream.lookAhead() == '(') {
+ // no type specifier, maybe a constructor or a cast operator??
+
+ token_stream.rewind((int) index);
+
+ InitDeclaratorAST *declarator = 0;
+ if (parseInitDeclarator(declarator)) {
+ switch (token_stream.lookAhead()) {
+ case ';': {
+ token_stream.nextToken();
+
+ SimpleDeclarationAST *ast
+ = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarators = snoc(ast->init_declarators,
+ declarator, _M_pool);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case ':': {
+ CtorInitializerAST *ctorInit = 0;
+ StatementAST *funBody = 0;
+
+ if (parseCtorInitializer(ctorInit)
+ && parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarator = declarator;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+
+ case '{': {
+ StatementAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->init_declarator = declarator;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+
+ case '(':
+ case '[':
+ // ops!! it seems a declarator
+ goto start_decl;
+ break;
+ }
+
+ }
+ }
+
+start_decl:
+ token_stream.rewind((int) index);
+
+ if (token_stream.lookAhead() == Token_const
+ && token_stream.lookAhead(1) == Token_identifier
+ && token_stream.lookAhead(2) == '=') {
+ // constant definition
+ token_stream.nextToken(); // skip const
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ if (!parseInitDeclaratorList(declarators)) {
+ syntaxError();
+ return false;
+ }
+
+ ADVANCE(';', ";");
+
+#if defined(__GNUC__)
+#warning "mark the ast as constant"
+#endif
+ SimpleDeclarationAST *ast = CreateNode<SimpleDeclarationAST>(_M_pool);
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+
+ TypeSpecifierAST *spec = 0;
+ if (parseTypeSpecifier(spec)) {
+ Q_ASSERT(spec);
+
+ if (!hasFunSpec)
+ parseFunctionSpecifier(funSpec); // e.g. "void inline"
+
+ spec->cv = cv;
+
+ const ListNode<InitDeclaratorAST*> *declarators = 0;
+ InitDeclaratorAST *decl = 0;
+ int startDeclarator = (int) token_stream.cursor();
+ bool maybeFunctionDefinition = false;
+
+ if (token_stream.lookAhead() != ';') {
+ if (parseInitDeclarator(decl) && token_stream.lookAhead() == '{') {
+ // function definition
+ maybeFunctionDefinition = true;
+ } else {
+ token_stream.rewind((int) startDeclarator);
+ if (!parseInitDeclaratorList(declarators)) {
+ syntaxError();
+ return false;
+ }
+ }
+ }
+
+ switch (token_stream.lookAhead()) {
+ case ';': {
+ token_stream.nextToken();
+ SimpleDeclarationAST *ast
+ = CreateNode<SimpleDeclarationAST>(_M_pool);
+
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->type_specifier = spec;
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->init_declarators = declarators;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '{': {
+ if (!maybeFunctionDefinition) {
+ syntaxError();
+ return false;
+ }
+
+ StatementAST *funBody = 0;
+ if (parseFunctionBody(funBody)) {
+ FunctionDefinitionAST *ast
+ = CreateNode<FunctionDefinitionAST>(_M_pool);
+
+ ast->win_decl_specifiers = winDeclSpec;
+ ast->storage_specifiers = storageSpec;
+ ast->function_specifiers = funSpec;
+ ast->type_specifier = spec;
+ ast->init_declarator = decl;
+ ast->function_body = funBody;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ break;
+ } // end switch
+ }
+
+ syntaxError();
+ return false;
+}
+
+bool Parser::skipFunctionBody(StatementAST *&)
+{
+#if defined(__GNUC__)
+#warning "Parser::skipFunctionBody() -- implement me"
+#endif
+ Q_ASSERT(0); // ### not implemented
+ return 0;
+}
+
+bool Parser::parseFunctionBody(StatementAST *&node)
+{
+ if (control->skipFunctionBody())
+ return skipFunctionBody(node);
+
+ return parseCompoundStatement(node);
+}
+
+bool Parser::parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node)
+{
+ if (parseClassSpecifier(node))
+ return true;
+ else if (parseEnumSpecifier(node))
+ return true;
+ else if (parseTypeSpecifier(node))
+ return true;
+
+ return false;
+}
+
+bool Parser::parseTryBlockStatement(StatementAST *&node)
+{
+#if defined(__GNUC__)
+#warning "implement me"
+#endif
+ CHECK(Token_try);
+
+ StatementAST *stmt = 0;
+ if (!parseCompoundStatement(stmt)) {
+ syntaxError();
+ return false;
+ }
+
+ if (token_stream.lookAhead() != Token_catch) {
+ reportError(QLatin1String("catch expected"));
+ return false;
+ }
+
+ while (token_stream.lookAhead() == Token_catch) {
+ token_stream.nextToken();
+ ADVANCE('(', "(");
+ ConditionAST *cond = 0;
+ if (token_stream.lookAhead() == Token_ellipsis) {
+ token_stream.nextToken();
+ } else if (!parseCondition(cond, false)) {
+ reportError(QLatin1String("condition expected"));
+ return false;
+ }
+ ADVANCE(')', ")");
+
+ StatementAST *body = 0;
+ if (!parseCompoundStatement(body)) {
+ syntaxError();
+ return false;
+ }
+ }
+
+ node = stmt;
+ return true;
+}
+
+bool Parser::parsePrimaryExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ PrimaryExpressionAST *ast = CreateNode<PrimaryExpressionAST>(_M_pool);
+
+ switch (token_stream.lookAhead()) {
+ case Token_string_literal:
+ parseStringLiteral(ast->literal);
+ break;
+
+ case Token_number_literal:
+ case Token_char_literal:
+ case Token_true:
+ case Token_false:
+ case Token_this:
+ ast->token = token_stream.cursor();
+ token_stream.nextToken();
+ break;
+
+ case '(':
+ token_stream.nextToken();
+
+ if (token_stream.lookAhead() == '{') {
+ if (!parseCompoundStatement(ast->expression_statement))
+ return false;
+ } else {
+ if (!parseExpression(ast->sub_expression))
+ return false;
+ }
+
+ CHECK(')');
+ break;
+
+ default:
+ if (!parseName(ast->name))
+ return false;
+
+ break;
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+
+/*
+ postfix-expression-internal:
+ [ expression ]
+ ( expression-list [opt] )
+ (.|->) template [opt] id-expression
+ (.|->) pseudo-destructor-name
+ ++
+ --
+*/
+bool Parser::parsePostfixExpressionInternal(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case '[': {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(']');
+
+ SubscriptExpressionAST *ast
+ = CreateNode<SubscriptExpressionAST>(_M_pool);
+
+ ast->subscript = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '(': {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ CHECK(')');
+
+ FunctionCallAST *ast = CreateNode<FunctionCallAST>(_M_pool);
+ ast->arguments = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case '.':
+ case Token_arrow: {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ std::size_t templ = 0;
+ if (token_stream.lookAhead() == Token_template) {
+ templ = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ int saved = int(token_stream.cursor());
+ NameAST *name = 0;
+
+ if (parseName(name, true) && name->unqualified_name
+ && name->unqualified_name->template_arguments
+ && token_stream.lookAhead() == '(') {
+ // a template method call
+ // ### reverse the logic
+ } else {
+ token_stream.rewind(saved);
+ name = 0;
+
+ if (!parseName(name, templ != 0))
+ return false;
+ }
+
+ ClassMemberAccessAST *ast = CreateNode<ClassMemberAccessAST>(_M_pool);
+ ast->op = op;
+ ast->name = name;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_incr:
+ case Token_decr: {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ IncrDecrExpressionAST *ast = CreateNode<IncrDecrExpressionAST>(_M_pool);
+ ast->op = op;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/*
+ postfix-expression:
+ simple-type-specifier ( expression-list [opt] )
+ primary-expression postfix-expression-internal*
+*/
+bool Parser::parsePostfixExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_dynamic_cast:
+ case Token_static_cast:
+ case Token_reinterpret_cast:
+ case Token_const_cast: {
+ std::size_t castOp = token_stream.cursor();
+ token_stream.nextToken();
+
+ CHECK('<');
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ CHECK('>');
+
+ CHECK('(');
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')');
+
+ CppCastExpressionAST *ast = CreateNode<CppCastExpressionAST>(_M_pool);
+ ast->op = castOp;
+ ast->type_id = typeId;
+ ast->expression = expr;
+
+ ExpressionAST *e = 0;
+ while (parsePostfixExpressionInternal(e))
+ ast->sub_expressions = snoc(ast->sub_expressions, e, _M_pool);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_typename: {
+ std::size_t token = token_stream.cursor();
+ token_stream.nextToken();
+
+ NameAST* name = 0;
+ if (!parseName(name, true))
+ return false;
+
+ CHECK('(');
+ ExpressionAST *expr = 0;
+ parseCommaExpression(expr);
+ CHECK(')');
+
+ TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+ ast->typename_token = token;
+ ast->name = name;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_typeid: {
+ token_stream.nextToken();
+
+ CHECK('(');
+ TypeIdAST *typeId = 0;
+ parseTypeId(typeId);
+ CHECK(')');
+
+ TypeIdentificationAST *ast = CreateNode<TypeIdentificationAST>(_M_pool);
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ default:
+ break;
+ }
+
+ std::size_t saved_pos = token_stream.cursor();
+
+ TypeSpecifierAST *typeSpec = 0;
+ ExpressionAST *expr = 0;
+
+ // let's try to parse a type
+ NameAST *name = 0;
+ if (parseName(name, true)) {
+ Q_ASSERT(name->unqualified_name);
+
+ bool has_template_args = name->unqualified_name->template_arguments != 0;
+
+ if (has_template_args && token_stream.lookAhead() == '(') {
+ ExpressionAST *cast_expr = 0;
+ if (parseCastExpression(cast_expr)
+ && cast_expr->kind == AST::Kind_CastExpression) {
+ token_stream.rewind((int) saved_pos);
+ parsePrimaryExpression(expr);
+ goto L_no_rewind;
+ }
+ }
+ }
+
+ token_stream.rewind((int) saved_pos);
+
+L_no_rewind:
+ if (!expr && parseSimpleTypeSpecifier(typeSpec)
+ && token_stream.lookAhead() == '(') {
+ token_stream.nextToken(); // skip '('
+ parseCommaExpression(expr);
+ CHECK(')');
+ } else if (expr) {
+ typeSpec = 0;
+ } else {
+ typeSpec = 0;
+ token_stream.rewind((int) start);
+
+ if (!parsePrimaryExpression(expr))
+ return false;
+ }
+
+ const ListNode<ExpressionAST*> *sub_expressions = 0;
+ ExpressionAST *sub_expression = 0;
+
+ while (parsePostfixExpressionInternal(sub_expression))
+ sub_expressions = snoc(sub_expressions, sub_expression, _M_pool);
+
+ if (sub_expressions || !expr || (typeSpec && expr)) {
+ PostfixExpressionAST *ast = CreateNode<PostfixExpressionAST>(_M_pool);
+ ast->type_specifier = typeSpec;
+ ast->expression = expr;
+ ast->sub_expressions = sub_expressions;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ } else
+ node = expr;
+
+ return true;
+}
+
+bool Parser::parseUnaryExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ switch (token_stream.lookAhead()) {
+ case Token_incr:
+ case Token_decr:
+ case '*':
+ case '&':
+ case '+':
+ case '-':
+ case '!':
+ case '~': {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *expr = 0;
+ if (!parseCastExpression(expr))
+ return false;
+
+ UnaryExpressionAST *ast = CreateNode<UnaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->expression = expr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+ return true;
+
+ case Token_sizeof: {
+ std::size_t sizeof_token = token_stream.cursor();
+ token_stream.nextToken();
+
+ SizeofExpressionAST *ast = CreateNode<SizeofExpressionAST>(_M_pool);
+ ast->sizeof_token = sizeof_token;
+
+ std::size_t index = token_stream.cursor();
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ if (parseTypeId(ast->type_id) && token_stream.lookAhead() == ')') {
+ token_stream.nextToken(); // skip )
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ }
+
+ ast->type_id = 0;
+ token_stream.rewind((int) index);
+ }
+
+ if (!parseUnaryExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ return true;
+ }
+
+ default:
+ break;
+ }
+
+ int token = token_stream.lookAhead();
+
+ if (token == Token_new
+ || (token == Token_scope && token_stream.lookAhead(1) == Token_new))
+ return parseNewExpression(node);
+
+ if (token == Token_delete
+ || (token == Token_scope && token_stream.lookAhead(1) == Token_delete))
+ return parseDeleteExpression(node);
+
+ return parsePostfixExpression(node);
+}
+
+bool Parser::parseNewExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NewExpressionAST *ast = CreateNode<NewExpressionAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == Token_new) {
+ ast->scope_token = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_new);
+ ast->new_token = token_stream.cursor() - 1;
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ parseCommaExpression(ast->expression);
+ CHECK(')');
+ }
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+ parseTypeId(ast->type_id);
+ CHECK(')');
+ } else {
+ parseNewTypeId(ast->new_type_id);
+ }
+
+ parseNewInitializer(ast->new_initializer);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewTypeId(NewTypeIdAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ TypeSpecifierAST *typeSpec = 0;
+ if (!parseTypeSpecifier(typeSpec))
+ return false;
+
+ NewTypeIdAST *ast = CreateNode<NewTypeIdAST>(_M_pool);
+ ast->type_specifier = typeSpec;
+
+ parseNewDeclarator(ast->new_declarator);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewDeclarator(NewDeclaratorAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ NewDeclaratorAST *ast = CreateNode<NewDeclaratorAST>(_M_pool);
+
+ PtrOperatorAST *ptrOp = 0;
+ if (parsePtrOperator(ptrOp)) {
+ ast->ptr_op = ptrOp;
+ parseNewDeclarator(ast->sub_declarator);
+ }
+
+ while (token_stream.lookAhead() == '[') {
+ token_stream.nextToken();
+ ExpressionAST *expr = 0;
+ parseExpression(expr);
+ ast->expressions = snoc(ast->expressions, expr, _M_pool);
+ ADVANCE(']', "]");
+ }
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseNewInitializer(NewInitializerAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK('(');
+
+ NewInitializerAST *ast = CreateNode<NewInitializerAST>(_M_pool);
+
+ parseCommaExpression(ast->expression);
+
+ CHECK(')');
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseDeleteExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ DeleteExpressionAST *ast = CreateNode<DeleteExpressionAST>(_M_pool);
+
+ if (token_stream.lookAhead() == Token_scope
+ && token_stream.lookAhead(1) == Token_delete) {
+ ast->scope_token = token_stream.cursor();
+ token_stream.nextToken();
+ }
+
+ CHECK(Token_delete);
+ ast->delete_token = token_stream.cursor() - 1;
+
+ if (token_stream.lookAhead() == '[') {
+ ast->lbracket_token = token_stream.cursor();
+ token_stream.nextToken();
+ CHECK(']');
+ ast->rbracket_token = token_stream.cursor() - 1;
+ }
+
+ if (!parseCastExpression(ast->expression))
+ return false;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseCastExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == '(') {
+ token_stream.nextToken();
+
+ CastExpressionAST *ast = CreateNode<CastExpressionAST>(_M_pool);
+
+ if (parseTypeId(ast->type_id)) {
+ if (token_stream.lookAhead() == ')') {
+ token_stream.nextToken();
+
+ if (parseCastExpression(ast->expression)) {
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+ }
+ }
+ }
+ }
+
+ token_stream.rewind((int) start);
+ return parseUnaryExpression(node);
+}
+
+bool Parser::parsePmExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseCastExpression(node) || !node) // ### fixme
+ return false;
+
+ while (token_stream.lookAhead() == Token_ptrmem) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseCastExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseMultiplicativeExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parsePmExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '*'
+ || token_stream.lookAhead() == '/'
+ || token_stream.lookAhead() == '%') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parsePmExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+
+bool Parser::parseAdditiveExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseMultiplicativeExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '+' || token_stream.lookAhead() == '-') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseMultiplicativeExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseShiftExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAdditiveExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == Token_shift) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAdditiveExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseRelationalExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseShiftExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == '<'
+ || (token_stream.lookAhead() == '>' && !templArgs)
+ || token_stream.lookAhead() == Token_leq
+ || token_stream.lookAhead() == Token_geq) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseShiftExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseEqualityExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseRelationalExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_eq
+ || token_stream.lookAhead() == Token_not_eq) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseRelationalExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseAndExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseEqualityExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '&') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseEqualityExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseExclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAndExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '^') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseInclusiveOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseExclusiveOrExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == '|') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseExclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalAndExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseInclusiveOrExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_and) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseInclusiveOrExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseLogicalOrExpression(ExpressionAST *&node, bool templArgs)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseLogicalAndExpression(node, templArgs))
+ return false;
+
+ while (token_stream.lookAhead() == Token_or) {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseLogicalAndExpression(rightExpr, templArgs))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseConditionalExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseLogicalOrExpression(node))
+ return false;
+
+ if (token_stream.lookAhead() == '?') {
+ token_stream.nextToken();
+
+ ExpressionAST *leftExpr = 0;
+ if (!parseExpression(leftExpr))
+ return false;
+
+ CHECK(':');
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ ConditionalExpressionAST *ast
+ = CreateNode<ConditionalExpressionAST>(_M_pool);
+
+ ast->condition = node;
+ ast->left_expression = leftExpr;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseAssignmentExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (token_stream.lookAhead() == Token_throw && !parseThrowExpression(node))
+ return false;
+ else if (!parseConditionalExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == Token_assign
+ || token_stream.lookAhead() == '=') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseConditionalExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseConstantExpression(ExpressionAST *&node)
+{
+ return parseConditionalExpression(node);
+}
+
+bool Parser::parseExpression(ExpressionAST *&node)
+{
+ return parseCommaExpression(node);
+}
+
+bool Parser::parseCommaExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ if (!parseAssignmentExpression(node))
+ return false;
+
+ while (token_stream.lookAhead() == ',') {
+ std::size_t op = token_stream.cursor();
+ token_stream.nextToken();
+
+ ExpressionAST *rightExpr = 0;
+ if (!parseAssignmentExpression(rightExpr))
+ return false;
+
+ BinaryExpressionAST *ast = CreateNode<BinaryExpressionAST>(_M_pool);
+ ast->op = op;
+ ast->left_expression = node;
+ ast->right_expression = rightExpr;
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+ }
+
+ return true;
+}
+
+bool Parser::parseThrowExpression(ExpressionAST *&node)
+{
+ std::size_t start = token_stream.cursor();
+
+ CHECK(Token_throw);
+
+ ThrowExpressionAST *ast = CreateNode<ThrowExpressionAST>(_M_pool);
+ ast->throw_token = token_stream.cursor() - 1;
+
+ parseAssignmentExpression(ast->expression);
+
+ UPDATE_POS(ast, start, token_stream.cursor());
+ node = ast;
+
+ return true;
+}
+
+bool Parser::parseQ_ENUMS(DeclarationAST *&node)
+{
+
+ if ((token_stream.lookAhead() != Token_Q_ENUMS) &&
+ (token_stream.lookAhead() != Token_Q_ENUM))
+ return false;
+
+ if (token_stream.lookAhead(1) != '(')
+ return false;
+
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ int firstToken = token_stream.cursor();
+ while (token_stream.lookAhead() != ')')
+ token_stream.nextToken();
+
+ QEnumsAST *ast = CreateNode<QEnumsAST>(_M_pool);
+ UPDATE_POS(ast, firstToken, token_stream.cursor());
+ node = ast;
+
+ token_stream.nextToken();
+
+ return true;
+}
+
+bool Parser::parseQ_PROPERTY(DeclarationAST *&node)
+{
+ if (token_stream.lookAhead() != Token_Q_PROPERTY)
+ return false;
+
+ if (token_stream.lookAhead(1) != '(')
+ return false;
+
+ token_stream.nextToken();
+ token_stream.nextToken();
+
+ int firstToken = token_stream.cursor();
+ while (token_stream.lookAhead() != ')')
+ token_stream.nextToken();
+
+ QPropertyAST *ast = CreateNode<QPropertyAST>(_M_pool);
+ UPDATE_POS(ast, firstToken, token_stream.cursor());
+ node = ast;
+
+// const Token &t1 = token_stream[firstToken];
+// const Token &t2 = token_stream[token_stream.cursor()];
+// printf("property: %s\n",
+// qPrintable(QString::fromLatin1(t1.text + t1.position, t2.position - t1.position)));
+
+ token_stream.nextToken();
+
+ return true;
+}
+
+bool Parser::block_errors(bool block)
+{
+ bool current = _M_block_errors;
+ _M_block_errors = block;
+ return current;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/sources/shiboken2/ApiExtractor/parser/parser.h b/sources/shiboken2/ApiExtractor/parser/parser.h
new file mode 100644
index 000000000..7aa5b9ad7
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/parser.h
@@ -0,0 +1,204 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PARSER_H
+#define PARSER_H
+
+#include "ast.h"
+#include "lexer.h"
+
+#include <QtCore/QString>
+
+class FileSymbol;
+class Control;
+
+class Parser
+{
+public:
+ Parser(Control *control);
+ ~Parser();
+
+ LocationManager &location() { return _M_location; }
+
+ TranslationUnitAST *parse(const char *contents, std::size_t size, pool *p);
+
+private:
+ void reportError(const QString& msg);
+ void syntaxError();
+ void tokenRequiredError(int expected);
+
+public:
+ bool skipFunctionBody(StatementAST *&node);
+
+public:
+ bool parse_Attribute__();
+ bool parseAbstractDeclarator(DeclaratorAST *&node);
+ bool parseAccessSpecifier(DeclarationAST *&node);
+ bool parseAdditiveExpression(ExpressionAST *&node);
+ bool parseAndExpression(ExpressionAST *&node, bool templArgs = false);
+ bool parseAsmDefinition(DeclarationAST *&node);
+ bool parseAssignmentExpression(ExpressionAST *&node);
+ bool parseBaseClause(BaseClauseAST *&node);
+ bool parseBaseSpecifier(BaseSpecifierAST *&node);
+ bool parseBlockDeclaration(DeclarationAST *&node);
+ bool parseCastExpression(ExpressionAST *&node);
+ bool parseClassSpecifier(TypeSpecifierAST *&node);
+ bool parseForwardDeclarationSpecifier(TypeSpecifierAST *&node);
+ bool parseCommaExpression(ExpressionAST *&node);
+ bool parseCompoundStatement(StatementAST *&node);
+ bool parseCondition(ConditionAST *&node, bool initRequired = true);
+ bool parseConditionalExpression(ExpressionAST *&node);
+ bool parseConstantExpression(ExpressionAST *&node);
+ bool parseCtorInitializer(CtorInitializerAST *&node);
+ bool parseCvQualify(const ListNode<std::size_t> *&node);
+ bool parseDeclaration(DeclarationAST *&node);
+ bool parseDeclarationInternal(DeclarationAST *&node);
+ bool parseDeclarationStatement(StatementAST *&node);
+ bool parseDeclarator(DeclaratorAST *&node);
+ bool parseDeleteExpression(ExpressionAST *&node);
+ bool parseDoStatement(StatementAST *&node);
+ bool parseElaboratedTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseEnumSpecifier(TypeSpecifierAST *&node);
+ bool parseEnumerator(EnumeratorAST *&node);
+ bool parseEqualityExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseExceptionSpecification(ExceptionSpecificationAST *&node);
+ bool parseExclusiveOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseExpression(ExpressionAST *&node);
+ bool parseExpressionOrDeclarationStatement(StatementAST *&node);
+ bool parseExpressionStatement(StatementAST *&node);
+ bool parseForInitStatement(StatementAST *&node);
+ bool parseForStatement(StatementAST *&node);
+ bool parseFunctionBody(StatementAST *&node);
+ bool parseFunctionSpecifier(const ListNode<std::size_t> *&node);
+ bool parseIfStatement(StatementAST *&node);
+ bool parseInclusiveOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseInitDeclarator(InitDeclaratorAST *&node);
+ bool parseInitDeclaratorList(const ListNode<InitDeclaratorAST*> *&node);
+ bool parseInitializer(InitializerAST *&node);
+ bool parseInitializerClause(InitializerClauseAST *&node);
+ bool parseLabeledStatement(StatementAST *&node);
+ bool parseLinkageBody(LinkageBodyAST *&node);
+ bool parseLinkageSpecification(DeclarationAST *&node);
+ bool parseLogicalAndExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseLogicalOrExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseMemInitializer(MemInitializerAST *&node);
+ bool parseMemInitializerList(const ListNode<MemInitializerAST*> *&node);
+ bool parseMemberSpecification(DeclarationAST *&node);
+ bool parseMultiplicativeExpression(ExpressionAST *&node);
+ bool parseName(NameAST *&node, bool acceptTemplateId = false);
+ bool parseNamespace(DeclarationAST *&node);
+ bool parseNamespaceAliasDefinition(DeclarationAST *&node);
+ bool parseNewDeclarator(NewDeclaratorAST *&node);
+ bool parseNewExpression(ExpressionAST *&node);
+ bool parseNewInitializer(NewInitializerAST *&node);
+ bool parseNewTypeId(NewTypeIdAST *&node);
+ bool parseNoExcept();
+ bool parseOperator(OperatorAST *&node);
+ bool parseOperatorFunctionId(OperatorFunctionIdAST *&node);
+ bool parseParameterDeclaration(ParameterDeclarationAST *&node);
+ bool parseParameterDeclarationClause(ParameterDeclarationClauseAST *&node);
+ bool parseParameterDeclarationList(const ListNode<ParameterDeclarationAST*> *&node);
+ bool parsePmExpression(ExpressionAST *&node);
+ bool parsePostfixExpression(ExpressionAST *&node);
+ bool parsePostfixExpressionInternal(ExpressionAST *&node);
+ bool parsePrimaryExpression(ExpressionAST *&node);
+ bool parsePtrOperator(PtrOperatorAST *&node);
+ bool parsePtrToMember(PtrToMemberAST *&node);
+ bool parseRelationalExpression(ExpressionAST *&node,
+ bool templArgs = false);
+ bool parseShiftExpression(ExpressionAST *&node);
+ bool parseSimpleTypeSpecifier(TypeSpecifierAST *&node,
+ bool onlyIntegral = false);
+ bool parseStatement(StatementAST *&node);
+ bool parseStorageClassSpecifier(const ListNode<std::size_t> *&node);
+ bool parseStringLiteral(StringLiteralAST *&node);
+ bool parseSwitchStatement(StatementAST *&node);
+ bool parseTemplateArgument(TemplateArgumentAST *&node);
+ bool parseTemplateArgumentList(const ListNode<TemplateArgumentAST*> *&node,
+ bool reportError = true);
+ bool parseTemplateDeclaration(DeclarationAST *&node);
+ bool parseTemplateParameter(TemplateParameterAST *&node);
+ bool parseTemplateParameterList(const ListNode<TemplateParameterAST*> *&node);
+ bool parseThrowExpression(ExpressionAST *&node);
+ bool parseTranslationUnit(TranslationUnitAST *&node);
+ bool parseTryBlockStatement(StatementAST *&node);
+ bool parseTypeId(TypeIdAST *&node);
+ bool parseTypeIdList(const ListNode<TypeIdAST*> *&node);
+ bool parseTypeParameter(TypeParameterAST *&node);
+ bool parseTypeSpecifier(TypeSpecifierAST *&node);
+ bool parseTypeSpecifierOrClassSpec(TypeSpecifierAST *&node);
+ bool parseTypedef(DeclarationAST *&node);
+ bool parseUnaryExpression(ExpressionAST *&node);
+ bool parseUnqualifiedName(UnqualifiedNameAST *&node,
+ bool parseTemplateId = true);
+ bool parseUsing(DeclarationAST *&node);
+ bool parseUsingDirective(DeclarationAST *&node);
+ bool parseWhileStatement(StatementAST *&node);
+ bool parseWinDeclSpec(WinDeclSpecAST *&node);
+
+ bool parseQ_PROPERTY(DeclarationAST *&node);
+ bool parseQ_ENUMS(DeclarationAST *&node);
+
+ bool skipUntil(int token);
+ bool skipUntilDeclaration();
+ bool skipUntilStatement();
+ bool skip(int l, int r);
+
+ void advance();
+
+ // private:
+ TokenStream token_stream;
+ LocationTable location_table;
+ LocationTable line_table;
+
+ bool block_errors(bool block);
+
+private:
+ QString tokenText(AST *) const;
+
+ LocationManager _M_location;
+ Control *control;
+ Lexer lexer;
+ pool *_M_pool;
+ bool _M_block_errors;
+
+private:
+ Parser(const Parser& source);
+ void operator = (const Parser& source);
+};
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/r++.macros b/sources/shiboken2/ApiExtractor/parser/r++.macros
new file mode 100644
index 000000000..455276c84
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/r++.macros
@@ -0,0 +1,28 @@
+
+#define __attribute__(a...)
+#define __typeof__ __typeof
+
+#define __extension
+#define __extension__
+
+#define __restrict
+#define __restrict__
+
+#define __volatile volatile
+#define __volatile__ volatile
+
+#define __inline inline
+#define __inline__ inline
+
+#define __const const
+#define __const__ const
+
+#define __asm asm
+#define __asm__ asm
+
+#define __GNUC__ 3
+//#define __GNUC_MINOR__ 4
+
+#define __ROBC__ 0
+#define __ROBC_MINOR__ 1
+
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h b/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h
new file mode 100644
index 000000000..4331ef7d4
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp-allocator.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+**
+** 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 "parser/rxx_allocator.h"
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp b/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp
new file mode 100644
index 000000000..ccc150339
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/builtin-macros.cpp
@@ -0,0 +1,28 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h
new file mode 100644
index 000000000..d2e16b994
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-cctype.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_CCTYPE_H
+#define PP_CCTYPE_H
+
+#include <cctype>
+
+namespace rpp
+{
+
+inline bool pp_isalpha(int __ch)
+{
+ return std::isalpha((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isalnum(int __ch)
+{
+ return std::isalnum((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isdigit(int __ch)
+{
+ return std::isdigit((unsigned char) __ch) != 0;
+}
+
+inline bool pp_isspace(int __ch)
+{
+ return std::isspace((unsigned char) __ch) != 0;
+}
+
+} // namespace rpp
+
+#endif // PP_CCTYPE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration b/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration
new file mode 100644
index 000000000..15586dd88
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-configuration
@@ -0,0 +1,86 @@
+#define __DBL_MIN_EXP__ (-1021)
+#define __FLT_MIN__ 1.17549435e-38F
+#define __CHAR_BIT__ 8
+#define __WCHAR_MAX__ 2147483647
+#define __DBL_DENORM_MIN__ 4.9406564584124654e-324
+#define __FLT_EVAL_METHOD__ 2
+#define __DBL_MIN_10_EXP__ (-307)
+#define __FINITE_MATH_ONLY__ 0
+#define __GNUC_PATCHLEVEL__ 2
+#define __SHRT_MAX__ 32767
+#define __LDBL_MAX__ 1.18973149535723176502e+4932L
+#define __UINTMAX_TYPE__ long long unsigned int
+#define __linux 1
+#define __unix 1
+#define __LDBL_MAX_EXP__ 16384
+#define __linux__ 1
+#define __SCHAR_MAX__ 127
+#define __USER_LABEL_PREFIX__
+#define __STDC_HOSTED__ 1
+#define __LDBL_HAS_INFINITY__ 1
+#define __DBL_DIG__ 15
+#define __FLT_EPSILON__ 1.19209290e-7F
+#define __GXX_WEAK__ 1
+#define __LDBL_MIN__ 3.36210314311209350626e-4932L
+#define __unix__ 1
+#define __DECIMAL_DIG__ 21
+#define __gnu_linux__ 1
+#define __LDBL_HAS_QUIET_NAN__ 1
+#define __GNUC__ 4
+#define __DBL_MAX__ 1.7976931348623157e+308
+#define __DBL_HAS_INFINITY__ 1
+#define __cplusplus 1
+#define __DEPRECATED 1
+#define __DBL_MAX_EXP__ 1024
+#define __GNUG__ 4
+#define __LONG_LONG_MAX__ 9223372036854775807LL
+#define __GXX_ABI_VERSION 1002
+#define __FLT_MIN_EXP__ (-125)
+#define __DBL_MIN__ 2.2250738585072014e-308
+#define __FLT_MIN_10_EXP__ (-37)
+#define __DBL_HAS_QUIET_NAN__ 1
+#define __REGISTER_PREFIX__
+#define __NO_INLINE__ 1
+#define __i386 1
+#define __FLT_MANT_DIG__ 24
+#define __VERSION__ "4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9)"
+#define i386 1
+#define __i486__ 1
+#define unix 1
+#define __i386__ 1
+#define __SIZE_TYPE__ unsigned int
+#define __ELF__ 1
+#define __FLT_RADIX__ 2
+#define __LDBL_EPSILON__ 1.08420217248550443401e-19L
+#define __FLT_HAS_QUIET_NAN__ 1
+#define __FLT_MAX_10_EXP__ 38
+#define __LONG_MAX__ 2147483647L
+#define __FLT_HAS_INFINITY__ 1
+#define linux 1
+#define __EXCEPTIONS 1
+#define __LDBL_MANT_DIG__ 64
+#define __WCHAR_TYPE__ int
+#define __FLT_DIG__ 6
+#define __INT_MAX__ 2147483647
+#define __i486 1
+#define __FLT_MAX_EXP__ 128
+#define __DBL_MANT_DIG__ 53
+#define __WINT_TYPE__ unsigned int
+#define __LDBL_MIN_EXP__ (-16381)
+#define __LDBL_MAX_10_EXP__ 4932
+#define __DBL_EPSILON__ 2.2204460492503131e-16
+#define __tune_i486__ 1
+#define __INTMAX_MAX__ 9223372036854775807LL
+#define __FLT_DENORM_MIN__ 1.40129846e-45F
+#define __FLT_MAX__ 3.40282347e+38F
+#define __INTMAX_TYPE__ long long int
+#define __GNUC_MINOR__ 0
+#define __DBL_MAX_10_EXP__ 308
+#define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+#define __PTRDIFF_TYPE__ int
+#define __LDBL_MIN_10_EXP__ (-4931)
+#define __LDBL_DIG__ 18
+#define _GNU_SOURCE 1
+
+
+#define __STDC__
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h
new file mode 100644
index 000000000..3d8aee029
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine-bits.h
@@ -0,0 +1,1300 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_ENGINE_BITS_H
+#define PP_ENGINE_BITS_H
+
+#include "pp.h"
+#include <sys/stat.h>
+#include <cstdio>
+#include <iostream>
+
+namespace rpp
+{
+
+inline std::string pp::fix_file_path(std::string const &filename) const
+{
+#if defined (PP_OS_WIN)
+ std::string s = filename;
+ for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
+ if (*it == '/')
+ *it = '\\';
+ }
+ return s;
+#else
+ return filename;
+#endif
+}
+
+inline bool pp::is_absolute(std::string const &filename) const
+{
+#if defined(PP_OS_WIN)
+ return filename.length() >= 3
+ && filename.at(1) == ':'
+ && (filename.at(2) == '\\' || filename.at(2) == '/');
+#else
+ return filename.length() >= 1
+ && filename.at(0) == '/';
+#endif
+}
+
+template <typename _OutputIterator>
+void pp::file(std::string const &filename, _OutputIterator __result)
+{
+ FILE *fp = std::fopen(filename.c_str(), "rb");
+ if (fp != 0) {
+ std::string was = env.current_file;
+ env.current_file = filename;
+ file(fp, __result);
+ env.current_file = was;
+ }
+ //else
+ //std::cerr << "** WARNING file ``" << filename << " not found!" << std::endl;
+}
+
+template <typename _OutputIterator>
+void pp::file(FILE *fp, _OutputIterator __result)
+{
+ assert(fp != 0);
+
+#if defined (HAVE_MMAP)
+ struct stat st;
+ fstat(FILENO(fp), &st);
+ std::size_t size = st.st_size;
+ char *buffer = 0;
+ buffer = (char *) ::mmap(0, size, PROT_READ, MAP_SHARED, FILENO(fp), 0);
+ fclose(fp);
+ if (!buffer || buffer == (char*) - 1)
+ return;
+ this->operator()(buffer, buffer + size, __result);
+ ::munmap(buffer, size);
+#else
+ std::string buffer;
+ while (!feof(fp)) {
+ char tmp[1024];
+ int read = (int) fread(tmp, sizeof(char), 1023, fp);
+ tmp[read] = '\0';
+ buffer += tmp;
+ }
+ fclose(fp);
+ this->operator()(buffer.c_str(), buffer.c_str() + buffer.size(), __result);
+#endif
+}
+
+template <typename _InputIterator>
+bool pp::find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot)
+{
+ int was = env.current_line;
+
+ while (__first != __last) {
+ if (pp_isspace(*__first)) {
+ if (*__first == '\n')
+ ++env.current_line;
+
+ ++__first;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == 'i') {
+ _InputIterator __begin = __first;
+ __first = skip_identifier(__begin, __last);
+ env.current_line += skip_identifier.lines;
+
+ std::string __directive(__begin, __first);
+
+ if (__directive == "ifndef") {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ __begin = __first;
+ __first = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+
+ if (__begin != __first && __first != __last) {
+ __prot->assign(__begin, __first);
+ return true;
+ }
+ }
+ }
+ break;
+ } else
+ break;
+ }
+
+ env.current_line = was;
+ return false;
+}
+
+inline pp::PP_DIRECTIVE_TYPE pp::find_directive(char const *__directive, std::size_t __size) const
+{
+ switch (__size) {
+ case 0:
+ return PP_UNNAMED_DIRECTIVE;
+ case 2:
+ if (__directive[0] == 'i'
+ && __directive[1] == 'f')
+ return PP_IF;
+ break;
+
+ case 4:
+ if (__directive[0] == 'e' && !strcmp(__directive, "elif"))
+ return PP_ELIF;
+ else if (__directive[0] == 'e' && !strcmp(__directive, "else"))
+ return PP_ELSE;
+ break;
+
+ case 5:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifdef"))
+ return PP_IFDEF;
+ else if (__directive[0] == 'u' && !strcmp(__directive, "undef"))
+ return PP_UNDEF;
+ else if (__directive[0] == 'e') {
+ if (!strcmp(__directive, "endif"))
+ return PP_ENDIF;
+ else if (!strcmp(__directive, "error"))
+ return PP_ERROR;
+ }
+ break;
+
+ case 6:
+ if (__directive[0] == 'i' && !strcmp(__directive, "ifndef"))
+ return PP_IFNDEF;
+ else if (__directive[0] == 'd' && !strcmp(__directive, "define"))
+ return PP_DEFINE;
+ else if (__directive[0] == 'p' && !strcmp(__directive, "pragma"))
+ return PP_PRAGMA;
+ break;
+
+ case 7:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include"))
+ return PP_INCLUDE;
+ else if (!strcmp(__directive, "warning"))
+ return PP_WARNING;
+ break;
+
+ case 12:
+ if (__directive[0] == 'i' && !strcmp(__directive, "include_next"))
+ return PP_INCLUDE_NEXT;
+ break;
+
+ default:
+ break;
+ }
+ std::cerr << "** WARNING unknown directive '#" << __directive << "' at " << env.current_file << ":" << env.current_line << std::endl;
+ return PP_UNKNOWN_DIRECTIVE;
+}
+
+inline bool pp::file_isdir(std::string const &__filename) const
+{
+ struct stat __st;
+ if (stat(__filename.c_str(), &__st) == 0)
+#if defined(PP_OS_WIN)
+ return (__st.st_mode & _S_IFDIR) == _S_IFDIR;
+#else
+ return (__st.st_mode & S_IFDIR) == S_IFDIR;
+#endif
+ else
+ return false;
+}
+
+inline bool pp::file_exists(std::string const &__filename) const
+{
+ struct stat __st;
+ return stat(__filename.c_str(), &__st) == 0;
+}
+
+inline FILE *pp::find_include_file(std::string const &__input_filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path) const
+{
+ assert(__filepath != 0);
+ assert(! __input_filename.empty());
+
+ __filepath->assign(__input_filename);
+
+ if (is_absolute(*__filepath) && !file_isdir(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+ if (! env.current_file.empty())
+ _PP_internal::extract_file_path(env.current_file, __filepath);
+
+ if (__include_policy == INCLUDE_LOCAL && ! __skip_current_path) {
+ std::string __tmp(*__filepath);
+ __tmp += __input_filename;
+
+ if (file_exists(__tmp) && !file_isdir(__tmp)) {
+ __filepath->append(__input_filename);
+ return std::fopen(__filepath->c_str(), "r");
+ }
+ }
+
+ std::vector<std::string>::const_iterator it = include_paths.begin();
+
+ if (__skip_current_path) {
+ it = std::find(include_paths.begin(), include_paths.end(), *__filepath);
+
+ if (it != include_paths.end())
+ ++it;
+
+ else
+ it = include_paths.begin();
+ }
+
+ for (; it != include_paths.end(); ++it) {
+ if (__skip_current_path && it == include_paths.begin())
+ continue;
+
+ __filepath->assign(*it);
+ __filepath->append(__input_filename);
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath))
+ return std::fopen(__filepath->c_str(), "r");
+
+#ifdef Q_OS_MAC
+ // try in Framework path on Mac, if there is a path in front
+ // ### what about escaped slashes?
+ size_t slashPos = __input_filename.find('/');
+ if (slashPos != std::string::npos) {
+ __filepath->assign(*it);
+ __filepath->append(__input_filename.substr(0, slashPos));
+ __filepath->append(".framework/Headers/");
+ __filepath->append(__input_filename.substr(slashPos + 1, std::string::npos));
+
+ if (file_exists(*__filepath) && !file_isdir(*__filepath)) {
+ return fopen(__filepath->c_str(), "r");
+ }
+ }
+#endif // Q_OS_MAC
+ }
+
+ return 0;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+ __first = skip_blanks(__first, __last);
+
+ PP_DIRECTIVE_TYPE d = find_directive(__directive, __size);
+ switch (d) {
+ case PP_UNNAMED_DIRECTIVE:
+ /* There are many boost headers that include the character '#'
+ * at the beginning of any line and just do nothing else with
+ * that unnamed directive. Well, as that's not an error so
+ * we'll just ignore this unnamed directive for now.
+ */
+ ++__last;
+ return ++__first;
+ case PP_DEFINE:
+ if (! skipping())
+ return handle_define(__first, __last);
+ break;
+
+ case PP_INCLUDE:
+ case PP_INCLUDE_NEXT:
+ if (! skipping())
+ return handle_include(d == PP_INCLUDE_NEXT, __first, __last, __result);
+ break;
+
+ case PP_UNDEF:
+ if (! skipping())
+ return handle_undef(__first, __last);
+ break;
+
+ case PP_ELIF:
+ return handle_elif(__first, __last);
+
+ case PP_ELSE:
+ return handle_else(__first, __last);
+
+ case PP_ENDIF:
+ return handle_endif(__first, __last);
+
+ case PP_IF:
+ return handle_if(__first, __last);
+
+ case PP_IFDEF:
+ return handle_ifdef(false, __first, __last);
+
+ case PP_IFNDEF:
+ return handle_ifdef(true, __first, __last);
+
+ default:
+ break;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+_InputIterator pp::handle_include(bool __skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result)
+{
+ if (pp_isalpha(*__first) || *__first == '_') {
+ pp_macro_expander expand_include(env);
+ std::string name;
+ name.reserve(255);
+ expand_include(__first, __last, std::back_inserter(name));
+ std::string::iterator it = skip_blanks(name.begin(), name.end());
+ if (it != name.end() && !(*it == '<' || *it == '"')) {
+ std::cerr << "** WARNING APIExtractor does not support the use "
+ "of #include directives without passing either "
+ "\"<path/to/header.h>\" or \"./path/to/header.h\", "
+ "for example. Invalid use at " << env.current_file
+ << ":" << env.current_line << "." << std::endl;
+ return __last;
+ }
+
+ handle_include(__skip_current_path, it, name.end(), __result);
+ return __first;
+ }
+
+ assert(*__first == '<' || *__first == '"');
+ int quote = (*__first == '"') ? '"' : '>';
+ ++__first;
+
+ _InputIterator end_name = __first;
+ for (; end_name != __last; ++end_name) {
+ assert(*end_name != '\n');
+
+ if (*end_name == quote)
+ break;
+ }
+
+ std::string filename(__first, end_name);
+
+#ifdef PP_OS_WIN
+ std::replace(filename.begin(), filename.end(), '/', '\\');
+#endif
+
+ std::string filepath;
+ FILE *fp = find_include_file(filename, &filepath, quote == '>' ? INCLUDE_GLOBAL : INCLUDE_LOCAL, __skip_current_path);
+
+#if defined (PP_HOOK_ON_FILE_INCLUDED)
+ PP_HOOK_ON_FILE_INCLUDED(env.current_file, fp ? filepath : filename, fp);
+#endif
+
+ if (fp != 0) {
+ std::string old_file = env.current_file;
+ env.current_file = filepath;
+ int __saved_lines = env.current_line;
+
+ env.current_line = 1;
+ //output_line (env.current_file, 1, __result);
+
+ file(fp, __result);
+
+ // restore the file name and the line position
+ env.current_file = old_file;
+ env.current_line = __saved_lines;
+
+ // sync the buffer
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+#ifndef RPP_JAMBI
+// else
+// std::cerr << "*** WARNING " << filename << ": No such file or directory" << std::endl;
+#endif
+
+ return __first;
+}
+
+template <typename _InputIterator, typename _OutputIterator>
+void pp::operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result)
+{
+#ifndef PP_NO_SMART_HEADER_PROTECTION
+ std::string __prot;
+ __prot.reserve(255);
+ pp_fast_string __tmp(__prot.c_str(), __prot.size());
+
+ if (find_header_protection(__first, __last, &__prot)
+ && env.resolve(&__tmp) != 0) {
+ // std::cerr << "** DEBUG found header protection:" << __prot << std::endl;
+ return;
+ }
+#endif
+
+ env.current_line = 1;
+ char __buffer[512];
+
+ while (true) {
+ __first = skip_blanks(__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first == __last)
+ break;
+ else if (*__first == '#') {
+ assert(*__first == '#');
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+ env.current_line += skip_identifier.lines;
+ std::size_t __size = end_id - __first;
+
+ assert(__size < 512);
+ char *__cp = __buffer;
+ std::copy(__first, end_id, __cp);
+ __cp[__size] = '\0';
+
+ end_id = skip_blanks(end_id, __last);
+ __first = skip(end_id, __last);
+
+ int was = env.current_line;
+ (void) handle_directive(__buffer, __size, end_id, __first, __result);
+
+ if (env.current_line != was) {
+ env.current_line = was;
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ } else if (*__first == '\n') {
+ // ### compress the line
+ *__result++ = *__first++;
+ ++env.current_line;
+ } else if (skipping())
+ __first = skip(__first, __last);
+ else {
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ __first = expand(__first, __last, __result);
+ env.current_line += expand.lines;
+
+ if (expand.generated_lines)
+ _PP_internal::output_line(env.current_file, env.current_line, __result);
+ }
+ }
+}
+
+inline pp::pp(pp_environment &__env):
+ env(__env), expand(env)
+{
+ iflevel = 0;
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+}
+
+inline std::back_insert_iterator<std::vector<std::string> > pp::include_paths_inserter()
+{
+ return std::back_inserter(include_paths);
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_begin()
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::iterator pp::include_paths_end()
+{
+ return include_paths.end();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_begin() const
+{
+ return include_paths.begin();
+}
+
+inline std::vector<std::string>::const_iterator pp::include_paths_end() const
+{
+ return include_paths.end();
+}
+
+inline void pp::push_include_path(std::string const &__path)
+{
+ if (__path.empty() || __path [__path.size() - 1] != PATH_SEPARATOR) {
+ std::string __tmp(__path);
+ __tmp += PATH_SEPARATOR;
+ include_paths.push_back(__tmp);
+ }
+
+ else
+ include_paths.push_back(__path);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_define(_InputIterator __first, _InputIterator __last)
+{
+ pp_macro macro;
+#if defined (PP_WITH_MACRO_POSITION)
+ macro.file = pp_symbol::get(env.current_file);
+#endif
+ std::string definition;
+
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ pp_fast_string const *macro_name = pp_symbol::get(__first, end_macro_name);
+ __first = end_macro_name;
+
+ if (__first != __last && *__first == '(') {
+ macro.function_like = true;
+ macro.formals.reserve(5);
+
+ __first = skip_blanks(++__first, __last); // skip '('
+ _InputIterator arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+
+ while (__first != __last && *__first == ',') {
+ __first = skip_blanks(++__first, __last);
+
+ arg_end = skip_identifier(__first, __last);
+ if (__first != arg_end)
+ macro.formals.push_back(pp_symbol::get(__first, arg_end));
+
+ __first = skip_blanks(arg_end, __last);
+
+ if (*__first == '.') {
+ macro.variadics = true;
+ while (*__first == '.')
+ ++__first;
+ }
+ }
+
+ assert(*__first == ')');
+ ++__first;
+ }
+
+ __first = skip_blanks(__first, __last);
+
+ /* Note: Sometimes one can include a path between brackets (for
+ * e.g., when defining a macro or so) so that we cannot simply
+ * ignore that. The in_path variable will handle this situation.
+ */
+ bool in_path = false;
+ while (__first != __last && *__first != '\n') {
+ if ((*__first == '<' || *__first == '"') &&
+ (*(__first + 1) != '*' && *(__first + 1) != '/')) {
+ in_path = true;
+ goto skip_path;
+ }
+
+ if (in_path) {
+ if (*__first == '>' || *__first == '"') {
+ in_path = false;
+ goto skip_path;
+ } else if (*__first == ',' || *__first == ' ' || *__first == '\\') {
+ in_path = false;
+ continue;
+ }
+ }
+
+ if (*__first == '/') {
+ if (*(__first + 1) != '*' && *(__first + 1) != '/') {
+ in_path = true;
+ goto skip_path;
+ } else {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ if (__first == __last)
+ break;
+ }
+ }
+
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ __begin = skip_blanks(++__begin, __last);
+
+ if (__begin != __last && *__begin == '\n') {
+ ++macro.lines;
+ __first = skip_blanks(++__begin, __last);
+ definition += ' ';
+ continue;
+ }
+ }
+
+skip_path:
+ definition += *__first++;
+ }
+
+ macro.definition = pp_symbol::get(definition);
+ env.bind(macro_name, macro);
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::skip(_InputIterator __first, _InputIterator __last)
+{
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+
+ while (__first != __last && *__first != '\n') {
+ if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ env.current_line += skip_comment_or_divop.lines;
+ } else if (*__first == '"') {
+ __first = skip_string_literal(__first, __last);
+ env.current_line += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ env.current_line += skip_char_literal.lines;
+ } else if (*__first == '\\') {
+ __first = skip_blanks(++__first, __last);
+ env.current_line += skip_blanks.lines;
+
+ if (__first != __last && *__first == '\n') {
+ ++__first;
+ ++env.current_line;
+ }
+ } else
+ ++__first;
+ }
+
+ return __first;
+}
+
+inline bool pp::test_if_level()
+{
+ bool result = !_M_skipping[iflevel++];
+ _M_skipping[iflevel] = _M_skipping[iflevel - 1];
+ _M_true_test[iflevel] = false;
+ return result;
+}
+
+inline int pp::skipping() const
+{
+ return _M_skipping[iflevel];
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_primary(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ bool expect_paren = false;
+ int token;
+ __first = next_token(__first, __last, &token);
+
+ switch (token) {
+ case TOKEN_NUMBER:
+ result->set_long(token_value);
+ break;
+
+ case TOKEN_UNUMBER:
+ result->set_ulong(token_uvalue);
+ break;
+
+ case TOKEN_DEFINED:
+ __first = next_token(__first, __last, &token);
+
+ if (token == '(') {
+ expect_paren = true;
+ __first = next_token(__first, __last, &token);
+ }
+
+ if (token != TOKEN_IDENTIFIER) {
+ std::cerr << "** WARNING expected ``identifier'' found:" << char(token) << std::endl;
+ result->set_long(0);
+ break;
+ }
+
+ result->set_long(env.resolve(token_text->c_str(), token_text->size()) != 0);
+
+ next_token(__first, __last, &token); // skip '('
+
+ if (expect_paren) {
+ _InputIterator next = next_token(__first, __last, &token);
+ if (token != ')')
+ std::cerr << "** WARNING expected ``)''" << std::endl;
+ else
+ __first = next;
+ }
+ break;
+
+ case TOKEN_IDENTIFIER:
+ result->set_long(0);
+ break;
+
+ case '-':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(- result->l);
+ return __first;
+
+ case '+':
+ __first = eval_primary(__first, __last, result);
+ return __first;
+
+ case '!':
+ __first = eval_primary(__first, __last, result);
+ result->set_long(result->is_zero());
+ return __first;
+
+ case '(':
+ __first = eval_constant_expression(__first, __last, result);
+ next_token(__first, __last, &token);
+
+ if (token != ')') {
+ std::cerr << "** WARNING expected ``)'' = " << token << " (at "
+ << env.current_file << ":" << env.current_line
+ << ")." << std::endl;
+ } else {
+ __first = next_token(__first, __last, &token);
+ }
+ break;
+
+ default:
+ result->set_long(0);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_primary(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '*' || token == '/' || token == '%') {
+ Value value;
+ __first = eval_primary(next, __last, &value);
+
+ if (token == '*')
+ result->op_mult(value);
+ else if (token == '/') {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_div(value);
+ } else {
+ if (value.is_zero()) {
+ std::cerr << "** WARNING division by zero" << std::endl;
+ result->set_long(0);
+ } else
+ result->op_mod(value);
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_additive(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_multiplicative(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '+' || token == '-') {
+ Value value;
+ __first = eval_multiplicative(next, __last, &value);
+
+ if (token == '+')
+ result->op_add(value);
+ else
+ result->op_sub(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_shift(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_additive(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_LT_LT || token == TOKEN_GT_GT) {
+ Value value;
+ __first = eval_additive(next, __last, &value);
+
+ if (token == TOKEN_LT_LT)
+ result->op_lhs(value);
+ else
+ result->op_rhs(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_relational(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_shift(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '<'
+ || token == '>'
+ || token == TOKEN_LT_EQ
+ || token == TOKEN_GT_EQ) {
+ Value value;
+ __first = eval_shift(next, __last, &value);
+
+ switch (token) {
+ default:
+ assert(0);
+ break;
+
+ case '<':
+ result->op_lt(value);
+ break;
+
+ case '>':
+ result->op_gt(value);
+ break;
+
+ case TOKEN_LT_EQ:
+ result->op_le(value);
+ break;
+
+ case TOKEN_GT_EQ:
+ result->op_ge(value);
+ break;
+ }
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_equality(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_relational(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_EQ_EQ || token == TOKEN_NOT_EQ) {
+ Value value;
+ __first = eval_relational(next, __last, &value);
+
+ if (token == TOKEN_EQ_EQ)
+ result->op_eq(value);
+ else
+ result->op_ne(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_equality(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '&') {
+ Value value;
+ __first = eval_equality(next, __last, &value);
+ result->op_bit_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_xor(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '^') {
+ Value value;
+ __first = eval_and(next, __last, &value);
+ result->op_bit_xor(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_xor(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == '|') {
+ Value value;
+ __first = eval_xor(next, __last, &value);
+ result->op_bit_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_AND_AND) {
+ Value value;
+ __first = eval_or(next, __last, &value);
+ result->op_and(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_and(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ while (token == TOKEN_OR_OR) {
+ Value value;
+ __first = eval_logical_and(next, __last, &value);
+ result->op_or(value);
+ next = next_token(__first, __last, &token);
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ __first = eval_logical_or(__first, __last, result);
+
+ int token;
+ _InputIterator next = next_token(__first, __last, &token);
+
+ if (token == '?') {
+ Value left_value;
+ __first = eval_constant_expression(next, __last, &left_value);
+ __first = skip_blanks(__first, __last);
+
+ __first = next_token(__first, __last, &token);
+ if (token == ':') {
+ Value right_value;
+ __first = eval_constant_expression(__first, __last, &right_value);
+
+ *result = !result->is_zero() ? left_value : right_value;
+ } else {
+ std::cerr << "** WARNING expected ``:'' = " << int (token) << std::endl;
+ *result = left_value;
+ }
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::eval_expression(_InputIterator __first, _InputIterator __last, Value *result)
+{
+ return __first = eval_constant_expression(skip_blanks(__first, __last), __last, result);
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_if(_InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ pp_macro_expander expand_condition(env);
+ std::string condition;
+ condition.reserve(255);
+ expand_condition(skip_blanks(__first, __last), __last, std::back_inserter(condition));
+
+ Value result;
+ result.set_long(0);
+ eval_expression(condition.c_str(), condition.c_str() + condition.size(), &result);
+
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_else(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (iflevel > 0 && _M_skipping[iflevel - 1]) {
+ _M_skipping[iflevel] = true;
+ } else {
+ _M_skipping[iflevel] = _M_true_test[iflevel];
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_elif(_InputIterator __first, _InputIterator __last)
+{
+ assert(iflevel > 0);
+
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #else without #if" << std::endl;
+ } else if (!_M_true_test[iflevel] && !_M_skipping[iflevel - 1]) {
+ Value result;
+ __first = eval_expression(__first, __last, &result);
+ _M_true_test[iflevel] = !result.is_zero();
+ _M_skipping[iflevel] = result.is_zero();
+ } else {
+ _M_skipping[iflevel] = true;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_endif(_InputIterator __first, _InputIterator /*__last*/)
+{
+ if (iflevel == 0 && !skipping()) {
+ std::cerr << "** WARNING #endif without #if" << std::endl;
+ } else {
+ _M_skipping[iflevel] = 0;
+ _M_true_test[iflevel] = 0;
+
+ --iflevel;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last)
+{
+ if (test_if_level()) {
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ bool value = env.resolve(__buffer, __size) != 0;
+
+ __first = end_macro_name;
+
+ if (check_undefined)
+ value = !value;
+
+ _M_true_test[iflevel] = value;
+ _M_skipping[iflevel] = !value;
+ }
+
+ return __first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::handle_undef(_InputIterator __first, _InputIterator __last)
+{
+ __first = skip_blanks(__first, __last);
+ _InputIterator end_macro_name = skip_identifier(__first, __last);
+ assert(end_macro_name != __first);
+
+ std::size_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, end_macro_name, __size);
+#else
+ __size = std::distance(__first, end_macro_name);
+#endif
+
+ assert(__size < 256);
+
+ char __buffer [256];
+ std::copy(__first, end_macro_name, __buffer);
+
+ pp_fast_string const __tmp(__buffer, __size);
+ env.unbind(&__tmp);
+
+ __first = end_macro_name;
+
+ return __first;
+}
+
+template <typename _InputIterator>
+char pp::peek_char(_InputIterator __first, _InputIterator __last)
+{
+ if (__first == __last)
+ return 0;
+
+ return *++__first;
+}
+
+template <typename _InputIterator>
+_InputIterator pp::next_token(_InputIterator __first, _InputIterator __last, int *kind)
+{
+ __first = skip_blanks(__first, __last);
+
+ if (__first == __last) {
+ *kind = 0;
+ return __first;
+ }
+
+ char ch = *__first;
+ char ch2 = peek_char(__first, __last);
+
+ switch (ch) {
+ case '/':
+ if (ch2 == '/' || ch2 == '*') {
+ __first = skip_comment_or_divop(__first, __last);
+ return next_token(__first, __last, kind);
+ }
+ ++__first;
+ *kind = '/';
+ break;
+
+ case '<':
+ ++__first;
+ if (ch2 == '<') {
+ ++__first;
+ *kind = TOKEN_LT_LT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_LT_EQ;
+ } else
+ *kind = '<';
+
+ return __first;
+
+ case '>':
+ ++__first;
+ if (ch2 == '>') {
+ ++__first;
+ *kind = TOKEN_GT_GT;
+ } else if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_GT_EQ;
+ } else
+ *kind = '>';
+
+ return __first;
+
+ case '!':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_NOT_EQ;
+ } else
+ *kind = '!';
+
+ return __first;
+
+ case '=':
+ ++__first;
+ if (ch2 == '=') {
+ ++__first;
+ *kind = TOKEN_EQ_EQ;
+ } else
+ *kind = '=';
+
+ return __first;
+
+ case '|':
+ ++__first;
+ if (ch2 == '|') {
+ ++__first;
+ *kind = TOKEN_OR_OR;
+ } else
+ *kind = '|';
+
+ return __first;
+
+ case '&':
+ ++__first;
+ if (ch2 == '&') {
+ ++__first;
+ *kind = TOKEN_AND_AND;
+ } else
+ *kind = '&';
+
+ return __first;
+
+ default:
+ if (pp_isalpha(ch) || ch == '_') {
+ _InputIterator end = skip_identifier(__first, __last);
+ _M_current_text.assign(__first, end);
+
+ token_text = &_M_current_text;
+ __first = end;
+
+ if (*token_text == "defined")
+ *kind = TOKEN_DEFINED;
+ else
+ *kind = TOKEN_IDENTIFIER;
+ } else if (pp_isdigit(ch)) {
+ _InputIterator end = skip_number(__first, __last);
+ std::string __str(__first, __last);
+ char ch = __str [__str.size() - 1];
+ if (ch == 'u' || ch == 'U') {
+ token_uvalue = strtoul(__str.c_str(), 0, 0);
+ *kind = TOKEN_UNUMBER;
+ } else {
+ token_value = strtol(__str.c_str(), 0, 0);
+ *kind = TOKEN_NUMBER;
+ }
+ __first = end;
+ } else
+ *kind = *__first++;
+ }
+
+ return __first;
+}
+
+} // namespace rpp
+
+#endif // PP_ENGINE_BITS_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h
new file mode 100644
index 000000000..689d7720e
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-engine.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_ENGINE_H
+#define PP_ENGINE_H
+
+#include <string>
+#include <vector>
+#include "pp-scanner.h"
+#include "pp-macro-expander.h"
+#include "pp-environment.h"
+
+namespace rpp
+{
+
+struct Value {
+ Value() : kind(Kind_Long), l(0) {}
+
+ enum Kind {
+ Kind_Long,
+ Kind_ULong,
+ };
+
+ Kind kind;
+
+ union {
+ long l;
+ unsigned long ul;
+ };
+
+ inline bool is_ulong() const {
+ return kind == Kind_ULong;
+ }
+
+ inline void set_ulong(unsigned long v) {
+ ul = v;
+ kind = Kind_ULong;
+ }
+
+ inline void set_long(long v) {
+ l = v;
+ kind = Kind_Long;
+ }
+
+ inline bool is_zero() const {
+ return l == 0;
+ }
+
+#define PP_DEFINE_BIN_OP(name, op) \
+ inline Value &name (const Value &other) \
+ { \
+ if (is_ulong () || other.is_ulong ()) \
+ set_ulong (ul op other.ul); \
+ else \
+ set_long (l op other.l); \
+ return *this; \
+ }
+
+ PP_DEFINE_BIN_OP(op_add, +)
+ PP_DEFINE_BIN_OP(op_sub, -)
+ PP_DEFINE_BIN_OP(op_mult, *)
+ PP_DEFINE_BIN_OP(op_div, /)
+ PP_DEFINE_BIN_OP(op_mod, %)
+ PP_DEFINE_BIN_OP(op_lhs, <<)
+ PP_DEFINE_BIN_OP(op_rhs, >>)
+ PP_DEFINE_BIN_OP(op_lt, <)
+ PP_DEFINE_BIN_OP(op_gt, >)
+ PP_DEFINE_BIN_OP(op_le, <=)
+ PP_DEFINE_BIN_OP(op_ge, >=)
+ PP_DEFINE_BIN_OP(op_eq, ==)
+ PP_DEFINE_BIN_OP(op_ne, !=)
+ PP_DEFINE_BIN_OP(op_bit_and, &)
+ PP_DEFINE_BIN_OP(op_bit_or, |)
+ PP_DEFINE_BIN_OP(op_bit_xor, ^)
+ PP_DEFINE_BIN_OP(op_and, &&)
+ PP_DEFINE_BIN_OP(op_or, ||)
+
+#undef PP_DEFINE_BIN_OP
+};
+
+class pp
+{
+ pp_environment &env;
+ pp_macro_expander expand;
+ pp_skip_identifier skip_identifier;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_number skip_number;
+ std::vector<std::string> include_paths;
+ std::string _M_current_text;
+
+ enum { MAX_LEVEL = 512 };
+ int _M_skipping[MAX_LEVEL];
+ int _M_true_test[MAX_LEVEL];
+ int iflevel;
+
+ union {
+ long token_value;
+ unsigned long token_uvalue;
+ std::string *token_text;
+ };
+
+ enum INCLUDE_POLICY {
+ INCLUDE_GLOBAL,
+ INCLUDE_LOCAL
+ };
+
+ enum TOKEN_TYPE {
+ TOKEN_NUMBER = 1000,
+ TOKEN_UNUMBER,
+ TOKEN_IDENTIFIER,
+ TOKEN_DEFINED,
+ TOKEN_LT_LT,
+ TOKEN_LT_EQ,
+ TOKEN_GT_GT,
+ TOKEN_GT_EQ,
+ TOKEN_EQ_EQ,
+ TOKEN_NOT_EQ,
+ TOKEN_OR_OR,
+ TOKEN_AND_AND,
+ };
+
+ enum PP_DIRECTIVE_TYPE {
+ PP_UNKNOWN_DIRECTIVE,
+ PP_UNNAMED_DIRECTIVE,
+ PP_DEFINE,
+ PP_INCLUDE,
+ PP_INCLUDE_NEXT,
+ PP_ELIF,
+ PP_ELSE,
+ PP_ENDIF,
+ PP_IF,
+ PP_IFDEF,
+ PP_IFNDEF,
+ PP_UNDEF,
+ PP_PRAGMA,
+ PP_ERROR,
+ PP_WARNING
+ };
+
+public:
+ pp(pp_environment &__env);
+
+ inline std::back_insert_iterator<std::vector<std::string> > include_paths_inserter();
+
+ inline void push_include_path(std::string const &__path);
+
+ inline std::vector<std::string>::iterator include_paths_begin();
+ inline std::vector<std::string>::iterator include_paths_end();
+
+ inline std::vector<std::string>::const_iterator include_paths_begin() const;
+ inline std::vector<std::string>::const_iterator include_paths_end() const;
+
+ template <typename _InputIterator>
+ inline _InputIterator eval_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _OutputIterator>
+ void file(std::string const &filename, _OutputIterator __result);
+
+ template <typename _OutputIterator>
+ void file(FILE *fp, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ void operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+private:
+ inline bool file_isdir(std::string const &__filename) const;
+ inline bool file_exists(std::string const &__filename) const;
+ FILE *find_include_file(std::string const &__filename, std::string *__filepath,
+ INCLUDE_POLICY __include_policy, bool __skip_current_path = false) const;
+
+ inline int skipping() const;
+ bool test_if_level();
+
+ inline std::string fix_file_path(std::string const &filename) const;
+ inline bool is_absolute(std::string const &filename) const;
+
+ PP_DIRECTIVE_TYPE find_directive(char const *__directive, std::size_t __size) const;
+
+ template <typename _InputIterator>
+ bool find_header_protection(_InputIterator __first, _InputIterator __last, std::string *__prot);
+
+ template <typename _InputIterator>
+ _InputIterator skip(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator eval_primary(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_multiplicative(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_additive(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_shift(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_relational(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_equality(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_xor(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_and(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_logical_or(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator>
+ _InputIterator eval_constant_expression(_InputIterator __first, _InputIterator __last, Value *result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_directive(char const *__directive, std::size_t __size,
+ _InputIterator __first, _InputIterator __last, _OutputIterator __result);
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator handle_include(bool skip_current_path, _InputIterator __first, _InputIterator __last,
+ _OutputIterator __result);
+
+ template <typename _InputIterator>
+ _InputIterator handle_define(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_if(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_else(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_elif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_endif(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_ifdef(bool check_undefined, _InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator handle_undef(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ inline char peek_char(_InputIterator __first, _InputIterator __last);
+
+ template <typename _InputIterator>
+ _InputIterator next_token(_InputIterator __first, _InputIterator __last, int *kind);
+};
+
+} // namespace rpp
+
+#endif // PP_ENGINE_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h
new file mode 100644
index 000000000..23f22e483
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-environment.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_ENVIRONMENT_H
+#define PP_ENVIRONMENT_H
+
+#include <vector>
+#include <string>
+#include <cstring>
+#include "pp-macro.h"
+
+namespace rpp
+{
+
+class pp_environment
+{
+public:
+ typedef std::vector<pp_macro*>::const_iterator const_iterator;
+
+public:
+ pp_environment():
+ current_line(0),
+ _M_hash_size(4093) {
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ }
+
+ ~pp_environment() {
+ for (std::size_t i = 0; i < _M_macros.size(); ++i)
+ delete _M_macros [i];
+
+ delete [] _M_base;
+ }
+
+ const_iterator first_macro() const {
+ return _M_macros.begin();
+ }
+ const_iterator last_macro() const {
+ return _M_macros.end();
+ }
+
+ inline void bind(pp_fast_string const *__name, pp_macro const &__macro) {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *m = new pp_macro(__macro);
+ m->name = __name;
+ m->next = _M_base [h];
+ m->hash_code = h;
+ _M_base [h] = m;
+
+ _M_macros.push_back(m);
+
+ if (_M_macros.size() == _M_hash_size)
+ rehash();
+ }
+
+ inline void unbind(pp_fast_string const *__name) {
+ if (pp_macro *m = resolve(__name))
+ m->hidden = true;
+ }
+
+ inline void unbind(char const *__s, std::size_t __size) {
+ pp_fast_string __tmp(__s, __size);
+ unbind(&__tmp);
+ }
+
+ inline pp_macro *resolve(pp_fast_string const *__name) const {
+ std::size_t h = hash_code(*__name) % _M_hash_size;
+ pp_macro *it = _M_base [h];
+
+ while (it && it->name && it->hash_code == h && (*it->name != *__name || it->hidden))
+ it = it->next;
+
+ return it;
+ }
+
+ inline pp_macro *resolve(char const *__data, std::size_t __size) const {
+ pp_fast_string const __tmp(__data, __size);
+ return resolve(&__tmp);
+ }
+
+ std::string current_file;
+ int current_line;
+
+private:
+ inline std::size_t hash_code(pp_fast_string const &s) const {
+ std::size_t hash_value = 0;
+
+ for (std::size_t i = 0; i < s.size(); ++i)
+ hash_value = (hash_value << 5) - hash_value + s.at(i);
+
+ return hash_value;
+ }
+
+ void rehash() {
+ delete[] _M_base;
+
+ _M_hash_size <<= 1;
+
+ _M_base = (pp_macro **) memset(new pp_macro* [_M_hash_size], 0, _M_hash_size * sizeof(pp_macro*));
+ for (std::size_t index = 0; index < _M_macros.size(); ++index) {
+ pp_macro *elt = _M_macros [index];
+ std::size_t h = hash_code(*elt->name) % _M_hash_size;
+ elt->next = _M_base [h];
+ elt->hash_code = h;
+ _M_base [h] = elt;
+ }
+ }
+
+private:
+ std::vector<pp_macro*> _M_macros;
+ pp_macro **_M_base;
+ std::size_t _M_hash_size;
+};
+
+} // namespace rpp
+
+#endif // PP_ENVIRONMENT_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h
new file mode 100644
index 000000000..2814b6d44
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-fwd.h
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_FWD_H
+#define PP_FWD_H
+
+namespace rpp
+{
+
+template <typename _CharT> class pp_string;
+
+typedef pp_string<char> pp_fast_string;
+
+} // namespace rpp
+
+#endif // PP_FWD_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h
new file mode 100644
index 000000000..33efa0c27
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-internal.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_INTERNAL_H
+#define PP_INTERNAL_H
+
+#include <algorithm>
+#include <string>
+#include "pp.h"
+
+namespace rpp
+{
+
+namespace _PP_internal
+{
+
+inline void extract_file_path(const std::string &__filename, std::string *__filepath)
+{
+ std::size_t __index = __filename.rfind(PATH_SEPARATOR);
+
+ if (__index == std::string::npos)
+ *__filepath = "/";
+
+ else
+ __filepath->assign(__filename, 0, __index + 1);
+}
+
+template <typename _OutputIterator>
+void output_line(const std::string &__filename, int __line, _OutputIterator __result)
+{
+ std::string __msg;
+
+ __msg += "# ";
+
+ char __line_descr[16];
+ pp_snprintf(__line_descr, 16, "%d", __line);
+ __msg += __line_descr;
+
+ __msg += " \"";
+
+ if (__filename.empty())
+ __msg += "<internal>";
+ else
+ __msg += __filename;
+
+ __msg += "\"\n";
+ std::copy(__msg.begin(), __msg.end(), __result);
+}
+
+template <typename _InputIterator>
+inline bool comment_p(_InputIterator __first, _InputIterator __last) /*const*/
+{
+ if (__first == __last)
+ return false;
+
+ if (*__first != '/')
+ return false;
+
+ if (++__first == __last)
+ return false;
+
+ return (*__first == '/' || *__first == '*');
+}
+
+struct _Compare_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs < *__rhs;
+ }
+};
+
+struct _Equal_to_string: public std::binary_function<bool, pp_fast_string const *, pp_fast_string const *> {
+ inline bool operator()(pp_fast_string const *__lhs, pp_fast_string const *__rhs) const {
+ return *__lhs == *__rhs;
+ }
+};
+
+struct _Hash_string: public std::unary_function<std::size_t, pp_fast_string const *> {
+ inline std::size_t operator()(pp_fast_string const *__s) const {
+ char const *__ptr = __s->begin();
+ std::size_t __size = __s->size();
+ std::size_t __h = 0;
+
+ for (std::size_t i = 0; i < __size; ++i)
+ __h = (__h << 5) - __h + __ptr [i];
+
+ return __h;
+ }
+};
+
+} // _PP_internal
+
+} // namespace rpp
+
+#endif // PP_INTERNAL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h
new file mode 100644
index 000000000..35964fea4
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-iterator.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_ITERATOR_H
+#define PP_ITERATOR_H
+
+#include <iterator>
+
+namespace rpp
+{
+
+class pp_null_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+public:
+ pp_null_output_iterator() {}
+
+ template <typename _Tp>
+ pp_null_output_iterator &operator=(_Tp const &) {
+ return *this;
+ }
+
+ inline pp_null_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_null_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_null_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+template <typename _Container>
+class pp_output_iterator
+ : public std::iterator<std::output_iterator_tag, void, void, void, void>
+{
+ std::string &_M_result;
+
+public:
+ explicit pp_output_iterator(std::string &__result):
+ _M_result(__result) {}
+
+ inline pp_output_iterator<_Container>& operator=(const pp_output_iterator<_Container>& other)
+ {
+ _M_result = other._M_result;
+ return *this;
+ }
+
+ inline pp_output_iterator &operator=(typename _Container::const_reference __v) {
+ if (_M_result.capacity() == _M_result.size())
+ _M_result.reserve(_M_result.capacity() << 2);
+
+ _M_result.push_back(__v);
+ return *this;
+ }
+
+ inline pp_output_iterator &operator *() {
+ return *this;
+ }
+ inline pp_output_iterator &operator ++ () {
+ return *this;
+ }
+ inline pp_output_iterator operator ++ (int) {
+ return *this;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_ITERATOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h
new file mode 100644
index 000000000..db93c3214
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro-expander.h
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_MACRO_EXPANDER_H
+#define PP_MACRO_EXPANDER_H
+
+namespace rpp
+{
+
+struct pp_frame {
+ pp_macro *expanding_macro;
+ std::vector<std::string> *actuals;
+
+ pp_frame(pp_macro *__expanding_macro, std::vector<std::string> *__actuals):
+ expanding_macro(__expanding_macro), actuals(__actuals) {}
+};
+
+class pp_macro_expander
+{
+ pp_environment &env;
+ pp_frame *frame;
+
+ pp_skip_number skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_argument skip_argument;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ pp_skip_blanks skip_blanks;
+ pp_skip_whitespaces skip_whitespaces;
+
+ std::string const *resolve_formal(pp_fast_string const *__name) {
+ assert(__name != 0);
+
+ if (! frame)
+ return 0;
+
+ assert(frame->expanding_macro != 0);
+
+ std::vector<pp_fast_string const *> const formals = frame->expanding_macro->formals;
+ for (std::size_t index = 0; index < formals.size(); ++index) {
+ pp_fast_string const *formal = formals[index];
+
+ if (*formal != *__name)
+ continue;
+
+ else if (frame->actuals && index < frame->actuals->size())
+ return &(*frame->actuals)[index];
+
+ else
+ assert(0); // internal error?
+ }
+
+ return 0;
+ }
+
+public: // attributes
+ int lines;
+ int generated_lines;
+
+public:
+ pp_macro_expander(pp_environment &__env, pp_frame *__frame = 0):
+ env(__env), frame(__frame), lines(0), generated_lines(0) {}
+
+ template <typename _InputIterator, typename _OutputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
+ generated_lines = 0;
+ __first = skip_blanks(__first, __last);
+ lines = skip_blanks.lines;
+
+ while (__first != __last) {
+ if (*__first == '\n') {
+ *__result++ = *__first;
+ ++lines;
+
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ if (__first != __last && *__first == '#')
+ break;
+ } else if (*__first == '#') {
+ __first = skip_blanks(++__first, __last);
+ lines += skip_blanks.lines;
+
+ _InputIterator end_id = skip_identifier(__first, __last);
+
+ // ### rewrite: not safe
+ char name_buffer[512], *cp = name_buffer;
+ std::copy(__first, end_id, cp);
+ std::size_t name_size = end_id - __first;
+ name_buffer[name_size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ *__result++ = '\"';
+
+ for (std::string::const_iterator it = skip_whitespaces(actual->begin(), actual->end());
+ it != actual->end(); ++it) {
+ if (*it == '"') {
+ *__result++ = '\\';
+ *__result++ = *it;
+ }
+
+ else if (*it == '\n') {
+ *__result++ = '"';
+ *__result++ = '\n';
+ *__result++ = '"';
+ }
+
+ else
+ *__result++ = *it;
+ }
+
+ *__result++ = '\"';
+ __first = end_id;
+ } else
+ *__result++ = '#'; // ### warning message?
+ } else if (*__first == '\"') {
+ _InputIterator next_pos = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (*__first == '\'') {
+ _InputIterator next_pos = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (_PP_internal::comment_p(__first, __last)) {
+ __first = skip_comment_or_divop(__first, __last);
+ int n = skip_comment_or_divop.lines;
+ lines += n;
+
+ while (n-- > 0)
+ *__result++ = '\n';
+ } else if (pp_isspace(*__first)) {
+ for (; __first != __last; ++__first) {
+ if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ *__result = ' ';
+ } else if (pp_isdigit(*__first)) {
+ _InputIterator next_pos = skip_number(__first, __last);
+ lines += skip_number.lines;
+ std::copy(__first, next_pos, __result);
+ __first = next_pos;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ _InputIterator name_begin = __first;
+ _InputIterator name_end = skip_identifier(__first, __last);
+ __first = name_end; // advance
+
+ // search for the paste token
+ _InputIterator next = skip_blanks(__first, __last);
+ if (next != __last && *next == '#') {
+ ++next;
+ if (next != __last && *next == '#')
+ __first = skip_blanks(++next, __last);
+ }
+
+ // ### rewrite: not safe
+
+ std::ptrdiff_t name_size;
+#if defined(__SUNPRO_CC)
+ std::distance(name_begin, name_end, name_size);
+#else
+ name_size = std::distance(name_begin, name_end);
+#endif
+ assert(name_size >= 0 && name_size < 512);
+
+ char name_buffer[512], *cp = name_buffer;
+ std::size_t __size = name_end - name_begin;
+ std::copy(name_begin, name_end, cp);
+ name_buffer[__size] = '\0';
+
+ pp_fast_string fast_name(name_buffer, name_size);
+
+ if (std::string const *actual = resolve_formal(&fast_name)) {
+ std::copy(actual->begin(), actual->end(), __result);
+ continue;
+ }
+
+ static bool hide_next = false; // ### remove me
+
+ pp_macro *macro = env.resolve(name_buffer, name_size);
+ if (! macro || macro->hidden || hide_next) {
+ hide_next = ! strcmp(name_buffer, "defined");
+
+ if (__size == 8 && name_buffer [0] == '_' && name_buffer [1] == '_') {
+ if (! strcmp(name_buffer, "__LINE__")) {
+ char buf [16];
+ char *end = buf + pp_snprintf(buf, 16, "%d", env.current_line + lines);
+
+ std::copy(&buf [0], end, __result);
+ continue;
+ }
+
+ else if (! strcmp(name_buffer, "__FILE__")) {
+ __result++ = '"';
+ std::copy(env.current_file.begin(), env.current_file.end(), __result); // ### quote
+ __result++ = '"';
+ continue;
+ }
+ }
+
+ std::copy(name_begin, name_end, __result);
+ continue;
+ }
+
+ if (! macro->function_like) {
+ pp_macro *m = 0;
+
+ if (macro->definition) {
+ macro->hidden = true;
+
+ std::string __tmp;
+ __tmp.reserve(256);
+
+ pp_macro_expander expand_macro(env);
+ expand_macro(macro->definition->begin(), macro->definition->end(), std::back_inserter(__tmp));
+ generated_lines += expand_macro.lines;
+
+ if (! __tmp.empty()) {
+ std::string::iterator __begin_id = skip_whitespaces(__tmp.begin(), __tmp.end());
+ std::string::iterator __end_id = skip_identifier(__begin_id, __tmp.end());
+
+ if (__end_id == __tmp.end()) {
+ std::string __id;
+ __id.assign(__begin_id, __end_id);
+
+ std::size_t x;
+#if defined(__SUNPRO_CC)
+ std::distance(__begin_id, __end_id, x);
+#else
+ x = std::distance(__begin_id, __end_id);
+#endif
+ m = env.resolve(__id.c_str(), x);
+ }
+
+ if (! m)
+ std::copy(__tmp.begin(), __tmp.end(), __result);
+ }
+
+ macro->hidden = false;
+ }
+
+ if (! m)
+ continue;
+
+ macro = m;
+ }
+
+ // function like macro
+ _InputIterator arg_it = skip_whitespaces(__first, __last);
+
+ if (arg_it == __last || *arg_it != '(') {
+ std::copy(name_begin, name_end, __result);
+ lines += skip_whitespaces.lines;
+ __first = arg_it;
+ continue;
+ }
+
+ std::vector<std::string> actuals;
+ actuals.reserve(5);
+ ++arg_it; // skip '('
+
+ pp_macro_expander expand_actual(env, frame);
+
+ _InputIterator arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ if (arg_it != arg_end) {
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ while (arg_it != __last && *arg_end == ',') {
+ ++arg_it; // skip ','
+
+ arg_end = skip_argument_variadics(actuals, macro, arg_it, __last);
+ std::string actual(arg_it, arg_end);
+ actuals.resize(actuals.size() + 1);
+ actuals.back().reserve(255);
+ expand_actual(actual.begin(), actual.end(), std::back_inserter(actuals.back()));
+ arg_it = arg_end;
+ }
+
+ assert(arg_it != __last && *arg_it == ')');
+
+ ++arg_it; // skip ')'
+ __first = arg_it;
+
+#if 0 // ### enable me
+ assert((macro->variadics && macro->formals.size() >= actuals.size())
+ || macro->formals.size() == actuals.size());
+#endif
+
+ pp_frame frame(macro, &actuals);
+ pp_macro_expander expand_macro(env, &frame);
+ macro->hidden = true;
+ expand_macro(macro->definition->begin(), macro->definition->end(), __result);
+ macro->hidden = false;
+ generated_lines += expand_macro.lines;
+ } else
+ *__result++ = *__first++;
+ }
+
+ return __first;
+ }
+
+ template <typename _InputIterator>
+ _InputIterator skip_argument_variadics(std::vector<std::string> const &__actuals, pp_macro *__macro,
+ _InputIterator __first, _InputIterator __last) {
+ _InputIterator arg_end = skip_argument(__first, __last);
+
+ while (__macro->variadics && __first != arg_end && arg_end != __last && *arg_end == ','
+ && (__actuals.size() + 1) == __macro->formals.size()) {
+ arg_end = skip_argument(++arg_end, __last);
+ }
+
+ return arg_end;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_EXPANDER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h
new file mode 100644
index 000000000..9e95840a1
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-macro.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_MACRO_H
+#define PP_MACRO_H
+
+#include <vector>
+#include "pp-fwd.h"
+
+namespace rpp
+{
+
+struct pp_macro {
+#if defined (PP_WITH_MACRO_POSITION)
+ pp_fast_string const *file;
+#endif
+ pp_fast_string const *name;
+ pp_fast_string const *definition;
+ std::vector<pp_fast_string const *> formals;
+
+ union {
+ int unsigned state;
+
+ struct {
+ int unsigned hidden: 1;
+ int unsigned function_like: 1;
+ int unsigned variadics: 1;
+ };
+ };
+
+ int lines;
+ pp_macro *next;
+ std::size_t hash_code;
+
+ inline pp_macro():
+#if defined (PP_WITH_MACRO_POSITION)
+ file(0),
+#endif
+ name(0),
+ definition(0),
+ state(0),
+ lines(0),
+ next(0),
+ hash_code(0) {}
+};
+
+} // namespace rpp
+
+#endif // PP_MACRO_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration b/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration
new file mode 100644
index 000000000..ba356c323
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-qt-configuration
@@ -0,0 +1,24 @@
+#define __cplusplus 1
+
+#define __STDC__ 1
+
+// Qt
+#define QOBJECTDEFS_H
+
+// not yet supported
+#define Q_SLOTS slots
+#define Q_SIGNALS signals
+#define Q_FLAGS(a)
+#define Q_PRIVATE_SLOT(a, b)
+#define Q_DECLARE_INTERFACE(a,b)
+#define Q_INTERFACES(a)
+#define Q_GADGET
+#define Q_OVERRIDE(a)
+#define Q_OS_OS2
+#define Q_NO_USING_KEYWORD
+#define QT_NO_QOBJECT_CHECK
+#define QT_NO_MEMBER_TEMPLATES
+// There are symbols in Qt that exist in Debug but
+// not in release
+#define QT_NO_DEBUG
+
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h
new file mode 100644
index 000000000..0c5007e0f
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-scanner.h
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_SCANNER_H
+#define PP_SCANNER_H
+
+#include "pp-cctype.h"
+#include <cassert>
+
+namespace rpp
+{
+
+struct pp_skip_blanks {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (*__first == '\\') {
+ _InputIterator __begin = __first;
+ ++__begin;
+
+ if (__begin != __last && *__begin == '\n')
+ ++__first;
+ else
+ break;
+ } else if (*__first == '\n' || !pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_whitespaces {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isspace(*__first))
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_comment_or_divop {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ MAYBE_BEGIN,
+ BEGIN,
+ MAYBE_END,
+ END,
+ IN_COMMENT,
+ IN_CXX_COMMENT
+ } state(MAYBE_BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case MAYBE_BEGIN:
+ if (*__first != '/')
+ return __first;
+
+ state = BEGIN;
+ break;
+
+ case BEGIN:
+ if (*__first == '*')
+ state = IN_COMMENT;
+ else if (*__first == '/')
+ state = IN_CXX_COMMENT;
+ else
+ return __first;
+ break;
+
+ case IN_COMMENT:
+ if (*__first == '*')
+ state = MAYBE_END;
+ break;
+
+ case IN_CXX_COMMENT:
+ if (*__first == '\n')
+ return __first;
+ break;
+
+ case MAYBE_END:
+ if (*__first == '/')
+ state = END;
+ else if (*__first != '*')
+ state = IN_COMMENT;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_identifier {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '_')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_number {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ if (! pp_isalnum(*__first) && *__first != '.')
+ break;
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_string_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\"')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\"')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+
+ case END:
+ return __first;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_char_literal {
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ enum {
+ BEGIN,
+ IN_STRING,
+ QUOTE,
+ END
+ } state(BEGIN);
+
+ lines = 0;
+
+ for (; state != END && __first != __last; lines += (*__first != '\n' ? 0 : 1), ++__first) {
+ switch (state) {
+ default:
+ assert(0);
+ break;
+
+ case BEGIN:
+ if (*__first != '\'')
+ return __first;
+ state = IN_STRING;
+ break;
+
+ case IN_STRING:
+ assert(*__first != '\n');
+
+ if (*__first == '\'')
+ state = END;
+ else if (*__first == '\\')
+ state = QUOTE;
+ break;
+
+ case QUOTE:
+ state = IN_STRING;
+ break;
+ }
+ }
+
+ return __first;
+ }
+};
+
+struct pp_skip_argument {
+ pp_skip_identifier skip_number;
+ pp_skip_identifier skip_identifier;
+ pp_skip_string_literal skip_string_literal;
+ pp_skip_char_literal skip_char_literal;
+ pp_skip_comment_or_divop skip_comment_or_divop;
+ int lines;
+
+ template <typename _InputIterator>
+ _InputIterator operator()(_InputIterator __first, _InputIterator __last) {
+ int depth = 0;
+ lines = 0;
+
+ while (__first != __last) {
+ if (!depth && (*__first == ')' || *__first == ','))
+ break;
+ else if (*__first == '(')
+ ++depth, ++__first;
+ else if (*__first == ')')
+ --depth, ++__first;
+ else if (*__first == '\"') {
+ __first = skip_string_literal(__first, __last);
+ lines += skip_string_literal.lines;
+ } else if (*__first == '\'') {
+ __first = skip_char_literal(__first, __last);
+ lines += skip_char_literal.lines;
+ } else if (*__first == '/') {
+ __first = skip_comment_or_divop(__first, __last);
+ lines += skip_comment_or_divop.lines;
+ } else if (pp_isalpha(*__first) || *__first == '_') {
+ __first = skip_identifier(__first, __last);
+ lines += skip_identifier.lines;
+ } else if (pp_isdigit(*__first)) {
+ __first = skip_number(__first, __last);
+ lines += skip_number.lines;
+ } else if (*__first == '\n') {
+ ++__first;
+ ++lines;
+ } else
+ ++__first;
+ }
+
+ return __first;
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SCANNER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h
new file mode 100644
index 000000000..25db0389a
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-string.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_STRING_H
+#define PP_STRING_H
+
+namespace rpp
+{
+
+template <typename _CharT>
+class pp_string
+{
+ typedef std::char_traits<_CharT> traits_type;
+ typedef std::size_t size_type;
+
+ _CharT const *_M_begin;
+ std::size_t _M_size;
+
+public:
+ inline pp_string():
+ _M_begin(0), _M_size(0) {}
+
+ explicit pp_string(std::string const &__s):
+ _M_begin(__s.c_str()), _M_size(__s.size()) {}
+
+ inline pp_string(_CharT const *__begin, std::size_t __size):
+ _M_begin(__begin), _M_size(__size) {}
+
+ inline _CharT const *begin() const {
+ return _M_begin;
+ }
+ inline _CharT const *end() const {
+ return _M_begin + _M_size;
+ }
+
+ inline _CharT at(std::size_t index) const {
+ return _M_begin [index];
+ }
+
+ inline std::size_t size() const {
+ return _M_size;
+ }
+
+ inline int compare(pp_string const &__other) const {
+ size_type const __size = this->size();
+ size_type const __osize = __other.size();
+ size_type const __len = std::min(__size, __osize);
+
+ int __r = traits_type::compare(_M_begin, __other._M_begin, __len);
+ if (!__r)
+ __r = (int)(__size - __osize);
+
+ return __r;
+ }
+
+ inline bool operator == (pp_string const &__other) const {
+ return compare(__other) == 0;
+ }
+
+ inline bool operator != (pp_string const &__other) const {
+ return compare(__other) != 0;
+ }
+
+ inline bool operator < (pp_string const &__other) const {
+ return compare(__other) < 0;
+ }
+
+ inline bool operator == (char const *s) const {
+ std::size_t n = strlen(s);
+
+ if (n != _M_size)
+ return false;
+
+ return ! strncmp(_M_begin, s, n);
+ }
+
+ inline bool operator != (char const *s) const {
+ return ! operator == (s);
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_STRING_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h
new file mode 100644
index 000000000..9b06d2643
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp-symbol.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_SYMBOL_H
+#define PP_SYMBOL_H
+
+#include <cassert>
+#include <iterator>
+#include "pp-fwd.h"
+#include "parser/rxx_allocator.h"
+
+namespace rpp
+{
+
+class pp_symbol
+{
+ static rxx_allocator<char> &allocator_instance() {
+ static rxx_allocator<char>__allocator;
+ return __allocator;
+ }
+ static rxx_allocator<pp_fast_string> &ppfs_allocator_instance ()
+ {
+ static rxx_allocator<pp_fast_string>__ppfs_allocator;
+ return __ppfs_allocator;
+ }
+
+public:
+ static int &N() {
+ static int __N;
+ return __N;
+ }
+
+ static pp_fast_string const *get(char const *__data, std::size_t __size) {
+ ++N();
+ char *data = allocator_instance().allocate(__size + 1);
+ memcpy(data, __data, __size);
+ data[__size] = '\0';
+
+ pp_fast_string *where = ppfs_allocator_instance ().allocate (sizeof (pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ template <typename _InputIterator>
+ static pp_fast_string const *get(_InputIterator __first, _InputIterator __last) {
+ ++N();
+ std::ptrdiff_t __size;
+#if defined(__SUNPRO_CC)
+ std::distance(__first, __last, __size);
+#else
+ __size = std::distance(__first, __last);
+#endif
+ assert(__size >= 0 && __size < 512);
+
+ char *data = allocator_instance().allocate(__size + 1);
+ std::copy(__first, __last, data);
+ data[__size] = '\0';
+
+ pp_fast_string *where = ppfs_allocator_instance ().allocate (sizeof (pp_fast_string));
+ return new(where) pp_fast_string(data, __size);
+ }
+
+ static pp_fast_string const *get(std::string const &__s) {
+ return get(__s.c_str(), __s.size());
+ }
+};
+
+} // namespace rpp
+
+#endif // PP_SYMBOL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/pp.h b/sources/shiboken2/ApiExtractor/parser/rpp/pp.h
new file mode 100644
index 000000000..dfeeac432
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/pp.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 PP_H
+#define PP_H
+
+#if defined(_WIN64) || defined(WIN64) || defined(__WIN64__) \
+ || defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
+# define PP_OS_WIN
+#endif
+
+#include <set>
+#include <map>
+#include <vector>
+#include <string>
+#include <iterator>
+#include <iostream>
+#include <cassert>
+#include <cctype>
+#include <cstdio>
+
+#include <fcntl.h>
+
+#ifdef HAVE_MMAP
+# include <sys/mman.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#if (_MSC_VER >= 1400)
+# define FILENO _fileno
+#else
+# define FILENO fileno
+#endif
+
+#if defined (PP_OS_WIN)
+# define PATH_SEPARATOR '\\'
+#else
+# define PATH_SEPARATOR '/'
+#endif
+
+#if defined (RPP_JAMBI)
+# include "parser/rxx_allocator.h"
+#else
+# include "parser/rpp-allocator.h"
+#endif
+
+#if defined (_MSC_VER)
+# define pp_snprintf _snprintf
+#else
+# define pp_snprintf snprintf
+#endif
+
+#include "pp-fwd.h"
+#include "pp-cctype.h"
+#include "pp-string.h"
+#include "pp-symbol.h"
+#include "pp-internal.h"
+#include "pp-iterator.h"
+#include "pp-macro.h"
+#include "pp-environment.h"
+#include "pp-scanner.h"
+#include "pp-macro-expander.h"
+#include "pp-engine.h"
+#include "pp-engine-bits.h"
+
+#endif // PP_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp
new file mode 100644
index 000000000..315343321
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
+** 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 "preprocessor.h"
+
+#include <string>
+#include <cstdio>
+
+// register callback for include hooks
+static void includeFileHook(const std::string &, const std::string &, FILE *);
+
+#define PP_HOOK_ON_FILE_INCLUDED(A, B, C) includeFileHook(A, B, C)
+#include "pp.h"
+
+using namespace rpp;
+
+#include <QtCore/QtCore>
+
+class PreprocessorPrivate
+{
+public:
+ QByteArray result;
+ pp_environment env;
+ QStringList includePaths;
+
+ void initPP(pp &proc) {
+ foreach(QString path, includePaths)
+ proc.push_include_path(path.toStdString());
+ }
+};
+
+QHash<QString, QStringList> includedFiles;
+
+void includeFileHook(const std::string &fileName, const std::string &filePath, FILE *)
+{
+ includedFiles[QString::fromStdString(fileName)].append(QString::fromStdString(filePath));
+}
+
+Preprocessor::Preprocessor()
+{
+ d = new PreprocessorPrivate;
+ includedFiles.clear();
+}
+
+Preprocessor::~Preprocessor()
+{
+ delete d;
+}
+
+void Preprocessor::processFile(const QString &fileName)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ d->result.reserve(d->result.size() + 20 * 1024);
+
+ d->result += "# 1 \"" + fileName.toLatin1() + "\"\n"; // ### REMOVE ME
+ proc.file(fileName.toLocal8Bit().constData(), std::back_inserter(d->result));
+}
+
+void Preprocessor::processString(const QByteArray &str)
+{
+ pp proc(d->env);
+ d->initPP(proc);
+
+ proc(str.begin(), str.end(), std::back_inserter(d->result));
+}
+
+QByteArray Preprocessor::result() const
+{
+ return d->result;
+}
+
+void Preprocessor::addIncludePaths(const QStringList &includePaths)
+{
+ d->includePaths += includePaths;
+}
+
+QStringList Preprocessor::macroNames() const
+{
+ QStringList macros;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ macros += QString::fromLatin1(m->name->begin(), m->name->size());
+ ++it;
+ }
+
+ return macros;
+}
+
+QList<Preprocessor::MacroItem> Preprocessor::macros() const
+{
+ QList<MacroItem> items;
+
+ pp_environment::const_iterator it = d->env.first_macro();
+ while (it != d->env.last_macro()) {
+ const pp_macro *m = *it;
+ MacroItem item;
+ item.name = QString::fromLatin1(m->name->begin(), m->name->size());
+ item.definition = QString::fromLatin1(m->definition->begin(),
+ m->definition->size());
+ for (size_t i = 0; i < m->formals.size(); ++i) {
+ item.parameters += QString::fromLatin1(m->formals[i]->begin(),
+ m->formals[i]->size());
+ }
+ item.isFunctionLike = m->function_like;
+
+#ifdef PP_WITH_MACRO_POSITION
+ item.fileName = QString::fromLatin1(m->file->begin(), m->file->size());
+#endif
+ items += item;
+
+ ++it;
+ }
+
+ return items;
+}
+
+/*
+int main()
+{
+ Preprocessor pp;
+
+ QStringList paths;
+ paths << "/usr/include";
+ pp.addIncludePaths(paths);
+
+ pp.processFile("pp-configuration");
+ pp.processFile("/usr/include/stdio.h");
+
+ qDebug() << pp.result();
+
+ return 0;
+}
+*/
+
diff --git a/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h
new file mode 100644
index 000000000..7d00a5d09
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rpp/preprocessor.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2005 Harald Fernengel <harry@kdevelop.org>
+** 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 PREPROCESSOR_H
+#define PREPROCESSOR_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qstringlist.h>
+
+class PreprocessorPrivate;
+
+class Preprocessor
+{
+public:
+ Preprocessor();
+ ~Preprocessor();
+
+ void processFile(const QString &fileName);
+ void processString(const QByteArray &str);
+
+ void addIncludePaths(const QStringList &includePaths);
+
+ QByteArray result() const;
+
+ QStringList macroNames() const;
+
+ struct MacroItem {
+ QString name;
+ QStringList parameters;
+ QString definition;
+ bool isFunctionLike;
+#ifdef PP_WITH_MACRO_POSITION
+ QString fileName;
+#endif
+ };
+ QList<MacroItem> macros() const;
+
+private:
+ Q_DISABLE_COPY(Preprocessor)
+ PreprocessorPrivate *d;
+};
+
+#endif
diff --git a/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h b/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h
new file mode 100644
index 000000000..8325edbdf
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/rxx_allocator.h
@@ -0,0 +1,146 @@
+/* This file is part of KDevelop
+ Copyright 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef RXX_ALLOCATOR_H
+#define RXX_ALLOCATOR_H
+
+#include <cstddef>
+#include <cstdlib>
+#include <string.h>
+#include <memory>
+
+// Stride calculation
+template <typename T>
+struct Tchar {
+ T t;
+ char c;
+};
+
+#define strideof(T) \
+ ((sizeof(Tchar<T>) > sizeof(T)) ? \
+ sizeof(Tchar<T>)-sizeof(T) : sizeof(T))
+
+
+/**The allocator which uses fixed size blocks for allocation of its elements.
+Block size is currently 64k, allocated space is not reclaimed,
+if the size of the element being allocated extends the amount of free
+memory in the block then a new block is allocated.
+
+The allocator supports standard c++ library interface but does not
+make use of allocation hints.
+*/
+template <class _Tp> class rxx_allocator {
+public:
+ typedef _Tp value_type;
+ typedef _Tp* pointer;
+ typedef const _Tp* const_pointer;
+ typedef _Tp& reference;
+ typedef const _Tp& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ static const size_type max_block_count = size_type(-1);
+ static const size_type _S_block_size = 1 << 16; // 64K
+
+ rxx_allocator() {
+ init();
+ }
+
+ rxx_allocator(const rxx_allocator &/*__o*/) {
+ init();
+ }
+
+ ~rxx_allocator() {
+ for (size_type index = 0; index < _M_block_index + 1; ++index)
+ delete[] _M_storage[index];
+
+ ::free(_M_storage);
+ }
+
+ pointer address(reference __val) { return &__val; }
+ const_pointer address(const_reference __val) const { return &__val; }
+
+ /**Allocates @p __n elements continuosly in the pool. Warning! no
+ check is done to check if the size of those @p __n elements
+ fit into the block. You should assure you do not allocate more
+ than the size of a block.*/
+ pointer allocate(size_type __n, const void* = 0) {
+ const size_type bytes = __n * sizeof(_Tp);
+
+ if (_M_current_block == 0
+ || _S_block_size < _M_current_index + bytes)
+ {
+ ++_M_block_index;
+
+ _M_storage = reinterpret_cast<char**>
+ (::realloc(_M_storage, sizeof(char*) * (1 + _M_block_index)));
+
+ _M_current_block = _M_storage[_M_block_index] = reinterpret_cast<char*>
+ (new char[_S_block_size]);
+
+ ::memset(_M_current_block, 0, _S_block_size);
+ _M_current_index = 0;
+ }
+
+ pointer p = reinterpret_cast<pointer>
+ (_M_current_block + _M_current_index);
+
+ _M_current_index += bytes;
+
+ return p;
+ }
+
+ pointer allocate(size_type __n, size_type stride, const void* = 0) {
+ if (reinterpret_cast<size_type>(_M_current_block + _M_current_index) % stride > 0)
+ _M_current_index += stride - reinterpret_cast<size_type>(_M_current_block + _M_current_index) % stride;
+ return allocate(__n);
+ }
+
+ /**Deallocate does nothing in this implementation.*/
+ void deallocate(pointer /*__p*/, size_type /*__n*/) {}
+
+ size_type max_size() const { return size_type(-1) / sizeof(_Tp); }
+
+ void construct(pointer __p, const_reference __val) { new (__p) _Tp(__val); }
+ void destroy(pointer __p) { __p->~_Tp(); }
+
+ template <class _Tp1> struct rebind {
+ typedef rxx_allocator<_Tp1> other;
+ };
+
+private:
+
+ void init()
+ {
+ _M_block_index = max_block_count;
+ _M_current_index = 0;
+ _M_storage = 0;
+ _M_current_block = 0;
+ }
+
+ template <class _Tp1> rxx_allocator(const rxx_allocator<_Tp1> &__o) {}
+
+private:
+ size_type _M_block_index;
+ size_type _M_current_index;
+ char *_M_current_block;
+ char **_M_storage;
+};
+
+#endif // RXX_ALLOCATOR_H
+
diff --git a/sources/shiboken2/ApiExtractor/parser/smallobject.cpp b/sources/shiboken2/ApiExtractor/parser/smallobject.cpp
new file mode 100644
index 000000000..9cee247e0
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/smallobject.cpp
@@ -0,0 +1,33 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "smallobject.h"
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/smallobject.h b/sources/shiboken2/ApiExtractor/parser/smallobject.h
new file mode 100644
index 000000000..99e4ea44a
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/smallobject.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 SMALLOBJECT_H
+#define SMALLOBJECT_H
+
+#include "rxx_allocator.h"
+#include <cstring>
+
+class pool
+{
+ rxx_allocator<char> __alloc;
+
+public:
+ inline void *allocate(std::size_t __size);
+ inline void *allocate(std::size_t __size, std::size_t __stride);
+};
+
+inline void *pool::allocate(std::size_t __size)
+{
+ return __alloc.allocate(__size);
+}
+
+inline void *pool::allocate(std::size_t __size, std::size_t __stride)
+{
+ return __alloc.allocate(__size, __stride);
+}
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/symbol.h b/sources/shiboken2/ApiExtractor/parser/symbol.h
new file mode 100644
index 000000000..588653846
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/symbol.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 SYMBOL_H
+#define SYMBOL_H
+
+#include <QtCore/QString>
+#include <cstring>
+
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+
+struct NameSymbol
+{
+ const char *data;
+ std::size_t count;
+
+ inline QString as_string() const
+ {
+ return QString::fromUtf8(data, (int) count);
+ }
+
+ inline bool operator == (const NameSymbol &other) const
+ {
+ return count == other.count
+ && !std::strncmp(data, other.data, count);
+ }
+
+protected:
+ inline NameSymbol() {}
+ inline NameSymbol(const char *d, std::size_t c)
+ : data(d), count(c) {}
+
+private:
+ void operator = (const NameSymbol &);
+
+ friend class NameTable;
+};
+
+inline uint qHash(const NameSymbol &r)
+{
+ uint hash_value = 0;
+
+ for (std::size_t i = 0; i < r.count; ++i)
+ hash_value = (hash_value << 5) - hash_value + r.data[i];
+
+ return hash_value;
+}
+
+inline uint qHash(const QPair<const char*, std::size_t> &r)
+{
+ uint hash_value = 0;
+
+ for (std::size_t i = 0; i < r.second; ++i)
+ hash_value = (hash_value << 5) - hash_value + r.first[i];
+
+ return hash_value;
+}
+
+class NameTable
+{
+public:
+ typedef QPair<const char *, std::size_t> KeyType;
+ typedef QHash<KeyType, NameSymbol*> ContainerType;
+
+public:
+ NameTable() {}
+
+ ~NameTable()
+ {
+ qDeleteAll(_M_storage);
+ }
+
+ inline const NameSymbol *findOrInsert(const char *str, std::size_t len)
+ {
+ KeyType key(str, len);
+
+ NameSymbol *name = _M_storage.value(key);
+ if (!name) {
+ name = new NameSymbol(str, len);
+ _M_storage.insert(key, name);
+ }
+
+ return name;
+ }
+
+ inline std::size_t count() const { return _M_storage.size(); }
+
+private:
+ ContainerType _M_storage;
+
+private:
+ NameTable(const NameTable &other);
+ void operator=(const NameTable &other);
+};
+
+#endif // SYMBOL_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/sources/shiboken2/ApiExtractor/parser/tokens.cpp b/sources/shiboken2/ApiExtractor/parser/tokens.cpp
new file mode 100644
index 000000000..eace3c9fa
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/tokens.cpp
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 <QtCore/qglobal.h>
+
+#include "tokens.h"
+
+static char const * const _S_token_names[] = {
+ "K_DCOP",
+ "Q_OBJECT",
+ "Q_PROPERTY",
+ "__attribute__",
+ "__typeof",
+ "and",
+ "and_eq",
+ "arrow",
+ "asm",
+ "assign",
+ "auto",
+ "bitand",
+ "bitor",
+ "bool",
+ "break",
+ "case",
+ "catch",
+ "char",
+ "char_literal",
+ "class",
+ "comment",
+ "compl",
+ "concat",
+ "const",
+ "const_cast",
+ "continue",
+ "decr",
+ "default",
+ "delete",
+ "do",
+ "double",
+ "dynamic_cast",
+ "ellipsis",
+ "else",
+ "emit",
+ "enum",
+ "eq",
+ "explicit",
+ "export",
+ "extern",
+ "false",
+ "float",
+ "for",
+ "friend",
+ "geq",
+ "goto",
+ "identifier",
+ "if",
+ "incr",
+ "inline",
+ "int",
+ "k_dcop",
+ "k_dcop_signals",
+ "leq",
+ "long",
+ "mutable",
+ "namespace",
+ "new",
+ "noexcept",
+ "not",
+ "not_eq",
+ "number_literal",
+ "operator",
+ "or",
+ "or_eq",
+ "preproc",
+ "private",
+ "protected",
+ "ptrmem",
+ "public",
+ "register",
+ "reinterpret_cast",
+ "return",
+ "scope",
+ "shift",
+ "short",
+ "signals",
+ "signed",
+ "sizeof",
+ "slots",
+ "static",
+ "static_cast",
+ "string_literal",
+ "struct",
+ "switch",
+ "template",
+ "this",
+ "throw",
+ "true",
+ "try",
+ "typedef",
+ "typeid",
+ "typename",
+ "union",
+ "unsigned",
+ "using",
+ "virtual",
+ "void",
+ "volatile",
+ "wchar_t",
+ "while",
+ "whitespaces",
+ "xor",
+ "xor_eq",
+ "Q_ENUMS",
+ "Q_ENUM"
+};
+
+static char _S_printable[][2] = {
+ { char(32), '\0' },
+ { char(33), '\0' },
+ { char(34), '\0' },
+ { char(35), '\0' },
+ { char(36), '\0' },
+ { char(37), '\0' },
+ { char(38), '\0' },
+ { char(39), '\0' },
+ { char(40), '\0' },
+ { char(41), '\0' },
+ { char(42), '\0' },
+ { char(43), '\0' },
+ { char(44), '\0' },
+ { char(45), '\0' },
+ { char(46), '\0' },
+ { char(47), '\0' },
+ { char(48), '\0' },
+ { char(49), '\0' },
+ { char(50), '\0' },
+ { char(51), '\0' },
+ { char(52), '\0' },
+ { char(53), '\0' },
+ { char(54), '\0' },
+ { char(55), '\0' },
+ { char(56), '\0' },
+ { char(57), '\0' },
+ { char(58), '\0' },
+ { char(59), '\0' },
+ { char(60), '\0' },
+ { char(61), '\0' },
+ { char(62), '\0' },
+ { char(63), '\0' },
+ { char(64), '\0' },
+ { char(65), '\0' },
+ { char(66), '\0' },
+ { char(67), '\0' },
+ { char(68), '\0' },
+ { char(69), '\0' },
+ { char(70), '\0' },
+ { char(71), '\0' },
+ { char(72), '\0' },
+ { char(73), '\0' },
+ { char(74), '\0' },
+ { char(75), '\0' },
+ { char(76), '\0' },
+ { char(77), '\0' },
+ { char(78), '\0' },
+ { char(79), '\0' },
+ { char(80), '\0' },
+ { char(81), '\0' },
+ { char(82), '\0' },
+ { char(83), '\0' },
+ { char(84), '\0' },
+ { char(85), '\0' },
+ { char(86), '\0' },
+ { char(87), '\0' },
+ { char(88), '\0' },
+ { char(89), '\0' },
+ { char(90), '\0' },
+ { char(91), '\0' },
+ { char(92), '\0' },
+ { char(93), '\0' },
+ { char(94), '\0' },
+ { char(95), '\0' },
+ { char(96), '\0' },
+ { char(97), '\0' },
+ { char(98), '\0' },
+ { char(99), '\0' },
+ { char(100), '\0' },
+ { char(101), '\0' },
+ { char(102), '\0' },
+ { char(103), '\0' },
+ { char(104), '\0' },
+ { char(105), '\0' },
+ { char(106), '\0' },
+ { char(107), '\0' },
+ { char(108), '\0' },
+ { char(109), '\0' },
+ { char(110), '\0' },
+ { char(111), '\0' },
+ { char(112), '\0' },
+ { char(113), '\0' },
+ { char(114), '\0' },
+ { char(115), '\0' },
+ { char(116), '\0' },
+ { char(117), '\0' },
+ { char(118), '\0' },
+ { char(119), '\0' },
+ { char(120), '\0' },
+ { char(121), '\0' },
+ { char(122), '\0' },
+ { char(123), '\0' },
+ { char(124), '\0' },
+ { char(125), '\0' },
+ { char(126), '\0' },
+ { char(127), '\0' },
+};
+
+char const *token_name(int token)
+{
+ if (token == 0)
+ return "eof";
+ else if (token >= 32 && token <= 127)
+ return _S_printable[token - 32];
+ else if (token >= 1000)
+ return _S_token_names[token - 1000];
+
+ Q_ASSERT(0);
+ return 0;
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/tokens.h b/sources/shiboken2/ApiExtractor/parser/tokens.h
new file mode 100644
index 000000000..46ec96e74
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/tokens.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 TOKENS_H
+#define TOKENS_H
+
+enum TOKEN_KIND {
+ Token_EOF = 0,
+
+ Token_K_DCOP = 1000,
+ Token_Q_OBJECT,
+ Token_Q_PROPERTY,
+ Token___attribute__,
+ Token___typeof,
+ Token_and,
+ Token_and_eq,
+ Token_arrow,
+ Token_asm,
+ Token_assign,
+ Token_auto,
+ Token_bitand,
+ Token_bitor,
+ Token_bool,
+ Token_break,
+ Token_case,
+ Token_catch,
+ Token_char,
+ Token_char_literal,
+ Token_class,
+ Token_comment,
+ Token_compl,
+ Token_concat,
+ Token_const,
+ Token_const_cast,
+ Token_continue,
+ Token_decr,
+ Token_default,
+ Token_delete,
+ Token_do,
+ Token_double,
+ Token_dynamic_cast,
+ Token_ellipsis,
+ Token_else,
+ Token_emit,
+ Token_enum,
+ Token_eq,
+ Token_explicit,
+ Token_export,
+ Token_extern,
+ Token_false,
+ Token_float,
+ Token_for,
+ Token_friend,
+ Token_geq,
+ Token_goto,
+ Token_identifier,
+ Token_if,
+ Token_incr,
+ Token_inline,
+ Token_int,
+ Token_k_dcop,
+ Token_k_dcop_signals,
+ Token_leq,
+ Token_long,
+ Token_mutable,
+ Token_namespace,
+ Token_new,
+ Token_noexcept,
+ Token_not,
+ Token_not_eq,
+ Token_number_literal,
+ Token_operator,
+ Token_or,
+ Token_or_eq,
+ Token_preproc,
+ Token_private,
+ Token_protected,
+ Token_ptrmem,
+ Token_public,
+ Token_register,
+ Token_reinterpret_cast,
+ Token_return,
+ Token_scope,
+ Token_shift,
+ Token_short,
+ Token_signals,
+ Token_signed,
+ Token_sizeof,
+ Token_slots,
+ Token_static,
+ Token_static_cast,
+ Token_string_literal,
+ Token_struct,
+ Token_switch,
+ Token_template,
+ Token_this,
+ Token_throw,
+ Token_true,
+ Token_try,
+ Token_typedef,
+ Token_typeid,
+ Token_typename,
+ Token_union,
+ Token_unsigned,
+ Token_using,
+ Token_virtual,
+ Token_void,
+ Token_volatile,
+ Token_wchar_t,
+ Token_while,
+ Token_whitespaces,
+ Token_xor,
+ Token_xor_eq,
+ Token_Q_ENUMS,
+ Token_Q_ENUM,
+ Token_Q_INVOKABLE,
+
+ TOKEN_KIND_COUNT
+};
+
+char const *token_name(int token);
+
+#endif
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp b/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp
new file mode 100644
index 000000000..c08f210fa
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/type_compiler.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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$
+**
+****************************************************************************/
+
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+
+#include "type_compiler.h"
+#include "name_compiler.h"
+#include "lexer.h"
+#include "symbol.h"
+#include "tokens.h"
+#include "binder.h"
+
+#include <QtCore/QString>
+
+TypeCompiler::TypeCompiler(Binder *binder)
+ : _M_binder(binder), _M_token_stream(binder->tokenStream())
+{
+}
+
+void TypeCompiler::run(TypeSpecifierAST *node)
+{
+ _M_type.clear();
+ _M_cv.clear();
+
+ visit(node);
+
+ if (node && node->cv) {
+ const ListNode<std::size_t> *it = node->cv->toFront();
+ const ListNode<std::size_t> *end = it;
+ do {
+ int kind = _M_token_stream->kind(it->element);
+ if (!_M_cv.contains(kind))
+ _M_cv.append(kind);
+
+ it = it->next;
+ } while (it != end);
+ }
+}
+
+void TypeCompiler::visitClassSpecifier(ClassSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitEnumSpecifier(EnumSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node)
+{
+ visit(node->name);
+}
+
+void TypeCompiler::visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node)
+{
+ if (const ListNode<std::size_t> *it = node->integrals) {
+ it = it->toFront();
+ const ListNode<std::size_t> *end = it;
+ QString current_item;
+ do {
+ std::size_t token = it->element;
+ current_item += QLatin1String(token_name(_M_token_stream->kind(token)));
+ current_item += QLatin1Char(' ');
+ it = it->next;
+ } while (it != end);
+ _M_type += current_item.trimmed();
+ } else if (node->type_of) {
+ // ### implement me
+ _M_type += QLatin1String("typeof<...>");
+ }
+
+ visit(node->name);
+}
+
+void TypeCompiler::visitName(NameAST *node)
+{
+ NameCompiler name_cc(_M_binder);
+ name_cc.run(node);
+ _M_type = name_cc.qualifiedName();
+}
+
+QStringList TypeCompiler::cvString() const
+{
+ QStringList lst;
+
+ foreach (int q, cv()) {
+ if (q == Token_const)
+ lst.append(QLatin1String("const"));
+ else if (q == Token_volatile)
+ lst.append(QLatin1String("volatile"));
+ }
+
+ return lst;
+}
+
+bool TypeCompiler::isConstant() const
+{
+ return _M_cv.contains(Token_const);
+}
+
+bool TypeCompiler::isVolatile() const
+{
+ return _M_cv.contains(Token_volatile);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/type_compiler.h b/sources/shiboken2/ApiExtractor/parser/type_compiler.h
new file mode 100644
index 000000000..6755b30c3
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/type_compiler.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 TYPE_COMPILER_H
+#define TYPE_COMPILER_H
+
+#include "default_visitor.h"
+
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QList>
+
+class TokenStream;
+class Binder;
+
+class TypeCompiler: protected DefaultVisitor
+{
+public:
+ TypeCompiler(Binder *binder);
+
+ inline QStringList qualifiedName() const { return _M_type; }
+ inline QList<int> cv() const { return _M_cv; }
+
+ bool isConstant() const;
+ bool isVolatile() const;
+
+ QStringList cvString() const;
+
+ void run(TypeSpecifierAST *node);
+
+protected:
+ virtual void visitClassSpecifier(ClassSpecifierAST *node);
+ virtual void visitEnumSpecifier(EnumSpecifierAST *node);
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *node);
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *node);
+
+ virtual void visitName(NameAST *node);
+
+private:
+ Binder *_M_binder;
+ TokenStream *_M_token_stream;
+ QStringList _M_type;
+ QList<int> _M_cv;
+};
+
+#endif // TYPE_COMPILER_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
+
diff --git a/sources/shiboken2/ApiExtractor/parser/visitor.cpp b/sources/shiboken2/ApiExtractor/parser/visitor.cpp
new file mode 100644
index 000000000..e13e4acb3
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/visitor.cpp
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 "visitor.h"
+
+Visitor::visitor_fun_ptr Visitor::_S_table[AST::NODE_KIND_COUNT] = {
+ 0,
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAccessSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitAsmDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBaseSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitBinaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCastExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassMemberAccess),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitClassSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCompoundStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCondition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitConditionalExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCppCastExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitCtorInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarationStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDeleteExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitDoStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitElaboratedTypeSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitEnumerator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExceptionSpecification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionOrDeclarationStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitExpressionStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionCall),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitFunctionDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIfStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitIncrDecrExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitInitializerClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLabeledStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageBody),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitLinkageSpecification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitMemInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitName),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespace),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNamespaceAliasDefinition),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewDeclarator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewInitializer),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitNewTypeId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitOperatorFunctionId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitParameterDeclarationClause),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPostfixExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPrimaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrOperator),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitPtrToMember),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitReturnStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSimpleTypeSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSizeofExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitStringLiteral),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSubscriptExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitSwitchStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateArgument),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateDeclaration),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTemplateParameter),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitThrowExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTranslationUnit),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTryBlockStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeId),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeIdentification),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypeParameter),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitTypedef),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnaryExpression),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUnqualifiedName),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsing),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitUsingDirective),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWhileStatement),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitWinDeclSpec),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQProperty),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitForwardDeclarationSpecifier),
+ reinterpret_cast<Visitor::visitor_fun_ptr>(&Visitor::visitQEnums)
+};
+
+Visitor::Visitor()
+{
+}
+
+Visitor::~Visitor()
+{
+}
+
+void Visitor::visit(AST *node)
+{
+ if (node)
+ (this->*_S_table[node->kind])(node);
+}
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/parser/visitor.h b/sources/shiboken2/ApiExtractor/parser/visitor.h
new file mode 100644
index 000000000..b1fbf8763
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/parser/visitor.h
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2002-2005 Roberto Raggi <roberto@kdevelop.org>
+** 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 VISITOR_H
+#define VISITOR_H
+
+#include "ast.h"
+
+class Visitor
+{
+public:
+ Visitor();
+ virtual ~Visitor();
+
+ virtual void visit(AST *node);
+
+protected:
+ virtual void visitAccessSpecifier(AccessSpecifierAST *) {}
+ virtual void visitAsmDefinition(AsmDefinitionAST *) {}
+ virtual void visitBaseClause(BaseClauseAST *) {}
+ virtual void visitBaseSpecifier(BaseSpecifierAST *) {}
+ virtual void visitBinaryExpression(BinaryExpressionAST *) {}
+ virtual void visitCastExpression(CastExpressionAST *) {}
+ virtual void visitClassMemberAccess(ClassMemberAccessAST *) {}
+ virtual void visitClassSpecifier(ClassSpecifierAST *) {}
+ virtual void visitCompoundStatement(CompoundStatementAST *) {}
+ virtual void visitCondition(ConditionAST *) {}
+ virtual void visitConditionalExpression(ConditionalExpressionAST *) {}
+ virtual void visitCppCastExpression(CppCastExpressionAST *) {}
+ virtual void visitCtorInitializer(CtorInitializerAST *) {}
+ virtual void visitDeclarationStatement(DeclarationStatementAST *) {}
+ virtual void visitDeclarator(DeclaratorAST *) {}
+ virtual void visitDeleteExpression(DeleteExpressionAST *) {}
+ virtual void visitDoStatement(DoStatementAST *) {}
+ virtual void visitElaboratedTypeSpecifier(ElaboratedTypeSpecifierAST *) {}
+ virtual void visitEnumSpecifier(EnumSpecifierAST *) {}
+ virtual void visitEnumerator(EnumeratorAST *) {}
+ virtual void visitExceptionSpecification(ExceptionSpecificationAST *) {}
+ virtual void visitExpressionOrDeclarationStatement(ExpressionOrDeclarationStatementAST *) {}
+ virtual void visitExpressionStatement(ExpressionStatementAST *) {}
+ virtual void visitForStatement(ForStatementAST *) {}
+ virtual void visitFunctionCall(FunctionCallAST *) {}
+ virtual void visitFunctionDefinition(FunctionDefinitionAST *) {}
+ virtual void visitIfStatement(IfStatementAST *) {}
+ virtual void visitIncrDecrExpression(IncrDecrExpressionAST *) {}
+ virtual void visitInitDeclarator(InitDeclaratorAST *) {}
+ virtual void visitInitializer(InitializerAST *) {}
+ virtual void visitInitializerClause(InitializerClauseAST *) {}
+ virtual void visitLabeledStatement(LabeledStatementAST *) {}
+ virtual void visitLinkageBody(LinkageBodyAST *) {}
+ virtual void visitLinkageSpecification(LinkageSpecificationAST *) {}
+ virtual void visitMemInitializer(MemInitializerAST *) {}
+ virtual void visitName(NameAST *) {}
+ virtual void visitNamespace(NamespaceAST *) {}
+ virtual void visitNamespaceAliasDefinition(NamespaceAliasDefinitionAST *) {}
+ virtual void visitNewDeclarator(NewDeclaratorAST *) {}
+ virtual void visitNewExpression(NewExpressionAST *) {}
+ virtual void visitNewInitializer(NewInitializerAST *) {}
+ virtual void visitNewTypeId(NewTypeIdAST *) {}
+ virtual void visitOperator(OperatorAST *) {}
+ virtual void visitOperatorFunctionId(OperatorFunctionIdAST *) {}
+ virtual void visitParameterDeclaration(ParameterDeclarationAST *) {}
+ virtual void visitParameterDeclarationClause(ParameterDeclarationClauseAST *) {}
+ virtual void visitPostfixExpression(PostfixExpressionAST *) {}
+ virtual void visitPrimaryExpression(PrimaryExpressionAST *) {}
+ virtual void visitPtrOperator(PtrOperatorAST *) {}
+ virtual void visitPtrToMember(PtrToMemberAST *) {}
+ virtual void visitReturnStatement(ReturnStatementAST *) {}
+ virtual void visitSimpleDeclaration(SimpleDeclarationAST *) {}
+ virtual void visitSimpleTypeSpecifier(SimpleTypeSpecifierAST *) {}
+ virtual void visitSizeofExpression(SizeofExpressionAST *) {}
+ virtual void visitStringLiteral(StringLiteralAST *) {}
+ virtual void visitSubscriptExpression(SubscriptExpressionAST *) {}
+ virtual void visitSwitchStatement(SwitchStatementAST *) {}
+ virtual void visitTemplateArgument(TemplateArgumentAST *) {}
+ virtual void visitTemplateDeclaration(TemplateDeclarationAST *) {}
+ virtual void visitTemplateParameter(TemplateParameterAST *) {}
+ virtual void visitThrowExpression(ThrowExpressionAST *) {}
+ virtual void visitTranslationUnit(TranslationUnitAST *) {}
+ virtual void visitTryBlockStatement(TryBlockStatementAST *) {}
+ virtual void visitTypeId(TypeIdAST *) {}
+ virtual void visitTypeIdentification(TypeIdentificationAST *) {}
+ virtual void visitTypeParameter(TypeParameterAST *) {}
+ virtual void visitTypedef(TypedefAST *) {}
+ virtual void visitUnaryExpression(UnaryExpressionAST *) {}
+ virtual void visitUnqualifiedName(UnqualifiedNameAST *) {}
+ virtual void visitUsing(UsingAST *) {}
+ virtual void visitUsingDirective(UsingDirectiveAST *) {}
+ virtual void visitWhileStatement(WhileStatementAST *) {}
+ virtual void visitWinDeclSpec(WinDeclSpecAST *) {}
+ virtual void visitQProperty(QPropertyAST *) {}
+ virtual void visitForwardDeclarationSpecifier(ForwardDeclarationSpecifierAST *) {}
+ virtual void visitQEnums(QEnumsAST *) {}
+
+private:
+ typedef void (Visitor::*visitor_fun_ptr)(AST *);
+ static visitor_fun_ptr _S_table[];
+};
+
+template <class _Tp>
+void visitNodes(Visitor *v, const ListNode<_Tp> *nodes)
+{
+ if (!nodes)
+ return;
+
+ const ListNode<_Tp>
+ *it = nodes->toFront(),
+ *end = it;
+
+ do {
+ v->visit(it->element);
+ it = it->next;
+ } while (it != end);
+}
+
+#endif // VISITOR_H
+
+// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/sources/shiboken2/ApiExtractor/qtdocparser.cpp b/sources/shiboken2/ApiExtractor/qtdocparser.cpp
new file mode 100644
index 000000000..f1421ff91
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/qtdocparser.cpp
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** 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 <QtXmlPatterns/QXmlQuery>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QUrl>
+
+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;
+ foreach (DocModification docModif, metaClass->typeEntry()->docModifications()) {
+ if (docModif.signature().isEmpty())
+ classModifs.append(docModif);
+ else
+ signedModifs.append(docModif);
+ }
+
+ Documentation doc(getDocumentation(xquery, query, classModifs));
+ metaClass->setDocumentation(doc);
+
+
+ //Functions Documentation
+ AbstractMetaFunctionList funcs = metaClass->functionsInTargetLang();
+ foreach (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("\"]");
+
+ int i = 1;
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+ 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)
+ + QLatin1String("][@left=\"") + type + QLatin1String("\"]/..");
+ ++i;
+ }
+ }
+ query += QLatin1String("/description");
+ DocModificationList funcModifs;
+ foreach (DocModification funcModif, signedModifs) {
+ if (funcModif.signature() == func->minimalSignature())
+ funcModifs.append(funcModif);
+ }
+ doc.setValue(getDocumentation(xquery, query, funcModifs));
+ func->setDocumentation(doc);
+ }
+#if 0
+ // Fields
+ AbstractMetaFieldList fields = metaClass->fields();
+ foreach (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
+ AbstractMetaEnumList enums = metaClass->enums();
+ foreach (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..04c491853
--- /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() {}
+ virtual void fillDocumentation(AbstractMetaClass* metaClass);
+ virtual Documentation retrieveModuleDocumentation();
+ virtual Documentation retrieveModuleDocumentation(const QString& name);
+};
+
+#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 <QtCore/QSet>
+#include <cstring>
+#include <cstdarg>
+#include <cstdio>
+
+#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<QString> 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 <QLoggingCategory>
+#include <QString>
+
+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 <typename T>
+ 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..5429c1cb8
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/CMakeLists.txt
@@ -0,0 +1,73 @@
+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}
+ )
+ 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 @@
+<?xml version="1.0" ?>
+
+<WebXML>
+ <document>
+ <class name="A">
+ <description>oi
+ <para>Paragraph number 1</para>
+ <para>Paragraph number 2</para>
+ <para>Paragraph number 3</para>
+ </description>
+ </class>
+ </document>
+</WebXML>
diff --git a/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp b/sources/shiboken2/ApiExtractor/tests/testabstractmetaclass.cpp
new file mode 100644
index 000000000..028522159
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestAbstractMetaClass::testClassName()
+{
+ const char* cppCode ="class ClassName {};";
+ const char* xmlCode = "<typesystem package=\"Foo\"><value-type name=\"ClassName\"/></typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <namespace-type name=\"Namespace\"/>\n\
+ <value-type name=\"Namespace::ClassName\"/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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"))
+ classes.swap(0, 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()"))
+ ctors.swap(0, 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int'/>\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'/>\n\
+ <object-type name='C'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'/>\n\
+ <value-type name='A::B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <modify-function signature='method(A::B)'>\n\
+ <modify-argument index='1'>\n\
+ <replace-default-expression with='Hello'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </value-type>\n\
+ <value-type name='A::B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A'/>\n\
+ <value-type name='A::B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'/>\n\
+ <value-type name='A::B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'/>\n\
+ <object-type name='B'/>\n\
+ <value-type name='C'/>\n\
+ <object-type name='D'/>\n\
+ <object-type name='E'/>\n\
+ <value-type name='F'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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()"))
+ ctors.swap(0, 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)"))
+ ctors.swap(0, 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 = "\
+ <typesystem package='Foo'>\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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()"))
+ ctors.swap(0, 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 = "\
+ <typesystem package='Foo'>\n\
+ <object-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <object-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='bool'/>\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestAbstractMetaType::testConstCharPtrType()
+{
+ const char* cppCode ="const char* justAtest();\n";
+ const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ <primitive-type name='char'/>\n\
+ <function signature='justAtest()' />\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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 = "<typesystem package='Foo'>\n\
+ <value-type name='foo' since='0.1'/>\n\
+ <value-type name='foo2' since='1.0'/>\n\
+ <value-type name='foo3' since='1.1'/>\n\
+ <function signature='justAtest()' since='0.1'/>\n\
+ <function signature='justAtest2()' since='1.1'/>\n\
+ <function signature='justAtest3()'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "<typesystem package='Foo'>\n\
+ <value-type name='object' since='0.1'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "<typesystem package=\"Foo\">\n\
+ <primitive-type name='char'/>\n\
+ <value-type name='A'/>\n\
+ <function signature='justAtest()'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+
+ 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 = "<typesystem package=\"Foo\">\n\
+ <value-type name='C' />\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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<typename T>\n\
+ class A {};\n\
+ \n\
+ class B {};\n\
+ typedef A<B> C;\n\
+ \n\
+ void func(C c);\n";
+ const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ <container-type name='A' type='list'/>\n\
+ <value-type name='B' />\n\
+ <function signature='func(A&lt;B&gt;)'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+
+ 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<B >"));
+}
+
+
+void TestAbstractMetaType::testObjectTypeUsedAsValue()
+{
+ const char* cppCode ="\
+ class A {\n\
+ void method(A);\n\
+ };\n";
+ const char* xmlCode = "<typesystem package='Foo'>\n\
+ <object-type name='A'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+
+ 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 <QObject>
+
+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..6e1da17ae
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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<int& , C<char*> * > * *, const type3* const ) const ";
+ AddedFunction f2(QLatin1String(sig2), QLatin1String("const Abc<int& , C<char*> * > * *"), 0);
+ QCOMPARE(f2.name(), QLatin1String("_fu__nc_"));
+ QList< AddedFunction::TypeInfo > args = f2.arguments();
+ QCOMPARE(args.count(), 4);
+ retval = f2.returnType();
+ QCOMPARE(retval.name, QLatin1String("Abc<int& , C<char*> * >"));
+ QCOMPARE(retval.indirections, 2);
+ QCOMPARE(retval.isConstant, true);
+ QCOMPARE(retval.isReference, false);
+ retval = args[2];
+ QCOMPARE(retval.name, QLatin1String("Abc<int& , C<char*> * >"));
+ 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='float'/>\n\
+ <value-type name='B'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='b(int, float = 4.6, const B&amp;)' return-type='int' access='protected'>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='A(int)'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func()'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func()'>\n\
+ <inject-code class='target' position='end'>Hi!, I am the code.</inject-code>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func'>\n\
+ <inject-code class='target' position='end'>Hi!, I am the code.</inject-code>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func(int, int)'>\n\
+ <modify-argument index='2'>\n\
+ <replace-default-expression with='2'/>\n\
+ </modify-argument>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'/>\n\
+ <add-function signature='func(int, int)'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='char'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func(int,char,...)'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='func(int, int)' static='yes'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'/>\n\
+ <add-function signature='globalFunc(int, int)' static='yes'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ <add-function signature='globalFunc2(int, int)' static='yes'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <add-function signature='globalFunc(int, int)' static='yes' since='1.3'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ <add-function signature='globalFunc2(int, int)' static='yes' since='0.1'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Package'>\n\
+ <primitive-type name='float'/>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='Foo'>\n\
+ <add-function signature='method(float, int)'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ <modify-argument index='2'>\n\
+ <replace-default-expression with='0'/>\n\
+ <rename to='varName'/>\n\
+ </modify-argument>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 T> class Foo { }; typedef Foo<int> FooInt;\n";
+ const char xmlCode[] = "\
+ <typesystem package='Package'>\n\
+ <custom-type name='PySequence'/>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='FooInt'>\n\
+ <add-function signature='FooInt(PySequence)'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ <add-function signature='method()'>\n\
+ <inject-code class='target' position='beginning'>custom_code();</inject-code>\n\
+ </add-function>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ AbstractMetaClassList classes = builder->classes();
+ AbstractMetaClass* foo = AbstractMetaClass::findClass(classes, QLatin1String("FooInt"));
+ QVERIFY(foo);
+ QVERIFY(foo->hasNonPrivateConstructor());
+ AbstractMetaFunctionList lst = foo->queryFunctions(AbstractMetaClass::Constructors);
+ foreach(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 T> class Foo { };\n";
+ const char xmlCode[] = "\
+ <typesystem package='Package'>\n\
+ <primitive-type name='int'/>\n\
+ <container-type name='Foo' type='list'/>\n\
+ <add-function signature='func(Foo&lt;int>)'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..5385c9140
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestArrayArgument::testArrayArgumentWithSizeDefinedByInteger()
+{
+ const char* cppCode ="\
+ struct A {\n\
+ enum SomeEnum { Value0, Value1, NValues };\n\
+ void method(double[3]);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='double'/>\n\
+ <object-type name='A'>\n\
+ <enum-type name='SomeEnum'/>\n\
+ </object-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='double'/>\n\
+ <object-type name='A'>\n\
+ <enum-type name='SomeEnum'/>\n\
+ </object-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='double'/>\n\
+ <enum-type name='SomeEnum'/>\n\
+ <object-type name='A'>\n\
+ </object-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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;
+ foreach (AbstractMetaEnumValue* enumValue, someEnum->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 <QObject>
+
+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 <QFileInfo>
+#include <QDir>
+#include <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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("\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <conversion-rule file='") + filePath + QLatin1String("/utf8code.txt'/>\n\
+ <inject-code class='target' file='") + filePath
+ + QLatin1String("/utf8code.txt'/>\n\
+ </value-type>\n\
+ <value-type name='A::B'/>\n\
+ </typesystem>\n");
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <inject-code class='target' since='1.0'>\n\
+ test Inject code\n\
+ </inject-code>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <inject-code class='target' since='1.0'>\n\
+ test Inject code\n\
+ </inject-code>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestContainer::testContainerType()
+{
+ const char* cppCode ="\
+ namespace std {\n\
+ template<class T>\n\
+ class list {\n\
+ T get(int x) { return 0; }\n\
+ };\n\
+ }\n\
+ class A : public std::list<int> {\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='std' generate='no' />\n\
+ <container-type name='std::list' type='list' />\n\
+ <object-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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<const ContainerTypeEntry*>(classA->typeEntry()->baseContainerType())->type(), ContainerTypeEntry::ListContainer);
+}
+
+void TestContainer::testListOfValueType()
+{
+ const char* cppCode ="\
+ namespace std {\n\
+ template<class T>\n\
+ class list {\n\
+ T get(int x) { return 0; }\n\
+ };\n\
+ }\n\
+ class ValueType {};\n\
+ class A : public std::list<ValueType> {\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='std' generate='no'/>\n\
+ <container-type name='std::list' type='list'/>\n\
+ <value-type name='ValueType'/>\n\
+ <value-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..cae4a3a62
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ <value-type name='C'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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;
+ foreach(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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A' />\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A' />\n\
+ <value-type name='B'>\n\
+ <modify-function signature='operator A() const' remove='all'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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[] = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+#include <QFile>
+#include <QTemporaryFile>
+
+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("\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <conversion-rule file='") + file.fileName() + QLatin1String("'/>\n\
+ </value-type>\n\
+ </typesystem>\n");
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='char'/>\n\
+ <primitive-type name='A'>\n\
+ <conversion-rule>\n\
+ <native-to-target>\n\
+ DoThis();\n\
+ return ConvertFromCppToPython(%IN);\n\
+ </native-to-target>\n\
+ <target-to-native>\n\
+ <add-conversion type='TargetNone' check='%IN == Target_None'>\n\
+ DoThat();\n\
+ DoSomething();\n\
+ %OUT = A();\n\
+ </add-conversion>\n\
+ <add-conversion type='B' check='CheckIfInputObjectIsB(%IN)'>\n\
+ %OUT = %IN.createA();\n\
+ </add-conversion>\n\
+ <add-conversion type='String' check='String_Check(%IN)'>\n\
+ %OUT = new A(String_AsString(%IN), String_GetSize(%IN));\n\
+ </add-conversion>\n\
+ </target-to-native>\n\
+ </conversion-rule>\n\
+ </primitive-type>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='Date'>\n\
+ <conversion-rule>\n\
+ <target-to-native replace='no'>\n\
+ <add-conversion type='TargetDate' check='TargetDate_Check(%IN)'>\n\
+if (!TargetDateTimeAPI) TargetDateTime_IMPORT;\n\
+%OUT = new Date(TargetDate_Day(%IN), TargetDate_Month(%IN), TargetDate_Year(%IN));\n\
+ </add-conversion>\n\
+ </target-to-native>\n\
+ </conversion-rule>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <!-- single line -->\n\
+ <template name='native_to_target'>return ConvertFromCppToPython(%IN);</template>\n\
+ <!-- multi-line -->\n\
+ <template name='target_to_native'>\n\
+%OUT = %IN.createA();\n\
+ </template>\n\
+ <primitive-type name='A'>\n\
+ <conversion-rule>\n\
+ <native-to-target>\n\
+ <insert-template name='native_to_target'/>\n\
+ </native-to-target>\n\
+ <target-to-native>\n\
+ <add-conversion type='TargetType'>\n\
+ <insert-template name='target_to_native'/>\n\
+ </add-conversion>\n\
+ </target-to-native>\n\
+ </conversion-rule>\n\
+ </primitive-type>\n\
+ </typesystem>\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<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestCtorInformation::testCtorIsPrivate()
+{
+ const char* cppCode = "class Control { public: Control() {} };\n\
+ class Subject { private: Subject() {} };\n\
+ class CtorLess { };\n";
+ const char* xmlCode = "<typesystem package='Foo'>\n\
+ <value-type name='Control'/>\n\
+ <object-type name='Subject'/>\n\
+ <value-type name='CtorLess'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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<typename T>\n\
+ struct Base { Base(double) {} };\n\
+ typedef Base<int> Derived;\n";
+ const char* xmlCode = "<typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='double'/>\n\
+ <object-type name='Base' generate='no'/>\n\
+ <object-type name='Derived'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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 = "\
+<typesystem package='Foo'>\n\
+ <value-type name='ValueA'/>\n\
+ <value-type name='ValueB'/>\n\
+ <object-type name='ObjectA'/>\n\
+ <object-type name='ObjectB'/>\n\
+ <namespace-type name='NamespaceA'>\n\
+ <value-type name='InnerClassA'/>\n\
+ <namespace-type name='InnerNamespaceA'/>\n\
+ </namespace-type>\n\
+ <namespace-type name='NamespaceB'/>\n\
+ <enum-type name='EnumA'/>\n\
+ <enum-type name='EnumB'/>\n\
+ <function signature='funcA()'/>\n\
+ <function signature='funcB()'/>\n\
+</typesystem>\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<AbstractMetaBuilder> 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<AbstractMetaBuilder> 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 = "\
+<typesystem package='Foo'>\n\
+ <value-type name='ValueA'>\n\
+ <modify-function signature='func()'>\n\
+ <remove class='all'/>\n\
+ </modify-function>\n\
+ </value-type>\n\
+</typesystem>\n";
+
+void TestDropTypeEntries::testDropEntryWithChildTags()
+{
+ QStringList droppedEntries(QLatin1String("Foo.ValueA"));
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode2, xmlCode2, false, Q_NULLPTR, droppedEntries));
+ QVERIFY(!builder.isNull());
+ QVERIFY(!AbstractMetaClass::findClass(builder->classes(), QLatin1String("ValueA")));
+}
+
+
+void TestDropTypeEntries::testDontDropEntryWithChildTags()
+{
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestDtorInformation::testDtorIsPrivate()
+{
+ const char* cppCode ="class Control { public: ~Control() {} }; class Subject { private: ~Subject() {} };";
+ const char* xmlCode = "<typesystem package=\"Foo\"><value-type name=\"Control\"/><value-type name=\"Subject\"/></typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 = "<typesystem package=\"Foo\"><value-type name=\"Control\"/><value-type name=\"Subject\"/></typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 = "<typesystem package=\"Foo\"><value-type name=\"Control\"/><value-type name=\"Subject\"/></typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 = "<typesystem package=\"Foo\"><value-type name=\"Control\"/><value-type name=\"Subject\"/></typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..6700239d6
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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 = "\
+ <typesystem package=\"Foo\">\n\
+ <enum-type name='GlobalEnum'/>\n\
+ <value-type name='A'>\n\
+ <enum-type name='ClassEnum'/>\n\
+ </value-type>\n\
+ <function signature='func(A::ClassEnum)'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <enum-type name='ClassEnum' since='0.1'/>\n\
+ <enum-type name='ClassEnum2' since='0.2'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <!-- Uses the first value of the enum to identify it. -->\n\
+ <enum-type identified-by-value='Global0'/>\n\
+ <value-type name='A'>\n\
+ <!-- Uses the second value of the enum to identify it. -->\n\
+ <enum-type identified-by-value='A1'/>\n\
+ <enum-type identified-by-value='isThis'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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<int>(true));
+ QCOMPARE(enumValueIsThis->stringValue(), QLatin1String("true"));
+
+ AbstractMetaEnumValue* enumValueIsThat = anonEnumIsThis->values().last();
+ QCOMPARE(enumValueIsThat->name(), QLatin1String("isThat"));
+ QCOMPARE(enumValueIsThat->value(), static_cast<int>(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 = "\
+ <typesystem package=\"Foo\">\n\
+ <enum-type name='EnumA'/>\n\
+ <enum-type name='EnumB'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+
+ 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <namespace-type name='A'>\n\
+ <enum-type name='EnumA'/>\n\
+ <enum-type name='EnumB'/>\n\
+ </namespace-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <enum-type name='EnumA'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'>\n\
+ <enum-type name='PublicEnum'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <enum-type name='EnumA'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..94158377e
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestExtraInclude::testClassExtraInclude()
+{
+ const char* cppCode ="struct A {};\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <extra-includes>\n\
+ <include file-name='header.h' location='global'/>\n\
+ </extra-includes>\n\
+ </value-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+ AbstractMetaClassList classes = builder->classes();
+ const AbstractMetaClass *classA = AbstractMetaClass::findClass(classes, QLatin1String("A"));
+ QVERIFY(classA);
+
+ QList<Include> 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 = "\
+ <typesystem package='Foo'>\n\
+ <extra-includes>\n\
+ <include file-name='header1.h' location='global'/>\n\
+ <include file-name='header2.h' location='global'/>\n\
+ </extra-includes>\n\
+ <value-type name='A'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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);
+
+ QList<Include> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestFunctionTag::testFunctionTagForSpecificSignature()
+{
+ const char cppCode[] = "void globalFunction(int); void globalFunction(float); void dummy();\n";
+ const char xmlCode[] = "\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='float'/>\n\
+ <function signature='globalFunction(int)'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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[] = "\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='float'/>\n\
+ <function signature='globalFunction(int)'/>\n\
+ <function signature='globalFunction(float)'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <function signature='global_function_with_ugly_name()' rename='smooth'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+
+ 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 <QObject>
+
+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..4438550b2
--- /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 <abstractmetalang.h>
+#include <typesystem.h>
+#include <QtTest/QTest>
+
+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 = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ <value-type name='C'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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 = "\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'>\n\
+ <modify-function signature='A(const B&amp;)'>\n\
+ <access modifier='private'/>\n\
+ </modify-function>\n\
+ </value-type>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <custom-type name='TARGETLANGTYPE'/>\n\
+ <value-type name='A'>\n\
+ <add-function signature='A(const C&amp;)'/>\n\
+ </value-type>\n\
+ <value-type name='B'>\n\
+ <add-function signature='B(TARGETLANGTYPE*)'/>\n\
+ </value-type>\n\
+ <value-type name='C'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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\
+ <typesystem package='Foo'>\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode));
+ QVERIFY(!builder.isNull());
+ 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;
+ foreach(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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestInsertTemplate::testInsertTemplateOnClassInjectCode()
+{
+ const char* cppCode ="struct A{};\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <template name='code_template'>\n\
+ code template content\n\
+ </template>\n\
+ <value-type name='A'>\n\
+ <inject-code class='native'>\n\
+ <insert-template name='code_template'/>\n\
+ </inject-code>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <template name='code_template'>\n\
+ code template content\n\
+ </template>\n\
+ <inject-code class='native'>\n\
+ <insert-template name='code_template'/>\n\
+ </inject-code>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <inject-code class='native'>\n\
+ <insert-template name='this_code_template_does_not_exists'/>\n\
+ </inject-code>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <template name='code_template'>\n\
+ code template content\n\
+ </template>\n\
+ <inject-code class='native'>\n\
+ <insert-template name='this_code_template_does_not_exists'/>\n\
+ <insert-template name='code_template'/>\n\
+ </inject-code>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QCoreApplication>
+#include <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+#include <qtdocparser.h>
+
+void TestModifyDocumentation::testModifyDocumentation()
+{
+ const char* cppCode ="struct B { void b(); }; class A {};\n";
+ const char* xmlCode = "<typesystem package=\"Foo\">\n\
+ <value-type name='B'>\n\
+ <modify-function signature='b()' remove='all'/>\n\
+ </value-type>\n\
+ <value-type name='A'>\n\
+ <modify-documentation xpath='description/para[3]'>\n\
+ &lt;para>Some changed contents here&lt;/para>\n\
+ </modify-documentation>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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("<para>Some changed contents here</para>"));
+ 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("<?xml version=\"1.0\"?>\n\
+<description>oi\n\
+ <para>Paragraph number 1</para>\n\
+ <para>Paragraph number 2</para>\n\
+ <para>Some changed contents here</para>\n\
+</description>\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 <QObject>
+
+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..0e6bdc248
--- /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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestModifyFunction::testRenameArgument()
+{
+ const char* cppCode ="\
+ struct A {\n\
+ void method(int=0);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <object-type name='A'>\n\
+ <modify-function signature='method(int)'>\n\
+ <modify-argument index='1'>\n\
+ <rename to='otherArg'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A' />\n\
+ <object-type name='B'>\n\
+ <modify-function signature='method()'>\n\
+ <modify-argument index='return'>\n\
+ <define-ownership owner='c++'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <object-type name='A'>\n\
+ <modify-function signature='call(int*)'>\n\
+ <modify-argument index='1' invalidate-after-use='true'/>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ <object-type name='B' />\n\
+ <object-type name='C'>\n\
+ <modify-function signature='call2(int*)'>\n\
+ <modify-argument index='1' invalidate-after-use='true'/>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ <object-type name='D'>\n\
+ <modify-function signature='call2(int*)'>\n\
+ <modify-argument index='1' invalidate-after-use='true'/>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ <object-type name='E' />\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <object-type name='A' />\n\
+ <object-type name='B'>\n\
+ <modify-function signature='method()' since='0.1'>\n\
+ <modify-argument index='return'>\n\
+ <define-ownership owner='c++'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ <modify-function signature='methodB()' since='0.2'>\n\
+ <modify-argument index='return'>\n\
+ <define-ownership owner='c++'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='A'/>\n\
+ <function signature='function(A*)'>\n\
+ <modify-function signature='function(A*)'>\n\
+ <modify-argument index='1'>\n\
+ <replace-type modified-type='A'/>\n\
+ <replace-default-expression with='A()'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </function>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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);
+ QList<ArgumentModification> 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 <QObject>
+
+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..67c9089ce
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testmultipleinheritance.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "testmultipleinheritance.h"
+#include <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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 = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A' />\n\
+ <object-type name='B' />\n\
+ <object-type name='C' />\n\
+ <object-type name='D' />\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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;
+ foreach (AbstractMetaFunction* f, classD->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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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 = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='Namespace'>\n\
+ <enum-type name='Option' />\n\
+ </namespace-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+ 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 = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='OuterNamespace'>\n\
+ <namespace-type name='InnerNamespace'>\n\
+ <value-type name='SomeClass'/>\n\
+ </namespace-type>\n\
+ </namespace-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+// 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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestNestedTypes::testNestedTypesModifications()
+{
+ const char* cppCode ="\
+ namespace OuterNamespace {\n\
+ namespace InnerNamespace {\n\
+ struct SomeClass {\n\
+ void method() {}\n\
+ };\n\
+ };\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='OuterNamespace'>\n\
+ <namespace-type name='InnerNamespace'>\n\
+ <inject-code class='native'>custom_code1();</inject-code>\n\
+ <add-function signature='method()' return-type='OuterNamespace::InnerNamespace::SomeClass'>\n\
+ <inject-code class='target'>custom_code2();</inject-code>\n\
+ </add-function>\n\
+ <object-type name='SomeClass' target-lang-name='RenamedSomeClass'>\n\
+ <modify-function signature='method()' remove='all'/>\n\
+ </object-type>\n\
+ </namespace-type>\n\
+ </namespace-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='Namespace'>\n\
+ <value-type name='SomeClass'>\n\
+ <add-function signature='createSomeClass(Namespace::SomeClass)'/>\n\
+ </value-type>\n\
+ </namespace-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestNumericalTypedef::testNumericalTypedef()
+{
+ const char* cppCode ="\
+ typedef double real;\n\
+ void funcDouble(double);\n\
+ void funcReal(real);\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='double'/>\n\
+ <primitive-type name='real'/>\n\
+ <function signature='funcDouble(double)'/>\n\
+ <function signature='funcReal(real)'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='short'/>\n\
+ <primitive-type name='unsigned short'/>\n\
+ <primitive-type name='ushort'/>\n\
+ <function signature='funcUnsignedShort(unsigned short)'/>\n\
+ <function signature='funcUShort(ushort)'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestPrimitiveTypeTag::testPrimitiveTypeDefaultConstructor()
+{
+ const char* cppCode ="\
+ struct A {};\n\
+ struct B {};\n";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='A' default-constructor='A()'/>\n\
+ <object-type name='B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+
+ 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestRefCountTag::testReferenceCountTag()
+{
+ const char* cppCode ="\
+ struct A {};\n\
+ struct B {\n\
+ void keepObject(B* b);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'>\n\
+ <modify-function signature='keepObject(B*)'>\n\
+ <modify-argument index='1'>\n\
+ <reference-count action='add'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'>\n\
+ <modify-function signature='keepObject(B*, B*)'>\n\
+ <modify-argument index='1' since='0.1'>\n\
+ <reference-count action='add'/>\n\
+ </modify-argument>\n\
+ <modify-argument index='2' since='0.2'>\n\
+ <reference-count action='add'/>\n\
+ </modify-argument>\n\
+ </modify-function>\n\
+ </object-type>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestReferenceToPointer::testReferenceToPointerArgument()
+{
+ const char* cppCode ="\
+ struct A {};\n\
+ struct B {\n\
+ void dummy(A*&);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\">\n\
+ <object-type name='A'/>\n\
+ <object-type name='B'/>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+ 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestRemoveField::testRemoveField()
+{
+ const char* cppCode ="\
+ struct A {\n\
+ int fieldA;\n\
+ int fieldB;\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int'/>\n\
+ <value-type name='A'>\n\
+ <modify-field name='fieldB' remove='all'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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 <QtTest/QTest>
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+// When a constructor able to trigger implicity conversions is removed
+// it should not appear in the implicity conversion list.
+void TestRemoveImplConv::testRemoveImplConv()
+{
+ const char* cppCode ="\
+ struct A {};\n\
+ struct B {};\n\
+ struct C {\n\
+ C(const A&);\n\
+ C(const B&);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'/>\n\
+ <value-type name='B'/>\n\
+ <value-type name='C'>\n\
+ <modify-function signature='C(const A&amp;)' remove='all'/>\n\
+ </value-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..6b27227d6
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testremoveoperatormethod.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "testremoveoperatormethod.h"
+#include <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestRemoveOperatorMethod::testRemoveOperatorMethod()
+{
+ const char* cppCode ="\
+ #include <stdint.h>\n\
+ \n\
+ struct Char {};\n\
+ struct ByteArray {};\n\
+ struct String {};\n\
+ \n\
+ struct A {\n\
+ A& operator>>(char&);\n\
+ A& operator>>(char*);\n\
+ A& operator>>(short&);\n\
+ A& operator>>(unsigned short&);\n\
+ A& operator>>(int&);\n\
+ A& operator>>(unsigned int&);\n\
+ A& operator>>(int64_t&);\n\
+ A& operator>>(uint64_t&);\n\
+ A& operator>>(float&);\n\
+ A& operator>>(double&);\n\
+ A& operator>>(Char&);\n\
+ A& operator>>(ByteArray&);\n\
+ A& operator>>(String&);\n\
+ };\n";
+ const char* xmlCode = "\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='char'/>\n\
+ <primitive-type name='short'/>\n\
+ <primitive-type name='unsigned short'/>\n\
+ <primitive-type name='int'/>\n\
+ <primitive-type name='unsigned int'/>\n\
+ <primitive-type name='int64_t'/>\n\
+ <primitive-type name='uint64_t'/>\n\
+ <primitive-type name='float'/>\n\
+ <primitive-type name='double'/>\n\
+ <primitive-type name='Char'/>\n\
+ <primitive-type name='String'/>\n\
+ <value-type name='ByteArray'/>\n\
+ <object-type name='A'>\n\
+ <modify-function signature='operator&gt;&gt;(char&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(char*)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(short&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(unsigned short&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(int&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(unsigned int&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(int64_t&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(uint64_t&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(float&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(double&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(Char&amp;)' remove='all'/>\n\
+ <modify-function signature='operator&gt;&gt;(String&amp;)' remove='all'/>\n\
+ </object-type>\n\
+ </typesystem>\n";
+ QScopedPointer<AbstractMetaBuilder> 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();
+ foreach (const AbstractMetaFunction* f, classA->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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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\
+ <typesystem package='Foo'>\n\
+ <namespace-type name='A'/>\n\
+ <value-type name='A::B'/>\n\
+ <value-type name='A::B::C'/>\n\
+ <value-type name='A::D'/>\n\
+ </typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..76ba7d3b4
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testreverseoperators.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 "testreverseoperators.h"
+#include <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestReverseOperators::testReverseSum()
+{
+ const char cppCode[] = "struct A {\n\
+ A& operator+(int);\n\
+ };\n\
+ A& operator+(int, const A&);";
+ const char xmlCode[] = "\n\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int' />\n\
+ <value-type name='A' />\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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;
+ foreach(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\
+ <typesystem package=\"Foo\">\n\
+ <primitive-type name='int' />\n\
+ <value-type name='A' />\n\
+ <value-type name='B' />\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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().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;
+ foreach(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 <QObject>
+
+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..cb90383db
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testtemplates.cpp
@@ -0,0 +1,438 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** 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 <QtTest/QTest>
+#include <QTemporaryFile>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestTemplates::testTemplateWithNamespace()
+{
+ const char cppCode[] = "\n\
+ template<typename T> struct QList {}; \n\
+ struct Url {\n\
+ void name();\n\
+ };\n\
+ namespace Internet {\n\
+ struct Url{};\n\
+ struct Bookmarks {\n\
+ QList<Url> list();\n\
+ };\n\
+ }";
+ const char xmlCode0[] = "\n\
+ <typesystem package='Pakcage.Network'>\n\
+ <value-type name='Url'/>\n\
+ </typesystem>";
+
+ QTemporaryFile file;
+ QVERIFY(file.open());
+ file.write(xmlCode0);
+ file.close();
+
+ QString xmlCode1 = QString::fromLatin1("\n\
+ <typesystem package='Package.Internet'>\n\
+ <load-typesystem name='%1' generate='no'/>\n\
+ <container-type name='QList' type='list'/>\n\
+ <namespace-type name='Internet' generate='no'/>\n\
+ <value-type name='Internet::Url'/>\n\
+ <value-type name='Internet::Bookmarks'/>\n\
+ </typesystem>").arg(file.fileName());
+
+ QScopedPointer<AbstractMetaBuilder> 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<Internet::Url >"));
+}
+
+void TestTemplates::testTemplateOnContainers()
+{
+ const char cppCode[] = "\n\
+ struct Base {};\n\
+ template<typename T> struct QList {}; \n\
+ namespace Namespace {\n\
+ enum SomeEnum { E1, E2 };\n\
+ template<SomeEnum type> struct A {\n\
+ A<type> foo(const QList<A<type> >& a);\n\
+ };\n\
+ typedef A<E1> B;\n\
+ }\n\
+ ";
+ const char xmlCode[] = "\n\
+ <typesystem package=\"Package\">\n\
+ <container-type name='QList' type='list'/>\n\
+ <namespace-type name='Namespace'/>\n\
+ <enum-type name='Namespace::SomeEnum'/>\n\
+ <object-type name='Base'/>\n\
+ <object-type name='Namespace::A' generate='no'/>\n\
+ <object-type name='Namespace::B'/>\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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<typename T> struct List {};\n\
+ void func(List<int> arg) {}\n\
+ ";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <primitive-type name='int'/>\n\
+ <container-type name='List' type='list'/>\n\
+ <function signature='func(List&lt;int&gt;)'/>\n\
+ </typesystem>\n\
+ ";
+
+ QScopedPointer<AbstractMetaBuilder> 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<int>)"));
+ QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int >"));
+}
+
+void TestTemplates::testTemplatePointerAsArgument()
+{
+ const char cppCode[] = "\n\
+ template<typename T> struct List {};\n\
+ void func(List<int>* arg) {}\n\
+ ";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <primitive-type name='int'/>\n\
+ <container-type name='List' type='list'/>\n\
+ <function signature='func(List&lt;int&gt;*)'/>\n\
+ </typesystem>\n\
+ ";
+
+ QScopedPointer<AbstractMetaBuilder> 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<int>*)"));
+ QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int > *"));
+}
+
+void TestTemplates::testTemplateReferenceAsArgument()
+{
+ const char cppCode[] = "\n\
+ template<typename T> struct List {};\n\
+ void func(List<int>& arg) {}\n\
+ ";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <primitive-type name='int'/>\n\
+ <container-type name='List' type='list'/>\n\
+ <function signature='func(List&lt;int&gt;&amp;)'/>\n\
+ </typesystem>\n\
+ ";
+
+ QScopedPointer<AbstractMetaBuilder> 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<int>&)"));
+ QCOMPARE(func->arguments().first()->type()->cppSignature(), QLatin1String("List<int > &"));
+}
+
+void TestTemplates::testTemplateParameterFixup()
+{
+ const char cppCode[] = "\n\
+ template<typename T>\n\
+ struct List {\n\
+ struct Iterator {};\n\
+ void append(List l);\n\
+ void erase(List::Iterator it);\n\
+ };\n";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <container-type name='List' type='list'/>\n\
+ <value-type name='List::Iterator'/>\n\
+ </typesystem>\n";
+
+ QScopedPointer<AbstractMetaBuilder> 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<T >"
+ const AbstractMetaFunction *append = list->findFunction(QStringLiteral("append"));
+ QVERIFY(append);
+ QCOMPARE(append->arguments().size(), 1);
+ QCOMPARE(append->arguments().at(0)->type()->cppSignature(), QLatin1String("List<T >"));
+ // 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);
+ QCOMPARE(erase->arguments().at(0)->type()->cppSignature(), QLatin1String("List::Iterator"));
+}
+
+void TestTemplates::testInheritanceFromContainterTemplate()
+{
+ const char cppCode[] = "\n\
+ template<typename T>\n\
+ struct ListContainer {\n\
+ inline void push_front(const T& t);\n\
+ inline T& front();\n\
+ };\n\
+ struct FooBar {};\n\
+ struct FooBars : public ListContainer<FooBar> {};\n\
+ ";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <container-type name='ListContainer' type='list'/>\n\
+ <value-type name='FooBar'/>\n\
+ <value-type name='FooBars'>\n\
+ <modify-function signature='push_front(FooBar)' remove='all'/>\n\
+ <modify-function signature='front()' remove='all'/>\n\
+ </value-type>\n\
+ </typesystem>\n\
+ ";
+
+ QScopedPointer<AbstractMetaBuilder> 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<SomeEnum type> struct Future;\n\
+ template<SomeEnum type>\n\
+ struct A {\n\
+ A();\n\
+ void method();\n\
+ friend struct Future<type>;\n\
+ };\n\
+ typedef A<E1> B;\n\
+ template<SomeEnum type> struct Future {};\n\
+ ";
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <enum-type name='SomeEnum'/>\n\
+ <value-type name='A' generate='no'/>\n\
+ <value-type name='B'/>\n\
+ <value-type name='Future' generate='no'/>\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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<SomeEnum type> struct Future;\n\
+ template<SomeEnum type>\n\
+ struct A {\n\
+ A();\n\
+ void method();\n\
+ friend struct Future<type>;\n\
+ };\n\
+ typedef A<E1> B;\n\
+ template<SomeEnum type> struct Future {};\n\
+ };\n\
+ ";
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <namespace-type name='Namespace'/>\n\
+ <enum-type name='Namespace::SomeEnum'/>\n\
+ <value-type name='Namespace::A' generate='no'/>\n\
+ <value-type name='Namespace::B'/>\n\
+ <value-type name='Namespace::Future' generate='no'/>\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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<ClassType CLASS_TYPE>\n\
+ struct BaseTemplateClass {\n\
+ inline ClassType getClassType() const { CLASS_TYPE; }\n\
+ };\n\
+ typedef BaseTemplateClass<TypeOne> TypeOneClass;\n\
+ }\n\
+ ";
+
+ const char xmlCode[] = "\n\
+ <typesystem package='Package'>\n\
+ <namespace-type name='NSpace'>\n\
+ <enum-type name='ClassType'/>\n\
+ <object-type name='BaseTemplateClass' generate='no'/>\n\
+ <object-type name='TypeOneClass'/>\n\
+ </namespace-type>\n\
+ </typesystem>\n\
+ ";
+
+ QScopedPointer<AbstractMetaBuilder> 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<TypeOne>")));
+
+ 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<typename T>\n\
+ class Vector {\n\
+ void method(const Vector& vector);\n\
+ Vector otherMethod();\n\
+ };\n\
+ template <typename T>\n\
+ void Vector<T>::method(const Vector<T>& vector) {}\n\
+ template <typename T>\n\
+ Vector<T> Vector<T>::otherMethod() { return Vector<T>(); }\n\
+ typedef Vector<int> IntVector;\n\
+ ";
+ const char* xmlCode = "\n\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int'/>\n\
+ <container-type name='Vector' type='vector'/>\n\
+ <value-type name='IntVector'/>\n\
+ </typesystem>";
+
+ QScopedPointer<AbstractMetaBuilder> 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<const ContainerTypeEntry*>(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<int > & vector)"));
+
+ const AbstractMetaFunction* otherMethod = vector->findFunction(QLatin1String("otherMethod"));
+ QVERIFY(otherMethod);
+ QCOMPARE(otherMethod->signature(), QLatin1String("otherMethod()"));
+ QVERIFY(otherMethod->type());
+ QCOMPARE(otherMethod->type()->cppSignature(), QLatin1String("Vector<int >"));
+}
+
+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 <QObject>
+
+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 <QtTest/QTest>
+#include "graph.h"
+#include <QDebug>
+
+void TestTopoSort::testTopoSort()
+{
+ QLinkedList<int> result;
+ {
+ Graph g(3);
+ g.addEdge(1, 2);
+ g.addEdge(0, 1);
+ result = g.topologicalSort();
+ QCOMPARE(result.size(), 3);
+ QLinkedList<int>::iterator it = result.begin();
+ QCOMPARE(*it, 0);
+ QCOMPARE(*(++it), 1);
+ QCOMPARE(*(++it), 2);
+ }
+ {
+ Graph g(2);
+ result = g.topologicalSort();
+ QCOMPARE(result.size(), 2);
+ QLinkedList<int>::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<int> 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+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 = "<typesystem package=\"Foo\">"
+ "<value-type name=\"Rev_0\"/>"
+ "<value-type name=\"Rev_1\" revision=\"1\"/>"
+ "<object-type name=\"Rev_2\" revision=\"2\">"
+ " <enum-type name=\"Rev_3\" revision=\"3\" flags=\"Flag_4\" flags-revision=\"4\" />"
+ " <enum-type name=\"Rev_5\" revision=\"5\" flags=\"Flag_5\" />"
+ "</object-type>"
+ "</typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..d4eb2fdf6
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/tests/testutil.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 TESTUTIL_H
+#define TESTUTIL_H
+#include <QtCore/QBuffer>
+#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
+ buffer.setData(cppCode);
+ AbstractMetaBuilder *builder = new AbstractMetaBuilder;
+ if (!builder->build(&buffer)) {
+ 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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestValueTypeDefaultCtorTag::testValueTypeDefaultCtorTagArgument()
+{
+ const char* cppCode ="\n\
+ struct A {\n\
+ A(int,int);\n\
+ };\n\
+ struct B {};\n\
+ ";
+ const char* xmlCode = "\n\
+ <typesystem package='Foo'>\n\
+ <primitive-type name='int' />\n\
+ <value-type name='A' default-constructor='A(0, 0)' />\n\
+ <value-type name='B' />\n\
+ </typesystem>";
+ QScopedPointer<AbstractMetaBuilder> builder(TestUtil::parse(cppCode, xmlCode, false));
+ QVERIFY(!builder.isNull());
+
+ 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 <QObject>
+
+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 <QtTest/QTest>
+#include "testutil.h"
+#include <abstractmetalang.h>
+#include <typesystem.h>
+
+void TestVoidArg::testVoidParsedFunction()
+{
+ const char cppCode[] = "struct A { void a(void); };";
+ const char xmlCode[] = "\n\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A'/>\n\
+ </typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A' >\n\
+ <add-function signature=\"a(void)\"/>\n\
+ </value-type>\n\
+ </typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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\
+ <typesystem package=\"Foo\">\n\
+ <value-type name='A' />\n\
+ </typesystem>";
+ QScopedPointer<AbstractMetaBuilder> 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 <QObject>
+
+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..55170d7c1
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typedatabase.cpp
@@ -0,0 +1,699 @@
+/****************************************************************************
+**
+** 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 <QtCore/QFile>
+#include <QtCore/QDir>
+#include <QtCore/QPair>
+#include <QtCore/QVector>
+#include <QtCore/QRegularExpression>
+#include <QtCore/QVersionNumber>
+#include <QtCore/QXmlStreamReader>
+#include "reporthandler.h"
+// #include <tr1/tuple>
+#include <algorithm>
+
+// package -> api-version
+
+static QString wildcardToRegExp(QString w)
+{
+ w.replace(QLatin1Char('?'), QLatin1Char('.'));
+ w.replace(QLatin1Char('*'), QStringLiteral(".*"));
+ return w;
+}
+
+typedef QPair<QRegularExpression, QVersionNumber> ApiVersion;
+typedef QVector<ApiVersion> 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<IntTypeNormalizationEntry> 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<ContainerTypeEntry*>(type_entry);
+ return 0;
+}
+
+FunctionTypeEntry* TypeDatabase::findFunctionType(const QString& name) const
+{
+ TypeEntry* entry = findType(name);
+ if (entry && entry->type() == TypeEntry::FunctionType)
+ return static_cast<FunctionTypeEntry*>(entry);
+ return 0;
+}
+
+TypeEntry* TypeDatabase::findType(const QString& name) const
+{
+ QList<TypeEntry *> entries = findTypes(name);
+ foreach (TypeEntry *entry, entries) {
+ if (entry &&
+ (!entry->isPrimitive() || static_cast<PrimitiveTypeEntry *>(entry)->preferredTargetLangType())) {
+ return entry;
+ }
+ }
+ return 0;
+}
+
+QList<TypeEntry *> 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;
+}
+
+QList<const PrimitiveTypeEntry*> TypeDatabase::primitiveTypes() const
+{
+ TypeEntryHash entries = allEntries();
+ QList<const PrimitiveTypeEntry*> returned;
+ for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
+ foreach (TypeEntry *typeEntry, it.value()) {
+ if (typeEntry->isPrimitive())
+ returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry));
+ }
+ }
+ return returned;
+}
+
+QList<const ContainerTypeEntry*> TypeDatabase::containerTypes() const
+{
+ TypeEntryHash entries = allEntries();
+ QList<const ContainerTypeEntry*> returned;
+ for (TypeEntryHash::const_iterator it = entries.cbegin(), end = entries.cend(); it != end; ++it) {
+ foreach (TypeEntry *typeEntry, it.value()) {
+ if (typeEntry->isContainer())
+ returned.append(static_cast<ContainerTypeEntry *>(typeEntry));
+ }
+ }
+ return returned;
+}
+void TypeDatabase::addRejection(const QString& className, const QString& functionName,
+ const QString& fieldName, const QString& enumName)
+{
+ TypeRejection r;
+ r.class_name = className;
+ r.function_name = functionName;
+ r.field_name = fieldName;
+ r.enum_name = enumName;
+
+ m_rejections << r;
+}
+
+bool TypeDatabase::isClassRejected(const QString& className) const
+{
+ foreach (const TypeRejection& r, m_rejections) {
+ if (r.class_name == className && r.function_name == QLatin1String("*")
+ && r.field_name == QLatin1String("*") && r.enum_name == QLatin1String("*")) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool TypeDatabase::isEnumRejected(const QString& className, const QString& enumName) const
+{
+ foreach (const TypeRejection& r, m_rejections) {
+ if (r.enum_name == enumName
+ && (r.class_name == className || r.class_name == QLatin1String("*"))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void TypeDatabase::addType(TypeEntry *e)
+{
+ m_entries[e->qualifiedCppName()].append(e);
+}
+
+bool TypeDatabase::isFunctionRejected(const QString& className, const QString& functionName) const
+{
+ foreach (const TypeRejection& r, m_rejections)
+ if (r.function_name == functionName &&
+ (r.class_name == className || r.class_name == QLatin1String("*")))
+ return true;
+ return false;
+}
+
+
+bool TypeDatabase::isFieldRejected(const QString& className, const QString& fieldName) const
+{
+ foreach (const TypeRejection& r, m_rejections)
+ if (r.field_name == fieldName &&
+ (r.class_name == className || r.class_name == QLatin1String("*")))
+ return true;
+ return false;
+}
+
+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<FlagsTypeEntry *>(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;
+ foreach (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;
+
+ foreach (const QString &_warning, m_suppressedWarnings) {
+ QString warning = _warning;
+ 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();
+ foreach (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
+{
+ QList<TypeEntry*> entries = findTypes(name);
+
+ foreach (TypeEntry* entry, entries) {
+ if (entry && entry->isPrimitive() && static_cast<PrimitiveTypeEntry*>(entry)->preferredTargetLangType())
+ return static_cast<PrimitiveTypeEntry*>(entry);
+ }
+
+ return 0;
+}
+
+ComplexTypeEntry* TypeDatabase::findComplexType(const QString& name) const
+{
+ QList<TypeEntry*> entries = findTypes(name);
+ foreach (TypeEntry* entry, entries) {
+ if (entry && entry->isComplex())
+ return static_cast<ComplexTypeEntry*>(entry);
+ }
+ return 0;
+}
+
+ObjectTypeEntry* TypeDatabase::findObjectType(const QString& name) const
+{
+ QList<TypeEntry*> entries = findTypes(name);
+ foreach (TypeEntry* entry, entries) {
+ if (entry && entry->isObject())
+ return static_cast<ObjectTypeEntry*>(entry);
+ }
+ return 0;
+}
+
+NamespaceTypeEntry* TypeDatabase::findNamespaceType(const QString& name) const
+{
+ QList<TypeEntry*> entries = findTypes(name);
+ foreach (TypeEntry* entry, entries) {
+ if (entry && entry->isNamespace())
+ return static_cast<NamespaceTypeEntry*>(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<const TypeEntry*, std::pair<int, int> > 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<int, QList<TypeEntry*> > GroupedTypeEntries;
+ GroupedTypeEntries groupedEntries;
+
+ // Group type entries by revision numbers
+ TypeEntryHash allEntries = tdb->allEntries();
+ foreach (QList<TypeEntry*> entryList, allEntries) {
+ foreach (TypeEntry* entry, entryList) {
+ 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
+ QList<TypeEntry*>::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);
+
+ foreach (TypeEntry* entry, 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..4255cf458
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typedatabase.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** 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 "typesystem_enums.h"
+#include "typesystem_typedefs.h"
+
+#include <QtCore/QStringList>
+
+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;
+
+ QList<const PrimitiveTypeEntry*> primitiveTypes() const;
+
+ QList<const ContainerTypeEntry*> containerTypes() const;
+
+ void addRejection(const QString& className, const QString& functionName,
+ const QString& fieldName, const QString& enumName);
+ bool isClassRejected(const QString& className) const;
+ bool isFunctionRejected(const QString& className, const QString& functionName) const;
+ bool isFieldRejected(const QString& className, const QString& fieldName) const;
+ bool isEnumRejected(const QString& className, const QString& enumName) 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:
+ QList<TypeEntry *> 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<QString, bool> m_parsedTypesystemFiles;
+
+ QList<TypeRejection> 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/typeparser.cpp b/sources/shiboken2/ApiExtractor/typeparser.cpp
new file mode 100644
index 000000000..67120a1ac
--- /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 <QtCore/QDebug>
+#include <QtCore/QStack>
+#include <QtCore/QTextStream>
+
+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<Info *> 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;
+ foreach (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..9ccd0992c
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typeparser.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** 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 <QtCore/QList>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+
+class TypeParser
+{
+public:
+ struct Info
+ {
+ Info() : referenceType(NoReference), is_constant(false), is_busted(false), indirections(0) { }
+ QStringList qualified_name;
+ QStringList arrays;
+ QList<Info> 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..869904d43
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typesystem.cpp
@@ -0,0 +1,2667 @@
+/****************************************************************************
+**
+** 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 <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QXmlStreamAttributes>
+#include <QtCore/QXmlStreamReader>
+
+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 QList<CustomConversion*> customConversionsForReview = QList<CustomConversion*>();
+
+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<const QFile *>(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<QString, QString> *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);
+ foreach (CustomConversion* customConversion, customConversionsForReview) {
+ foreach (CustomConversion::TargetToNativeConversion* toNative, customConversion->targetToNativeConversions())
+ toNative->setSourceType(m_database->findType(toNative->sourceTypeName()));
+ }
+ }
+ break;
+ case StackElement::ObjectTypeEntry:
+ case StackElement::ValueTypeEntry:
+ case StackElement::InterfaceTypeEntry:
+ case StackElement::NamespaceTypeEntry: {
+ ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(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<TypeEntry*>(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 <class String> // 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 QRegExp whiteSpace(QLatin1String("\\s"));
+ 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<QString, QString> &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<QString, QString> &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<QString, StackElement::ElementType>::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<QString, QString> 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 QRegExp functionNameRegExp(QLatin1String("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ if (!functionNameRegExp.exactMatch(rename)) {
+ 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()) {
+ foreach (const QString &flagName, flagNames.split(QLatin1Char(',')))
+ 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<ComplexTypeEntry *>(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<ComplexTypeEntry *>(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<FunctionTypeEntry*>(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<QString, QString> 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<QString, TypeSystem::Language> 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<QString, QString> 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<QString, QString> 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(QLatin1String("class"), QLatin1String("*"));
+ attributes.insert(QLatin1String("function-name"), QLatin1String("*"));
+ attributes.insert(QLatin1String("field-name"), QLatin1String("*"));
+ attributes.insert(QLatin1String("enum-name"), QLatin1String("*"));
+ 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<TypeSystemTypeEntry*>(
+ 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("<reject-enum-value> node must be used inside a <enum-type> 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<QString, TypeSystem::Language> 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<TypeEntry*>(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<TypeEntry*>(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<TypeEntry*>(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<QString, TypeSystem::Language> 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<QString, TypeSystem::Ownership> 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<QString, TypeSystem::Language> 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<QString, FunctionModification::Modifiers> 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<QString, ReferenceCount::Action> 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:");
+ foreach (const QString &action, actions.keys())
+ m_error += QLatin1Char(' ') + action;
+ }
+
+ 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<QString, ArgumentOwner::Action> 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<QString, TypeSystem::Language> 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<QString, TypeSystem::CodeSnipPosition> 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<QString, Include::IncludeType> 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<ComplexTypeEntry *>(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: {
+ QString cls = attributes[QLatin1String("class")];
+ QString function = attributes[QLatin1String("function-name")];
+ QString field = attributes[QLatin1String("field-name")];
+ QString enum_ = attributes[QLatin1String("enum-name")];
+ if (cls == QLatin1String("*") && function == QLatin1String("*") && field == QLatin1String("*") && enum_ == QLatin1String("*")) {
+ m_error = QLatin1String("bad reject entry, neither 'class', 'function-name' nor "
+ "'field' specified");
+ return false;
+ }
+ m_database->addRejection(cls, function, field, enum_);
+ }
+ 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<const PrimitiveTypeEntry*, QString> 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<const ComplexTypeEntry*, QString> 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<QString, QString>::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;
+ foreach (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) {
+ foreach (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;
+ QRegExp regex(QLatin1String("\\w"));
+ 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<const PrimitiveTypeEntry *>(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<const TypeEntry*, CustomConversion*> 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()
+{
+ foreach (TargetToNativeConversion* targetToNativeConversion, m_d->targetToNativeConversions)
+ delete targetToNativeConversion;
+ m_d->targetToNativeConversions.clear();
+ 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..a8ee0ced4
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typesystem.h
@@ -0,0 +1,1947 @@
+/****************************************************************************
+**
+** 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 <QtCore/QHash>
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QMap>
+
+//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 QTextStream;
+QT_END_NAMESPACE
+
+class EnumTypeEntry;
+class FlagsTypeEntry;
+
+typedef QMap<int, QString> 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(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));
+ }
+
+ QList<CodeSnipFragment> 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<QString, QString> replaceRules;
+};
+
+
+class CodeSnip : public CodeSnipAbstract
+{
+public:
+ 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(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
+ QList<ReferenceCount> 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<TypeSystem::Language, TypeSystem::Ownership> 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(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;
+
+ QList<ArgumentModification> argument_mods;
+
+private:
+ FunctionModification() {}
+
+ 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);
+
+ /// 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.
+ QList<TypeInfo> 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;
+ QList<TypeInfo> 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(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)
+ {
+ 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<QString, bool> 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
+ {
+ return m_nestedType->targetLangName() + QLatin1String("[]");
+ }
+ QString targetLangApiName() const
+ {
+ 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
+ {
+ return m_targetLangName;
+ }
+ void setTargetLangName(const QString &targetLangName)
+ {
+ m_targetLangName = targetLangName;
+ }
+
+ QString targetLangApiName() const
+ {
+ 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;
+
+ virtual bool preferredConversion() const
+ {
+ return m_preferredConversion;
+ }
+ virtual void setPreferredConversion(bool b)
+ {
+ m_preferredConversion = b;
+ }
+
+ virtual bool preferredTargetLangType() const
+ {
+ return m_preferredTargetLangType;
+ }
+ virtual void setPreferredTargetLangType(bool b)
+ {
+ m_preferredTargetLangType = b;
+ }
+
+ void setTargetLangPackage(const QString& package);
+ QString targetLangPackage() const;
+private:
+ QString m_targetLangName;
+ QString m_targetLangApiName;
+ QString m_defaultConstructor;
+ uint m_preferredConversion : 1;
+ uint m_preferredTargetLangType : 1;
+ PrimitiveTypeEntry* m_referencedTypeEntry;
+};
+
+struct 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
+ {
+ 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;
+
+ QString qualifier() const
+ {
+ return m_qualifier;
+ }
+ void setQualifier(const QString &q)
+ {
+ m_qualifier = q;
+ }
+
+ virtual bool preferredConversion() const
+ {
+ 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;
+ QList<EnumValueRedirection> 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;
+ QString targetLangName() const
+ {
+ return m_targetLangName;
+ }
+ QString targetLangApiName() const;
+ virtual bool preferredConversion() const
+ {
+ 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
+ {
+ 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<TypeFlag> 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;
+ }
+
+ virtual QString lookupName() const
+ {
+ return m_lookupName.isEmpty() ? targetLangName() : m_lookupName;
+ }
+
+ QString targetLangApiName() const;
+
+ 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;
+ }
+
+ virtual QString qualifiedCppName() const
+ {
+ 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
+ {
+ 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<QString, Type> 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
+ {
+ return true;
+ }
+
+ virtual bool isNativeIdBased() const
+ {
+ 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;
+ QString targetLangName() const;
+ QString targetLangPackage() const;
+
+ virtual bool isNativeIdBased() const
+ {
+ return false;
+ }
+};
+
+class CharTypeEntry : public ValueTypeEntry
+{
+public:
+ CharTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, CharType, vr)
+ {
+ setCodeGeneration(GenerateNothing);
+ }
+
+ QString targetLangApiName() const;
+ QString targetLangName() const;
+ QString targetLangPackage() const
+ {
+ return QString();
+ }
+
+ virtual bool isNativeIdBased() const
+ {
+ return false;
+ }
+};
+
+class VariantTypeEntry: public ValueTypeEntry
+{
+public:
+ VariantTypeEntry(const QString &name, double vr) : ValueTypeEntry(name, VariantType, vr) { }
+
+ QString targetLangApiName() const;
+ QString targetLangName() const;
+ QString targetLangPackage() const;
+
+ virtual bool isNativeIdBased() const
+ {
+ 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;
+ }
+
+ virtual bool isNativeIdBased() const
+ {
+ return true;
+ }
+ virtual QString qualifiedCppName() const
+ {
+ 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;
+ }
+
+ virtual bool isNativeIdBased() const
+ {
+ return true;
+ }
+
+private:
+ InterfaceTypeEntry *m_interface;
+};
+
+struct TypeRejection
+{
+ QString class_name;
+ QString function_name;
+ QString field_name;
+ QString enum_name;
+};
+
+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 QList<TargetToNativeConversion*> 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 <QStack>
+#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<QString, QString> &attributes,
+ const QString &name,
+ double since);
+ bool endElement(const QStringRef& localName);
+ template <class String> // QString/QStringRef
+ bool characters(const String &ch);
+ void fetchAttributeValues(const QString &name, const QXmlStreamAttributes &atts,
+ QHash<QString, QString> *acceptedAttributes);
+
+ bool importFileElement(const QXmlStreamAttributes &atts);
+ bool convertBoolean(const QString &, const QString &, bool);
+ void addFlags(const QString &name, QString flagName,
+ const QHash<QString, QString> &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<StackElementContext*> m_contextStack;
+
+ QHash<QString, StackElement::ElementType> 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..04b669655
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/typesystem_typedefs.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 TYPESYSTEM_TYPEDEFS_H
+#define TYPESYSTEM_TYPEDEFS_H
+
+#include <QtCore/QHash>
+#include <QtCore/QList>
+
+class CodeSnip;
+class ContainerTypeEntry;
+class DocModification;
+class PrimitiveTypeEntry;
+class TemplateEntry;
+class TypeEntry;
+
+struct AddedFunction;
+struct FieldModification;
+struct FunctionModification;
+
+typedef QHash<QString, QList<TypeEntry *> > TypeEntryHash;
+typedef QHash<QString, TypeEntry *> SingleTypeEntryHash;
+typedef QHash<QString, TemplateEntry *> TemplateEntryHash;
+
+typedef QList<AddedFunction> AddedFunctionList;
+typedef QList<CodeSnip> CodeSnipList;
+typedef QList<const ContainerTypeEntry *> ContainerTypeEntryList;
+typedef QList<DocModification> DocModificationList;
+typedef QList<FieldModification> FieldModificationList;
+typedef QList<FunctionModification> FunctionModificationList;
+typedef QList<const PrimitiveTypeEntry *> PrimitiveTypeEntryList;
+
+#endif // TYPESYSTEM_TYPEDEFS_H
diff --git a/sources/shiboken2/CMakeLists.txt b/sources/shiboken2/CMakeLists.txt
new file mode 100644
index 000000000..96d4ec5cc
--- /dev/null
+++ b/sources/shiboken2/CMakeLists.txt
@@ -0,0 +1,244 @@
+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()
+
+## 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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. <http://fsf.org/>
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+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:
+
+ <program> Copyright (C) <year> <name of author>
+ 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
+<http://www.gnu.org/licenses/>.
+
+ 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
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
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.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ 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.
+
+ <signature of Ty Coon>, 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. <http://fsf.org/>
+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=<plugin name> [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=<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="<TypeEntry0>[;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=<file>
+Text file containing a description of the binding project. Replaces and overrides command line arguments.
+.IP \-\-include\-paths=\fI<path>[: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>[: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 <lauro.neto at openbossa dot org>, Bruno Araujo <bruno.araujo at openbossa dot org>, Hugo Lima <hugo.lima at openbossa dot org>
+
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 %}
+<div class="section">
+ <h1>{{ project }} {{ version }}</h1>
+
+ <p>{{ project }} is a plugin (front-end) for Generator Runner. It generates bindings for C++ libraries using CPython source code.</p>
+
+ <h2>Documentation</h2>
+ <table class="contentstable" align="center" style="margin-left: 30px"><tr>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Contents</a><br/>
+ <span class="linkdescr">for a complete overview</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("faq") }}">FAQ</a><br/>
+ <span class="linkdescr">answers for frequent asked questions</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("commandlineoptions") }}">Command line options</a><br/>
+ <span class="linkdescr">explains the few flags used to change {{ project }} behaviour</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("typesystemvariables") }}">Type System Variables</a><br/>
+ <span class="linkdescr">describes the type system variables that could be used in user custom code</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("typeconverters") }}">Type Converters</a><br/>
+ <span class="linkdescr">describes how to define type converters</span></p>
+ </td>
+ <td width="50%">
+ <p class="biglink"><a class="biglink" href="{{ pathto("codeinjectionsemantics") }}">Code Injection Semantics</a><br/>
+ <span class="linkdescr">explains how custom code injection is interpreted by {{ project }}</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("sequenceprotocol") }}">Sequence Protocol</a><br/>
+ <span class="linkdescr">support for python sequence protocol</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("ownership") }}">Object Ownership</a><br/>
+ <span class="linkdescr">object ownership features</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("wordsofadvice") }}">Words of Advice</a><br/>
+ <span class="linkdescr">Advice for binding developers and users.</span></p>
+ </td></tr>
+ </table>
+</div>
+{% 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 %}
+<div id="container">
+<div class="header">
+ <div class="header_container">
+ <div class="logo"><a href="http://www.pyside.org"><img alt="PySide" src="{{ pathto('_static/pysidelogo.png', 1) }}" width="199" height="102" /></a></div>
+ {{ relbar() }}
+ </div>
+</div>
+{%- endblock -%}
+
+{%- block footer %}
+ <div class="footer">
+ <a href="http://www.qt.io/"><img src="{{ pathto('_static/logo_qt.png', 1) }}" alt="Qt" border="0" /></a>
+ <a href="http://www.python.org"><img src="{{ pathto('_static/logo_python.jpg', 1) }}" alt="Python" border="0" /></a>
+ </div>
+</div>
+{%- 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" %}
+<div id="searchbox" style="display: none">
+ <h3>{{ _('Quick search') }}</h3>
+ <form class="search" action="{{ pathto('search') }}" method="get">
+ <input type="text" name="q" id="q" size="18" />
+ <input type="submit" value="{{ _('Go') }}" id="search_button" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+</div>
+<script type="text/javascript">$('#searchbox').show(0);</script>
+{%- 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_header.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/bg_topo.jpg
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/fakebar.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_python.jpg
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/logo_qt.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/pysidelogo.png
Binary files 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
--- /dev/null
+++ b/sources/shiboken2/doc/_themes/pysidedocs/static/relbar_bg.png
Binary files 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
+<http://www.pyside.org/docs/apiextractor/typesystem_manipulating_objects.html#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
+
+ <inject-code class="native | target" position="beginning | end">
+ // custom code
+ </inject-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
+
+ <inject-code class="target" position="beginning | end">
+ %CPPSELF.originalMethodName();
+ </inject-code>
+
+
+instead of
+
+
+ .. code-block:: xml
+
+ <inject-code class="target" position="beginning | end">
+ %CPPSELF.%FUNCTION_NAME();
+ </inject-code>
+
+
+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: <modify-function><inject-code class="native" position="beginning">
+ // Uses: pre method call custom code, modify the argument before the
+ // Python call.
+
+ (... Python method call goes in here ...)
+
+ // INJECT-CODE: <modify-function><inject-code class="native" position="end">
+ // Uses: post method call custom code, modify the result before delivering
+ // it to C++ caller.
+
+ (... Python method and argument tuple are dereferenced here ...)
+
+ return Shiboken::Converter<int>::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<double >::toCpp(arg);
+
+ // INJECT-CODE: <modify-function><inject-code class="target" position="beginning">
+ // Uses: pre method call custom code.
+
+ py_result = Shiboken::Converter<double >::toPython(
+ PyInjectCode_cptr(self)->InjectCode::overloadedMethod(cpp_arg0)
+ );
+
+ // INJECT-CODE: <modify-function><inject-code class="target" position="end">
+ // Uses: post method call custom code.
+
+ } else if (PyNumber_Check(arg)) {
+ (... other overload calling code ...)
+ } else goto PyInjectCode_overloadedMethod_TypeError;
+
+ 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 <shiboken.h>
+ (...)
+ #include "injectcode_wrapper.h"
+ using namespace Shiboken;
+
+ // INJECT-CODE: <value/object-type><inject-code class="native" position="beginning">
+ // Uses: prototype declarations
+
+ (... C++ wrapper virtual methods, if any ...)
+
+ (... Python wrapper code ...)
+
+ PyAPI_FUNC(void)
+ init_injectcode(PyObject *module)
+ {
+ (...)
+ }
+
+ (...)
+
+ // INJECT-CODE: <value/object-type><inject-code class="native" position="end">
+ // Uses: definition of functions prototyped at ``native/beginning``.
+
+ // End of ``CLASSNAME_wrapper.cpp``
+
+
+.. _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: <value/object-type><inject-code class="target" position="beginning">
+ // Uses: Alter something in the PyInjectCode_Type (tp_flags value for example)
+ // before registering it.
+
+ if (PyType_Ready(&PyInjectCode_Type) < 0)
+ return;
+
+ Py_INCREF(&PyInjectCode_Type);
+ PyModule_AddObject(module, "InjectCode",
+ ((PyObject*)&PyInjectCode_Type));
+
+ // INJECT-CODE: <value/object-type><inject-code class="target" position="end">
+ // Uses: do something right after the class is registered, like set some static
+ // variable injected on this same file elsewhere.
+ }
+
+ (...)
+
+ // 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: <typesystem><inject-code class="target" position="beginning">
+ // 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: <typesystem><inject-code class="target" position="end">
+ // Uses: do something after the module is registered and initialized.
+
+ if (PyErr_Occurred())
+ Py_FatalError("can't initialize module sample");
+ }
+
+ (...)
+
+ // 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=<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="<TypeEntry0>[;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=<path>[:<path>:...]``
+ 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=<path>[:<path>:...]``
+ 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
+# "<project> v<release> 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 <link> 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="800"
+ height="340"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="dependency-pyqtb.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/var/www/lauro/dependency-pyqtb.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3270"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3679"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3480"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3498"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3541"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0425"
+ inkscape:cx="400"
+ inkscape:cy="170"
+ inkscape:document-units="px"
+ inkscape:current-layer="g3995"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1280"
+ inkscape:window-height="951"
+ inkscape:window-x="0"
+ inkscape:window-y="25" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-94.976306,-355.09425)" />
+ <g
+ id="g4087"
+ transform="translate(2.4157429e-6,1.9999951)">
+ <g
+ id="g3995"
+ transform="translate(6,-3.2661035e-8)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.66823119px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1"
+ d="M 281.95594,47.06539 L 314.12853,47.06538"
+ id="path2877"
+ inkscape:connector-type="polyline" />
+ <g
+ id="g3801"
+ transform="translate(-9.3125054,-154.20033)">
+ <rect
+ y="286.49988"
+ x="322.2547"
+ height="73.367416"
+ width="194.85175"
+ id="rect3595"
+ style="fill:#9ac5ff;fill-opacity:1;fill-rule:evenodd;stroke:#003378;stroke-width:0.8142156;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ ry="10.318988"
+ rx="8.598484" />
+ <g
+ transform="translate(1.7229236,-30.915768)"
+ id="g3599">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="336.95081"
+ id="text2443"><tspan
+ sodipodi:role="line"
+ id="tspan2445"
+ x="329.46826"
+ y="336.95081">API Extractor</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="352.61548"
+ id="text2447"><tspan
+ sodipodi:role="line"
+ id="tspan2449"
+ x="329.46826"
+ y="352.61548">0.2</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="368.15546"
+ id="text2451"><tspan
+ sodipodi:role="line"
+ x="329.46826"
+ y="368.15546"
+ id="tspan2453">Headers and libraries - compile-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="383.47839"
+ id="text2455"><tspan
+ sodipodi:role="line"
+ id="tspan2457"
+ x="329.46826"
+ y="383.47839">LGPL version 2.1</tspan></text>
+ </g>
+ </g>
+ <g
+ id="g3729"
+ transform="translate(-9.3125054,-153.6367)">
+ <rect
+ y="164.01837"
+ x="322.2547"
+ height="73.367416"
+ width="194.85175"
+ id="rect2459"
+ style="fill:#9ac5ff;fill-opacity:1;fill-rule:evenodd;stroke:#003378;stroke-width:0.8142156;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ ry="10.318988"
+ rx="8.598484" />
+ <g
+ transform="translate(3.673984,2.3276517)"
+ id="g3585">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="181.23659"
+ id="text2461"><tspan
+ sodipodi:role="line"
+ id="tspan2463"
+ x="329.46826"
+ y="181.23659">Shiboken (generator)</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="196.90126"
+ id="text2465"><tspan
+ sodipodi:role="line"
+ id="tspan2467"
+ x="329.46826"
+ y="196.90126">0.1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="212.44124"
+ id="text2469"><tspan
+ sodipodi:role="line"
+ x="329.46826"
+ y="212.44124"
+ id="tspan2471">Binary executable - compile-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="227.76418"
+ id="text2473"><tspan
+ sodipodi:role="line"
+ id="tspan2475"
+ x="329.46826"
+ y="227.76418">GPL version 2</tspan></text>
+ </g>
+ </g>
+ <g
+ id="g3789"
+ transform="translate(-9.3125054,-154.20033)">
+ <rect
+ y="406.48441"
+ x="322.2547"
+ height="73.367416"
+ width="194.85175"
+ id="rect3597"
+ style="fill:#f3a6a6;fill-opacity:1;fill-rule:evenodd;stroke:#6a0e0e;stroke-width:0.8142156;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ ry="10.318988"
+ rx="8.598484" />
+ <g
+ transform="translate(-0.7447933,-64)"
+ id="g3633">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#350707;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="489.09369"
+ id="text2565"><tspan
+ sodipodi:role="line"
+ id="tspan2567"
+ x="329.46826"
+ y="489.09369">boost::graph</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#350707;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="504.75836"
+ id="text2569"><tspan
+ sodipodi:role="line"
+ id="tspan2571"
+ x="329.46826"
+ y="504.75836">1.38.0</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#350707;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="520.29834"
+ id="text2573"><tspan
+ sodipodi:role="line"
+ x="329.46826"
+ y="520.29834"
+ id="tspan2575">headers and libraries - compile-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#350707;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="535.62128"
+ id="text2577"><tspan
+ sodipodi:role="line"
+ id="tspan2579"
+ x="329.46826"
+ y="535.62128">Boost Software License 1.0</tspan></text>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.77180147px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1"
+ d="M 410.36806,130.70564 L 410.36806,83.52386"
+ id="path2879"
+ inkscape:connector-type="polyline" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.77360356px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-mid:none;marker-end:none;stroke-opacity:1"
+ d="M 410.36806,252.57322 L 410.36806,207.23899"
+ id="path2881"
+ inkscape:connector-type="polyline" />
+ <g
+ id="g3565"
+ transform="translate(1.4608973,-106.88798)">
+ <rect
+ ry="22.567146"
+ y="268.8403"
+ x="6.7667637"
+ height="163.45378"
+ width="273.78238"
+ id="rect7541"
+ style="fill:#e3e2db;stroke:#000000;stroke-width:1.30499184;stroke-opacity:1"
+ rx="22.567146" />
+ <g
+ transform="translate(0.2849671,3.2991583)"
+ id="g3547">
+ <g
+ id="g3516"
+ transform="translate(0,63.999998)">
+ <text
+ id="text7543"
+ y="339.74512"
+ x="76.614265"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#350707;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="339.74512"
+ x="76.614265"
+ id="tspan7545"
+ sodipodi:role="line">Boost</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="321.55374"
+ x="21.614267"
+ height="22.5"
+ width="43.163269"
+ id="rect7555"
+ style="fill:#f3a6a6;fill-opacity:1;stroke:#6a0e0e;stroke-width:0.64285713;stroke-opacity:1"
+ rx="6.4285707" />
+ </g>
+ <g
+ id="g3521"
+ transform="translate(0,-2.9523642)">
+ <text
+ id="text7547"
+ y="372.67505"
+ x="76.614265"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#1c2d0f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="372.67505"
+ x="76.614265"
+ id="tspan7549"
+ sodipodi:role="line">Qt Software</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="355.4823"
+ x="21.614267"
+ height="22.5"
+ width="43.163269"
+ id="rect7561"
+ style="fill:#97ce6c;fill-opacity:1;stroke:#385a1e;stroke-width:0.64285713;stroke-opacity:1"
+ rx="6.4285707" />
+ </g>
+ <g
+ id="g3486"
+ transform="translate(0,2.8342009e-5)">
+ <text
+ id="text7551"
+ y="304.38055"
+ x="76.614265"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#00193c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="304.38055"
+ x="76.614265"
+ id="tspan7553"
+ sodipodi:role="line">INdT/Nokia</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="286.4823"
+ x="21.614267"
+ height="22.5"
+ width="43.163269"
+ id="rect7563"
+ style="fill:#9ac5ff;fill-opacity:1;stroke:#003378;stroke-width:0.64285713;stroke-opacity:1"
+ rx="6.4285707" />
+ </g>
+ <g
+ id="g3526"
+ transform="translate(-1.3182277,-35.976168)"
+ style="fill:#ffe052;fill-opacity:1">
+ <text
+ id="text3528"
+ y="372.67505"
+ x="76.614265"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#3c3100;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="372.67505"
+ x="76.614265"
+ id="tspan3530"
+ sodipodi:role="line">Python Foundation</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="355.4823"
+ x="21.614267"
+ height="22.5"
+ width="43.163269"
+ id="rect3532"
+ style="fill:#ffe052;fill-opacity:1;stroke:#786200;stroke-width:0.64285713;stroke-opacity:1"
+ rx="6.4285707" />
+ </g>
+ </g>
+ </g>
+ <g
+ id="g3717"
+ transform="translate(232.28126,-66.767457)">
+ <rect
+ y="77.149132"
+ x="322.2547"
+ height="73.367416"
+ width="194.85175"
+ id="rect3657"
+ style="fill:#9ac5ff;fill-opacity:1;fill-rule:evenodd;stroke:#003378;stroke-width:0.8142156;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ ry="10.318988"
+ rx="8.598484" />
+ <g
+ transform="translate(4.8773009,-84.541588)"
+ id="g3659">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="181.23659"
+ id="text3661"><tspan
+ sodipodi:role="line"
+ id="tspan3663"
+ x="329.46826"
+ y="181.23659">libshiboken</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="196.90126"
+ id="text3665"><tspan
+ sodipodi:role="line"
+ id="tspan3667"
+ x="329.46826"
+ y="196.90126">0.1</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="212.44124"
+ id="text3669"><tspan
+ sodipodi:role="line"
+ x="329.46826"
+ y="212.44124"
+ id="tspan3671">Headers and libraries - compile-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#00183c;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="227.76418"
+ id="text3673"><tspan
+ sodipodi:role="line"
+ id="tspan3675"
+ x="329.46826"
+ y="227.76418">LGPL version 2.1</tspan></text>
+ </g>
+ </g>
+ <g
+ id="g3752"
+ transform="translate(-10.802055,-155.79173)">
+ <rect
+ rx="8.3239012"
+ y="166.21593"
+ x="18.860012"
+ height="73.282379"
+ width="274.18781"
+ id="rect2417"
+ style="fill:#97ce6c;fill-opacity:1;fill-rule:evenodd;stroke:#385a1e;stroke-width:0.96558368px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="9.2689295" />
+ <g
+ id="g3741">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#1c2d0f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="29.111408"
+ y="183.02223"
+ id="text2419"><tspan
+ sodipodi:role="line"
+ id="tspan2421"
+ x="29.111408"
+ y="183.02223">Qt 4.5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#1c2d0f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="29.111408"
+ y="198.68694"
+ id="text2423"><tspan
+ sodipodi:role="line"
+ id="tspan2425"
+ x="29.111408"
+ y="198.68694">4.5</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#1c2d0f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="29.111408"
+ y="214.22688"
+ id="text2427"><tspan
+ sodipodi:role="line"
+ id="tspan2429"
+ x="29.111408"
+ y="214.22688">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#1c2d0f;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="29.111408"
+ y="224.19267"
+ id="text2431"><tspan
+ sodipodi:role="line"
+ id="tspan2433"
+ x="29.111408"
+ y="224.19267">GNU General Public License v3 /</tspan><tspan
+ id="tspan2472"
+ sodipodi:role="line"
+ x="29.111408"
+ y="234.5208">GNU Lesser General Public Licence v2.1</tspan></text>
+ </g>
+ </g>
+ <g
+ id="g3765"
+ transform="translate(201.65125,55.15042)">
+ <rect
+ y="77.208275"
+ x="322.31384"
+ height="73.24913"
+ width="255.99348"
+ id="rect3767"
+ style="fill:#ffe052;fill-opacity:1;fill-rule:evenodd;stroke:#786200;stroke-width:0.93250537;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ ry="10.318988"
+ rx="8.598484" />
+ <g
+ transform="translate(4.8773009,-84.541588)"
+ id="g3769">
+ <text
+ xml:space="preserve"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#3c3100;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="181.23659"
+ id="text3771"><tspan
+ sodipodi:role="line"
+ id="tspan3773"
+ x="329.46826"
+ y="181.23659">Python</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#3c3100;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="196.90126"
+ id="text3775"><tspan
+ sodipodi:role="line"
+ id="tspan3777"
+ x="329.46826"
+ y="196.90126">2.6</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#3c3100;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="212.44124"
+ id="text3779"><tspan
+ sodipodi:role="line"
+ x="329.46826"
+ y="212.44124"
+ id="tspan3781">Headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ xml:space="preserve"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#3c3100;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="329.46826"
+ y="227.76418"
+ id="text3783"><tspan
+ sodipodi:role="line"
+ id="tspan3785"
+ x="329.46826"
+ y="227.76418">Python license</tspan></text>
+ </g>
+ </g>
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.77180147px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1"
+ d="M 651.96184,131.80908 L 651.96184,84.6273"
+ id="path3787"
+ inkscape:connector-type="polyline" />
+ </g>
+ </g>
+</svg>
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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="900"
+ height="560"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="dependency-pyside.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="/tmp/dependency-pyside.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow1Lstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lstart"
+ style="overflow:visible">
+ <path
+ id="path3270"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.8,0,0,0.8,10,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Lend"
+ style="overflow:visible">
+ <path
+ id="path3679"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,-10,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="0.79440331"
+ inkscape:cx="-36.66006"
+ inkscape:cy="372.04724"
+ inkscape:document-units="px"
+ inkscape:current-layer="svg2"
+ showgrid="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1278"
+ inkscape:window-height="949"
+ inkscape:window-x="0"
+ inkscape:window-y="0">
+ <sodipodi:guide
+ orientation="1,0"
+ position="384.28571,590"
+ id="guide2601" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="678.57143,491.42857"
+ id="guide2603" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="78.571429,257.14286"
+ id="guide2605" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="93.571429,280.71429"
+ id="guide7565" />
+ <sodipodi:guide
+ orientation="1,0"
+ position="148.57143,216.42857"
+ id="guide7567" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-78.088635,-190.95252)" />
+ <g
+ id="g5394"
+ transform="translate(6.1314759,14.304617)">
+ <g
+ transform="translate(-65.84289,-190.95252)"
+ id="g5205">
+ <g
+ id="g5171">
+ <rect
+ rx="9.3643799"
+ y="338.7739"
+ x="678.57141"
+ height="73.281754"
+ width="274.54263"
+ id="rect2393"
+ style="fill:#aaeeff;fill-rule:evenodd;stroke:#006078;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="13.104657" />
+ <text
+ id="text2395"
+ y="355.93701"
+ x="683.46539"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="355.93701"
+ x="683.46539"
+ id="tspan2397"
+ sodipodi:role="line">boost::python</tspan></text>
+ <text
+ id="text2399"
+ y="371.60172"
+ x="683.46539"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="371.60172"
+ x="683.46539"
+ id="tspan2401"
+ sodipodi:role="line">1.38.0</tspan></text>
+ <text
+ id="text2403"
+ y="387.14166"
+ x="683.46539"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2435"
+ y="387.14166"
+ x="683.46539"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2413"
+ y="402.4646"
+ x="683.46539"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="402.4646"
+ x="683.46539"
+ id="tspan2415"
+ sodipodi:role="line">Boost Software License 1.0</tspan></text>
+ </g>
+ <g
+ id="g5193">
+ <rect
+ rx="8.3239012"
+ y="342.86383"
+ x="78.571426"
+ height="73.282379"
+ width="274.18781"
+ id="rect2417"
+ style="fill:#b3ff80;fill-rule:evenodd;stroke:#2a7800;stroke-width:0.96558368px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="9.2689295" />
+ <text
+ id="text2419"
+ y="359.67014"
+ x="88.822823"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="359.67014"
+ x="88.822823"
+ id="tspan2421"
+ sodipodi:role="line">Qt 4.5</tspan></text>
+ <text
+ id="text2423"
+ y="375.33484"
+ x="88.822823"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="375.33484"
+ x="88.822823"
+ id="tspan2425"
+ sodipodi:role="line">4.5</tspan></text>
+ <text
+ id="text2427"
+ y="390.87479"
+ x="88.822823"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="390.87479"
+ x="88.822823"
+ id="tspan2429"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2431"
+ y="400.84058"
+ x="88.822823"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="400.84058"
+ x="88.822823"
+ id="tspan2433"
+ sodipodi:role="line">GNU General Public License v3 /</tspan><tspan
+ y="411.1687"
+ x="88.822823"
+ sodipodi:role="line"
+ id="tspan2472">GNU Lesser General Public Licence v2.1</tspan></text>
+ </g>
+ <g
+ id="g5120">
+ <rect
+ y="496.43558"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2441"
+ style="fill:#e9ddaf;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="13.104635"
+ rx="10.404889" />
+ <text
+ id="text2443"
+ y="513.59869"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="513.59869"
+ x="389.17969"
+ id="tspan2445"
+ sodipodi:role="line">libapiextractor</tspan></text>
+ <text
+ id="text2447"
+ y="529.26337"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="529.26337"
+ x="389.17969"
+ id="tspan2449"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2451"
+ y="544.80334"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2453"
+ y="544.80334"
+ x="389.17969"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2455"
+ y="560.12628"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="560.12628"
+ x="389.17969"
+ id="tspan2457"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5131">
+ <rect
+ y="340.72134"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2459"
+ style="fill:#e9ddaf;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="10.309408"
+ rx="9.3644047" />
+ <text
+ id="text2461"
+ y="357.88449"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="357.88449"
+ x="389.17969"
+ id="tspan2463"
+ sodipodi:role="line">BoostPythonGenerator</tspan></text>
+ <text
+ id="text2465"
+ y="373.54916"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="373.54916"
+ x="389.17969"
+ id="tspan2467"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2469"
+ y="389.08914"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2471"
+ y="389.08914"
+ x="389.17969"
+ sodipodi:role="line">Binary executable - compile-time</tspan></text>
+ <text
+ id="text2473"
+ y="404.41208"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="404.41208"
+ x="389.17969"
+ id="tspan2475"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5142">
+ <rect
+ y="191.43562"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2523"
+ style="fill:#e9ddaf;fill-opacity:1;fill-rule:evenodd;stroke:#5f5019;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="14.285714" />
+ <text
+ id="text2525"
+ y="208.59874"
+ x="389.17966"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="208.59874"
+ x="389.17966"
+ id="tspan2527"
+ sodipodi:role="line">Qt Python bindings</tspan></text>
+ <text
+ id="text2529"
+ y="224.26344"
+ x="389.17966"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="224.26344"
+ x="389.17966"
+ id="tspan2531"
+ sodipodi:role="line">0.1</tspan></text>
+ <text
+ id="text2533"
+ y="239.80339"
+ x="389.17966"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2535"
+ y="239.80339"
+ x="389.17966"
+ sodipodi:role="line">Target</tspan></text>
+ <text
+ id="text2537"
+ y="255.12633"
+ x="389.17966"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="255.12633"
+ x="389.17966"
+ id="tspan2539"
+ sodipodi:role="line">LGPL version 2.1</tspan></text>
+ </g>
+ <g
+ id="g5182">
+ <rect
+ rx="10.404877"
+ y="648.57843"
+ x="384.28571"
+ height="73.281754"
+ width="274.54263"
+ id="rect2563"
+ style="fill:#aaeeff;fill-rule:evenodd;stroke:#006078;stroke-width:0.96620417px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ ry="11.287985" />
+ <text
+ id="text2565"
+ y="665.74158"
+ x="389.17969"
+ style="font-size:16.27989578px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="665.74158"
+ x="389.17969"
+ id="tspan2567"
+ sodipodi:role="line">boost::graph</tspan></text>
+ <text
+ id="text2569"
+ y="681.40625"
+ x="389.17969"
+ style="font-size:8.40044498px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="681.40625"
+ x="389.17969"
+ id="tspan2571"
+ sodipodi:role="line">1.38.0</tspan></text>
+ <text
+ id="text2573"
+ y="696.94623"
+ x="389.17969"
+ style="font-size:9.33067703px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2575"
+ y="696.94623"
+ x="389.17969"
+ sodipodi:role="line">headers and libraries - compile-time and run-time</tspan></text>
+ <text
+ id="text2577"
+ y="712.26917"
+ x="389.17969"
+ style="font-size:8.26250458px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="712.26917"
+ x="389.17969"
+ id="tspan2579"
+ sodipodi:role="line">Boost Software License 1.0</tspan></text>
+ </g>
+ </g>
+ <path
+ inkscape:connector-type="polyline"
+ id="path2869"
+ d="M 212.85114,151.42852 L 368.56822,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2871"
+ d="M 663.60462,147.33826 L 517.61788,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2877"
+ d="M 443.4684,149.28571 L 443.46839,74.247959"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2879"
+ d="M 443.4684,304.99994 L 443.4684,223.53367"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-end:none;stroke-opacity:1" />
+ <path
+ inkscape:connector-type="polyline"
+ id="path2881"
+ d="M 443.4684,457.14279 L 443.4684,379.2479"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;marker-start:url(#Arrow1Lstart);marker-mid:none;marker-end:none;stroke-opacity:1" />
+ <rect
+ ry="17.142857"
+ y="293.85626"
+ x="0.48279184"
+ height="124.28571"
+ width="211.42857"
+ id="rect7541"
+ style="fill:#e3e2db;stroke:#000000;stroke-opacity:1" />
+ <text
+ id="text7543"
+ y="325.44049"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="325.44049"
+ x="70.482788"
+ id="tspan7545"
+ sodipodi:role="line">Boost</tspan></text>
+ <text
+ id="text7547"
+ y="358.37042"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="358.37042"
+ x="70.482788"
+ id="tspan7549"
+ sodipodi:role="line">Qt Software</tspan></text>
+ <text
+ id="text7551"
+ y="394.07593"
+ x="70.482788"
+ style="font-size:20.61732101px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ y="394.07593"
+ x="70.482788"
+ id="tspan7553"
+ sodipodi:role="line">INdT/Nokia</tspan></text>
+ <rect
+ ry="6.4285707"
+ y="307.24911"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7555"
+ style="fill:#aaeeff;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ <rect
+ ry="6.4285707"
+ y="341.17767"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7561"
+ style="fill:#b3ff80;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ <rect
+ ry="6.4285707"
+ y="376.17767"
+ x="15.482792"
+ height="22.5"
+ width="43.163269"
+ id="rect7563"
+ style="fill:#e9ddaf;fill-opacity:1;stroke:#000000;stroke-width:0.64285713;stroke-opacity:1" />
+ </g>
+</svg>
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 <http://www.pyside.org/home-binding/binding-generator>`_
+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 <http://www.pyside.org/docs/apiextractor/typesystem.html>`_ 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
--- /dev/null
+++ b/sources/shiboken2/doc/images/bindinggen-development.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="640"
+ height="200"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="bindgen-development.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="bindinggen-development.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="EmptyDiamondL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyDiamondL"
+ style="overflow:visible">
+ <path
+ id="path3930"
+ d="M 0,-7.0710768 L -7.0710894,0 L 0,7.0710589 L 7.0710462,0 L 0,-7.0710768 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="EmptyTriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyTriangleInL"
+ style="overflow:visible">
+ <path
+ id="path3975"
+ d="M 5.77,0 L -2.88,5 L -2.88,-5 L 5.77,0 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3835"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.2,0,0,0.2,1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3832"
+ d="M 0,0 L 5,-5 L -12.5,0 L 5,5 L 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Tail"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Tail"
+ style="overflow:visible">
+ <g
+ id="g3859"
+ transform="scale(-1.2,-1.2)">
+ <path
+ id="path3861"
+ d="M -3.8048674,-3.9585227 L 0.54352094,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3863"
+ d="M -1.2866832,-3.9585227 L 3.0617053,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3865"
+ d="M 1.3053582,-3.9585227 L 5.6537466,0"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3867"
+ d="M -3.8048674,4.1775838 L 0.54352094,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3869"
+ d="M -1.2866832,4.1775838 L 3.0617053,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3871"
+ d="M 1.3053582,4.1775838 L 5.6537466,0.21974226"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0859375"
+ inkscape:cx="320"
+ inkscape:cy="136.17463"
+ inkscape:document-units="px"
+ inkscape:current-layer="g5658"
+ showgrid="false"
+ inkscape:window-width="1156"
+ inkscape:window-height="883"
+ inkscape:window-x="1396"
+ inkscape:window-y="35"
+ showguides="true"
+ inkscape:guide-bbox="true">
+ <sodipodi:guide
+ orientation="1,0"
+ position="-557.55608,678.10875"
+ id="guide7299" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-1758.7331,-2056.8567)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ transform="translate(4.1137413,-2.3429609)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g5658"
+ transform="translate(6.5767925,7.0112479)">
+ <g
+ id="g5634">
+ <g
+ id="g6271"
+ transform="translate(1086.3689,746.93837)">
+ <g
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)"
+ id="g6252">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.5317,1300.2858 L 1586.6222,1389.8124"
+ id="path11089"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2758"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path2760"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(134.35978,44.472131)"
+ id="g2777">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.82399696;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect5172"
+ width="185.49777"
+ height="75.08918"
+ x="2047.775"
+ y="2029.4594"
+ ry="3.0323718"
+ rx="2.6724329" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="2140.5562"
+ y="2062.9375"
+ id="text5174"><tspan
+ sodipodi:role="line"
+ x="2140.5562"
+ y="2062.9375"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan5176">Qt bindings</tspan><tspan
+ id="tspan6109"
+ sodipodi:role="line"
+ x="2140.5562"
+ y="2084.457"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">(generated code)</tspan></text>
+ </g>
+ <g
+ transform="translate(141.86951,-31.391207)"
+ id="g3216">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.64492828;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect3625"
+ width="185.67708"
+ height="75.268074"
+ x="1829.1727"
+ y="2105.2332"
+ ry="2.3353095"
+ rx="2.1257713" />
+ <text
+ xml:space="preserve"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1921.9705"
+ y="2136.9409"
+ id="text3627"
+ transform="scale(1.0000266,0.9999734)"><tspan
+ id="tspan3697"
+ sodipodi:role="line"
+ x="1921.9705"
+ y="2136.9409"
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">generator</tspan><tspan
+ sodipodi:role="line"
+ x="1921.9705"
+ y="2163.5559"
+ style="font-size:21.29199791px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan2464">front-end</tspan></text>
+ </g>
+ <g
+ id="g5641">
+ <g
+ id="g5465"
+ transform="translate(874.42628,746.93837)">
+ <g
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)"
+ id="g5467">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.5317,1300.2858 L 1586.6222,1389.8124"
+ id="path5469"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5471"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5473"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ </g>
+ </g>
+ </g>
+ <g
+ transform="translate(-194.79968,-212.08495)"
+ id="g5440">
+ <rect
+ rx="1.2158648"
+ ry="2.9911308"
+ y="2285.8806"
+ x="1953.809"
+ height="75.360634"
+ width="185.76964"
+ id="rect3166"
+ style="fill:#dfe994;fill-opacity:1;stroke:#d5f400;stroke-width:0.55236381;stroke-opacity:1" />
+ <text
+ id="text3168"
+ y="2328.8809"
+ x="2046.646"
+ style="font-size:27.94354057px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:19.56047821px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2328.8809"
+ x="2046.646"
+ sodipodi:role="line"
+ id="tspan5424">API Extractor</tspan></text>
+ </g>
+ <g
+ transform="translate(-102.30216,-279.71223)"
+ id="g5541">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5535"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5537"><tspan
+ sodipodi:role="line"
+ id="tspan5539"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">1</tspan></text>
+ </g>
+ <g
+ transform="translate(52.589867,-352.69787)"
+ id="g5546">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5548"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5550"><tspan
+ sodipodi:role="line"
+ id="tspan5552"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">2</tspan></text>
+ </g>
+ <g
+ transform="matrix(0,-1,1,0,697.50638,3244.256)"
+ id="g5624">
+ <g
+ id="g5626"
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5628"
+ d="M 1586.5317,1348.2858 L 1586.6222,1389.8124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ id="path5630"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ id="path5632"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="translate(5.3442137,15.993306)"
+ id="g5459">
+ <rect
+ rx="2.4652832"
+ ry="2.9818845"
+ y="2151.3206"
+ x="1965.7682"
+ height="75.127686"
+ width="185.53668"
+ id="rect3485"
+ style="fill:#b2e994;fill-opacity:1;stroke:#56f400;stroke-width:0.78531456;stroke-opacity:1" />
+ <text
+ id="text3487"
+ y="2184.2461"
+ x="2059.1909"
+ style="font-size:27.94354057px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan2509"
+ style="font-size:19.56047821px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2184.2461"
+ x="2059.1909"
+ sodipodi:role="line">typesystem</tspan><tspan
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="2205.1477"
+ x="2059.1909"
+ sodipodi:role="line"
+ id="tspan5432">(handwritten)</tspan></text>
+ </g>
+ <g
+ transform="matrix(0,-1,1,0,908.50929,3242.9612)"
+ id="g5648">
+ <g
+ id="g5650"
+ transform="matrix(0,-1,1,0,-294.81158,2953.0504)">
+ <path
+ sodipodi:nodetypes="cc"
+ inkscape:connector-type="polyline"
+ id="path5652"
+ d="M 1586.5317,1348.2858 L 1586.6222,1389.8124"
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.7489,1389.4756 L 1594.7468,1380.3688"
+ id="path5654"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker-start:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;display:inline"
+ d="M 1586.6031,1389.5063 L 1578.6052,1380.3994"
+ id="path5656"
+ inkscape:connector-type="polyline"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+ <g
+ transform="translate(299.78191,21.148391)"
+ id="g2771">
+ <rect
+ style="fill:#cce994;fill-opacity:1;stroke:#a1f400;stroke-width:0.62429351;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect2733"
+ width="185.69771"
+ height="75.288704"
+ x="1882.2529"
+ y="2146.085"
+ ry="2.2607138"
+ rx="2.0576432" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1975.134"
+ y="2180.2722"
+ id="text2735"><tspan
+ sodipodi:role="line"
+ x="1975.134"
+ y="2180.2722"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan2737">injected code</tspan><tspan
+ id="tspan2743"
+ sodipodi:role="line"
+ x="1975.134"
+ y="2201.7917"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">(handwritten)</tspan></text>
+ </g>
+ <g
+ transform="translate(200.4676,-222.96766)"
+ id="g5554">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5556"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5558"><tspan
+ sodipodi:role="line"
+ id="tspan5560"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">3</tspan></text>
+ </g>
+ <g
+ transform="translate(413.633,-206.84535)"
+ id="g5562">
+ <path
+ sodipodi:type="arc"
+ style="fill:#f28888;fill-opacity:1;stroke:#d5f400;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:3, 3;stroke-dashoffset:0;stroke-opacity:1"
+ id="path5564"
+ sodipodi:cx="255.10791"
+ sodipodi:cy="326.69064"
+ sodipodi:rx="38.848923"
+ sodipodi:ry="38.848923"
+ d="M 293.95683,326.69064 A 38.848923,38.848923 0 1 1 216.25899,326.69064 A 38.848923,38.848923 0 1 1 293.95683,326.69064 z"
+ transform="matrix(0.4405339,0,0,0.4405339,1842.2283,2282.9708)" />
+ <text
+ xml:space="preserve"
+ style="font-size:27.62000275px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="1946.3259"
+ y="2435.7"
+ id="text5566"><tspan
+ sodipodi:role="line"
+ id="tspan5568"
+ x="1946.3259"
+ y="2435.7"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:FreeMono;-inkscape-font-specification:FreeMono Bold">4</tspan></text>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/sources/shiboken2/doc/images/boostgen.png b/sources/shiboken2/doc/images/boostgen.png
new file mode 100644
index 000000000..ae9d9fc3d
--- /dev/null
+++ b/sources/shiboken2/doc/images/boostgen.png
Binary files differ
diff --git a/sources/shiboken2/doc/images/boostqtarch.png b/sources/shiboken2/doc/images/boostqtarch.png
new file mode 100644
index 000000000..f1b145e9c
--- /dev/null
+++ b/sources/shiboken2/doc/images/boostqtarch.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="350"
+ height="220"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.46"
+ version="1.0"
+ sodipodi:docname="boostqtarch.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="boostqtarch.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 L -2.2072895,0.016013256 L 8.7185884,-4.0017078 C 6.97309,-1.6296469 6.9831476,1.6157441 8.7185878,4.0337352 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.4812981"
+ inkscape:cx="145.70936"
+ inkscape:cy="94.089827"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1278"
+ inkscape:window-height="951"
+ inkscape:window-x="1592"
+ inkscape:window-y="29"
+ showguides="true"
+ inkscape:guide-bbox="true" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-61.076804,-301.50489)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ transform="translate(2.0918751e-6,-6.0000008)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g3010"
+ transform="matrix(0.9508755,0,0,0.9508755,11.317746,20.273572)">
+ <g
+ transform="translate(0,-9.7919846e-6)"
+ id="g2952">
+ <rect
+ style="fill:#dfe994;fill-opacity:1;stroke:#d5f400;stroke-width:0.7162478;stroke-opacity:1"
+ id="rect3166"
+ width="349.23203"
+ height="67.403336"
+ x="61.417336"
+ y="377.74161"
+ ry="2.6752985"
+ rx="2.285728" />
+ <text
+ xml:space="preserve"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="236.08904"
+ y="397.98755"
+ id="text3168"><tspan
+ sodipodi:role="line"
+ x="236.08904"
+ y="397.98755"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan3176">Boost::Python</tspan><tspan
+ sodipodi:role="line"
+ x="236.08904"
+ y="418.35535"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan2880">helper library to interface with CPython API</tspan><tspan
+ id="tspan2922"
+ sodipodi:role="line"
+ x="236.08904"
+ y="437.36487"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#4c5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and expose C++ entities to Python</tspan></text>
+ </g>
+ <g
+ transform="translate(0,-9.7025776e-6)"
+ id="g2959">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.71624762;stroke-opacity:1"
+ id="rect3542"
+ width="349.23203"
+ height="67.403351"
+ x="61.417336"
+ y="301.84543"
+ ry="2.675298"
+ rx="2.285728" />
+ <text
+ xml:space="preserve"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ x="236.5123"
+ y="322.09137"
+ id="text3544"><tspan
+ id="tspan3596"
+ sodipodi:role="line"
+ x="236.5123"
+ y="322.09137"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">Qt-Python Bindings</tspan><tspan
+ sodipodi:role="line"
+ x="236.5123"
+ y="342.45917"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan12937">Qt classes and functions</tspan><tspan
+ sodipodi:role="line"
+ x="236.5123"
+ y="361.46869"
+ style="font-size:15.20761585px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan2411">exported to Python</tspan></text>
+ </g>
+ <g
+ id="g2998">
+ <g
+ id="g2986">
+ <rect
+ rx="2.285728"
+ ry="2.675298"
+ y="453.63776"
+ x="61.417336"
+ height="67.403336"
+ width="172.02341"
+ id="rect3485"
+ style="fill:#b2e994;fill-opacity:1;stroke:#56f400;stroke-width:0.71624762;stroke-opacity:1" />
+ <text
+ id="text3487"
+ y="482.29712"
+ x="147.73038"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="482.29712"
+ x="147.73038"
+ sodipodi:role="line"
+ id="tspan3499">CPython</tspan><tspan
+ id="tspan2509"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#1f5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="508.01089"
+ x="147.73038"
+ sodipodi:role="line">API</tspan></text>
+ </g>
+ <g
+ id="g2992">
+ <rect
+ rx="2.285728"
+ ry="2.675298"
+ y="453.63776"
+ x="239.30101"
+ height="67.403351"
+ width="172.02295"
+ id="rect2459"
+ style="fill:#cce994;fill-opacity:1;stroke:#a1f400;stroke-width:0.71624762;stroke-opacity:1" />
+ <text
+ id="text2461"
+ y="481.97067"
+ x="324.86047"
+ style="font-size:29.38717079px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="481.97067"
+ x="324.86047"
+ sodipodi:role="line"
+ id="tspan2467">Qt4</tspan><tspan
+ id="tspan2490"
+ style="font-size:20.57102013px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#3a5800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="507.68445"
+ x="324.86047"
+ sodipodi:role="line">Libraries</tspan></text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
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
--- /dev/null
+++ b/sources/shiboken2/doc/images/converter.png
Binary files differ
diff --git a/sources/shiboken2/doc/images/genrunnerarch.png b/sources/shiboken2/doc/images/genrunnerarch.png
new file mode 100644
index 000000000..db1077cd0
--- /dev/null
+++ b/sources/shiboken2/doc/images/genrunnerarch.png
Binary files 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 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="980"
+ height="380"
+ id="svg2"
+ sodipodi:version="0.32"
+ inkscape:version="0.47pre4 r22446"
+ version="1.0"
+ sodipodi:docname="genrunnerarch.svg"
+ inkscape:output_extension="org.inkscape.output.svg.inkscape"
+ inkscape:export-filename="genrunnerarch.png"
+ inkscape:export-xdpi="56.549999"
+ inkscape:export-ydpi="56.549999">
+ <defs
+ id="defs4">
+ <marker
+ inkscape:stockid="EmptyDiamondL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyDiamondL"
+ style="overflow:visible">
+ <path
+ id="path3930"
+ d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ <marker
+ inkscape:stockid="EmptyTriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyTriangleInL"
+ style="overflow:visible">
+ <path
+ id="path3975"
+ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Sstart"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Sstart"
+ style="overflow:visible">
+ <path
+ id="path3835"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(0.2,0,0,0.2,1.2,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Arrow1Mend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow1Mend"
+ style="overflow:visible">
+ <path
+ id="path3832"
+ d="M 0,0 5,-5 -12.5,0 5,5 0,0 z"
+ style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.4,0,0,-0.4,-4,0)" />
+ </marker>
+ <marker
+ inkscape:stockid="Tail"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Tail"
+ style="overflow:visible">
+ <g
+ id="g3859"
+ transform="scale(-1.2,-1.2)">
+ <path
+ id="path3861"
+ d="M -3.8048674,-3.9585227 0.54352094,0"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3863"
+ d="M -1.2866832,-3.9585227 3.0617053,0"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3865"
+ d="M 1.3053582,-3.9585227 5.6537466,0"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3867"
+ d="M -3.8048674,4.1775838 0.54352094,0.21974226"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3869"
+ d="M -1.2866832,4.1775838 3.0617053,0.21974226"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ <path
+ id="path3871"
+ d="M 1.3053582,4.1775838 5.6537466,0.21974226"
+ style="fill:none;stroke:#000000;stroke-width:0.80000001;stroke-linecap:round;marker-start:none;marker-end:none" />
+ </g>
+ </marker>
+ <marker
+ inkscape:stockid="Arrow2Lend"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="Arrow2Lend"
+ style="overflow:visible">
+ <path
+ id="path3636"
+ style="font-size:12px;fill-rule:evenodd;stroke-width:0.625;stroke-linejoin:round"
+ d="M 8.7185878,4.0337352 -2.2072895,0.01601326 8.7185884,-4.0017078 c -1.7454984,2.3720609 -1.7354408,5.6174519 -6e-7,8.035443 z"
+ transform="matrix(-1.1,0,0,-1.1,-1.1,0)" />
+ </marker>
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 526.18109 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="744.09448 : 526.18109 : 1"
+ inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
+ id="perspective10" />
+ <inkscape:perspective
+ id="perspective3033"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3881"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3915"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective3956"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5100"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5322"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5365"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5391"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <marker
+ inkscape:stockid="EmptyTriangleInL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyTriangleInL-4"
+ style="overflow:visible">
+ <path
+ id="path3975-9"
+ d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="matrix(-0.8,0,0,-0.8,4.8,0)" />
+ </marker>
+ <inkscape:perspective
+ id="perspective5621"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <inkscape:perspective
+ id="perspective5643"
+ inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
+ inkscape:vp_z="1 : 0.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_x="0 : 0.5 : 1"
+ sodipodi:type="inkscape:persp3d" />
+ <marker
+ inkscape:stockid="EmptyDiamondL"
+ orient="auto"
+ refY="0"
+ refX="0"
+ id="EmptyDiamondL-7"
+ style="overflow:visible">
+ <path
+ id="path3930-7"
+ d="M 0,-7.0710768 -7.0710894,0 0,7.0710589 7.0710462,0 0,-7.0710768 z"
+ style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt;marker-start:none"
+ transform="scale(0.8,0.8)" />
+ </marker>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ gridtolerance="10000"
+ guidetolerance="10"
+ objecttolerance="10"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1.0716799"
+ inkscape:cx="460.27913"
+ inkscape:cy="148.01364"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ inkscape:window-width="1862"
+ inkscape:window-height="1019"
+ inkscape:window-x="20"
+ inkscape:window-y="89"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(472.44407,-697.53823)">
+ <flowRoot
+ xml:space="preserve"
+ id="flowRoot3229"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ transform="translate(2.0918751e-6,-6.0000008)"><flowRegion
+ id="flowRegion3231"><rect
+ id="rect3233"
+ width="125.74072"
+ height="40.5849"
+ x="388.45547"
+ y="279.5423" /></flowRegion><flowPara
+ id="flowPara3235" /></flowRoot> <g
+ id="g5867"
+ transform="translate(6.7062969,-7.6922472)">
+ <rect
+ rx="3.4968286"
+ ry="5.2462597"
+ y="713.31403"
+ x="-472.05276"
+ height="363.61459"
+ width="393.78473"
+ id="rect3609"
+ style="fill:#e4fae3;fill-opacity:0.65882353;stroke:#8eff89;stroke-width:0.78260708;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text3601"
+ y="742.43872"
+ x="-275.16165"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan3605"
+ style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="742.43872"
+ x="-275.16165"
+ sodipodi:role="line"><tspan
+ id="tspan2508"
+ style="font-weight:bold">API Extractor</tspan></tspan></text>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-587.62742,-106.48682)"
+ id="g3763">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.79775763;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect3737"
+ width="244.82956"
+ height="101.59812"
+ x="267.06232"
+ y="905.13727"
+ ry="3.1522403"
+ rx="2.4096873" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="389.39117"
+ y="931.86993"
+ id="text3739"><tspan
+ sodipodi:role="line"
+ x="389.39117"
+ y="931.86993"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan3741">ApiExtractor</tspan><tspan
+ id="tspan2523"
+ sodipodi:role="line"
+ x="389.39117"
+ y="953.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">commands the parsing and</tspan><tspan
+ id="tspan2517"
+ sodipodi:role="line"
+ x="389.39117"
+ y="973.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">building of the data model</tspan><tspan
+ id="tspan2519"
+ sodipodi:role="line"
+ x="389.39117"
+ y="993.38947"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and calls the user generators</tspan></text>
+ </g>
+ <rect
+ rx="2.1814992"
+ ry="5.2485871"
+ y="713.45312"
+ x="219.72128"
+ height="363.77597"
+ width="274.11292"
+ id="rect9190"
+ style="fill:#b8d1f1;fill-opacity:0.51184836;stroke:#0045a4;stroke-width:0.6182732;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text9192"
+ y="742.66901"
+ x="357.65579"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#002e7a;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan9194"
+ style="font-size:27.09890556px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002e7a;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="742.66901"
+ x="357.65579"
+ sodipodi:role="line"><tspan
+ id="tspan2512"
+ style="font-weight:bold;fill:#002e7a;fill-opacity:1">front-end</tspan><tspan
+ id="tspan2514"
+ style="font-size:22px;fill:#002e7a;fill-opacity:1" /></tspan></text>
+ <rect
+ rx="2.2192271"
+ ry="5.2485123"
+ y="713.23639"
+ x="-68.659073"
+ height="363.77075"
+ width="278.85358"
+ id="rect9190-9"
+ style="fill:#cbe990;fill-opacity:0.51184836;stroke:#6ca400;stroke-width:0.62359226;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <text
+ transform="scale(1.0000266,0.9999734)"
+ id="text9192-3"
+ y="741.71094"
+ x="70.291061"
+ style="font-size:38.71272278px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ xml:space="preserve"><tspan
+ id="tspan9194-7"
+ style="font-size:26px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ y="741.71094"
+ x="70.291061"
+ sodipodi:role="line">Generator Runner</tspan></text>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-687.04869,-241.74888)"
+ id="g9234-4">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.73640609;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect9206-4"
+ width="218.17299"
+ height="83.517967"
+ x="694.6994"
+ y="1044.8701"
+ ry="2.5912752"
+ rx="2.4978092" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="803.78589"
+ y="1072.3693"
+ id="text9208-3"><tspan
+ sodipodi:role="line"
+ x="803.78589"
+ y="1072.3693"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan9210-0">Generator</tspan><tspan
+ id="tspan9222-8"
+ sodipodi:role="line"
+ x="803.78589"
+ y="1093.8888"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">base class for front-end</tspan><tspan
+ id="tspan3946"
+ sodipodi:role="line"
+ x="803.78589"
+ y="1113.8888"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">output classes</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-726.09128,-46.791689)"
+ id="g10497-6">
+ <rect
+ style="fill:#89b3e7;fill-opacity:1;stroke:#0049a4;stroke-width:1.04736876;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect10444-8"
+ width="256.05252"
+ height="143.95157"
+ x="990.81482"
+ y="843.58032"
+ ry="4.4663219"
+ rx="2.9314826" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="1118.0945"
+ y="873.04047"
+ id="text10446-8"><tspan
+ sodipodi:role="line"
+ x="1118.0945"
+ y="873.04047"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan10448-4">SpecificGenerator</tspan><tspan
+ id="tspan4063"
+ sodipodi:role="line"
+ x="1118.0945"
+ y="894.56"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">generators written for any</tspan><tspan
+ id="tspan5381"
+ sodipodi:role="line"
+ x="1118.0945"
+ y="914.56"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">desired output,</tspan><tspan
+ id="tspan4065"
+ sodipodi:role="line"
+ x="1118.0945"
+ y="934.56"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"> e.g.: HppGenerator,</tspan><tspan
+ id="tspan4071"
+ sodipodi:role="line"
+ x="1118.0945"
+ y="954.56"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">CppGenerator,</tspan><tspan
+ id="tspan4073"
+ sodipodi:role="line"
+ x="1118.0945"
+ y="974.56"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#002758;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">ConverterGenerator</tspan></text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ transform="translate(109.91989,748.26874)"
+ id="path4056"
+ d="m -201.98482,41.728896 76.97065,5e-6"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4056-2"
+ d="m 197.04022,787.89746 35.38656,0"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-start:url(#EmptyTriangleInL)" />
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-1010.4541,91.401187)"
+ id="g10497">
+ <rect
+ style="fill:#addc52;fill-opacity:1;stroke:#6ca400;stroke-width:0.88060772;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect10444"
+ width="256.21927"
+ height="101.69494"
+ x="990.73145"
+ y="843.49695"
+ ry="3.1552441"
+ rx="2.9333918" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:start;text-anchor:start;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="1012.22"
+ y="870.08466"
+ id="text10446"><tspan
+ sodipodi:role="line"
+ x="1012.22"
+ y="870.08466"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan10448">Generator App</tspan><tspan
+ id="tspan10456"
+ sodipodi:role="line"
+ x="1012.22"
+ y="891.60419"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* loads generators</tspan><tspan
+ id="tspan5353"
+ sodipodi:role="line"
+ x="1012.22"
+ y="911.60419"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* setup API Extractor</tspan><tspan
+ id="tspan5355"
+ sodipodi:role="line"
+ x="1012.22"
+ y="931.60419"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;text-anchor:start;fill:#050800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">* executes each generator</tspan></text>
+ </g>
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4056-9"
+ d="m 72.409302,850.57374 0,56.99122"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path4056-2-0"
+ d="m -86.437722,825.54499 52.188784,0 0.06367,81.67009"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker-start:url(#EmptyDiamondL)" />
+ <path
+ sodipodi:nodetypes="cc"
+ id="path4056-91"
+ d="m -394.83596,853.70064 0,121.42437"
+ style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:6, 1;stroke-dashoffset:0" />
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-707.18032,-153.53291)"
+ id="g3809">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:1.00168562;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect3785"
+ width="332.48172"
+ height="82.830231"
+ x="302.83319"
+ y="1068.9153"
+ ry="3.1461167"
+ rx="3.8065021" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="469.03497"
+ y="1095.5493"
+ id="text3787"><tspan
+ id="tspan3791"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1095.5493"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">AbstractMetaBuilder</tspan><tspan
+ sodipodi:role="line"
+ x="469.03497"
+ y="1117.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans"
+ id="tspan3807">builds the data model with information</tspan><tspan
+ id="tspan2545"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1137.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">from headers and binding directives</tspan><tspan
+ id="tspan3795"
+ sodipodi:role="line"
+ x="469.03497"
+ y="1157.0688"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans" /></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-755.89347,194.37862)"
+ id="g3709">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.69825613;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect2821"
+ width="198.90968"
+ height="93.892342"
+ x="305.2475"
+ y="807.38849"
+ ry="2.6812849"
+ rx="2.1703238" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="405.17499"
+ y="831.81903"
+ id="text3611"><tspan
+ id="tspan3687"
+ sodipodi:role="line"
+ x="405.17499"
+ y="831.81903"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold">TypeDatabase</tspan><tspan
+ id="tspan5641"
+ sodipodi:role="line"
+ x="405.17499"
+ y="853.33856"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses typesystem</tspan><tspan
+ id="tspan3689"
+ sodipodi:role="line"
+ x="405.17499"
+ y="873.33856"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">and stores information</tspan></text>
+ </g>
+ <g
+ transform="matrix(0.9678438,0,0,0.9677923,-589.50555,-13.923919)"
+ id="g3728">
+ <rect
+ style="fill:#bff3bc;fill-opacity:1;stroke:#0af400;stroke-width:0.54871088;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect3625"
+ width="117.15066"
+ height="86.355225"
+ x="133.25664"
+ y="809.36938"
+ ry="2.6793056"
+ rx="1.3412292" />
+ <text
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;stroke:none;font-family:Bitstream Vera Sans"
+ x="191.58197"
+ y="838.75159"
+ id="text3627"><tspan
+ sodipodi:role="line"
+ x="191.58197"
+ y="838.75159"
+ style="font-size:22px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans Bold"
+ id="tspan3631">Parser</tspan><tspan
+ id="tspan3695"
+ sodipodi:role="line"
+ x="191.58197"
+ y="860.27112"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">parses the</tspan><tspan
+ id="tspan3697"
+ sodipodi:role="line"
+ x="191.58197"
+ y="880.27112"
+ style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;text-anchor:middle;fill:#035800;fill-opacity:1;font-family:Bitstream Vera Sans;-inkscape-font-specification:Bitstream Vera Sans">lib headers</tspan></text>
+ </g>
+ <path
+ sodipodi:nodetypes="ccc"
+ id="path4056-2-0-1"
+ d="m 197.39006,961.71122 158.27877,0 0.19429,-51.88885"
+ style="fill:none;stroke:#000000;stroke-width:1.38812411;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:8.32874408, 1.38812401;stroke-dashoffset:0;marker-start:none" />
+ </g>
+ </g>
+</svg>
diff --git a/sources/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 <ownership-virt-method>` or the transfer is due to the special case
+ of :ref:`parent ownership <ownership-parent>`.
+
+ 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 <parent-heuristic>`
+ command line switch.
+
+.. _return-value-heuristics:
+
+Return value heuristics
+-----------------------
+
+ When enabled, object returned as pointer in C++ will become child of the object on which the method
+ was called.
+
+ To activate this heuristic, use the :ref:`--enable-return-value-heuristic <return-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 <command-line>`. 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 <codeinjectionsemantics>` 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<path>[:<path>:...]
+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<path>[:<path>:...]
+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 <didier@raboud.com>, 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<shiboken.isValid>` (obj)
+ * def :meth:`wrapInstance<shiboken.wrapInstance>` (address, type)
+ * def :meth:`getCppPointer<shiboken.getCppPointer>` (obj)
+ * def :meth:`delete<shiboken.delete>` (obj)
+ * def :meth:`isOwnedByPython<shiboken.isOwnedByPython>` (obj)
+ * def :meth:`wasCreatedByPython<shiboken.wasCreatedByPython>` (obj)
+ * def :meth:`dump<shiboken.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 "<conversion-rule>" tag must be used.
+
+ .. code-block:: xml
+
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
+
+ <conversion-rule>
+
+ <native-to-target>
+ return PyComplex_FromDoubles(%in.real(), %in.imag());
+ </native-to-target>
+
+ <target-to-native>
+ <!-- The 'check' attribute can be derived from the 'type' attribute,
+ it is defined here to test the CHECKTYPE type system variable. -->
+ <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)">
+ double real = PyComplex_RealAsDouble(%in);
+ double imag = PyComplex_ImagAsDouble(%in);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+ </target-to-native>
+
+ </conversion-rule>
+
+ </primitive-type>
+
+
+The details will be given later, but the gist of it are the tags
+`<native-to-target> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#native-to-target>`_,
+which has only one conversion from C++ to Python, and
+`<target-to-native> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#target-to-native>`_,
+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 `<native-to-target> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#native-to-target>`_,
+to directly return the Python result of the conversion, and the added conversions inside the
+`<target-to-native> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#target-to-native>`_
+must attribute the Python to C++ conversion result to the :ref:`%out <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
+`<add-conversion> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#add-conversion>`_
+tag and a custom check must be added. Here's how to do it:
+
+ .. code-block:: xml
+
+ <!-- Code injection at module level. -->
+ <inject-code class="native" position="beginning">
+ static bool Check2TupleOfNumbers(PyObject* pyIn) {
+ if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2))
+ return false;
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0));
+ if (!SbkNumber_Check(pyReal))
+ return false;
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1));
+ if (!SbkNumber_Check(pyImag))
+ return false;
+ return true;
+ }
+ </inject-code>
+
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
+
+ <conversion-rule>
+
+ <native-to-target>
+ return PyComplex_FromDoubles(%in.real(), %in.imag());
+ </native-to-target>
+
+ <target-to-native>
+
+ <add-conversion type="PyComplex">
+ double real = PyComplex_RealAsDouble(%in);
+ double imag = PyComplex_ImagAsDouble(%in);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+
+ <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)">
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0));
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1));
+ double real = %CONVERTTOCPP[double](pyReal);
+ double imag = %CONVERTTOCPP[double](pyImag);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+
+ </target-to-native>
+
+ </conversion-rule>
+
+ </primitive-type>
+
+
+
+.. _container_conversions:
+
+Container Conversions
+=====================
+
+Converters for
+`<container-type> <http://www.pyside.org/docs/apiextractor/typesystem_specifying_types.html#container-type>`_
+are pretty much the same as for other type, except that they make use of the type system variables
+:ref:`%INTYPE_# <intype_n>` and :ref:`%OUTTYPE_# <outtype_n>`. |project| combines the conversion code for
+containers with the conversion defined (or automatically generated) for the containees.
+
+
+ .. code-block:: xml
+
+ <container-type name="std::map" type="map">
+ <include file-name="map" location="global"/>
+
+ <conversion-rule>
+
+ <native-to-target>
+ PyObject* %out = PyDict_New();
+ %INTYPE::const_iterator it = %in.begin();
+ for (; it != %in.end(); ++it) {
+ %INTYPE_0 key = it->first;
+ %INTYPE_1 value = it->second;
+ PyDict_SetItem(%out,
+ %CONVERTTOPYTHON[%INTYPE_0](key),
+ %CONVERTTOPYTHON[%INTYPE_1](value));
+ }
+ return %out;
+ </native-to-target>
+
+ <target-to-native>
+
+ <add-conversion type="PyDict">
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
+ %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
+ %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
+ %out.insert(%OUTTYPE::value_type(cppKey, cppValue));
+ }
+ </add-conversion>
+
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+
+
+.. _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
+
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
+ <conversion-rule file="complex_conversions.h"/>
+ </primitive-type>
+
+
+And implemented in a separate C++ file, like this:
+
+
+ .. code-block:: c++
+
+ namespace Shiboken {
+ template<> struct Converter<Complex>
+ {
+ static inline bool checkType(PyObject* pyObj) {
+ return PyComplex_Check(pyObj);
+ }
+ static inline bool isConvertible(PyObject* pyObj) {
+ return PyComplex_Check(pyObj);
+ }
+ static inline PyObject* toPython(void* cppobj) {
+ return toPython(*reinterpret_cast<Complex*>(cppobj));
+ }
+ static inline PyObject* toPython(const Complex& cpx) {
+ return PyComplex_FromDoubles(cpx.real(), cpx.imag());
+ }
+ static inline Complex toCpp(PyObject* pyobj) {
+ double real = PyComplex_RealAsDouble(pyobj);
+ double imag = PyComplex_ImagAsDouble(pyobj);
+ return Complex(real, imag);
+ }
+ };
+ }
+
+
+In this case, the parts of the implementation that will be used in the new conversion-rule
+are the ones in the two last method ``static inline PyObject* toPython(const Complex& cpx)``
+and ``static inline Complex toCpp(PyObject* pyobj)``. The ``isConvertible`` method is gone,
+and the ``checkType`` is now an attribute of the
+`<add-conversion> <http://www.pyside.org/docs/apiextractor/typesystem_conversionrule.html#add-conversion>`_
+tag. Refer back to the first example in this page and you will be able to correlate the above template
+with the new scheme of conversion rule definition.
diff --git a/sources/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 <codeinjectionsemantics>` 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
+
+ <modify-function signature="argRemoval(int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
+
+ The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the
+ value ``123``.
+
+
+.. _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 `<remove-default-expression/>
+ <http://www.pyside.org/docs/apiextractor/typesystem_arguments.html#remove-default-expression>`_
+ 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
+
+ <modify-function signature="argRemoval(int, Point, bool, Point, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <replace-default-expression with="Point(6, 9)"/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
+
+ As seen on the XML description, the function's ``a1`` and ``a3`` arguments
+ were removed. If any ``inject-code`` for this function uses ``%ARGUMENT_NAMES``
+ the resulting list will be the equivalent of using individual argument type
+ system variables this way:
+
+ .. code-block:: c++
+
+ %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 <return_type>` variable.
+ Example:
+
+ .. code-block:: c++
+
+ void argRemoval(int a0, int a1 = 123);
+
+
+ .. code-block:: xml
+
+ <modify-function signature="argRemoval(int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
+
+ The ``%1`` will be replaced by the C++ argument name, and ``%2`` will get the
+ value ``123``.
+
+
+.. _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 <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
+ <codeinjecting_method_native>`, 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 <endallowthreads>` variable.
+
+
+.. _endallowthreads:
+
+**%END_ALLOW_THREADS**
+
+ Replaced by a thread state restoring procedure.
+ Must match with a :ref:`%BEGIN_ALLOW_THREADS <beginallowthreads>` 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
+
+ <modify-function signature="overloadedMethod(int, char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int argc;
+ char** argv;
+ if (!PySequence_to_argc_argv(%PYARG_1, &amp;argc, &amp;argv)) {
+ PyErr_SetString(PyExc_TypeError, "error");
+ return 0;
+ }
+ %RETURN_TYPE foo = %CPPSELF.%FUNCTION_NAME(argc, argv);
+ %0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo);
+
+ for (int i = 0; i &lt; argc; ++i)
+ delete[] argv[i];
+ delete[] argv;
+ </inject-code>
+ </modify-function>
+
diff --git a/sources/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/ext/sparsehash/AUTHORS b/sources/shiboken2/ext/sparsehash/AUTHORS
new file mode 100644
index 000000000..ee92be88d
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/AUTHORS
@@ -0,0 +1,2 @@
+opensource@google.com
+
diff --git a/sources/shiboken2/ext/sparsehash/COPYING b/sources/shiboken2/ext/sparsehash/COPYING
new file mode 100644
index 000000000..e4956cfd9
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/COPYING
@@ -0,0 +1,28 @@
+Copyright (c) 2005, Google Inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/sources/shiboken2/ext/sparsehash/google/dense_hash_map b/sources/shiboken2/ext/sparsehash/google/dense_hash_map
new file mode 100644
index 000000000..09b0c4428
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/google/dense_hash_map
@@ -0,0 +1,310 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: Craig Silverstein
+//
+// This is just a very thin wrapper over densehashtable.h, just
+// like sgi stl's stl_hash_map is a very thin wrapper over
+// stl_hashtable. The major thing we define is operator[], because
+// we have a concept of a data_type which stl_hashtable doesn't
+// (it only has a key and a value).
+//
+// NOTE: this is exactly like sparse_hash_map.h, with the word
+// "sparse" replaced by "dense", except for the addition of
+// set_empty_key().
+//
+// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION.
+//
+// Otherwise your program will die in mysterious ways.
+//
+// In other respects, we adhere mostly to the STL semantics for
+// hash-map. One important exception is that insert() invalidates
+// iterators entirely. On the plus side, though, erase() doesn't
+// invalidate iterators at all, or even change the ordering of elements.
+//
+// Here are a few "power user" tips:
+//
+// 1) set_deleted_key():
+// If you want to use erase() you *must* call set_deleted_key(),
+// in addition to set_empty_key(), after construction.
+// The deleted and empty keys must differ.
+//
+// 2) resize(0):
+// When an item is deleted, its memory isn't freed right
+// away. This allows you to iterate over a hashtable,
+// and call erase(), without invalidating the iterator.
+// To force the memory to be freed, call resize(0).
+// For tr1 compatibility, this can also be called as rehash(0).
+//
+// 3) min_load_factor(0.0)
+// Setting the minimum load factor to 0.0 guarantees that
+// the hash table will never shrink.
+//
+// Guide to what kind of hash_map to use:
+// (1) dense_hash_map: fastest, uses the most memory
+// (2) sparse_hash_map: slowest, uses the least memory
+// (3) hash_map (STL): in the middle
+// Typically I use sparse_hash_map when I care about space and/or when
+// I need to save the hashtable on disk. I use hash_map otherwise. I
+// don't personally use dense_hash_set ever; some people use it for
+// small sets with lots of lookups.
+//
+// - dense_hash_map has, typically, a factor of 2 memory overhead (if your
+// data takes up X bytes, the hash_map uses X more bytes in overhead).
+// - sparse_hash_map has about 2 bits overhead per entry.
+// - sparse_hash_map can be 3-7 times slower than the others for lookup and,
+// especially, inserts. See time_hash_map.cc for details.
+//
+// See /usr/(local/)?doc/sparsehash-*/dense_hash_map.html
+// for information about how to use this class.
+
+#ifndef _DENSE_HASH_MAP_H_
+#define _DENSE_HASH_MAP_H_
+
+#include "google/sparsehash/sparseconfig.h"
+#include <stdio.h> // for FILE * in read()/write()
+#include <algorithm> // for the default template args
+#include <functional> // for equal_to
+#include <memory> // for alloc<>
+#include <utility> // for pair<>
+#include HASH_FUN_H // defined in config.h
+#include "google/sparsehash/densehashtable.h"
+
+
+_START_GOOGLE_NAMESPACE_
+
+using STL_NAMESPACE::pair;
+
+template <class Key, class T,
+ class HashFcn = SPARSEHASH_HASH<Key>, // defined in sparseconfig.h
+ class EqualKey = STL_NAMESPACE::equal_to<Key>,
+ class Alloc = STL_NAMESPACE::allocator<T> >
+class dense_hash_map {
+ private:
+ // Apparently select1st is not stl-standard, so we define our own
+ struct SelectKey {
+ const Key& operator()(const pair<const Key, T>& p) const {
+ return p.first;
+ }
+ };
+ struct SetKey {
+ void operator()(pair<const Key, T>* value, const Key& new_key) const {
+ *const_cast<Key*>(&value->first) = new_key;
+ // It would be nice to clear the rest of value here as well, in
+ // case it's taking up a lot of memory. We do this by clearing
+ // the value. This assumes T has a zero-arg constructor!
+ value->second = T();
+ }
+ };
+
+ // The actual data
+ typedef dense_hashtable<pair<const Key, T>, Key, HashFcn,
+ SelectKey, SetKey, EqualKey, Alloc> ht;
+ ht rep;
+
+ public:
+ typedef typename ht::key_type key_type;
+ typedef T data_type;
+ typedef T mapped_type;
+ typedef typename ht::value_type value_type;
+ typedef typename ht::hasher hasher;
+ typedef typename ht::key_equal key_equal;
+ typedef Alloc allocator_type;
+
+ typedef typename ht::size_type size_type;
+ typedef typename ht::difference_type difference_type;
+ typedef typename ht::pointer pointer;
+ typedef typename ht::const_pointer const_pointer;
+ typedef typename ht::reference reference;
+ typedef typename ht::const_reference const_reference;
+
+ typedef typename ht::iterator iterator;
+ typedef typename ht::const_iterator const_iterator;
+ typedef typename ht::local_iterator local_iterator;
+ typedef typename ht::const_local_iterator const_local_iterator;
+
+ // Iterator functions
+ iterator begin() { return rep.begin(); }
+ iterator end() { return rep.end(); }
+ const_iterator begin() const { return rep.begin(); }
+ const_iterator end() const { return rep.end(); }
+
+
+ // These come from tr1's unordered_map. For us, a bucket has 0 or 1 elements.
+ local_iterator begin(size_type i) { return rep.begin(i); }
+ local_iterator end(size_type i) { return rep.end(i); }
+ const_local_iterator begin(size_type i) const { return rep.begin(i); }
+ const_local_iterator end(size_type i) const { return rep.end(i); }
+
+ // Accessor functions
+ // TODO(csilvers): implement Alloc get_allocator() const;
+ hasher hash_funct() const { return rep.hash_funct(); }
+ hasher hash_function() const { return hash_funct(); }
+ key_equal key_eq() const { return rep.key_eq(); }
+
+
+ // Constructors
+ explicit dense_hash_map(size_type expected_max_items_in_table = 0,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal())
+ : rep(expected_max_items_in_table, hf, eql) { }
+
+ template <class InputIterator>
+ dense_hash_map(InputIterator f, InputIterator l,
+ size_type expected_max_items_in_table = 0,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal())
+ : rep(expected_max_items_in_table, hf, eql) {
+ rep.insert(f, l);
+ }
+ // We use the default copy constructor
+ // We use the default operator=()
+ // We use the default destructor
+
+ void clear() { rep.clear(); }
+ // This clears the hash map without resizing it down to the minimum
+ // bucket count, but rather keeps the number of buckets constant
+ void clear_no_resize() { rep.clear_no_resize(); }
+ void swap(dense_hash_map& hs) { rep.swap(hs.rep); }
+
+
+ // Functions concerning size
+ size_type size() const { return rep.size(); }
+ size_type max_size() const { return rep.max_size(); }
+ bool empty() const { return rep.empty(); }
+ size_type bucket_count() const { return rep.bucket_count(); }
+ size_type max_bucket_count() const { return rep.max_bucket_count(); }
+
+ // These are tr1 methods. bucket() is the bucket the key is or would be in.
+ size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
+ size_type bucket(const key_type& key) const { return rep.bucket(key); }
+ float load_factor() const {
+ return size() * 1.0f / bucket_count();
+ }
+ float max_load_factor() const {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ return grow;
+ }
+ void max_load_factor(float new_grow) {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ rep.set_resizing_parameters(shrink, new_grow);
+ }
+ // These aren't tr1 methods but perhaps ought to be.
+ float min_load_factor() const {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ return shrink;
+ }
+ void min_load_factor(float new_shrink) {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ rep.set_resizing_parameters(new_shrink, grow);
+ }
+ // Deprecated; use min_load_factor() or max_load_factor() instead.
+ void set_resizing_parameters(float shrink, float grow) {
+ return rep.set_resizing_parameters(shrink, grow);
+ }
+
+ void resize(size_type hint) { rep.resize(hint); }
+ void rehash(size_type hint) { resize(hint); } // the tr1 name
+
+ // Lookup routines
+ iterator find(const key_type& key) { return rep.find(key); }
+ const_iterator find(const key_type& key) const { return rep.find(key); }
+
+ data_type& operator[](const key_type& key) { // This is our value-add!
+ iterator it = find(key);
+ if (it != end()) {
+ return it->second;
+ } else {
+ return insert(value_type(key, data_type())).first->second;
+ }
+ }
+
+ size_type count(const key_type& key) const { return rep.count(key); }
+
+ pair<iterator, iterator> equal_range(const key_type& key) {
+ return rep.equal_range(key);
+ }
+ pair<const_iterator, const_iterator> equal_range(const key_type& key) const {
+ return rep.equal_range(key);
+ }
+
+ // Insertion routines
+ pair<iterator, bool> insert(const value_type& obj) { return rep.insert(obj); }
+ template <class InputIterator>
+ void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
+ void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
+ // required for std::insert_iterator; the passed-in iterator is ignored
+ iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
+
+
+ // Deletion and empty routines
+ // THESE ARE NON-STANDARD! I make you specify an "impossible" key
+ // value to identify deleted and empty buckets. You can change the
+ // deleted key as time goes on, or get rid of it entirely to be insert-only.
+ void set_empty_key(const key_type& key) { // YOU MUST CALL THIS!
+ rep.set_empty_key(value_type(key, data_type())); // rep wants a value
+ }
+ void set_deleted_key(const key_type& key) {
+ rep.set_deleted_key(key);
+ }
+ void clear_deleted_key() { rep.clear_deleted_key(); }
+
+ // These are standard
+ size_type erase(const key_type& key) { return rep.erase(key); }
+ void erase(iterator it) { rep.erase(it); }
+ void erase(iterator f, iterator l) { rep.erase(f, l); }
+
+
+ // Comparison
+ bool operator==(const dense_hash_map& hs) const { return rep == hs.rep; }
+ bool operator!=(const dense_hash_map& hs) const { return rep != hs.rep; }
+
+
+ // I/O -- this is an add-on for writing metainformation to disk
+ bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
+ bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
+ bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
+ bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
+};
+
+// We need a global swap as well
+template <class Key, class T, class HashFcn, class EqualKey, class Alloc>
+inline void swap(dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm1,
+ dense_hash_map<Key, T, HashFcn, EqualKey, Alloc>& hm2) {
+ hm1.swap(hm2);
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif /* _DENSE_HASH_MAP_H_ */
diff --git a/sources/shiboken2/ext/sparsehash/google/dense_hash_set b/sources/shiboken2/ext/sparsehash/google/dense_hash_set
new file mode 100644
index 000000000..faa21dc59
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/google/dense_hash_set
@@ -0,0 +1,287 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// This is just a very thin wrapper over densehashtable.h, just
+// like sgi stl's stl_hash_set is a very thin wrapper over
+// stl_hashtable. The major thing we define is operator[], because
+// we have a concept of a data_type which stl_hashtable doesn't
+// (it only has a key and a value).
+//
+// This is more different from dense_hash_map than you might think,
+// because all iterators for sets are const (you obviously can't
+// change the key, and for sets there is no value).
+//
+// NOTE: this is exactly like sparse_hash_set.h, with the word
+// "sparse" replaced by "dense", except for the addition of
+// set_empty_key().
+//
+// YOU MUST CALL SET_EMPTY_KEY() IMMEDIATELY AFTER CONSTRUCTION.
+//
+// Otherwise your program will die in mysterious ways.
+//
+// In other respects, we adhere mostly to the STL semantics for
+// hash-set. One important exception is that insert() invalidates
+// iterators entirely. On the plus side, though, erase() doesn't
+// invalidate iterators at all, or even change the ordering of elements.
+//
+// Here are a few "power user" tips:
+//
+// 1) set_deleted_key():
+// If you want to use erase() you must call set_deleted_key(),
+// in addition to set_empty_key(), after construction.
+// The deleted and empty keys must differ.
+//
+// 2) resize(0):
+// When an item is deleted, its memory isn't freed right
+// away. This allows you to iterate over a hashtable,
+// and call erase(), without invalidating the iterator.
+// To force the memory to be freed, call resize(0).
+// For tr1 compatibility, this can also be called as rehash(0).
+//
+// 3) min_load_factor(0.0)
+// Setting the minimum load factor to 0.0 guarantees that
+// the hash table will never shrink.
+//
+// Guide to what kind of hash_set to use:
+// (1) dense_hash_set: fastest, uses the most memory
+// (2) sparse_hash_set: slowest, uses the least memory
+// (3) hash_set (STL): in the middle
+// Typically I use sparse_hash_set when I care about space and/or when
+// I need to save the hashtable on disk. I use hash_set otherwise. I
+// don't personally use dense_hash_set ever; some people use it for
+// small sets with lots of lookups.
+//
+// - dense_hash_set has, typically, a factor of 2 memory overhead (if your
+// data takes up X bytes, the hash_set uses X more bytes in overhead).
+// - sparse_hash_set has about 2 bits overhead per entry.
+// - sparse_hash_map can be 3-7 times slower than the others for lookup and,
+// especially, inserts. See time_hash_map.cc for details.
+//
+// See /usr/(local/)?doc/sparsehash-*/dense_hash_set.html
+// for information about how to use this class.
+
+#ifndef _DENSE_HASH_SET_H_
+#define _DENSE_HASH_SET_H_
+
+#include <google/sparsehash/sparseconfig.h>
+#include <stdio.h> // for FILE * in read()/write()
+#include <algorithm> // for the default template args
+#include <functional> // for equal_to
+#include <memory> // for alloc<>
+#include <utility> // for pair<>
+#include HASH_FUN_H // defined in config.h
+#include <google/sparsehash/densehashtable.h>
+
+
+_START_GOOGLE_NAMESPACE_
+
+using STL_NAMESPACE::pair;
+
+template <class Value,
+ class HashFcn = SPARSEHASH_HASH<Value>, // defined in sparseconfig.h
+ class EqualKey = STL_NAMESPACE::equal_to<Value>,
+ class Alloc = STL_NAMESPACE::allocator<Value> >
+class dense_hash_set {
+ private:
+ // Apparently identity is not stl-standard, so we define our own
+ struct Identity {
+ Value& operator()(Value& v) const { return v; }
+ const Value& operator()(const Value& v) const { return v; }
+ };
+ struct SetKey {
+ void operator()(Value* value, const Value& new_key) const {
+ *value = new_key;
+ }
+ };
+
+ // The actual data
+ typedef dense_hashtable<Value, Value, HashFcn,
+ Identity, SetKey, EqualKey, Alloc> ht;
+ ht rep;
+
+ public:
+ typedef typename ht::key_type key_type;
+ typedef typename ht::value_type value_type;
+ typedef typename ht::hasher hasher;
+ typedef typename ht::key_equal key_equal;
+ typedef Alloc allocator_type;
+
+ typedef typename ht::size_type size_type;
+ typedef typename ht::difference_type difference_type;
+ typedef typename ht::const_pointer pointer;
+ typedef typename ht::const_pointer const_pointer;
+ typedef typename ht::const_reference reference;
+ typedef typename ht::const_reference const_reference;
+
+ typedef typename ht::const_iterator iterator;
+ typedef typename ht::const_iterator const_iterator;
+ typedef typename ht::const_local_iterator local_iterator;
+ typedef typename ht::const_local_iterator const_local_iterator;
+
+
+ // Iterator functions -- recall all iterators are const
+ iterator begin() const { return rep.begin(); }
+ iterator end() const { return rep.end(); }
+
+ // These come from tr1's unordered_set. For us, a bucket has 0 or 1 elements.
+ local_iterator begin(size_type i) const { return rep.begin(i); }
+ local_iterator end(size_type i) const { return rep.end(i); }
+
+
+ // Accessor functions
+ hasher hash_funct() const { return rep.hash_funct(); }
+ key_equal key_eq() const { return rep.key_eq(); }
+
+
+ // Constructors
+ explicit dense_hash_set(size_type expected_max_items_in_table = 0,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal())
+ : rep(expected_max_items_in_table, hf, eql) { }
+
+ template <class InputIterator>
+ dense_hash_set(InputIterator f, InputIterator l,
+ size_type expected_max_items_in_table = 0,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal())
+ : rep(expected_max_items_in_table, hf, eql) {
+ rep.insert(f, l);
+ }
+ // We use the default copy constructor
+ // We use the default operator=()
+ // We use the default destructor
+
+ void clear() { rep.clear(); }
+ // This clears the hash set without resizing it down to the minimum
+ // bucket count, but rather keeps the number of buckets constant
+ void clear_no_resize() { rep.clear_no_resize(); }
+ void swap(dense_hash_set& hs) { rep.swap(hs.rep); }
+
+
+ // Functions concerning size
+ size_type size() const { return rep.size(); }
+ size_type max_size() const { return rep.max_size(); }
+ bool empty() const { return rep.empty(); }
+ size_type bucket_count() const { return rep.bucket_count(); }
+ size_type max_bucket_count() const { return rep.max_bucket_count(); }
+
+ // These are tr1 methods. bucket() is the bucket the key is or would be in.
+ size_type bucket_size(size_type i) const { return rep.bucket_size(i); }
+ size_type bucket(const key_type& key) const { return rep.bucket(key); }
+ float load_factor() const {
+ return size() * 1.0f / bucket_count();
+ }
+ float max_load_factor() const {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ return grow;
+ }
+ void max_load_factor(float new_grow) {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ rep.set_resizing_parameters(shrink, new_grow);
+ }
+ // These aren't tr1 methods but perhaps ought to be.
+ float min_load_factor() const {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ return shrink;
+ }
+ void min_load_factor(float new_shrink) {
+ float shrink, grow;
+ rep.get_resizing_parameters(&shrink, &grow);
+ rep.set_resizing_parameters(new_shrink, grow);
+ }
+ // Deprecated; use min_load_factor() or max_load_factor() instead.
+ void set_resizing_parameters(float shrink, float grow) {
+ return rep.set_resizing_parameters(shrink, grow);
+ }
+
+ void resize(size_type hint) { rep.resize(hint); }
+ void rehash(size_type hint) { resize(hint); } // the tr1 name
+
+ // Lookup routines
+ iterator find(const key_type& key) const { return rep.find(key); }
+
+ size_type count(const key_type& key) const { return rep.count(key); }
+
+ pair<iterator, iterator> equal_range(const key_type& key) const {
+ return rep.equal_range(key);
+ }
+
+ // Insertion routines
+ pair<iterator, bool> insert(const value_type& obj) {
+ pair<typename ht::iterator, bool> p = rep.insert(obj);
+ return pair<iterator, bool>(p.first, p.second); // const to non-const
+ }
+ template <class InputIterator>
+ void insert(InputIterator f, InputIterator l) { rep.insert(f, l); }
+ void insert(const_iterator f, const_iterator l) { rep.insert(f, l); }
+ // required for std::insert_iterator; the passed-in iterator is ignored
+ iterator insert(iterator, const value_type& obj) { return insert(obj).first; }
+
+
+ // Deletion and empty routines
+ // THESE ARE NON-STANDARD! I make you specify an "impossible" key
+ // value to identify deleted and empty buckets. You can change the
+ // deleted key as time goes on, or get rid of it entirely to be insert-only.
+ void set_empty_key(const key_type& key) { rep.set_empty_key(key); }
+ void set_deleted_key(const key_type& key) { rep.set_deleted_key(key); }
+ void clear_deleted_key() { rep.clear_deleted_key(); }
+
+ // These are standard
+ size_type erase(const key_type& key) { return rep.erase(key); }
+ void erase(iterator it) { rep.erase(it); }
+ void erase(iterator f, iterator l) { rep.erase(f, l); }
+
+
+ // Comparison
+ bool operator==(const dense_hash_set& hs) const { return rep == hs.rep; }
+ bool operator!=(const dense_hash_set& hs) const { return rep != hs.rep; }
+
+
+ // I/O -- this is an add-on for writing metainformation to disk
+ bool write_metadata(FILE *fp) { return rep.write_metadata(fp); }
+ bool read_metadata(FILE *fp) { return rep.read_metadata(fp); }
+ bool write_nopointer_data(FILE *fp) { return rep.write_nopointer_data(fp); }
+ bool read_nopointer_data(FILE *fp) { return rep.read_nopointer_data(fp); }
+};
+
+template <class Val, class HashFcn, class EqualKey, class Alloc>
+inline void swap(dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs1,
+ dense_hash_set<Val, HashFcn, EqualKey, Alloc>& hs2) {
+ hs1.swap(hs2);
+}
+
+_END_GOOGLE_NAMESPACE_
+
+#endif /* _DENSE_HASH_SET_H_ */
diff --git a/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h b/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h
new file mode 100644
index 000000000..33b191ec8
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/google/sparsehash/densehashtable.h
@@ -0,0 +1,1062 @@
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ---
+// Author: Craig Silverstein
+//
+// A dense hashtable is a particular implementation of
+// a hashtable: one that is meant to minimize memory allocation.
+// It does this by using an array to store all the data. We
+// steal a value from the key space to indicate "empty" array
+// elements (ie indices where no item lives) and another to indicate
+// "deleted" elements.
+//
+// (Note it is possible to change the value of the delete key
+// on the fly; you can even remove it, though after that point
+// the hashtable is insert_only until you set it again. The empty
+// value however can't be changed.)
+//
+// To minimize allocation and pointer overhead, we use internal
+// probing, in which the hashtable is a single table, and collisions
+// are resolved by trying to insert again in another bucket. The
+// most cache-efficient internal probing schemes are linear probing
+// (which suffers, alas, from clumping) and quadratic probing, which
+// is what we implement by default.
+//
+// Type requirements: value_type is required to be Copy Constructible
+// and Default Constructible. It is not required to be (and commonly
+// isn't) Assignable.
+//
+// You probably shouldn't use this code directly. Use
+// <google/dense_hash_map> or <google/dense_hash_set> instead.
+
+// You can change the following below:
+// HT_OCCUPANCY_FLT -- how full before we double size
+// HT_EMPTY_FLT -- how empty before we halve size
+// HT_MIN_BUCKETS -- default smallest bucket size
+//
+// You can also change enlarge_resize_percent (which defaults to
+// HT_OCCUPANCY_FLT), and shrink_resize_percent (which defaults to
+// HT_EMPTY_FLT) with set_resizing_parameters().
+//
+// How to decide what values to use?
+// shrink_resize_percent's default of .4 * OCCUPANCY_FLT, is probably good.
+// HT_MIN_BUCKETS is probably unnecessary since you can specify
+// (indirectly) the starting number of buckets at construct-time.
+// For enlarge_resize_percent, you can use this chart to try to trade-off
+// expected lookup time to the space taken up. By default, this
+// code uses quadratic probing, though you can change it to linear
+// via _JUMP below if you really want to.
+//
+// From http://www.augustana.ca/~mohrj/courses/1999.fall/csc210/lecture_notes/hashing.html
+// NUMBER OF PROBES / LOOKUP Successful Unsuccessful
+// Quadratic collision resolution 1 - ln(1-L) - L/2 1/(1-L) - L - ln(1-L)
+// Linear collision resolution [1+1/(1-L)]/2 [1+1/(1-L)2]/2
+//
+// -- enlarge_resize_percent -- 0.10 0.50 0.60 0.75 0.80 0.90 0.99
+// QUADRATIC COLLISION RES.
+// probes/successful lookup 1.05 1.44 1.62 2.01 2.21 2.85 5.11
+// probes/unsuccessful lookup 1.11 2.19 2.82 4.64 5.81 11.4 103.6
+// LINEAR COLLISION RES.
+// probes/successful lookup 1.06 1.5 1.75 2.5 3.0 5.5 50.5
+// probes/unsuccessful lookup 1.12 2.5 3.6 8.5 13.0 50.0 5000.0
+
+#ifndef _DENSEHASHTABLE_H_
+#define _DENSEHASHTABLE_H_
+
+// The probing method
+// Linear probing
+// #define JUMP_(key, num_probes) ( 1 )
+// Quadratic-ish probing
+#define JUMP_(key, num_probes) ( num_probes )
+
+
+#include "google/sparsehash/sparseconfig.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h> // for abort()
+#include <algorithm> // For swap(), eg
+#include <iostream> // For cerr
+#include <memory> // For uninitialized_fill, uninitialized_copy
+#include <utility> // for pair<>
+#include <iterator> // for facts about iterator tags
+#include "google/type_traits.h" // for true_type, integral_constant, etc.
+
+_START_GOOGLE_NAMESPACE_
+
+using STL_NAMESPACE::pair;
+
+// Hashtable class, used to implement the hashed associative containers
+// hash_set and hash_map.
+
+// Value: what is stored in the table (each bucket is a Value).
+// Key: something in a 1-to-1 correspondence to a Value, that can be used
+// to search for a Value in the table (find() takes a Key).
+// HashFcn: Takes a Key and returns an integer, the more unique the better.
+// ExtractKey: given a Value, returns the unique Key associated with it.
+// SetKey: given a Value* and a Key, modifies the value such that
+// ExtractKey(value) == key. We guarantee this is only called
+// with key == deleted_key or key == empty_key.
+// EqualKey: Given two Keys, says whether they are the same (that is,
+// if they are both associated with the same Value).
+// Alloc: STL allocator to use to allocate memory. Currently ignored.
+
+template <class Value, class Key, class HashFcn,
+ class ExtractKey, class SetKey, class EqualKey, class Alloc>
+class dense_hashtable;
+
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+struct dense_hashtable_iterator;
+
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+struct dense_hashtable_const_iterator;
+
+// We're just an array, but we need to skip over empty and deleted elements
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+struct dense_hashtable_iterator {
+ public:
+ typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator;
+ typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator;
+
+ typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
+ typedef V value_type;
+ typedef STL_NAMESPACE::ptrdiff_t difference_type;
+ typedef size_t size_type;
+ typedef V& reference; // Value
+ typedef V* pointer;
+
+ // "Real" constructor and default constructor
+ dense_hashtable_iterator(const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h,
+ pointer it, pointer it_end, bool advance)
+ : ht(h), pos(it), end(it_end) {
+ if (advance) advance_past_empty_and_deleted();
+ }
+ dense_hashtable_iterator() { }
+ // The default destructor is fine; we don't define one
+ // The default operator= is fine; we don't define one
+
+ // Happy dereferencer
+ reference operator*() const { return *pos; }
+ pointer operator->() const { return &(operator*()); }
+
+ // Arithmetic. The only hard part is making sure that
+ // we're not on an empty or marked-deleted array element
+ void advance_past_empty_and_deleted() {
+ while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) )
+ ++pos;
+ }
+ iterator& operator++() {
+ assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this;
+ }
+ iterator operator++(int) { iterator tmp(*this); ++*this; return tmp; }
+
+ // Comparison.
+ bool operator==(const iterator& it) const { return pos == it.pos; }
+ bool operator!=(const iterator& it) const { return pos != it.pos; }
+
+
+ // The actual data
+ const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht;
+ pointer pos, end;
+};
+
+
+// Now do it all again, but with const-ness!
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+struct dense_hashtable_const_iterator {
+ public:
+ typedef dense_hashtable_iterator<V,K,HF,ExK,SetK,EqK,A> iterator;
+ typedef dense_hashtable_const_iterator<V,K,HF,ExK,SetK,EqK,A> const_iterator;
+
+ typedef STL_NAMESPACE::forward_iterator_tag iterator_category;
+ typedef V value_type;
+ typedef STL_NAMESPACE::ptrdiff_t difference_type;
+ typedef size_t size_type;
+ typedef const V& reference; // Value
+ typedef const V* pointer;
+
+ // "Real" constructor and default constructor
+ dense_hashtable_const_iterator(
+ const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *h,
+ pointer it, pointer it_end, bool advance)
+ : ht(h), pos(it), end(it_end) {
+ if (advance) advance_past_empty_and_deleted();
+ }
+ dense_hashtable_const_iterator() { }
+ // This lets us convert regular iterators to const iterators
+ dense_hashtable_const_iterator(const iterator &it)
+ : ht(it.ht), pos(it.pos), end(it.end) { }
+ // The default destructor is fine; we don't define one
+ // The default operator= is fine; we don't define one
+
+ // Happy dereferencer
+ reference operator*() const { return *pos; }
+ pointer operator->() const { return &(operator*()); }
+
+ // Arithmetic. The only hard part is making sure that
+ // we're not on an empty or marked-deleted array element
+ void advance_past_empty_and_deleted() {
+ while ( pos != end && (ht->test_empty(*this) || ht->test_deleted(*this)) )
+ ++pos;
+ }
+ const_iterator& operator++() {
+ assert(pos != end); ++pos; advance_past_empty_and_deleted(); return *this;
+ }
+ const_iterator operator++(int) { const_iterator tmp(*this); ++*this; return tmp; }
+
+ // Comparison.
+ bool operator==(const const_iterator& it) const { return pos == it.pos; }
+ bool operator!=(const const_iterator& it) const { return pos != it.pos; }
+
+
+ // The actual data
+ const dense_hashtable<V,K,HF,ExK,SetK,EqK,A> *ht;
+ pointer pos, end;
+};
+
+template <class Value, class Key, class HashFcn,
+ class ExtractKey, class SetKey, class EqualKey, class Alloc>
+class dense_hashtable {
+ public:
+ typedef Key key_type;
+ typedef Value value_type;
+ typedef HashFcn hasher;
+ typedef EqualKey key_equal;
+
+ typedef size_t size_type;
+ typedef STL_NAMESPACE::ptrdiff_t difference_type;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef dense_hashtable_iterator<Value, Key, HashFcn,
+ ExtractKey, SetKey, EqualKey, Alloc>
+ iterator;
+
+ typedef dense_hashtable_const_iterator<Value, Key, HashFcn,
+ ExtractKey, SetKey, EqualKey, Alloc>
+ const_iterator;
+
+ // These come from tr1. For us they're the same as regular iterators.
+ typedef iterator local_iterator;
+ typedef const_iterator const_local_iterator;
+
+ // How full we let the table get before we resize, by default.
+ // Knuth says .8 is good -- higher causes us to probe too much,
+ // though it saves memory.
+ static const float HT_OCCUPANCY_FLT; // = 0.5;
+
+ // How empty we let the table get before we resize lower, by default.
+ // (0.0 means never resize lower.)
+ // It should be less than OCCUPANCY_FLT / 2 or we thrash resizing
+ static const float HT_EMPTY_FLT; // = 0.4 * HT_OCCUPANCY_FLT
+
+ // Minimum size we're willing to let hashtables be.
+ // Must be a power of two, and at least 4.
+ // Note, however, that for a given hashtable, the initial size is a
+ // function of the first constructor arg, and may be >HT_MIN_BUCKETS.
+ static const size_t HT_MIN_BUCKETS = 4;
+
+ // By default, if you don't specify a hashtable size at
+ // construction-time, we use this size. Must be a power of two, and
+ // at least HT_MIN_BUCKETS.
+ static const size_t HT_DEFAULT_STARTING_BUCKETS = 32;
+
+
+ // ITERATOR FUNCTIONS
+ iterator begin() { return iterator(this, table,
+ table + num_buckets, true); }
+ iterator end() { return iterator(this, table + num_buckets,
+ table + num_buckets, true); }
+ const_iterator begin() const { return const_iterator(this, table,
+ table+num_buckets,true);}
+ const_iterator end() const { return const_iterator(this, table + num_buckets,
+ table+num_buckets,true);}
+
+ // These come from tr1 unordered_map. They iterate over 'bucket' n.
+ // For sparsehashtable, we could consider each 'group' to be a bucket,
+ // I guess, but I don't really see the point. We'll just consider
+ // bucket n to be the n-th element of the sparsetable, if it's occupied,
+ // or some empty element, otherwise.
+ local_iterator begin(size_type i) {
+ return local_iterator(this, table + i, table + i+1, false);
+ }
+ local_iterator end(size_type i) {
+ local_iterator it = begin(i);
+ if (!test_empty(i) && !test_deleted(i))
+ ++it;
+ return it;
+ }
+ const_local_iterator begin(size_type i) const {
+ return const_local_iterator(this, table + i, table + i+1, false);
+ }
+ const_local_iterator end(size_type i) const {
+ const_local_iterator it = begin(i);
+ if (!test_empty(i) && !test_deleted(i))
+ ++it;
+ return it;
+ }
+
+ // ACCESSOR FUNCTIONS for the things we templatize on, basically
+ hasher hash_funct() const { return hash; }
+ key_equal key_eq() const { return equals; }
+
+ private:
+ // Annoyingly, we can't copy values around, because they might have
+ // const components (they're probably pair<const X, Y>). We use
+ // explicit destructor invocation and placement new to get around
+ // this. Arg.
+ void set_value(value_type* dst, const value_type& src) {
+ dst->~value_type();
+ new(dst) value_type(src);
+ }
+
+ void destroy_buckets(size_type first, size_type last) {
+ for ( ; first != last; ++first)
+ table[first].~value_type();
+ }
+
+ // DELETE HELPER FUNCTIONS
+ // This lets the user describe a key that will indicate deleted
+ // table entries. This key should be an "impossible" entry --
+ // if you try to insert it for real, you won't be able to retrieve it!
+ // (NB: while you pass in an entire value, only the key part is looked
+ // at. This is just because I don't know how to assign just a key.)
+ private:
+ void squash_deleted() { // gets rid of any deleted entries we have
+ if ( num_deleted ) { // get rid of deleted before writing
+ dense_hashtable tmp(*this); // copying will get rid of deleted
+ swap(tmp); // now we are tmp
+ }
+ assert(num_deleted == 0);
+ }
+
+ public:
+ void set_deleted_key(const key_type &key) {
+ // the empty indicator (if specified) and the deleted indicator
+ // must be different
+ assert(!use_empty || !equals(key, get_key(emptyval)));
+ // It's only safe to change what "deleted" means if we purge deleted guys
+ squash_deleted();
+ use_deleted = true;
+ delkey = key;
+ }
+ void clear_deleted_key() {
+ squash_deleted();
+ use_deleted = false;
+ }
+
+ // These are public so the iterators can use them
+ // True if the item at position bucknum is "deleted" marker
+ bool test_deleted(size_type bucknum) const {
+ // The num_deleted test is crucial for read(): after read(), the ht values
+ // are garbage, and we don't want to think some of them are deleted.
+ return (use_deleted && num_deleted > 0 &&
+ equals(delkey, get_key(table[bucknum])));
+ }
+ bool test_deleted(const iterator &it) const {
+ return (use_deleted && num_deleted > 0 &&
+ equals(delkey, get_key(*it)));
+ }
+ bool test_deleted(const const_iterator &it) const {
+ return (use_deleted && num_deleted > 0 &&
+ equals(delkey, get_key(*it)));
+ }
+ // Set it so test_deleted is true. true if object didn't used to be deleted
+ // See below (at erase()) to explain why we allow const_iterators
+ bool set_deleted(const_iterator &it) {
+ assert(use_deleted); // bad if set_deleted_key() wasn't called
+ bool retval = !test_deleted(it);
+ // &* converts from iterator to value-type
+ set_key(const_cast<value_type*>(&(*it)), delkey);
+ return retval;
+ }
+ // Set it so test_deleted is false. true if object used to be deleted
+ bool clear_deleted(const_iterator &it) {
+ assert(use_deleted); // bad if set_deleted_key() wasn't called
+ // happens automatically when we assign something else in its place
+ return test_deleted(it);
+ }
+
+ // EMPTY HELPER FUNCTIONS
+ // This lets the user describe a key that will indicate empty (unused)
+ // table entries. This key should be an "impossible" entry --
+ // if you try to insert it for real, you won't be able to retrieve it!
+ // (NB: while you pass in an entire value, only the key part is looked
+ // at. This is just because I don't know how to assign just a key.)
+ public:
+ // These are public so the iterators can use them
+ // True if the item at position bucknum is "empty" marker
+ bool test_empty(size_type bucknum) const {
+ assert(use_empty); // we always need to know what's empty!
+ return equals(get_key(emptyval), get_key(table[bucknum]));
+ }
+ bool test_empty(const iterator &it) const {
+ assert(use_empty); // we always need to know what's empty!
+ return equals(get_key(emptyval), get_key(*it));
+ }
+ bool test_empty(const const_iterator &it) const {
+ assert(use_empty); // we always need to know what's empty!
+ return equals(get_key(emptyval), get_key(*it));
+ }
+
+ private:
+ // You can either set a range empty or an individual element
+ void set_empty(size_type bucknum) {
+ assert(use_empty);
+ set_value(&table[bucknum], emptyval);
+ }
+ void fill_range_with_empty(value_type* table_start, value_type* table_end) {
+ // Like set_empty(range), but doesn't destroy previous contents
+ STL_NAMESPACE::uninitialized_fill(table_start, table_end, emptyval);
+ }
+ void set_empty(size_type buckstart, size_type buckend) {
+ assert(use_empty);
+ destroy_buckets(buckstart, buckend);
+ fill_range_with_empty(table + buckstart, table + buckend);
+ }
+
+ public:
+ // TODO(csilvers): change all callers of this to pass in a key instead,
+ // and take a const key_type instead of const value_type.
+ void set_empty_key(const value_type &val) {
+ // Once you set the empty key, you can't change it
+ assert(!use_empty);
+ // The deleted indicator (if specified) and the empty indicator
+ // must be different.
+ assert(!use_deleted || !equals(get_key(val), delkey));
+ use_empty = true;
+ set_value(&emptyval, val);
+
+ assert(!table); // must set before first use
+ // num_buckets was set in constructor even though table was NULL
+ table = (value_type *) malloc(num_buckets * sizeof(*table));
+ assert(table);
+ fill_range_with_empty(table, table + num_buckets);
+ }
+
+ // FUNCTIONS CONCERNING SIZE
+ public:
+ size_type size() const { return num_elements - num_deleted; }
+ // Buckets are always a power of 2
+ size_type max_size() const { return (size_type(-1) >> 1U) + 1; }
+ bool empty() const { return size() == 0; }
+ size_type bucket_count() const { return num_buckets; }
+ size_type max_bucket_count() const { return max_size(); }
+ size_type nonempty_bucket_count() const { return num_elements; }
+ // These are tr1 methods. Their idea of 'bucket' doesn't map well to
+ // what we do. We just say every bucket has 0 or 1 items in it.
+ size_type bucket_size(size_type i) const {
+ return begin(i) == end(i) ? 0 : 1;
+ }
+
+
+
+ private:
+ // Because of the above, size_type(-1) is never legal; use it for errors
+ static const size_type ILLEGAL_BUCKET = size_type(-1);
+
+ private:
+ // This is the smallest size a hashtable can be without being too crowded
+ // If you like, you can give a min #buckets as well as a min #elts
+ size_type min_size(size_type num_elts, size_type min_buckets_wanted) {
+ size_type sz = HT_MIN_BUCKETS; // min buckets allowed
+ while ( sz < min_buckets_wanted || num_elts >= sz * enlarge_resize_percent )
+ sz *= 2;
+ return sz;
+ }
+
+ // Used after a string of deletes
+ void maybe_shrink() {
+ assert(num_elements >= num_deleted);
+ assert((bucket_count() & (bucket_count()-1)) == 0); // is a power of two
+ assert(bucket_count() >= HT_MIN_BUCKETS);
+
+ // If you construct a hashtable with < HT_DEFAULT_STARTING_BUCKETS,
+ // we'll never shrink until you get relatively big, and we'll never
+ // shrink below HT_DEFAULT_STARTING_BUCKETS. Otherwise, something
+ // like "dense_hash_set<int> x; x.insert(4); x.erase(4);" will
+ // shrink us down to HT_MIN_BUCKETS buckets, which is too small.
+ if (shrink_threshold > 0 &&
+ (num_elements-num_deleted) < shrink_threshold &&
+ bucket_count() > HT_DEFAULT_STARTING_BUCKETS ) {
+ size_type sz = bucket_count() / 2; // find how much we should shrink
+ while ( sz > HT_DEFAULT_STARTING_BUCKETS &&
+ (num_elements - num_deleted) < sz * shrink_resize_percent )
+ sz /= 2; // stay a power of 2
+ dense_hashtable tmp(*this, sz); // Do the actual resizing
+ swap(tmp); // now we are tmp
+ }
+ consider_shrink = false; // because we just considered it
+ }
+
+ // We'll let you resize a hashtable -- though this makes us copy all!
+ // When you resize, you say, "make it big enough for this many more elements"
+ void resize_delta(size_type delta) {
+ if ( consider_shrink ) // see if lots of deletes happened
+ maybe_shrink();
+ if ( bucket_count() > HT_MIN_BUCKETS &&
+ (num_elements + delta) <= enlarge_threshold )
+ return; // we're ok as we are
+
+ // Sometimes, we need to resize just to get rid of all the
+ // "deleted" buckets that are clogging up the hashtable. So when
+ // deciding whether to resize, count the deleted buckets (which
+ // are currently taking up room). But later, when we decide what
+ // size to resize to, *don't* count deleted buckets, since they
+ // get discarded during the resize.
+ const size_type needed_size = min_size(num_elements + delta, 0);
+ if ( needed_size > bucket_count() ) { // we don't have enough buckets
+ const size_type resize_to = min_size(num_elements - num_deleted + delta,
+ 0);
+ dense_hashtable tmp(*this, resize_to);
+ swap(tmp); // now we are tmp
+ }
+ }
+
+ // Increase number of buckets, assuming value_type has trivial copy
+ // constructor and destructor. (Really, we want it to have "trivial
+ // move", because that's what realloc does. But there's no way to
+ // capture that using type_traits, so we pretend that move(x, y) is
+ // equivalent to "x.~T(); new(x) T(y);" which is pretty much
+ // correct, if a bit conservative.)
+ void expand_array(size_t resize_to, true_type) {
+ table = (value_type *) realloc(table, resize_to * sizeof(value_type));
+ assert(table);
+ fill_range_with_empty(table + num_buckets, table + resize_to);
+ }
+
+ // Increase number of buckets, without special assumptions about value_type.
+ // TODO(austern): make this exception safe. Handle exceptions from
+ // value_type's copy constructor.
+ void expand_array(size_t resize_to, false_type) {
+ value_type* new_table =
+ (value_type *) malloc(resize_to * sizeof(value_type));
+ assert(new_table);
+ STL_NAMESPACE::uninitialized_copy(table, table + num_buckets, new_table);
+ fill_range_with_empty(new_table + num_buckets, new_table + resize_to);
+ destroy_buckets(0, num_buckets);
+ free(table);
+ table = new_table;
+ }
+
+ // Used to actually do the rehashing when we grow/shrink a hashtable
+ void copy_from(const dense_hashtable &ht, size_type min_buckets_wanted) {
+ clear(); // clear table, set num_deleted to 0
+
+ // If we need to change the size of our table, do it now
+ const size_type resize_to = min_size(ht.size(), min_buckets_wanted);
+ if ( resize_to > bucket_count() ) { // we don't have enough buckets
+ typedef integral_constant<bool,
+ (has_trivial_copy<value_type>::value &&
+ has_trivial_destructor<value_type>::value)>
+ realloc_ok; // we pretend mv(x,y) == "x.~T(); new(x) T(y)"
+ expand_array(resize_to, realloc_ok());
+ num_buckets = resize_to;
+ reset_thresholds();
+ }
+
+ // We use a normal iterator to get non-deleted bcks from ht
+ // We could use insert() here, but since we know there are
+ // no duplicates and no deleted items, we can be more efficient
+ assert((bucket_count() & (bucket_count()-1)) == 0); // a power of two
+ for ( const_iterator it = ht.begin(); it != ht.end(); ++it ) {
+ size_type num_probes = 0; // how many times we've probed
+ size_type bucknum;
+ const size_type bucket_count_minus_one = bucket_count() - 1;
+ for (bucknum = hash(get_key(*it)) & bucket_count_minus_one;
+ !test_empty(bucknum); // not empty
+ bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one) {
+ ++num_probes;
+ assert(num_probes < bucket_count()); // or else the hashtable is full
+ }
+ set_value(&table[bucknum], *it); // copies the value to here
+ num_elements++;
+ }
+ }
+
+ // Required by the spec for hashed associative container
+ public:
+ // Though the docs say this should be num_buckets, I think it's much
+ // more useful as req_elements. As a special feature, calling with
+ // req_elements==0 will cause us to shrink if we can, saving space.
+ void resize(size_type req_elements) { // resize to this or larger
+ if ( consider_shrink || req_elements == 0 )
+ maybe_shrink();
+ if ( req_elements > num_elements )
+ return resize_delta(req_elements - num_elements);
+ }
+
+ // Get and change the value of shrink_resize_percent and
+ // enlarge_resize_percent. The description at the beginning of this
+ // file explains how to choose the values. Setting the shrink
+ // parameter to 0.0 ensures that the table never shrinks.
+ void get_resizing_parameters(float* shrink, float* grow) const {
+ *shrink = shrink_resize_percent;
+ *grow = enlarge_resize_percent;
+ }
+ void set_resizing_parameters(float shrink, float grow) {
+ assert(shrink >= 0.0);
+ assert(grow <= 1.0);
+ if (shrink > grow/2.0f)
+ shrink = grow / 2.0f; // otherwise we thrash hashtable size
+ shrink_resize_percent = shrink;
+ enlarge_resize_percent = grow;
+ reset_thresholds();
+ }
+
+ // CONSTRUCTORS -- as required by the specs, we take a size,
+ // but also let you specify a hashfunction, key comparator,
+ // and key extractor. We also define a copy constructor and =.
+ // DESTRUCTOR -- needs to free the table
+ explicit dense_hashtable(size_type expected_max_items_in_table = 0,
+ const HashFcn& hf = HashFcn(),
+ const EqualKey& eql = EqualKey(),
+ const ExtractKey& ext = ExtractKey(),
+ const SetKey& set = SetKey())
+ : hash(hf), equals(eql), get_key(ext), set_key(set), num_deleted(0),
+ use_deleted(false), use_empty(false),
+ delkey(), emptyval(), enlarge_resize_percent(HT_OCCUPANCY_FLT),
+ shrink_resize_percent(HT_EMPTY_FLT), table(NULL),
+ num_buckets(expected_max_items_in_table == 0
+ ? HT_DEFAULT_STARTING_BUCKETS
+ : min_size(expected_max_items_in_table, 0)),
+ num_elements(0) {
+ // table is NULL until emptyval is set. However, we set num_buckets
+ // here so we know how much space to allocate once emptyval is set
+ reset_thresholds();
+ }
+
+ // As a convenience for resize(), we allow an optional second argument
+ // which lets you make this new hashtable a different size than ht
+ dense_hashtable(const dense_hashtable& ht,
+ size_type min_buckets_wanted = HT_DEFAULT_STARTING_BUCKETS)
+ : hash(ht.hash), equals(ht.equals),
+ get_key(ht.get_key), set_key(ht.set_key), num_deleted(0),
+ use_deleted(ht.use_deleted), use_empty(ht.use_empty),
+ delkey(ht.delkey), emptyval(ht.emptyval),
+ enlarge_resize_percent(ht.enlarge_resize_percent),
+ shrink_resize_percent(ht.shrink_resize_percent), table(NULL),
+ num_buckets(0), num_elements(0) {
+ reset_thresholds();
+ copy_from(ht, min_buckets_wanted); // copy_from() ignores deleted entries
+ }
+
+ dense_hashtable& operator= (const dense_hashtable& ht) {
+ if (&ht == this) return *this; // don't copy onto ourselves
+ clear();
+ hash = ht.hash;
+ equals = ht.equals;
+ get_key = ht.get_key;
+ set_key = ht.set_key;
+ use_deleted = ht.use_deleted;
+ use_empty = ht.use_empty;
+ delkey = ht.delkey;
+ set_value(&emptyval, ht.emptyval);
+ enlarge_resize_percent = ht.enlarge_resize_percent;
+ shrink_resize_percent = ht.shrink_resize_percent;
+ copy_from(ht, HT_MIN_BUCKETS); // sets num_deleted to 0 too
+ return *this;
+ }
+
+ ~dense_hashtable() {
+ if (table) {
+ destroy_buckets(0, num_buckets);
+ free(table);
+ }
+ }
+
+ // Many STL algorithms use swap instead of copy constructors
+ void swap(dense_hashtable& ht) {
+ STL_NAMESPACE::swap(hash, ht.hash);
+ STL_NAMESPACE::swap(equals, ht.equals);
+ STL_NAMESPACE::swap(get_key, ht.get_key);
+ STL_NAMESPACE::swap(set_key, ht.set_key);
+ STL_NAMESPACE::swap(num_deleted, ht.num_deleted);
+ STL_NAMESPACE::swap(use_deleted, ht.use_deleted);
+ STL_NAMESPACE::swap(use_empty, ht.use_empty);
+ STL_NAMESPACE::swap(enlarge_resize_percent, ht.enlarge_resize_percent);
+ STL_NAMESPACE::swap(shrink_resize_percent, ht.shrink_resize_percent);
+ STL_NAMESPACE::swap(delkey, ht.delkey);
+ { value_type tmp; // for annoying reasons, swap() doesn't work
+ set_value(&tmp, emptyval);
+ set_value(&emptyval, ht.emptyval);
+ set_value(&ht.emptyval, tmp);
+ }
+ STL_NAMESPACE::swap(table, ht.table);
+ STL_NAMESPACE::swap(num_buckets, ht.num_buckets);
+ STL_NAMESPACE::swap(num_elements, ht.num_elements);
+ reset_thresholds();
+ ht.reset_thresholds();
+ }
+
+ // It's always nice to be able to clear a table without deallocating it
+ void clear() {
+ if (table)
+ destroy_buckets(0, num_buckets);
+ num_buckets = min_size(0,0); // our new size
+ reset_thresholds();
+ table = (value_type *) realloc(table, num_buckets * sizeof(*table));
+ assert(table);
+ fill_range_with_empty(table, table + num_buckets);
+ num_elements = 0;
+ num_deleted = 0;
+ }
+
+ // Clear the table without resizing it.
+ // Mimicks the stl_hashtable's behaviour when clear()-ing in that it
+ // does not modify the bucket count
+ void clear_no_resize() {
+ if (table) {
+ set_empty(0, num_buckets);
+ }
+ // don't consider to shrink before another erase()
+ reset_thresholds();
+ num_elements = 0;
+ num_deleted = 0;
+ }
+
+ // LOOKUP ROUTINES
+ private:
+ // Returns a pair of positions: 1st where the object is, 2nd where
+ // it would go if you wanted to insert it. 1st is ILLEGAL_BUCKET
+ // if object is not found; 2nd is ILLEGAL_BUCKET if it is.
+ // Note: because of deletions where-to-insert is not trivial: it's the
+ // first deleted bucket we see, as long as we don't find the key later
+ pair<size_type, size_type> find_position(const key_type &key) const {
+ size_type num_probes = 0; // how many times we've probed
+ const size_type bucket_count_minus_one = bucket_count() - 1;
+ size_type bucknum = hash(key) & bucket_count_minus_one;
+ size_type insert_pos = ILLEGAL_BUCKET; // where we would insert
+ while ( 1 ) { // probe until something happens
+ if ( test_empty(bucknum) ) { // bucket is empty
+ if ( insert_pos == ILLEGAL_BUCKET ) // found no prior place to insert
+ return pair<size_type,size_type>(ILLEGAL_BUCKET, bucknum);
+ else
+ return pair<size_type,size_type>(ILLEGAL_BUCKET, insert_pos);
+
+ } else if ( test_deleted(bucknum) ) {// keep searching, but mark to insert
+ if ( insert_pos == ILLEGAL_BUCKET )
+ insert_pos = bucknum;
+
+ } else if ( equals(key, get_key(table[bucknum])) ) {
+ return pair<size_type,size_type>(bucknum, ILLEGAL_BUCKET);
+ }
+ ++num_probes; // we're doing another probe
+ bucknum = (bucknum + JUMP_(key, num_probes)) & bucket_count_minus_one;
+ assert(num_probes < bucket_count()); // don't probe too many times!
+ }
+ }
+
+ public:
+ iterator find(const key_type& key) {
+ if ( size() == 0 ) return end();
+ pair<size_type, size_type> pos = find_position(key);
+ if ( pos.first == ILLEGAL_BUCKET ) // alas, not there
+ return end();
+ else
+ return iterator(this, table + pos.first, table + num_buckets, false);
+ }
+
+ const_iterator find(const key_type& key) const {
+ if ( size() == 0 ) return end();
+ pair<size_type, size_type> pos = find_position(key);
+ if ( pos.first == ILLEGAL_BUCKET ) // alas, not there
+ return end();
+ else
+ return const_iterator(this, table + pos.first, table+num_buckets, false);
+ }
+
+ // This is a tr1 method: the bucket a given key is in, or what bucket
+ // it would be put in, if it were to be inserted. Shrug.
+ size_type bucket(const key_type& key) const {
+ pair<size_type, size_type> pos = find_position(key);
+ return pos.first == ILLEGAL_BUCKET ? pos.second : pos.first;
+ }
+
+ // Counts how many elements have key key. For maps, it's either 0 or 1.
+ size_type count(const key_type &key) const {
+ pair<size_type, size_type> pos = find_position(key);
+ return pos.first == ILLEGAL_BUCKET ? 0 : 1;
+ }
+
+ // Likewise, equal_range doesn't really make sense for us. Oh well.
+ pair<iterator,iterator> equal_range(const key_type& key) {
+ iterator pos = find(key); // either an iterator or end
+ if (pos == end()) {
+ return pair<iterator,iterator>(pos, pos);
+ } else {
+ const iterator startpos = pos++;
+ return pair<iterator,iterator>(startpos, pos);
+ }
+ }
+ pair<const_iterator,const_iterator> equal_range(const key_type& key) const {
+ const_iterator pos = find(key); // either an iterator or end
+ if (pos == end()) {
+ return pair<const_iterator,const_iterator>(pos, pos);
+ } else {
+ const const_iterator startpos = pos++;
+ return pair<const_iterator,const_iterator>(startpos, pos);
+ }
+ }
+
+
+ // INSERTION ROUTINES
+ private:
+ // If you know *this is big enough to hold obj, use this routine
+ pair<iterator, bool> insert_noresize(const value_type& obj) {
+ // First, double-check we're not inserting delkey or emptyval
+ assert(!use_empty || !equals(get_key(obj), get_key(emptyval)));
+ assert(!use_deleted || !equals(get_key(obj), delkey));
+ const pair<size_type,size_type> pos = find_position(get_key(obj));
+ if ( pos.first != ILLEGAL_BUCKET) { // object was already there
+ return pair<iterator,bool>(iterator(this, table + pos.first,
+ table + num_buckets, false),
+ false); // false: we didn't insert
+ } else { // pos.second says where to put it
+ if ( test_deleted(pos.second) ) { // just replace if it's been del.
+ const_iterator delpos(this, table + pos.second, // shrug:
+ table + num_buckets, false);// shouldn't need const
+ clear_deleted(delpos);
+ assert( num_deleted > 0);
+ --num_deleted; // used to be, now it isn't
+ } else {
+ ++num_elements; // replacing an empty bucket
+ }
+ set_value(&table[pos.second], obj);
+ return pair<iterator,bool>(iterator(this, table + pos.second,
+ table + num_buckets, false),
+ true); // true: we did insert
+ }
+ }
+
+ public:
+ // This is the normal insert routine, used by the outside world
+ pair<iterator, bool> insert(const value_type& obj) {
+ resize_delta(1); // adding an object, grow if need be
+ return insert_noresize(obj);
+ }
+
+ // When inserting a lot at a time, we specialize on the type of iterator
+ template <class InputIterator>
+ void insert(InputIterator f, InputIterator l) {
+ // specializes on iterator type
+ insert(f, l, typename STL_NAMESPACE::iterator_traits<InputIterator>::iterator_category());
+ }
+
+ // Iterator supports operator-, resize before inserting
+ template <class ForwardIterator>
+ void insert(ForwardIterator f, ForwardIterator l,
+ STL_NAMESPACE::forward_iterator_tag) {
+ size_type n = STL_NAMESPACE::distance(f, l); // TODO(csilvers): standard?
+ resize_delta(n);
+ for ( ; n > 0; --n, ++f)
+ insert_noresize(*f);
+ }
+
+ // Arbitrary iterator, can't tell how much to resize
+ template <class InputIterator>
+ void insert(InputIterator f, InputIterator l,
+ STL_NAMESPACE::input_iterator_tag) {
+ for ( ; f != l; ++f)
+ insert(*f);
+ }
+
+
+ // DELETION ROUTINES
+ size_type erase(const key_type& key) {
+ // First, double-check we're not trying to erase delkey or emptyval
+ assert(!use_empty || !equals(key, get_key(emptyval)));
+ assert(!use_deleted || !equals(key, delkey));
+ const_iterator pos = find(key); // shrug: shouldn't need to be const
+ if ( pos != end() ) {
+ assert(!test_deleted(pos)); // or find() shouldn't have returned it
+ set_deleted(pos);
+ ++num_deleted;
+ consider_shrink = true; // will think about shrink after next insert
+ return 1; // because we deleted one thing
+ } else {
+ return 0; // because we deleted nothing
+ }
+ }
+
+ // This is really evil: really it should be iterator, not const_iterator.
+ // But...the only reason keys are const is to allow lookup.
+ // Since that's a moot issue for deleted keys, we allow const_iterators
+ void erase(const_iterator pos) {
+ if ( pos == end() ) return; // sanity check
+ if ( set_deleted(pos) ) { // true if object has been newly deleted
+ ++num_deleted;
+ consider_shrink = true; // will think about shrink after next insert
+ }
+ }
+
+ void erase(const_iterator f, const_iterator l) {
+ for ( ; f != l; ++f) {
+ if ( set_deleted(f) ) // should always be true
+ ++num_deleted;
+ }
+ consider_shrink = true; // will think about shrink after next insert
+ }
+
+
+ // COMPARISON
+ bool operator==(const dense_hashtable& ht) const {
+ if (size() != ht.size()) {
+ return false;
+ } else if (this == &ht) {
+ return true;
+ } else {
+ // Iterate through the elements in "this" and see if the
+ // corresponding element is in ht
+ for ( const_iterator it = begin(); it != end(); ++it ) {
+ const_iterator it2 = ht.find(get_key(*it));
+ if ((it2 == ht.end()) || (*it != *it2)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ bool operator!=(const dense_hashtable& ht) const {
+ return !(*this == ht);
+ }
+
+
+ // I/O
+ // We support reading and writing hashtables to disk. Alas, since
+ // I don't know how to write a hasher or key_equal, you have to make
+ // sure everything but the table is the same. We compact before writing
+ //
+ // NOTE: These functions are currently TODO. They've not been implemented.
+ bool write_metadata(FILE *fp) {
+ squash_deleted(); // so we don't have to worry about delkey
+ return false; // TODO
+ }
+
+ bool read_metadata(FILE *fp) {
+ num_deleted = 0; // since we got rid before writing
+ assert(use_empty); // have to set this before calling us
+ if (table) free(table); // we'll make our own
+ // TODO: read magic number
+ // TODO: read num_buckets
+ reset_thresholds();
+ table = (value_type *) malloc(num_buckets * sizeof(*table));
+ assert(table);
+ fill_range_with_empty(table, table + num_buckets);
+ // TODO: read num_elements
+ for ( size_type i = 0; i < num_elements; ++i ) {
+ // TODO: read bucket_num
+ // TODO: set with non-empty, non-deleted value
+ }
+ return false; // TODO
+ }
+
+ // If your keys and values are simple enough, we can write them to
+ // disk for you. "simple enough" means value_type is a POD type
+ // that contains no pointers. However, we don't try to normalize
+ // endianness
+ bool write_nopointer_data(FILE *fp) const {
+ for ( const_iterator it = begin(); it != end(); ++it ) {
+ // TODO: skip empty/deleted values
+ if ( !fwrite(&*it, sizeof(*it), 1, fp) ) return false;
+ }
+ return false;
+ }
+
+ // When reading, we have to override the potential const-ness of *it
+ bool read_nopointer_data(FILE *fp) {
+ for ( iterator it = begin(); it != end(); ++it ) {
+ // TODO: skip empty/deleted values
+ if ( !fread(reinterpret_cast<void*>(&(*it)), sizeof(*it), 1, fp) )
+ return false;
+ }
+ return false;
+ }
+
+ private:
+ // The actual data
+ hasher hash; // required by hashed_associative_container
+ key_equal equals;
+ ExtractKey get_key;
+ SetKey set_key;
+ size_type num_deleted; // how many occupied buckets are marked deleted
+ bool use_deleted; // false until delkey has been set
+ bool use_empty; // you must do this before you start
+ // TODO(csilvers): make a pointer, and get rid of use_deleted (benchmark!)
+ key_type delkey; // which key marks deleted entries
+ value_type emptyval; // which key marks unused entries
+ float enlarge_resize_percent; // how full before resize
+ float shrink_resize_percent; // how empty before resize
+ size_type shrink_threshold; // num_buckets * shrink_resize_percent
+ size_type enlarge_threshold; // num_buckets * enlarge_resize_percent
+ value_type *table;
+ size_type num_buckets;
+ size_type num_elements;
+ bool consider_shrink; // true if we should try to shrink before next insert
+
+ void reset_thresholds() {
+ enlarge_threshold = static_cast<size_type>(num_buckets
+ * enlarge_resize_percent);
+ shrink_threshold = static_cast<size_type>(num_buckets
+ * shrink_resize_percent);
+ consider_shrink = false; // whatever caused us to reset already considered
+ }
+};
+
+// We need a global swap as well
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+inline void swap(dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &x,
+ dense_hashtable<V,K,HF,ExK,SetK,EqK,A> &y) {
+ x.swap(y);
+}
+
+#undef JUMP_
+
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+const typename dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::size_type
+dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::ILLEGAL_BUCKET;
+
+// How full we let the table get before we resize. Knuth says .8 is
+// good -- higher causes us to probe too much, though saves memory.
+// However, we go with .5, getting better performance at the cost of
+// more space (a trade-off densehashtable explicitly chooses to make).
+// Feel free to play around with different values, though.
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+const float dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_FLT = 0.5f;
+
+// How empty we let the table get before we resize lower.
+// It should be less than OCCUPANCY_FLT / 2 or we thrash resizing
+template <class V, class K, class HF, class ExK, class SetK, class EqK, class A>
+const float dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_EMPTY_FLT
+ = 0.4f * dense_hashtable<V,K,HF,ExK,SetK,EqK,A>::HT_OCCUPANCY_FLT;
+
+_END_GOOGLE_NAMESPACE_
+
+#endif /* _DENSEHASHTABLE_H_ */
diff --git a/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h b/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h
new file mode 100644
index 000000000..28c85d1f4
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/google/sparsehash/sparseconfig.h
@@ -0,0 +1,45 @@
+/*
+ * NOTE: This file is for internal use only.
+ * Do not use these #defines in your own program!
+ */
+
+/* Namespace for Google classes */
+#define GOOGLE_NAMESPACE ::google
+
+#ifdef _MSC_VER
+ /* the location of the header defining hash functions */
+ #define HASH_FUN_H <unordered_map>
+ /* the namespace of the hash<> function */
+ #define HASH_NAMESPACE stdext
+ /* The system-provided hash function including the namespace. */
+ #define SPARSEHASH_HASH HASH_NAMESPACE::hash_compare
+/* libc++ does not implement the tr1 namespce, instead the
+ * equivalient functionality is placed in namespace std,
+ * so use when it targeting such systems (OS X 10.7 onwards) */
+#elif defined(_LIBCPP_VERSION)
+ /* the location of the header defining hash functions */
+ #define HASH_FUN_H <functional>
+ /* the namespace of the hash<> function */
+ #define HASH_NAMESPACE std
+ /* The system-provided hash function including the namespace. */
+ #define SPARSEHASH_HASH HASH_NAMESPACE::hash
+#else
+ /* the location of the header defining hash functions */
+ #define HASH_FUN_H <tr1/functional>
+ /* the namespace of the hash<> function */
+ #define HASH_NAMESPACE std::tr1
+ /* The system-provided hash function including the namespace. */
+ #define SPARSEHASH_HASH HASH_NAMESPACE::hash
+#endif
+
+/* Define to 1 if the system has the type `long long'. */
+#define HAVE_LONG_LONG 1
+
+/* the namespace where STL code like vector<> is defined */
+#define STL_NAMESPACE std
+
+/* Stops putting the code inside the Google namespace */
+#define _END_GOOGLE_NAMESPACE_ }
+
+/* Puts following code inside the Google namespace */
+#define _START_GOOGLE_NAMESPACE_ namespace google {
diff --git a/sources/shiboken2/ext/sparsehash/google/type_traits.h b/sources/shiboken2/ext/sparsehash/google/type_traits.h
new file mode 100644
index 000000000..d9d4faf83
--- /dev/null
+++ b/sources/shiboken2/ext/sparsehash/google/type_traits.h
@@ -0,0 +1,250 @@
+// Copyright (c) 2006, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// ----
+// Author: Matt Austern
+//
+// Define a small subset of tr1 type traits. The traits we define are:
+// is_integral
+// is_floating_point
+// is_pointer
+// is_reference
+// is_pod
+// has_trivial_constructor
+// has_trivial_copy
+// has_trivial_assign
+// has_trivial_destructor
+// remove_const
+// remove_volatile
+// remove_cv
+// remove_reference
+// remove_pointer
+// is_convertible
+// We can add more type traits as required.
+
+#ifndef BASE_TYPE_TRAITS_H_
+#define BASE_TYPE_TRAITS_H_
+
+#include "google/sparsehash/sparseconfig.h"
+#include <utility> // For pair
+
+_START_GOOGLE_NAMESPACE_
+
+// integral_constant, defined in tr1, is a wrapper for an integer
+// value. We don't really need this generality; we could get away
+// with hardcoding the integer type to bool. We use the fully
+// general integer_constant for compatibility with tr1.
+
+template<class T, T v>
+struct integral_constant {
+ static const T value = v;
+ typedef T value_type;
+ typedef integral_constant<T, v> type;
+};
+
+template <class T, T v> const T integral_constant<T, v>::value;
+
+// Abbreviations: true_type and false_type are structs that represent
+// boolean true and false values.
+typedef integral_constant<bool, true> true_type;
+typedef integral_constant<bool, false> false_type;
+
+// Types small_ and big_ are guaranteed such that sizeof(small_) <
+// sizeof(big_)
+typedef char small_;
+
+struct big_ {
+ char dummy[2];
+};
+
+// is_integral is false except for the built-in integer types.
+template <class T> struct is_integral : false_type { };
+template<> struct is_integral<bool> : true_type { };
+template<> struct is_integral<char> : true_type { };
+template<> struct is_integral<unsigned char> : true_type { };
+template<> struct is_integral<signed char> : true_type { };
+#if defined(_MSC_VER)
+// wchar_t is not by default a distinct type from unsigned short in
+// Microsoft C.
+// See http://msdn2.microsoft.com/en-us/library/dh8che7s(VS.80).aspx
+template<> struct is_integral<__wchar_t> : true_type { };
+#else
+template<> struct is_integral<wchar_t> : true_type { };
+#endif
+template<> struct is_integral<short> : true_type { };
+template<> struct is_integral<unsigned short> : true_type { };
+template<> struct is_integral<int> : true_type { };
+template<> struct is_integral<unsigned int> : true_type { };
+template<> struct is_integral<long> : true_type { };
+template<> struct is_integral<unsigned long> : true_type { };
+#ifdef HAVE_LONG_LONG
+template<> struct is_integral<long long> : true_type { };
+template<> struct is_integral<unsigned long long> : true_type { };
+#endif
+
+
+// is_floating_point is false except for the built-in floating-point types.
+template <class T> struct is_floating_point : false_type { };
+template<> struct is_floating_point<float> : true_type { };
+template<> struct is_floating_point<double> : true_type { };
+template<> struct is_floating_point<long double> : true_type { };
+
+
+// is_pointer is false except for pointer types.
+template <class T> struct is_pointer : false_type { };
+template <class T> struct is_pointer<T*> : true_type { };
+
+
+// is_reference is false except for reference types.
+template<typename T> struct is_reference : false_type {};
+template<typename T> struct is_reference<T&> : true_type {};
+
+
+// We can't get is_pod right without compiler help, so fail conservatively.
+// We will assume it's false except for arithmetic types and pointers,
+// and const versions thereof. Note that std::pair is not a POD.
+template <class T> struct is_pod
+ : integral_constant<bool, (is_integral<T>::value ||
+ is_floating_point<T>::value ||
+ is_pointer<T>::value)> { };
+template <class T> struct is_pod<const T> : is_pod<T> { };
+
+
+// We can't get has_trivial_constructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// constructors. (3) array of a type with a trivial constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_constructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_constructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_constructor<T>::value &&
+ has_trivial_constructor<U>::value)> { };
+template <class A, int N> struct has_trivial_constructor<A[N]>
+ : has_trivial_constructor<A> { };
+template <class T> struct has_trivial_constructor<const T>
+ : has_trivial_constructor<T> { };
+
+// We can't get has_trivial_copy right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial copy constructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_copy : is_pod<T> { };
+template <class T, class U> struct has_trivial_copy<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_copy<T>::value &&
+ has_trivial_copy<U>::value)> { };
+template <class A, int N> struct has_trivial_copy<A[N]>
+ : has_trivial_copy<A> { };
+template <class T> struct has_trivial_copy<const T> : has_trivial_copy<T> { };
+
+// We can't get has_trivial_assign right without compiler help, so fail
+// conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial copy
+// constructors. (3) array of a type with a trivial assign constructor.
+template <class T> struct has_trivial_assign : is_pod<T> { };
+template <class T, class U> struct has_trivial_assign<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_assign<T>::value &&
+ has_trivial_assign<U>::value)> { };
+template <class A, int N> struct has_trivial_assign<A[N]>
+ : has_trivial_assign<A> { };
+
+// We can't get has_trivial_destructor right without compiler help, so
+// fail conservatively. We will assume it's false except for: (1) types
+// for which is_pod is true. (2) std::pair of types with trivial
+// destructors. (3) array of a type with a trivial destructor.
+// (4) const versions thereof.
+template <class T> struct has_trivial_destructor : is_pod<T> { };
+template <class T, class U> struct has_trivial_destructor<std::pair<T, U> >
+ : integral_constant<bool,
+ (has_trivial_destructor<T>::value &&
+ has_trivial_destructor<U>::value)> { };
+template <class A, int N> struct has_trivial_destructor<A[N]>
+ : has_trivial_destructor<A> { };
+template <class T> struct has_trivial_destructor<const T>
+ : has_trivial_destructor<T> { };
+
+// Specified by TR1 [4.7.1]
+template<typename T> struct remove_const { typedef T type; };
+template<typename T> struct remove_const<T const> { typedef T type; };
+template<typename T> struct remove_volatile { typedef T type; };
+template<typename T> struct remove_volatile<T volatile> { typedef T type; };
+template<typename T> struct remove_cv {
+ typedef typename remove_const<typename remove_volatile<T>::type>::type type;
+};
+
+
+// Specified by TR1 [4.7.2]
+template<typename T> struct remove_reference { typedef T type; };
+template<typename T> struct remove_reference<T&> { typedef T type; };
+
+// Specified by TR1 [4.7.4] Pointer modifications.
+template<typename T> struct remove_pointer { typedef T type; };
+template<typename T> struct remove_pointer<T*> { typedef T type; };
+template<typename T> struct remove_pointer<T* const> { typedef T type; };
+template<typename T> struct remove_pointer<T* volatile> { typedef T type; };
+template<typename T> struct remove_pointer<T* const volatile> {
+ typedef T type; };
+
+// Specified by TR1 [4.6] Relationships between types
+#ifndef _MSC_VER
+namespace internal {
+
+// This class is an implementation detail for is_convertible, and you
+// don't need to know how it works to use is_convertible. For those
+// who care: we declare two different functions, one whose argument is
+// of type To and one with a variadic argument list. We give them
+// return types of different size, so we can use sizeof to trick the
+// compiler into telling us which function it would have chosen if we
+// had called it with an argument of type From. See Alexandrescu's
+// _Modern C++ Design_ for more details on this sort of trick.
+
+template <typename From, typename To>
+struct ConvertHelper {
+ static small_ Test(To);
+ static big_ Test(...);
+ static From Create();
+};
+} // namespace internal
+
+// Inherits from true_type if From is convertible to To, false_type otherwise.
+template <typename From, typename To>
+struct is_convertible
+ : integral_constant<bool,
+ sizeof(internal::ConvertHelper<From, To>::Test(
+ internal::ConvertHelper<From, To>::Create()))
+ == sizeof(small_)> {
+};
+#endif
+
+_END_GOOGLE_NAMESPACE_
+
+#endif // BASE_TYPE_TRAITS_H_
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..d7f98a90f
--- /dev/null
+++ b/sources/shiboken2/generator/generator.cpp
@@ -0,0 +1,854 @@
+/****************************************************************************
+**
+** 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 <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+#include <QDebug>
+#include <typedatabase.h>
+
+struct Generator::GeneratorPrivate {
+ const ApiExtractor* apiextractor;
+ QString outDir;
+ // License comment
+ QString licenseComment;
+ QString packageName;
+ int numGenerated;
+ QStringList instantiatedContainersNames;
+ QStringList instantiatedSmartPointerNames;
+ QList<const AbstractMetaType *> instantiatedContainers;
+ QList<const AbstractMetaType *> instantiatedSmartPointers;
+
+};
+
+Generator::Generator() : m_d(new GeneratorPrivate)
+{
+ m_d->numGenerated = 0;
+ m_d->instantiatedContainers = QList<const AbstractMetaType *>();
+ m_d->instantiatedSmartPointers = QList<const AbstractMetaType *>();
+ m_d->instantiatedContainersNames = QStringList();
+ m_d->instantiatedSmartPointerNames = QStringList();
+}
+
+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) {
+ foreach (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;
+ foreach (const AbstractMetaType* t, type->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());
+ foreach (const AbstractMetaArgument* arg, func->arguments())
+ addInstantiatedContainersAndSmartPointers(arg->type(), func->signature());
+}
+
+void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass)
+{
+ if (!metaClass->typeEntry()->generateCode())
+ return;
+ foreach (const AbstractMetaFunction* func, metaClass->functions())
+ collectInstantiatedContainersAndSmartPointers(func);
+ foreach (const AbstractMetaField* field, metaClass->fields())
+ addInstantiatedContainersAndSmartPointers(field->type(), field->name());
+ foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
+ collectInstantiatedContainersAndSmartPointers(innerClass);
+}
+
+void Generator::collectInstantiatedContainersAndSmartPointers()
+{
+ foreach (const AbstractMetaFunction* func, globalFunctions())
+ collectInstantiatedContainersAndSmartPointers(func);
+ foreach (const AbstractMetaClass* metaClass, classes())
+ collectInstantiatedContainersAndSmartPointers(metaClass);
+}
+
+QList<const AbstractMetaType*> Generator::instantiatedContainers() const
+{
+ return m_d->instantiatedContainers;
+}
+
+QList<const AbstractMetaType*> Generator::instantiatedSmartPointers() const
+{
+ return m_d->instantiatedSmartPointers;
+}
+
+QMap< QString, QString > Generator::options() const
+{
+ return QMap<QString, QString>();
+}
+
+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();
+}
+
+QList<const PrimitiveTypeEntry*> Generator::primitiveTypes() const
+{
+ return m_d->apiextractor->primitiveTypes();
+}
+
+QList<const ContainerTypeEntry*> 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()
+{
+ foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) {
+ GeneratorContext context(cls);
+ if (!generateFileForContext(context))
+ return false;
+ }
+
+ foreach (const AbstractMetaType *type, 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());
+
+ foreach (AbstractMetaArgument *arg, func->arguments())
+ 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
+ QStringList lst(code.split(QLatin1Char('\n')));
+ QRegExp nonSpaceRegex(QLatin1String("[^\\s]"));
+ int spacesToRemove = 0;
+ foreach(QString line, lst) {
+ if (!line.trimmed().isEmpty()) {
+ spacesToRemove = line.indexOf(nonSpaceRegex);
+ if (spacesToRemove == -1)
+ spacesToRemove = 0;
+ break;
+ }
+ }
+
+ static QRegExp emptyLine(QLatin1String("\\s*[\\r]?[\\n]?\\s*"));
+
+ foreach(QString line, lst) {
+ if (!line.isEmpty() && !emptyLine.exactMatch(line)) {
+ 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<const ComplexTypeEntry*>(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<const PrimitiveTypeEntry*>(type)->defaultConstructor();
+ // If a non-C++ (i.e. defined by the user) primitive type does not have
+ // a default constructor defined by the user, the empty constructor is
+ // heuristically returned. If this is wrong the build of the generated
+ // 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<const ComplexTypeEntry*>(metaClass->typeEntry());
+ if (cType->hasDefaultConstructor())
+ return cType->defaultConstructor();
+
+ AbstractMetaFunctionList constructors = metaClass->queryFunctions(AbstractMetaClass::Constructors);
+ int maxArgs = 0;
+ foreach (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;
+ foreach (TypeEntry* templateType, metaClass->templateArguments())
+ templateTypes << templateType->qualifiedCppName();
+
+ // Empty constructor.
+ if (maxArgs == 0)
+ return QLatin1String("::") + qualifiedCppName + QLatin1String("()");
+
+ QList<const AbstractMetaFunction*> candidates;
+
+ // Constructors with C++ primitive types, enums or pointers only.
+ // Start with the ones with fewer arguments.
+ for (int i = 1; i <= maxArgs; ++i) {
+ foreach (const AbstractMetaFunction* ctor, constructors) {
+ if (ctor->isUserAdded() || ctor->isPrivate() || ctor->functionType() != AbstractMetaFunction::ConstructorFunction)
+ continue;
+
+ AbstractMetaArgumentList arguments = ctor->arguments();
+ if (arguments.size() != i)
+ continue;
+
+ QStringList args;
+ foreach (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.
+ foreach (const AbstractMetaFunction* ctor, candidates) {
+ QStringList args;
+ foreach (const AbstractMetaArgument* arg, ctor->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<typename T>
+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..f734ff9d7
--- /dev/null
+++ b/sources/shiboken2/generator/generator.h
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** 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 <abstractmetalang_typedefs.h>
+#include <dependency.h>
+#include <QtCore/QObject>
+#include <QtCore/QSharedPointer>
+#include <QtCore/QTextStream>
+#include <QtCore/QVector>
+
+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<int>. To
+ * distinguish this case, the member m_forSmartPointer is set to true.
+ *
+ * In the future the second case might be generalized for all template type instantiations.
+ */
+class GeneratorContext {
+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<QString, QString> args);
+
+ virtual QMap<QString, QString> 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
+ QList<const PrimitiveTypeEntry*> primitiveTypes() const;
+
+ /// Returns all container types found by APIExtractor
+ QList<const ContainerTypeEntry*> 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<QString> 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<QString, QString>& 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;
+
+ QList<const AbstractMetaType*> instantiatedContainers() const;
+ QList<const AbstractMetaType*> 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<Generator> GeneratorPtr;
+typedef QVector<GeneratorPtr> 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..874540e54
--- /dev/null
+++ b/sources/shiboken2/generator/main.cpp
@@ -0,0 +1,529 @@
+/****************************************************************************
+**
+** 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 <QCoreApplication>
+#include <QElapsedTimer>
+#include <QLinkedList>
+#include <QLibrary>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <iostream>
+#include <apiextractor.h>
+#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<QString, QString>& other);
+ virtual ~ArgsHandler();
+
+ inline QMap<QString, QString>& 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<QString, QString>* m_args;
+};
+
+ArgsHandler::ArgsHandler(const QMap<QString, QString>& other)
+ : m_args(new QMap<QString, QString>(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<QString, QString>::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<QString, QString>& options)
+{
+ QMap<QString, QString>::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<Generator*>*);
+
+static bool processProjectFile(QFile& projectFile, QMap<QString, QString>& args)
+{
+ QByteArray line = projectFile.readLine().trimmed();
+ if (line.isEmpty() || line != "[generator-project]")
+ return false;
+
+ QStringList includePaths;
+ 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 == "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 (!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<QString, QString> getInitializedArguments()
+{
+ QMap<QString, QString> args;
+ QStringList arguments = QCoreApplication::arguments();
+ QString appName = arguments.first();
+ arguments.removeFirst();
+
+ QString projectFileName;
+ foreach (const QString& arg, 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<QString, QString> getCommandLineArgs()
+{
+ QMap<QString, QString> args = getInitializedArguments();
+ QStringList arguments = QCoreApplication::arguments();
+ arguments.removeFirst();
+
+ int argNum = 0;
+ foreach (const QString &carg, 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<QString, QString> generalOptions;
+ generalOptions.insert(QLatin1String("project-file=<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=<path>"),
+ QLatin1String("The directory where the generated files will be written"));
+ generalOptions.insert(QLatin1String("include-paths=<path>[" PATH_SPLITTER "<path>" PATH_SPLITTER "...]"),
+ QLatin1String("Include paths used by the C++ parser"));
+ generalOptions.insert(QLatin1String("typesystem-paths=<path>[" PATH_SPLITTER "<path>" 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=<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=\"<TypeEntry0>[;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();
+ foreach (const GeneratorPtr &generator, generators) {
+ QMap<QString, QString> 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<QString, QString> 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"))) {
+ QStringList versions = argsHandler.removeArg(QLatin1String("api-version")).split(QLatin1Char('|'));
+ foreach (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())
+ extractor.addIncludePath(path.split(QLatin1String(PATH_SPLITTER)));
+
+ 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<QString, QString> projectFileArgs = getInitializedArguments();
+ if (!projectFileArgs.isEmpty()) {
+ QMap<QString, QString>::const_iterator it =
+ projectFileArgs.constBegin();
+ for ( ; it != projectFileArgs.constEnd(); ++it)
+ argsHandler.removeArg(it.key());
+ }
+ foreach (const GeneratorPtr &generator, generators) {
+ QMap<QString, QString> options = generator->options();
+ if (!options.isEmpty()) {
+ QMap<QString, QString>::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;
+
+ foreach (const GeneratorPtr &g, 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..a7a176907
--- /dev/null
+++ b/sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp
@@ -0,0 +1,1704 @@
+/****************************************************************************
+**
+** 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 <abstractmetalang.h>
+#include <reporthandler.h>
+#include <typesystem.h>
+#include <qtdocparser.h>
+#include <doxygenparser.h>
+#include <typedatabase.h>
+#include <algorithm>
+#include <QtCore/QStack>
+#include <QtCore/QTextStream>
+#include <QtCore/QXmlStreamReader>
+#include <QtCore/QFile>
+#include <QtCore/QDir>
+#include <fileout.h>
+#include <limits>
+
+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();
+ foreach (AbstractMetaFunction* f, func->ownerClass()->functions()) {
+ 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;
+ foreach (const AbstractMetaClass* cls, m_generator->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;
+ foreach (const AbstractMetaClass* cls, m_generator->classes()) {
+ if (cls->name() == currentClass) {
+ metaClass = cls;
+ break;
+ }
+ }
+
+ if (metaClass) {
+ QList<const AbstractMetaFunction*> funcList;
+ foreach (const AbstractMetaFunction* func, metaClass->queryFunctionsByName(methodName)) {
+ if (methodName == func->name())
+ funcList.append(func);
+ }
+
+ const AbstractMetaClass* implementingClass = 0;
+ foreach (const AbstractMetaFunction* func, 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;
+ foreach (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 << "<Code snippet \"" << location << ':' << identifier << "\" not found>" << endl;
+ } else {
+ foreach (const QString &line, code.split(QLatin1Char('\n'))) {
+ 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;
+ foreach (TableCell cell, m_currentTable.first()) {
+ 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) {
+ QStringList lst(reader.text().toString().split(QLatin1Char('\n')));
+ foreach(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) {
+ QStringList lst(reader.text().toString().split(QLatin1Char('\n')));
+ foreach(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 << "<Code snippet \"" << location << "\" not found>" << endl;
+ } else {
+ foreach (QString line, code.split(QLatin1Char('\n'))) {
+ 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<int> colWidths(table.first().count());
+ QVector<int> 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) {
+ QStringList rowLines = row[j].data.split(QLatin1Char('\n')); // cache this would be a good idea
+ foreach (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<QString, QString> 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<QString, QString>::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 {
+ QStringList lines = doc.value().split(QLatin1Char('\n'));
+ QRegExp regex(QLatin1String("\\S")); // non-space character
+ int typesystemIndentation = std::numeric_limits<int>().max();
+ // check how many spaces must be removed from the begining of each line
+ foreach (QString line, lines) {
+ int idx = line.indexOf(regex);
+ if (idx >= 0)
+ typesystemIndentation = qMin(typesystemIndentation, idx);
+ }
+ foreach (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;
+ foreach (AbstractMetaClass* c, allClasses) {
+ if (c != metaClass && c->inheritsFrom(metaClass))
+ res << c;
+ }
+
+ if (res.isEmpty())
+ return;
+
+ s << "**Inherited by:** ";
+ QStringList classes;
+ foreach (AbstractMetaClass* c, 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<AbstractMetaClass*>(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);
+
+
+ foreach (AbstractMetaFunction* func, 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;
+
+ foreach (AbstractMetaFunction* func, cppClass->functions()) {
+ 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);
+ foreach (QString func, functions)
+ s << '*' << INDENT << func << endl;
+
+ s << endl << endl;
+ }
+}
+
+void QtDocGenerator::writeEnums(QTextStream& s, const AbstractMetaClass* cppClass)
+{
+ static const QString section_title = QLatin1String(".. attribute:: ");
+
+ foreach (AbstractMetaEnum* en, cppClass->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:: ");
+
+ foreach (AbstractMetaField* field, cppClass->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(' '));
+
+ AbstractMetaFunctionList lst = cppClass->queryFunctions(AbstractMetaClass::Constructors | AbstractMetaClass::Visible);
+
+ bool first = true;
+ QHash<QString, AbstractMetaArgument*> arg_map;
+
+ foreach(AbstractMetaFunction* func, lst) {
+ if (func->isModifiedRemoved())
+ continue;
+
+ if (first) {
+ first = false;
+ s << sectionTitle;
+ } else {
+ s << sectionTitleSpace;
+ }
+ writeFunction(s, false, cppClass, func);
+ foreach(AbstractMetaArgument* arg, func->arguments())
+ {
+ if (!arg_map.contains(arg->name())) {
+ arg_map.insert(arg->name(), arg);
+ }
+ }
+ }
+
+ s << endl;
+
+ foreach (AbstractMetaArgument* arg, arg_map.values()) {
+ Indentation indentation(INDENT);
+ writeParamerteType(s, cppClass, arg);
+ }
+
+ s << endl;
+
+ foreach (AbstractMetaFunction* func, lst) {
+ writeFormatedText(s, func->documentation(), cppClass);
+ }
+}
+
+QString QtDocGenerator::parseArgDocStyle(const AbstractMetaClass* cppClass, const AbstractMetaFunction* func)
+{
+ QString ret;
+ int optArgs = 0;
+
+ foreach (AbstractMetaArgument* arg, func->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("*/");
+
+ foreach (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);
+ QStringList rows = codeBlock.split(QLatin1Char('\n'));
+ int currenRow = 0;
+ int offset = 0;
+
+ foreach(QString row, rows) {
+ foreach(QString invalidString, invalidStrings) {
+ row = 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;
+
+ foreach (DocModification mod, cppClass->typeEntry()->docModifications()) {
+ 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;
+ foreach (AbstractMetaArgument* arg, func->arguments()) {
+
+ 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
+ foreach (FunctionModification mod, func->modifications()) {
+ foreach (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<QChar, QStringList> TocMap;
+ TocMap tocMap;
+ QChar Q = QLatin1Char('Q');
+ QChar idx;
+ foreach (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(&currentColData);
+ QMutableMapIterator<QChar, QStringList> 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
+ foreach (QString item, 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<QString, QStringList>::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;
+ foreach (QString className, 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<QString, QString>& 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<DocParser*>(new DoxygenParser)
+ : static_cast<DocParser*>(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<QString, QString> QtDocGenerator::options() const
+{
+ QMap<QString, QString> 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 <QtCore/QStack>
+#include <QtCore/QHash>
+#include <QtCore/QTextStream>
+#include <QXmlStreamReader>
+#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<TableCell> TableRow;
+ class Table : public QList<TableRow>
+ {
+ 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<TableRow>::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<QString, TagHandler> m_handlerMap;
+ QStack<TagHandler> m_handlers;
+ QTextStream m_output;
+ QString m_result;
+
+ QStack<QString*> 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<QString, QString>& args);
+
+ const char* name() const
+ {
+ return "QtDocGenerator";
+ }
+
+ QMap<QString, QString> 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<QString, QStringList> 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..68b62477e
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -0,0 +1,5689 @@
+/****************************************************************************
+**
+** 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 <memory>
+
+#include "cppgenerator.h"
+#include "overloaddata.h"
+#include <abstractmetalang.h>
+#include <reporthandler.h>
+#include <typedatabase.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QMetaObject>
+#include <QtCore/QTextStream>
+#include <QtCore/QDebug>
+#include <QMetaType>
+
+QHash<QString, QString> CppGenerator::m_nbFuncs = QHash<QString, QString>();
+QHash<QString, QString> CppGenerator::m_sqFuncs = QHash<QString, QString>();
+QHash<QString, QString> CppGenerator::m_mpFuncs = QHash<QString, QString>();
+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<QString, QString> 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();
+ }
+}
+
+QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
+ uint queryIn)
+{
+ // ( func_name, num_args ) => func_list
+ QMap<QPair<QString, int >, AbstractMetaFunctionList> results;
+ const AbstractMetaClass::OperatorQueryOptions query(queryIn);
+ foreach (AbstractMetaFunction* func, metaClass->operatorOverloads(query)) {
+ 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<QString, int > op(func->name(), args);
+ results[op].append(func);
+ }
+ return results.values();
+}
+
+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<const PrimitiveTypeEntry*>(func->type()->typeEntry());
+ while (pte->referencedTypeEntry())
+ pte = pte->referencedTypeEntry();
+ return func && func->isConstant() && pte->name() == QLatin1String("bool") && func->arguments().isEmpty();
+}
+
+typedef QMap<QString, AbstractMetaFunctionList> 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 <QDebug>\n";
+
+/*!
+ 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 <shiboken.h>" << endl;
+ if (usePySideExtensions()) {
+ s << includeQDebug;
+ s << "#include <pysidesignal.h>" << endl;
+ s << "#include <pysideproperty.h>" << endl;
+ s << "#include <pyside.h>" << endl;
+ s << "#include <destroylistener.h>" << endl;
+ }
+
+ s << "#include <typeresolver.h>" << endl;
+ s << "#include <typeinfo>" << endl;
+ if (usePySideExtensions() && metaClass->isQObject()) {
+ s << "#include <signalmanager.h>" << endl;
+ s << "#include <pysidemetafunction.h>" << endl;
+ }
+
+ // The multiple inheritance initialization function
+ // needs the 'set' class from C++ STL.
+ if (hasMultipleInheritanceInAncestry(metaClass))
+ s << "#include <set>" << 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;
+ foreach (AbstractMetaClass* innerClass, metaClass->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();
+ foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
+ lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+
+ //Extra includes
+ s << endl << "// Extra includes" << endl;
+ QList<Include> includes = metaClass->typeEntry()->extraIncludes();
+ foreach (AbstractMetaEnum* cppEnum, classEnums)
+ includes.append(cppEnum->typeEntry()->extraIncludes());
+ qSort(includes.begin(), includes.end());
+ foreach (const Include &inc, 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<const SmartPointerTypeEntry *>(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";
+ }
+
+ foreach (const AbstractMetaFunction* func, filterFunctions(metaClass)) {
+ 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<QString> seenSignatures;
+ foreach (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<const SmartPointerTypeEntry *>(
+ 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);
+ }
+ }
+
+ QString className = cpythonTypeName(metaClass);
+ className.remove(QRegExp(QLatin1String("_Type$")));
+
+ 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()) {
+ QList<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions(
+ metaClass,
+ AbstractMetaClass::ArithmeticOp
+ | AbstractMetaClass::LogicalOp
+ | AbstractMetaClass::BitwiseOp);
+
+ foreach (const AbstractMetaFunctionList &allOverloads, opOverloads) {
+ AbstractMetaFunctionList overloads;
+ foreach (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()) {
+ foreach (const AbstractMetaField* metaField, metaClass->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;
+ foreach (const AbstractMetaField* metaField, metaClass->fields()) {
+ if (metaField->isStatic())
+ continue;
+
+ bool hasSetter = !metaField->type()->isConstant();
+ s << INDENT << "{const_cast<char*>(\"" << 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);
+
+
+ foreach (AbstractMetaEnum* cppEnum, 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;
+ foreach (const AbstractMetaArgument* arg, func->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<const ContainerTypeEntry*>(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) {
+ foreach (const FunctionModification &mod, func->modifications()) {
+ foreach (const ArgumentModification &argMod, mod.argument_mods) {
+ if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) {
+ QRegExp regex(QLatin1String("%(\\d+)"));
+ defaultReturnExpr = argMod.replacedDefaultExpression;
+ int offset = 0;
+ while ((offset = regex.indexIn(defaultReturnExpr, offset)) != -1) {
+ int argId = regex.cap(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(regex.cap(0), func->arguments()[argId]->name());
+ }
+ }
+ }
+ }
+ 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;
+ foreach (const AbstractMetaArgument* arg, func->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<int> invalidateArgs;
+ foreach (const FunctionModification &funcMod, func->modifications()) {
+ foreach (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;
+ }
+ foreach (int argIndex, invalidateArgs) {
+ s << INDENT << "if (invalidateArg" << argIndex << ')' << endl;
+ Indentation indentation(INDENT);
+ s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(" PYTHON_ARGS ", ";
+ s << (argIndex - 1) << "));" << endl;
+ }
+
+
+ foreach (const FunctionModification &funcMod, func->modifications()) {
+ foreach (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<PyObject*>(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<void*>(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<PySideQFlagsObject*>(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<PyObject*>(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<const EnumTypeEntry*>(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();
+ foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
+ lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+ if (!classEnums.isEmpty())
+ s << "// Python to C++ enum conversion." << endl;
+ foreach (const AbstractMetaEnum* metaEnum, 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<void*>(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()) {
+ foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) {
+ if (!func->isUserAdded())
+ implicitConvs << func;
+ }
+ }
+
+ if (!implicitConvs.isEmpty())
+ s << "// Implicit conversions." << endl;
+
+ AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
+ foreach (const AbstractMetaFunction* conv, 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;
+ foreach (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()) {
+ foreach (AbstractMetaFunction* func, implicitConversions(metaClass->typeEntry())) {
+ if (!func->isUserAdded())
+ implicitConvs << func;
+ }
+ }
+
+ if (!implicitConvs.isEmpty())
+ s << INDENT << "// Add implicit conversions to type converter." << endl;
+
+ AbstractMetaType* targetType = buildAbstractMetaTypeFromAbstractMetaClass(metaClass);
+ foreach (const AbstractMetaFunction* conv, 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;
+ foreach (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<QString> argNamesSet;
+ if (usePySideExtensions() && metaClass->isQObject()) {
+ // Write argNames variable with all known argument names.
+ foreach (const AbstractMetaFunction* func, overloadData.overloads()) {
+ foreach (const AbstractMetaArgument* arg, func->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<SbkObject*>(" PYTHON_SELF_VAR ");" << endl;
+
+ if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) {
+ s << INDENT << "SbkObjectType* type = reinterpret_cast<SbkObjectType*>(" PYTHON_SELF_VAR "->ob_type);" << endl;
+ s << INDENT << "SbkObjectType* myType = reinterpret_cast<SbkObjectType*>(" << 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;
+ foreach(AbstractMetaFunction* func, overloads) {
+ foreach (const CodeSnip &cs, func->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;
+ foreach(AbstractMetaFunction* func, overloads) {
+ Indentation indent(INDENT);
+ foreach (const CodeSnip &cs, func->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<char*>(\"" << 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<char*>(\"" << revOpName << "\"));" << endl;
+ s << INDENT << "if (revOpMethod && PyCallable_Check(revOpMethod)) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << PYTHON_RETURN_VAR " = PyObject_CallFunction(revOpMethod, const_cast<char*>(\"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 << '}';
+ }
+ }
+ QList<int> invalidArgsLength = overloadData.invalidArgumentLengths();
+ if (!invalidArgsLength.isEmpty()) {
+ QStringList invArgsLen;
+ foreach (int i, 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;
+ foreach (const AbstractMetaFunction* f, overloadData.overloads()) {
+ QStringList args;
+ foreach(AbstractMetaArgument* arg, f->arguments()) {
+ QString strArg;
+ AbstractMetaType* argType = arg->type();
+ if (isCString(argType)) {
+ strArg = QLatin1String("\" SBK_STR_NAME \"");
+ } else if (argType->isPrimitive()) {
+ const PrimitiveTypeEntry* ptp = reinterpret_cast<const PrimitiveTypeEntry*>(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();
+ strArg.remove(QRegExp(QLatin1String("^signed\\s+")));
+ 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 QRegExp pyArgsRegex(QLatin1String(PYTHON_ARGS"(\\[\\d+[-]?\\d*\\])"));
+ pyArgsRegex.indexIn(argumentName);
+ return QLatin1String(PYTHON_TO_CPP_VAR) + pyArgsRegex.cap(1);
+}
+
+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<const TypeEntry*> numericTypes;
+
+ foreach (OverloadData* od, overloadData->previousOverloadData()->nextOverloadData()) {
+ foreach (const AbstractMetaFunction* func, od->overloads()) {
+ 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<const SbkObjectType *>("
+ << 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;
+ foreach (AbstractMetaArgument* arg, func->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();
+ QList<const AbstractMetaFunction*> 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) {
+ foreach (const AbstractMetaFunction* func, parentOverloadData->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.
+ if (hasDefaultCall) {
+ isFirst = false;
+ int numArgs = parentOverloadData->argPos() + 1;
+ s << INDENT << "if (numArgs == " << numArgs << ") {" << endl;
+ {
+ Indentation indent(INDENT);
+ const AbstractMetaFunction* func = referenceFunction;
+ foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) {
+ const AbstractMetaFunction* defValFunc = overloadData->getFunctionWithDefaultValue();
+ if (defValFunc) {
+ func = defValFunc;
+ break;
+ }
+ }
+ s << INDENT << "overloadId = " << parentOverloadData->headOverloadData()->overloads().indexOf(func);
+ s << "; // " << func->minimalSignature() << endl;
+ }
+ s << INDENT << '}';
+ }
+
+ foreach (OverloadData* overloadData, parentOverloadData->nextOverloadData()) {
+ 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)
+{
+ QList<const AbstractMetaFunction*> 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 QRegExp regex(QLatin1String(CONVERTTOCPP_REGEX));
+ int pos = 0;
+ while ((pos = regex.indexIn(code, pos)) != -1) {
+ pos += regex.matchedLength();
+ QStringList list = regex.capturedTexts();
+ QString varName = list.at(1);
+ QString leftCode = code.left(pos);
+ QString rightCode = code.mid(pos);
+ rightCode.replace(varName, QLatin1Char('*') + varName);
+ code = leftCode + 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)
+{
+ 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* ";
+ foreach (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()) {
+ foreach (const CodeSnip &cs, func->injectedCodeSnips()) {
+ if (cs.position == TypeSystem::CodeSnipPositionEnd) {
+ s << INDENT << "overloadId = " << func->ownerClass()->functions().indexOf(const_cast<AbstractMetaFunction* const>(func)) << ';' << endl;
+ break;
+ }
+ }
+ }
+
+ if (func->isAbstract()) {
+ s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" 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_cast<const ::";
+ if (func->ownerClass()->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<const ::" << methodCallClassName;
+ mc << "*>(" << 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<SbkObject*>(" 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<SbkObjectType *>(" << 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.
+ QList<ArgumentModification> ownership_mods;
+ // Python object reference management.
+ QList<ArgumentModification> refcount_mods;
+ foreach (const FunctionModification &func_mod, func->modifications()) {
+ foreach (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;
+ foreach (const ArgumentModification &arg_mod, 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()) {
+ foreach (const ArgumentModification &arg_mod, 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<SbkObject*>(" 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;
+ AbstractMetaClassList baseClases = getBaseClasses(metaClass);
+ if (!baseClases.isEmpty()) {
+ foreach (const AbstractMetaClass* baseClass, baseClases) {
+ result.append(QString::fromLatin1("((size_t) static_cast<const %1*>(class_ptr)) - base")
+ .arg(baseClass->qualifiedCppName()));
+ result.append(QString::fromLatin1("((size_t) static_cast<const %1*>((%2*)((void*)class_ptr))) - base")
+ .arg(baseClass->qualifiedCppName(), metaClass->qualifiedCppName()));
+ }
+ foreach (const AbstractMetaClass* baseClass, baseClases)
+ result.append(getAncestorMultipleInheritance(baseClass));
+ }
+ return result;
+}
+
+void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+{
+ QString className = metaClass->qualifiedCppName();
+ 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<int> offsets;" << endl;
+ s << INDENT << "std::set<int>::iterator it;" << endl;
+ s << INDENT << "const " << className << "* class_ptr = reinterpret_cast<const " << className << "*>(cptr);" << endl;
+ s << INDENT << "size_t base = (size_t) class_ptr;" << endl;
+
+ foreach (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;
+ foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) {
+ s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast<SbkObjectType*>(" << 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<const FlagsTypeEntry*>(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<const EnumTypeEntry*>(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 QList<const AbstractMetaClass*>& conversions)
+{
+ s << INDENT << "// Extended implicit conversions for " << externalType->qualifiedTargetLangName() << '.' << endl;
+ foreach (const AbstractMetaClass* sourceClass, conversions) {
+ const QString converterVar = QLatin1String("reinterpret_cast<SbkObjectType *>(")
+ + 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<QString, QPair<QString, QString> >::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)
+{
+ foreach (AbstractMetaField* f, metaClass->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();
+ QString className = cpythonTypeName(metaClass);
+ className.remove(QRegExp(QLatin1String("_Type$")));
+ QString baseClassName(QLatin1Char('0'));
+ AbstractMetaFunctionList ctors;
+ foreach (AbstractMetaFunction* f, metaClass->queryFunctions(AbstractMetaClass::Constructors)) {
+ if (!f->isPrivate() && !f->isModifiedRemoved() && !classContext.forSmartPointer())
+ ctors.append(f);
+ }
+
+ if (!metaClass->baseClass())
+ baseClassName = QLatin1String("reinterpret_cast<PyTypeObject*>(&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();
+ foreach (AbstractMetaFunction* func, metaClass->functions()) {
+ 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<QString, QString> 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<QString, QString> 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<QString, QString> 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<QString, QString>::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<QString, QString> 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<QString, QString>::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<QString, QString> 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());
+
+ QList<AbstractMetaFunctionList> opOverloads =
+ filterGroupedOperatorFunctions(metaClass,
+ AbstractMetaClass::ArithmeticOp
+ | AbstractMetaClass::LogicalOp
+ | AbstractMetaClass::BitwiseOp);
+
+ foreach (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<QString, QString>::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<PyTypeObject*>(&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<PyTypeObject*>(&SbkObject_Type)->tp_clear(" PYTHON_SELF_VAR ");" << endl;
+ s << '}' << endl;
+}
+
+void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
+{
+ const AbstractMetaClass *metaClass = context.metaClass();
+ QString className = cpythonTypeName(metaClass);
+ className.remove(QRegExp(QLatin1String("_Type$")));
+ 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<void *>("
+ << cppField
+ << ") == reinterpret_cast<void *>("
+ << CPP_SELF_VAR << ")) {\n";
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "pyOut = reinterpret_cast<PyObject *>(Shiboken::Object::findColocatedChild("
+ << "reinterpret_cast<SbkObject *>(self), reinterpret_cast<const SbkObjectType *>("
+ << 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<SbkObjectType *>(" << 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<SbkObject*>(" 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);
+ foreach (const AbstractMetaFunctionList &overloads, filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp)) {
+ 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;
+ foreach (const AbstractMetaFunction* func, overloads) {
+ if (!func->isStatic() &&
+ ShibokenGenerator::isNumber(func->arguments()[0]->type()->typeEntry()))
+ alternativeNumericTypes++;
+ }
+
+ bool first = true;
+ OverloadData overloadData(overloads, this);
+ foreach (OverloadData* od, overloadData.nextOverloadData()) {
+ 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;
+ foreach (const AbstractMetaEnum* cppEnum, 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;
+ }
+ }
+
+ foreach (const AbstractMetaEnumValue* enumValue, cppEnum->values()) {
+ 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<SbkObjectType *>(" << 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
+ foreach (const AbstractMetaFunction* cppSignal, metaClass->cppSignalFunctions()) {
+ if (cppSignal->declaringClass() != metaClass)
+ continue;
+ foreach (AbstractMetaArgument* arg, cppSignal->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<int>(), &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<PyTypeObject*>(&" << 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;
+ foreach (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<SbkObjectType *>(" << 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<SbkObjectType*>(";
+ 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();
+ foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
+ lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass);
+
+ ErrorCode errorCode(QString::null);
+ writeEnumsInitialization(s, classEnums);
+
+ if (metaClass->hasSignals())
+ writeSignalInitialization(s, metaClass);
+
+ // Write static fields
+ foreach (const AbstractMetaField* field, metaClass->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
+ foreach (AbstractMetaFunction* func, metaClass->functions()) {
+ if (func->isConstructor() && !func->arguments().count()) {
+ canBeValue = true;
+ break;
+ }
+ }
+ }
+
+ if (canBeValue) {
+ foreach (const QString &name, 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;
+ }
+ }
+ }
+
+ foreach (AbstractMetaEnum* metaEnum, metaClass->enums()) {
+ if (!metaEnum->isPrivate() && !metaEnum->isAnonymous()) {
+ foreach (const QString &name, 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()) {
+ AbstractMetaClassList ancestors = getAllAncestors(metaClass);
+ foreach (AbstractMetaClass* ancestor, ancestors) {
+ if (ancestor->baseClass())
+ continue;
+ if (ancestor->isPolymorphic()) {
+ s << INDENT << "if (instanceType == reinterpret_cast<SbkObjectType*>(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<char *>(" 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<PyObject*>(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<PySideProperty*>(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<SbkObject*>(" PYTHON_SELF_VAR ")->ob_dict) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast<SbkObject*>(" 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;
+
+ foreach (const AbstractMetaFunction* func, getMethodsWithBothStaticAndNonStaticMethods(metaClass)) {
+ 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<Include> 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;
+ foreach (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);
+
+ foreach (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.
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ 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 <sbkpython.h>" << endl;
+ s << "#include <shiboken.h>" << endl;
+ s << "#include <algorithm>" << endl;
+ if (usePySideExtensions()) {
+ s << includeQDebug;
+ s << "#include <pyside.h>" << endl;
+ }
+
+ s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl;
+ foreach (const Include& include, includes)
+ s << include;
+ s << endl;
+
+ // Global enums
+ AbstractMetaEnumList globalEnums = this->globalEnums();
+ foreach (const AbstractMetaClass* metaClass, classes()) {
+ const AbstractMetaClass* encClass = metaClass->enclosingClass();
+ if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass)
+ continue;
+ lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
+ }
+
+ TypeDatabase* typeDb = TypeDatabase::instance();
+ TypeSystemTypeEntry* moduleEntry = reinterpret_cast<TypeSystemTypeEntry*>(typeDb->findType(packageName()));
+
+ //Extra includes
+ s << endl << "// Extra includes" << endl;
+ QList<Include> extraIncludes;
+ if (moduleEntry)
+ extraIncludes = moduleEntry->extraIncludes();
+ foreach (AbstractMetaEnum* cppEnum, globalEnums)
+ extraIncludes.append(cppEnum->typeEntry()->extraIncludes());
+ qSort(extraIncludes.begin(), extraIncludes.end());
+ foreach (const Include& inc, 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<PyObject*>(" << 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;
+ foreach (const AbstractMetaEnum* cppEnum, 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;
+ }
+ }
+
+ QStringList requiredModules = typeDb->requiredTargetImports();
+ if (!requiredModules.isEmpty())
+ s << "// Required modules' type and converter arrays." << endl;
+ foreach (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;
+ foreach (const AbstractMetaClass* sourceClass, extendedConverters[externalType]) {
+ AbstractMetaType* sourceType = buildAbstractMetaTypeFromAbstractMetaClass(sourceClass);
+ AbstractMetaType* targetType = buildAbstractMetaTypeFromTypeEntry(externalType);
+ writePythonToCppConversionFunctions(s, sourceType, targetType);
+ }
+ }
+ }
+
+ QList<const CustomConversion*> typeConversions = getPrimitiveCustomConversions();
+ if (!typeConversions.isEmpty()) {
+ s << endl << "// Primitive Type converters." << endl << endl;
+ foreach (const CustomConversion* conversion, typeConversions) {
+ s << "// C++ to Python conversion for type '" << conversion->ownerType()->qualifiedCppName() << "'." << endl;
+ writeCppToPythonFunction(s, conversion);
+ writeCustomConverterFunctions(s, conversion);
+ }
+ s << endl;
+ }
+
+ QList<const AbstractMetaType*> containers = instantiatedContainers();
+ if (!containers.isEmpty()) {
+ s << "// Container Type converters." << endl << endl;
+ foreach (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;
+ }
+
+ foreach (const QString& requiredModule, typeDb->requiredTargetImports()) {
+ 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;
+ foreach (const CustomConversion* conversion, typeConversions) {
+ writePrimitiveConverterInitialization(s, conversion);
+ s << endl;
+ }
+ }
+
+ if (!containers.isEmpty()) {
+ s << endl;
+ foreach (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;
+ foreach(const PrimitiveTypeEntry* pte, primitiveTypes()) {
+ 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<QByteArray> typeResolvers;
+ foreach (AbstractMetaClass* metaClass, classes()) {
+ if (!metaClass->isQObject() || !metaClass->typeEntry()->generateCode())
+ continue;
+ foreach (AbstractMetaFunction* func, metaClass->functions()) {
+ if (func->isSignal()) {
+ foreach (AbstractMetaArgument* arg, func->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()) {
+ foreach (AbstractMetaEnum* metaEnum, 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..5dc3f5a15
--- /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;
+ QString fileNameForContext(GeneratorContext &context) const;
+ QList<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
+ uint query);
+ void generateClass(QTextStream& s, GeneratorContext &classContext);
+ bool finishGeneration();
+
+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 QList<const AbstractMetaClass*>& 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<QString, QString> m_nbFuncs;
+
+ // Maps special function names to function parameters and return types
+ // used by CPython API in the sequence protocol.
+ QHash<QString, QPair<QString, QString> > m_sequenceProtocol;
+ // Sequence protocol structure members names.
+ static QHash<QString, QString> m_sqFuncs;
+
+ // Maps special function names to function parameters and return types
+ // used by CPython API in the mapping protocol.
+ QHash<QString, QPair<QString, QString> > m_mappingProtocol;
+ // Mapping protocol structure members names.
+ static QHash<QString, QString> 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..5ef5d5612
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp
@@ -0,0 +1,558 @@
+/****************************************************************************
+**
+** 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 <abstractmetalang.h>
+#include <typedatabase.h>
+#include <reporthandler.h>
+#include <fileout.h>
+
+#include <QtCore/QDir>
+#include <QtCore/QTextStream>
+#include <QtCore/QVariant>
+#include <QtCore/QRegExp>
+#include <QtCore/QDebug>
+
+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 <shiboken.h>" << 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;
+ foreach (AbstractMetaFunction *func, filterFunctions(metaClass)) {
+ if (func->isVirtual())
+ hasVirtualFunction = true;
+ writeFunction(s, func);
+ }
+
+ if (avoidProtectedHack() && metaClass->hasProtectedFields()) {
+ foreach (AbstractMetaField* field, metaClass->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;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ QString argName = arg->name();
+ const TypeEntry* enumTypeEntry = 0;
+ if (arg->type()->isFlags())
+ enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(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
+ foreach (const AbstractMetaFunction* f, func->ownerClass()->functions()) {
+ 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<const ComplexTypeEntry*>(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<const EnumTypeEntry*>(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());
+ foreach (const AbstractMetaEnum* metaEnum, metaClass->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<Include> includes;
+ QString macros;
+ QTextStream macrosStream(&macros);
+ QString sbkTypeFunctions;
+ QTextStream typeFunctions(&sbkTypeFunctions);
+ QString protectedEnumSurrogates;
+ QTextStream protEnumsSurrogates(&protectedEnumSurrogates);
+
+ Indentation indent(INDENT);
+
+ macrosStream << "// Type indices" << endl;
+ AbstractMetaEnumList globalEnums = this->globalEnums();
+ foreach (const AbstractMetaClass* metaClass, classes()) {
+ writeTypeIndexDefine(macrosStream, metaClass);
+ lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
+ }
+
+ foreach (const AbstractMetaEnum* metaEnum, globalEnums)
+ writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry());
+
+ // Write the smart pointer define indexes.
+ int smartPointerCountIndex = getMaxTypeIndex();
+ int smartPointerCount = 0;
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ 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;
+ QList<const PrimitiveTypeEntry*> primitives = primitiveTypes();
+ int pCount = 0;
+ foreach (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++);
+ }
+
+ foreach (const AbstractMetaType* container, instantiatedContainers()) {
+ //_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;
+ foreach (const AbstractMetaEnum* cppEnum, globalEnums) {
+ if (cppEnum->isAnonymous() || cppEnum->isPrivate())
+ continue;
+ includes << cppEnum->typeEntry()->include();
+ writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum);
+ writeSbkTypeFunction(typeFunctions, cppEnum);
+ }
+
+ foreach (AbstractMetaClass* metaClass, classes()) {
+ if (!shouldGenerate(metaClass))
+ continue;
+
+ //Includes
+ const TypeEntry* classType = metaClass->typeEntry();
+ includes << classType->include();
+
+ foreach (const AbstractMetaEnum* cppEnum, metaClass->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);
+ }
+
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ 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 <sbkpython.h>" << endl;
+ s << "#include <conversions.h>" << endl;
+ s << "#include <sbkenum.h>" << endl;
+ s << "#include <basewrapper.h>" << endl;
+ s << "#include <bindingmanager.h>" << endl;
+ s << "#include <memory>" << endl << endl;
+ if (usePySideExtensions())
+ s << "#include <pysidesignal.h>" << endl;
+
+ QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports();
+ if (!requiredTargetImports.isEmpty()) {
+ s << "// Module Includes" << endl;
+ foreach (const QString& requiredModule, requiredTargetImports)
+ s << "#include <" << getModuleHeaderFileName(requiredModule) << ">" << endl;
+ s << endl;
+ }
+
+ s << "// Binded library includes" << endl;
+ foreach (const Include& include, includes)
+ s << include;
+
+ if (!primitiveTypes().isEmpty()) {
+ s << "// Conversion Includes - Primitive Types" << endl;
+ foreach (const PrimitiveTypeEntry* ptype, primitiveTypes())
+ s << ptype->include();
+ s << endl;
+ }
+
+ if (!containerTypes().isEmpty()) {
+ s << "// Conversion Includes - Container Types" << endl;
+ foreach (const ContainerTypeEntry* ctype, containerTypes())
+ 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<PyTypeObject*>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n";
+}
+
+void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType)
+{
+ s << "template<> inline PyTypeObject* SbkType< ::" << metaType->cppSignature() << " >() "
+ << "{ return reinterpret_cast<PyTypeObject*>(" << cpythonTypeNameExt(metaType) << "); }\n";
+}
+
+void HeaderGenerator::writeInheritedOverloads(QTextStream& s)
+{
+ foreach (const AbstractMetaFunction* func, 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;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ QString argName = arg->name();
+ const TypeEntry* enumTypeEntry = 0;
+ if (arg->type()->isFlags())
+ enumTypeEntry = reinterpret_cast<const FlagsTypeEntry*>(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..72dcbf69f
--- /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 <QtCore/QSet>
+
+class AbstractMetaFunction;
+
+/**
+ * The HeaderGenerator generate the declarations of C++ bindings classes.
+ */
+class HeaderGenerator : public ShibokenGenerator
+{
+public:
+ QMap<QString, QString> options() const { return QMap<QString, QString>(); }
+protected:
+ QString fileNamePrefix() const;
+ QString fileNameForContext(GeneratorContext &context) const;
+ void generateClass(QTextStream& s, GeneratorContext &classContext);
+ bool finishGeneration();
+
+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<const AbstractMetaFunction*> 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..8731fe911
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/overloaddata.cpp
@@ -0,0 +1,1079 @@
+/****************************************************************************
+**
+** 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 <graph.h>
+#include "overloaddata.h"
+#include "shibokengenerator.h"
+
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QTemporaryFile>
+
+static const TypeEntry *getReferencedTypeEntry(const TypeEntry *typeEntry)
+{
+ if (typeEntry->isPrimitive()) {
+ const PrimitiveTypeEntry* pte = dynamic_cast<const PrimitiveTypeEntry*>(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;
+ foreach (const AbstractMetaType* cType, type->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<QString, int> map; // typeName -> id
+ QHash<int, OverloadData*> 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;
+ foreach (const AbstractMetaType* otherType, containerType->instantiations())
+ types << (otherType == instantiation ? impConv : getTypeName(otherType));
+
+ const ContainerTypeEntry* containerTypeEntry = dynamic_cast<const ContainerTypeEntry*>(containerType->typeEntry());
+ return containerTypeEntry->qualifiedCppName() + QLatin1Char('<')
+ + types.join(QLatin1String(", ")) + QLatin1String(" >");
+}
+
+static QString msgCyclicDependency(const QString &funcName, const QString &graphName,
+ const QList<const AbstractMetaFunction *> &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
+ foreach(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.
+ foreach(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();
+ }
+
+ foreach (const AbstractMetaType* instantiation, ov->argType()->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<PointF>)" and "method(list<Point>)",
+ // and being PointF implicitly convertible from Point, an list<T> instantiation with T
+ // as Point must come before the PointF instantiation, or else list<Point> will never
+ // be called. In the case of primitive types, list<double> must come before list<int>.
+ if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) {
+ foreach (const QString& primitive, nonIntegerPrimitives)
+ sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive));
+ } else {
+ foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation))
+ 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;
+
+ QList<const AbstractMetaFunction *> involvedConversions;
+
+ foreach(OverloadData* ov, m_nextOverloadData) {
+ const AbstractMetaType* targetType = ov->argType();
+ const QString targetTypeEntryName(getTypeName(ov));
+ int targetTypeId = sortData.map[targetTypeEntryName];
+
+ // Process implicit conversions
+ foreach(AbstractMetaFunction* function, m_generator->implicitConversions(targetType)) {
+ 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());
+ foreach (const AbstractMetaClass* ancestor, m_generator->getAllAncestors(metaClass)) {
+ 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
+ foreach (const AbstractMetaType* instantiation, targetType->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()))) {
+ foreach (const QString& primitive, 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 {
+ foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) {
+ 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")]);
+
+ foreach(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".
+ foreach (const QString& implicitFromInt, classesWithIntegerImplicitConversion)
+ graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]);
+ }
+
+
+ // Special case for double(int i) (not tracked by m_generator->implicitConversions
+ foreach (const QString& signedIntegerName, signedIntegerPrimitives) {
+ if (sortData.map.contains(signedIntegerName)) {
+ foreach (const QString& nonIntegerName, nonIntegerPrimitives) {
+ if (sortData.map.contains(nonIntegerName))
+ graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]);
+ }
+ }
+ }
+
+ // sort the overloads topologically based on the dependency graph.
+ QLinkedList<int> 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<QString, int>::const_iterator it = sortData.map.begin();
+ QHash<int, QString> 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();
+ foreach(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)
+{
+ foreach (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;
+ foreach (const AbstractMetaArgument* arg, func->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()) {
+ foreach (OverloadData* tmp, 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<QString> retTypes;
+ foreach (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
+{
+ foreach (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
+{
+ foreach (const AbstractMetaFunction* func, m_overloads) {
+ if (func->allowThread())
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasStaticFunction(const AbstractMetaFunctionList& overloads)
+{
+ foreach (const AbstractMetaFunction* func, overloads) {
+ if (func->isStatic())
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasStaticFunction() const
+{
+ foreach (const AbstractMetaFunction* func, m_overloads) {
+ if (func->isStatic())
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasInstanceFunction(const AbstractMetaFunctionList& overloads)
+{
+ foreach (const AbstractMetaFunction* func, overloads) {
+ if (!func->isStatic())
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasInstanceFunction() const
+{
+ foreach (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) {
+ foreach (OverloadData* pd, overloadData->nextOverloadData())
+ 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
+{
+ foreach (OverloadData* overloadData, m_nextOverloadData) {
+ if (overloadData->getFunctionWithDefaultValue())
+ return true;
+ }
+ return false;
+}
+
+static OverloadData* _findNextArgWithDefault(OverloadData* overloadData)
+{
+ if (overloadData->getFunctionWithDefaultValue())
+ return overloadData;
+
+ OverloadData* result = 0;
+ foreach (OverloadData* odata, overloadData->nextOverloadData()) {
+ 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
+{
+ foreach (const OverloadData* pd, m_nextOverloadData) {
+ if (pd->overloads().contains(func))
+ return false;
+ }
+ return true;
+}
+
+QList<const AbstractMetaFunction*> OverloadData::overloadsWithoutRepetition() const
+{
+ QList<const AbstractMetaFunction*> overloads = m_overloads;
+ foreach (const AbstractMetaFunction* func, m_overloads) {
+ if (func->minimalSignature().endsWith(QLatin1String("const")))
+ continue;
+ foreach (const AbstractMetaFunction* f, overloads) {
+ if ((func->minimalSignature() + QLatin1String("const")) == f->minimalSignature()) {
+ overloads.removeOne(f);
+ break;
+ }
+ }
+ }
+ return overloads;
+}
+
+const AbstractMetaFunction* OverloadData::getFunctionWithDefaultValue() const
+{
+ foreach (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;
+}
+
+QList<int> OverloadData::invalidArgumentLengths() const
+{
+ QSet<int> validArgLengths;
+
+ foreach (const AbstractMetaFunction* func, 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;
+ }
+
+ QList<int> 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<int, int> 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<int, int>(minArgs, maxArgs);
+}
+
+bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads)
+{
+ bool singleArgument = true;
+ foreach (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("&lt;"));
+ s.replace(QLatin1Char('>'), QLatin1String("&gt;"));
+ s.replace(QLatin1Char('&'), QLatin1String("&amp;"));
+ 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=\"";
+ foreach (const AbstractMetaFunction* func, 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=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
+ s << "<tr><td bgcolor=\"black\" align=\"center\" cellpadding=\"6\" colspan=\"2\"><font color=\"white\">";
+ if (rfunc->ownerClass())
+ s << rfunc->ownerClass()->name() << "::";
+ s << toHtml(rfunc->name()) << "</font>";
+ if (rfunc->isVirtual()) {
+ s << "<br/><font color=\"white\" point-size=\"10\">&lt;&lt;";
+ if (rfunc->isAbstract())
+ s << "pure ";
+ s << "virtual&gt;&gt;</font>";
+ }
+ s << "</td></tr>";
+
+ // Function return type
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">original type</td><td bgcolor=\"gray\" align=\"left\">";
+ if (rfunc->type())
+ s << toHtml(rfunc->type()->cppSignature());
+ else
+ s << "void";
+ s << "</td></tr>";
+
+ // Shows type changes for all function signatures
+ foreach (const AbstractMetaFunction* func, overloads()) {
+ if (func->typeReplaced(0).isEmpty())
+ continue;
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
+ s << "-type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(func->typeReplaced(0)) << "</td></tr>";
+ }
+
+ // Minimum and maximum number of arguments
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">minArgs</td><td bgcolor=\"gray\" align=\"left\">";
+ s << minArgs() << "</td></tr>";
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">maxArgs</td><td bgcolor=\"gray\" align=\"left\">";
+ s << maxArgs() << "</td></tr>";
+
+ if (rfunc->ownerClass()) {
+ if (rfunc->implementingClass() != rfunc->ownerClass())
+ s << "<tr><td align=\"right\">implementor</td><td align=\"left\">" << rfunc->implementingClass()->name() << "</td></tr>";
+ if (rfunc->declaringClass() != rfunc->ownerClass() && rfunc->declaringClass() != rfunc->implementingClass())
+ s << "<tr><td align=\"right\">declarator</td><td align=\"left\">" << rfunc->declaringClass()->name() << "</td></tr>";
+ }
+
+ // Overloads for the signature to present point
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
+ foreach (const AbstractMetaFunction* func, overloads())
+ s << 'f' << functionNumber(func) << ' ';
+ s << "</td></tr>";
+
+ s << "</table>> ];" << endl;
+
+ foreach (const OverloadData* pd, 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=<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">";
+
+ // Argument box title
+ s << "<tr><td bgcolor=\"black\" align=\"left\" cellpadding=\"2\" colspan=\"2\">";
+ s << "<font color=\"white\" point-size=\"11\">arg #" << argPos() << "</font></td></tr>";
+
+ // Argument type information
+ QString type = hasArgumentTypeReplace() ? argumentTypeReplaced() : argType()->cppSignature();
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(type) << "</td></tr>";
+ if (hasArgumentTypeReplace()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">orig. type</td><td bgcolor=\"gray\" align=\"left\">";
+ s << toHtml(argType()->cppSignature()) << "</td></tr>";
+ }
+
+ // Overloads for the signature to present point
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">overloads</td><td bgcolor=\"gray\" align=\"left\">";
+ foreach (const AbstractMetaFunction* func, overloads())
+ s << 'f' << functionNumber(func) << ' ';
+ s << "</td></tr>";
+
+ // Show default values (original and modified) for various functions
+ foreach (const AbstractMetaFunction* func, overloads()) {
+ const AbstractMetaArgument* arg = argument(func);
+ if (!arg)
+ continue;
+ QString argDefault = ShibokenGenerator::getDefaultValue(func, arg);
+ if (!argDefault.isEmpty() ||
+ argDefault != arg->originalDefaultValueExpression()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
+ s << "-default</td><td bgcolor=\"gray\" align=\"left\">";
+ s << argDefault << "</td></tr>";
+ }
+ if (argDefault != arg->originalDefaultValueExpression()) {
+ s << "<tr><td bgcolor=\"gray\" align=\"right\">f" << functionNumber(func);
+ s << "-orig-default</td><td bgcolor=\"gray\" align=\"left\">";
+ s << arg->originalDefaultValueExpression() << "</td></tr>";
+ }
+ }
+
+ s << "</table>>];" << endl;
+
+ foreach (const OverloadData* pd, 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;
+ foreach (const AbstractMetaFunction* func, overloads) {
+ if (hasArgumentWithDefaultValue(func))
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasArgumentWithDefaultValue() const
+{
+ if (maxArgs() == 0)
+ return false;
+ foreach (const AbstractMetaFunction* func, overloads()) {
+ if (hasArgumentWithDefaultValue(func))
+ return true;
+ }
+ return false;
+}
+
+bool OverloadData::hasArgumentWithDefaultValue(const AbstractMetaFunction* func)
+{
+ foreach (const AbstractMetaArgument* arg, func->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;
+ foreach (AbstractMetaArgument* arg, func->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..959b96d0b
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/overloaddata.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** 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 <abstractmetalang_typedefs.h>
+#include <QtCore/QList>
+#include <QtCore/QBitArray>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+class ShibokenGenerator;
+
+class OverloadData;
+typedef QList<OverloadData*> OverloadDataList;
+
+class OverloadData
+{
+public:
+ 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).
+ QList<const AbstractMetaFunction*> overloadsWithoutRepetition() const;
+ const QList<const AbstractMetaFunction*>& overloads() const { return m_overloads; }
+ OverloadDataList nextOverloadData() const { return m_nextOverloadData; }
+ OverloadData* previousOverloadData() const { return m_previousOverloadData; }
+
+ QList<int> invalidArgumentLengths() const;
+
+ static int numberOfRemovedArguments(const AbstractMetaFunction* func, int finalArgPos = -1);
+ static QPair<int, int> 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;
+ QList<const AbstractMetaFunction*> 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..7b664e105
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp
@@ -0,0 +1,2674 @@
+/****************************************************************************
+**
+** 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 <abstractmetalang.h>
+#include "overloaddata.h"
+#include <reporthandler.h>
+#include <typedatabase.h>
+#include <iostream>
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <limits>
+#include <memory>
+
+#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<QString, QString> ShibokenGenerator::m_pythonPrimitiveTypeName = QHash<QString, QString>();
+QHash<QString, QString> ShibokenGenerator::m_pythonOperators = QHash<QString, QString>();
+QHash<QString, QString> ShibokenGenerator::m_formatUnits = QHash<QString, QString>();
+QHash<QString, QString> ShibokenGenerator::m_tpFuncs = QHash<QString, QString>();
+QStringList ShibokenGenerator::m_knownPythonTypes = QStringList();
+
+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] = QRegExp(QLatin1String(CHECKTYPE_REGEX));
+ m_typeSystemConvRegEx[TypeSystemIsConvertibleFunction] = QRegExp(QLatin1String(ISCONVERTIBLE_REGEX));
+ m_typeSystemConvRegEx[TypeSystemToPythonFunction] = QRegExp(QLatin1String(CONVERTTOPYTHON_REGEX));
+ m_typeSystemConvRegEx[TypeSystemToCppFunction] = QRegExp(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;
+ foreach (const AbstractMetaFunction* func, metaClass->functions()) {
+ 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) {
+ foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) {
+ if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass)
+ continue;
+ if (!enumList.contains(const_cast<AbstractMetaEnum*>(metaEnum)))
+ enumList.append(const_cast<AbstractMetaEnum*>(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();
+
+ foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) {
+ foreach (const AbstractMetaEnumValue* enumValue, metaEnum->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 QRegExp enumValueRegEx(QLatin1String("^([A-Za-z_]\\w*)?$"));
+ 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 QRegExp numberRegEx(QLatin1String("^\\d+$")); // Numbers to flags
+ if (numberRegEx.exactMatch(value)) {
+ 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 QRegExp enumCombinationRegEx(QLatin1String("^([A-Za-z_][\\w:]*)\\(([^,\\(\\)]*)\\)$")); // FlagName(EnumItem|EnumItem|...)
+ if (prefix.isEmpty() && enumCombinationRegEx.indexIn(value) != -1) {
+ QString flagName = enumCombinationRegEx.cap(1);
+ QStringList enumItems = enumCombinationRegEx.cap(2).split(QLatin1Char('|'));
+ QString scope = searchForEnumScope(func->implementingClass(), enumItems.first());
+ if (!scope.isEmpty())
+ scope.append(QLatin1String("::"));
+
+ QStringList fixedEnumItems;
+ foreach (const QString& enumItem, 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.exactMatch(value)&& value != QLatin1String("NULL"))
+ prefix = resolveScopePrefix(metaClass, value);
+ } else if (arg->type()->isPrimitive() && arg->type()->name() == QLatin1String("int")) {
+ if (enumValueRegEx.exactMatch(value) && func->implementingClass())
+ prefix = resolveScopePrefix(func->implementingClass(), value);
+ } else if(arg->type()->isPrimitive()) {
+ static QRegExp unknowArgumentRegEx(QLatin1String("^(?:[A-Za-z_][\\w:]*\\()?([A-Za-z_]\\w*)(?:\\))?$")); // [PrimitiveType(] DESIREDNAME [)]
+ if (unknowArgumentRegEx.indexIn(value) != -1 && func->implementingClass()) {
+ foreach (const AbstractMetaField* field, func->implementingClass()->fields()) {
+ if (unknowArgumentRegEx.cap(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(unknowArgumentRegEx.cap(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<SbkObject *>(") + 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<SbkObject *>(") + 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;
+ foreach (const FunctionModification &funcMod, func->modifications()) {
+ foreach (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');
+ foreach (const AbstractMetaArgument* arg, func->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<const char*>()");
+ if (isVoidPointer(type))
+ return QLatin1String("Shiboken::Conversions::PrimitiveTypeConverter<void*>()");
+ 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<const PrimitiveTypeEntry*>(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<const ContainerTypeEntry *>(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)
+{
+ foreach (const FunctionModification &mod, func->modifications()) {
+ 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<const SbkObjectType *>(");
+ 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<SbkObjectType *>(")
+ + 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<const SbkObjectType *>(")
+ + 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<SbkObjectType *>(")
+ + 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<SbkObjectType *>(")
+ + 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<const SbkObjectType *>(")
+ + 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<const SbkObjectType *>(") + 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();
+ }
+
+ QList<ReferenceCount> referenceCounts;
+ referenceCounts = func->referenceCounts(func->implementingClass(), argument->argumentIndex() + 1);
+ 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;
+ foreach (AbstractMetaFunction *func, metaClass->functions()) {
+ 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;
+ foreach (const AbstractMetaClass* metaClass, classes()) {
+ // Use only the classes for the current module.
+ if (!shouldGenerate(metaClass))
+ continue;
+ foreach (AbstractMetaFunction* convOp, metaClass->operatorOverloads(AbstractMetaClass::ConversionOp)) {
+ // 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;
+}
+
+QList<const CustomConversion*> ShibokenGenerator::getPrimitiveCustomConversions()
+{
+ QList<const CustomConversion*> conversions;
+ foreach (const PrimitiveTypeEntry* type, primitiveTypes()) {
+ 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);
+ foreach (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;
+}
+
+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 QRegExp pyArgsRegex(QLatin1String("%PYARG_(\\d+)"));
+ if (language == TypeSystem::TargetLangCode) {
+ if (usePyArgs) {
+ code.replace(pyArgsRegex, QLatin1String(PYTHON_ARGS"[\\1-1]"));
+ } else {
+ static QRegExp pyArgsRegexCheck(QLatin1String("%PYARG_([2-9]+)"));
+ if (pyArgsRegexCheck.indexIn(code) != -1) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "Wrong index for %PYARG variable (" << pyArgsRegexCheck.cap(1) << ") on " << func->signature();
+ 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 QRegExp pyArgsAttributionRegex(QLatin1String("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"));
+ 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.
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ QString argTypeVar = QStringLiteral("%ARG%1_TYPE").arg(arg->argumentIndex() + 1);
+ QString argTypeVal = arg->type()->cppSignature();
+ code.replace(argTypeVar, argTypeVal);
+ }
+
+ int pos = 0;
+ static QRegExp cppArgTypeRegexCheck(QLatin1String("%ARG(\\d+)_TYPE"));
+ while ((pos = cppArgTypeRegexCheck.indexIn(code, pos)) != -1) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "Wrong index for %ARG#_TYPE variable (" << cppArgTypeRegexCheck.cap(1)
+ << ") on " << func->signature();
+ pos += cppArgTypeRegexCheck.matchedLength();
+ }
+
+ // 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<SbkObject*>(%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<SbkObject*>(%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.
+ ArgumentVarReplacementList argReplacements = getArgumentReplacement(func, usePyArgs, language, lastArg);
+
+ QStringList args;
+ foreach (const ArgumentVarReplacementPair &pair, argReplacements) {
+ if (pair.second.startsWith(QLatin1String(CPP_ARG_REMOVED)))
+ continue;
+ args << pair.second;
+ }
+ code.replace(QLatin1String("%ARGUMENT_NAMES"), args.join(QLatin1String(", ")));
+
+ foreach (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(QRegExp(QString::fromLatin1("%%1\\b").arg(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()) {
+ foreach (const AbstractMetaFunction* f, getFunctionOverloads(func->ownerClass(), func->name()))
+ 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 QRegExp expr(QLatin1String("\\s*\\*?\\s*[A-Za-z_][A-Za-z_0-9.]*\\s*(?:\\[[^\\[]+\\])*"));
+ return expr.exactMatch(code.trimmed());
+}
+
+// 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<QString, QString> StringPair;
+void ShibokenGenerator::replaceConverterTypeSystemVariable(TypeSystemConverterVariable converterVariable, QString& code)
+{
+ QRegExp& regex = m_typeSystemConvRegEx[converterVariable];
+ int pos = 0;
+ QList<StringPair> replacements;
+ while ((pos = regex.indexIn(code, pos)) != -1) {
+ pos += regex.matchedLength();
+ QStringList list = regex.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 = pos - list.first().count();
+ 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, pos);
+ 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, pos);
+ 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));
+ }
+ foreach (const StringPair &rep, replacements)
+ code.replace(rep.first, rep.second);
+}
+
+bool ShibokenGenerator::injectedCodeUsesCppSelf(const AbstractMetaFunction* func)
+{
+ CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode);
+ foreach (const CodeSnip &snip, 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);
+ foreach (const CodeSnip &snip, 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);
+ foreach (const CodeSnip &snip, 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 QRegExp overrideCallRegexCheck(QLatin1String("PyObject_Call\\s*\\(\\s*%PYTHON_METHOD_OVERRIDE\\s*,"));
+ CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, TypeSystem::NativeCode);
+ foreach (const CodeSnip &snip, snips) {
+ if (overrideCallRegexCheck.indexIn(snip.code()) != -1)
+ return true;
+ }
+ return false;
+}
+
+bool ShibokenGenerator::injectedCodeHasReturnValueAttribution(const AbstractMetaFunction* func, TypeSystem::Language language)
+{
+ static QRegExp retValAttributionRegexCheck_native(QLatin1String("%0\\s*=[^=]\\s*.+"));
+ static QRegExp retValAttributionRegexCheck_target(QLatin1String("%PYARG_0\\s*=[^=]\\s*.+"));
+ CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny, language);
+ foreach (const CodeSnip &snip, snips) {
+ if (language == TypeSystem::TargetLangCode) {
+ if (retValAttributionRegexCheck_target.indexIn(snip.code()) != -1)
+ return true;
+ } else {
+ if (retValAttributionRegexCheck_native.indexIn(snip.code()) != -1)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ShibokenGenerator::injectedCodeUsesArgument(const AbstractMetaFunction* func, int argumentIndex)
+{
+ CodeSnipList snips = func->injectedCodeSnips(TypeSystem::CodeSnipPositionAny);
+ foreach (const CodeSnip &snip, snips) {
+ QString code = snip.code();
+ if (code.contains(QLatin1String("%ARGUMENT_NAMES")))
+ return true;
+ if (code.contains(QRegExp(QStringLiteral("%%1\\b").arg(argumentIndex + 1))))
+ 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<QString, AbstractMetaFunctionList> 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;
+ foreach (AbstractMetaFunction* func, 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;
+ foreach (AbstractMetaFunction* func, 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) {
+ foreach (const QString &parent, metaClass->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);
+ foreach (AbstractMetaClass* base, 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);
+ foreach (const QString& instantiation, 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: ";
+ foreach (AbstractMetaFunction *func, 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<QString, AbstractMetaFunctionList> results;
+ foreach (AbstractMetaFunction* func, lst) {
+ if (isGroupable(func))
+ results[func->name()].append(func);
+ }
+ return results;
+}
+
+AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *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<QString> *seen)
+{
+ AbstractMetaFunctionList results;
+ seen->insert(func->minimalSignature());
+ results << const_cast<AbstractMetaFunction *>(func) << getInheritedOverloads(func, seen);
+ return results;
+}
+
+AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName)
+{
+ AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions();
+
+ AbstractMetaFunctionList results;
+ QSet<QString> seenSignatures;
+ foreach (AbstractMetaFunction* func, 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<int>::max();
+ int maxArgs = 0;
+ foreach (const AbstractMetaFunction* func, overloads) {
+ int numArgs = 0;
+ foreach (const AbstractMetaArgument* arg, func->arguments()) {
+ if (!func->argumentRemoved(arg->argumentIndex() + 1))
+ numArgs++;
+ }
+ maxArgs = std::max(maxArgs, numArgs);
+ minArgs = std::min(minArgs, numArgs);
+ }
+ return qMakePair(minArgs, maxArgs);
+}
+
+QMap<QString, QString> ShibokenGenerator::options() const
+{
+ QMap<QString, QString> 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)
+{
+ foreach (const CodeSnip& snip, 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;
+
+ foreach (CustomConversion::TargetToNativeConversion* toNative, toCppConversions)
+ code.append(toNative->conversion());
+}
+
+bool ShibokenGenerator::doSetup(const QMap<QString, QString>& 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;
+ foreach (const PrimitiveTypeEntry* type, primitiveTypes())
+ getCode(snips, type);
+ foreach (const ContainerTypeEntry* type, containerTypes())
+ getCode(snips, type);
+ foreach (const AbstractMetaClass* metaClass, classes())
+ getCode(snips, metaClass->typeEntry());
+ getCode(snips, td->findType(packageName()));
+ const FunctionGroupMap &functionGroups = getFunctionGroups();
+ for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) {
+ foreach (AbstractMetaFunction* func, it.value())
+ getCode(snips, func->injectedCodeSnips());
+ }
+
+ foreach (const QString& code, 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();
+ foreach (const AbstractMetaType* instantiation, type->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;
+ foreach (const AbstractMetaType* instantiation, metaClass->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
+ foreach(FunctionModification m, func->modifications()) {
+ foreach(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..837e7d640
--- /dev/null
+++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h
@@ -0,0 +1,554 @@
+/****************************************************************************
+**
+** 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 <generator.h>
+
+#include "typesystem.h"
+
+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<QString, AbstractMetaFunctionList> 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<QString> *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<QString> *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<int, int> 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;
+
+ /**
+ * 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;
+ QString functionReturnType(const AbstractMetaFunction* func, Options options = NoOption) const;
+
+ /// Utility function for writeCodeSnips.
+ typedef QPair<const AbstractMetaArgument*, QString> ArgumentVarReplacementPair;
+ typedef QList<ArgumentVarReplacementPair> 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 QList<CodeSnip>& 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 QList<CodeSnip>& 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 QList<CodeSnip>& 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;
+
+ /// 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<QString, QString>& 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<QString, QString> m_pythonPrimitiveTypeName;
+ static QHash<QString, QString> m_pythonOperators;
+ static QHash<QString, QString> m_formatUnits;
+ static QHash<QString, QString> 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<const TypeEntry*, QList<const AbstractMetaClass*> > 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.
+ QList<const CustomConversion*> 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<QString, AbstractMetaType*> AbstractMetaTypeCache;
+ AbstractMetaTypeCache m_metaTypeFromStringCache;
+
+ /// Type system converter variable replacement names and regular expressions.
+ QString m_typeSystemConvName[TypeSystemConverterVariables];
+ QRegExp 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 <Fill> 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..9ec49d5bd
--- /dev/null
+++ b/sources/shiboken2/libshiboken/CMakeLists.txt
@@ -0,0 +1,77 @@
+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)
+
+#Find installed sparsehash
+find_path(SPARSEHASH_INCLUDE_PATH sparseconfig.h PATH_SUFFIXES "/google/sparsehash")
+if(SPARSEHASH_INCLUDE_PATH)
+ message(STATUS "Using system hash found in: ${SPARSEHASH_INCLUDE_PATH}")
+else()
+ set(SPARSEHASH_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/ext/sparsehash)
+endif()
+
+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}
+ ${SPARSEHASH_INCLUDE_PATH})
+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}
+ 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<PyObject*>(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<PyTupleObject*>(m_pyObj); }
+ inline operator bool() const { return m_pyObj; }
+ inline PyObject* operator->() { return m_pyObj; }
+
+ template<typename T>
+ T cast()
+ {
+ return reinterpret_cast<T>(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..b3f99a8a5
--- /dev/null
+++ b/sources/shiboken2/libshiboken/basewrapper.cpp
@@ -0,0 +1,1518 @@
+/****************************************************************************
+**
+** 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 <string>
+#include <cstring>
+#include <cstddef>
+#include <set>
+#include <sstream>
+#include <algorithm>
+#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<SbkObject *>(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<char*>("__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<SbkObject*>(self);
+
+ //Visit children
+ Shiboken::ParentInfo* pInfo = sbkSelf->d->parentInfo;
+ if (pInfo) {
+ std::set<SbkObject*>::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<PyObject*>::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<SbkObject*>(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<SbkObject*>(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<SbkObjectType*>(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<SbkObjectType*>(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<PyTypeObject*>(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<SbkObjectType*>(PyType_Type.tp_new(metatype, args, kwds));
+ if (!newType)
+ return 0;
+
+ Shiboken::ObjectType::initPrivateData(newType);
+ SbkObjectTypePrivate* d = newType->d;
+
+ std::list<SbkObjectType*> bases = Shiboken::getCppBaseClasses(reinterpret_cast<PyTypeObject*>(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<SbkObjectType*>::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<PyObject*>(newType);
+}
+
+PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*)
+{
+ SbkObject* self = PyObject_GC_New(SbkObject, subtype);
+ Py_INCREF(reinterpret_cast<PyObject*>(subtype));
+ SbkObjectPrivate* d = new SbkObjectPrivate;
+
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(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<PyObject*>(self));
+ return reinterpret_cast<PyObject*>(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<PyObject*> &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<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
+
+ if (!PyType_IsSubtype(type, reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ continue;
+ } else {
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(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<PyTypeObject**>(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<PyTypeObject**>(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<std::pair<void*, SbkObjectType*> >::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 Module { void init(); }
+namespace Conversions { void init(); }
+
+void init()
+{
+ static bool shibokenAlreadInitialised = false;
+ if (shibokenAlreadInitialised)
+ return;
+
+ Module::init();
+ 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<PyTypeObject *>(&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<PyTypeObject*>(node) == m_typeToFind) {
+ m_found = true;
+ finish();
+ }
+ }
+ bool found() const { return m_found; }
+
+ private:
+ bool m_found;
+ PyTypeObject* m_typeToFind;
+};
+
+std::list<SbkObject*> splitPyObject(PyObject* pyObj)
+{
+ std::list<SbkObject*> 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<SbkObject*>(item));
+ }
+ }
+ } else {
+ result.push_back(reinterpret_cast<SbkObject*>(pyObj));
+ }
+ return result;
+}
+
+static void decRefPyObjectList(const std::list<PyObject*>& lst, PyObject *skip)
+{
+ std::list<PyObject*>::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<PyTypeObject*>(&SbkObject_Type));
+}
+
+bool isUserType(PyTypeObject* type)
+{
+ return checkType(type) && reinterpret_cast<SbkObjectType*>(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<SbkObjectType*>(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<PyTypeObject *>(baseType);
+ if (baseTypes) {
+ for (int i = 0; i < PySequence_Fast_GET_SIZE(baseTypes); ++i)
+ BindingManager::instance().addClassInheritance(reinterpret_cast<SbkObjectType *>(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<PyTypeObject *>(type)) < 0)
+ return false;
+
+ if (isInnerClass)
+ return PyDict_SetItemString(enclosingObject, typeName, reinterpret_cast<PyObject *>(type)) == 0;
+
+ //PyModule_AddObject steals type's reference.
+ Py_INCREF(reinterpret_cast<PyObject *>(type));
+ return PyModule_AddObject(enclosingObject, typeName, reinterpret_cast<PyObject *>(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<SbkObject*>& 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<Py_hash_t>(pyObj);
+}
+
+static void setSequenceOwnership(PyObject* pyObj, bool owner)
+{
+ if (PySequence_Check(pyObj)) {
+ std::list<SbkObject*> objs = splitPyObject(pyObj);
+ std::list<SbkObject*>::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<SbkObject*>(pyObj));
+ else
+ releaseOwnership(reinterpret_cast<SbkObject*>(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<SbkObjectType*>(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<PyObject *>(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<SbkObjectType*>(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<PyObject *>(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<SbkObject*>& seen);
+static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen);
+
+void invalidate(PyObject* pyobj)
+{
+ std::set<SbkObject*> seen;
+ recursive_invalidate(pyobj, seen);
+}
+
+void invalidate(SbkObject* self)
+{
+ std::set<SbkObject*> seen;
+ recursive_invalidate(self, seen);
+}
+
+static void recursive_invalidate(PyObject* pyobj, std::set<SbkObject*>& seen)
+{
+ std::list<SbkObject*> objs = splitPyObject(pyobj);
+ std::list<SbkObject*>::const_iterator it = objs.begin();
+ for (; it != objs.end(); it++)
+ recursive_invalidate(*it, seen);
+}
+
+static void recursive_invalidate(SbkObject* self, std::set<SbkObject*>& seen)
+{
+ // Skip if this object not is a valid object or if it's already been seen
+ if (!self || reinterpret_cast<PyObject *>(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<PyObject*> lst = iter->second;
+ std::list<PyObject*>::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<PyObject *>(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<PyObject*> lst = iter->second;
+ std::list<PyObject*>::const_iterator it = lst.begin();
+ while(it != lst.end()) {
+ if (Shiboken::Object::checkType(*it))
+ makeValid(reinterpret_cast<SbkObject*>(*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<SbkObjectType*>(type)->d->is_multicpp)
+ idx = getTypeIndexOnHierarchy(type, desiredType);
+ if (pyObj->d->cptr)
+ return pyObj->d->cptr[idx];
+ return 0;
+}
+
+std::vector<void*> cppPointers(SbkObject* pyObj)
+{
+ int n = getNumberOfCppBaseClasses(Py_TYPE(pyObj));
+ std::vector<void*> 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<SbkObjectType*>(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<SbkObject*>(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<PyObject*>(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<PyTypeObject*>(&SbkObject_Type))) {
+ return true;
+ }
+ return isValid(reinterpret_cast<SbkObject*>(pyObj), throwPyError);
+}
+
+SbkObject *findColocatedChild(SbkObject *wrapper,
+ const SbkObjectType *instanceType)
+{
+ // Degenerate case, wrapper is the correct wrapper.
+ if (reinterpret_cast<const void *>(Py_TYPE(wrapper)) == reinterpret_cast<const void *>(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<const void *>(Py_TYPE(*iChild)) == reinterpret_cast<const void *>(instanceType))
+ return const_cast<SbkObject *>((*iChild));
+ else
+ return findColocatedChild(const_cast<SbkObject *>(*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<SbkObjectType*>(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<SbkObject*>(SbkObjectTpNew(reinterpret_cast<PyTypeObject*>(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<PyObject*>(self));
+ }
+ return reinterpret_cast<PyObject*>(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<PyObject *>(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<SbkObject*>(parent);
+ SbkObject* child_ = reinterpret_cast<SbkObject*>(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<SbkObjectType*>(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<SbkObjectType*>(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<PyObject*> objects;
+ if (iter != refCountMap.end()) {
+ objects = (*iter).second;
+ std::list<PyObject*>::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<SbkObjectType*> bases;
+
+ if (self->d && self->d->cptr) {
+ if (ObjectType::isUserType(Py_TYPE(self)))
+ bases = getCppBaseClasses(Py_TYPE(self));
+ else
+ bases.push_back(reinterpret_cast<SbkObjectType*>(Py_TYPE(self)));
+
+ s << "C++ address....... ";
+ std::list<SbkObjectType*>::const_iterator it = bases.begin();
+ for (int i = 0; it != bases.end(); ++it, ++i)
+ s << reinterpret_cast<PyTypeObject *>(*it)->tp_name << '/' << self->d->cptr[i] << ' ';
+ s << "\n";
+ }
+ else {
+ s << "C++ address....... <<Deleted>>\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<PyObject *>(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<PyObject *>(*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<PyObject*>::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 <vector>
+#include <string>
+
+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<typename T>
+void callCppDestructor(void* cptr)
+{
+ delete reinterpret_cast<T*>(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<void*> 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 <list>
+#include <map>
+#include <set>
+#include <string>
+
+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<std::string, std::list<PyObject*> > RefCountMap;
+
+/// Linked list of SbkBaseWrapper pointers
+typedef std::set<SbkObject*> 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<SbkObject*> 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<SbkObjectType*> bases() const { return m_bases; }
+private:
+ std::list<SbkObjectType*> 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<PyTypeObject*>(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<std::pair<void*, SbkObjectType*> > 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<SbkObjectType*> 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..d7e122cd7
--- /dev/null
+++ b/sources/shiboken2/libshiboken/bindingmanager.cpp
@@ -0,0 +1,344 @@
+/****************************************************************************
+**
+** 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 "google/dense_hash_map"
+#include "sbkdbg.h"
+#include "gilstate.h"
+#include "sbkstring.h"
+#include "debugfreehook.h"
+
+#include <cstddef>
+#include <fstream>
+
+namespace Shiboken
+{
+
+typedef google::dense_hash_map<const void*, SbkObject*> WrapperMap;
+
+class Graph
+{
+public:
+ typedef std::list<SbkObjectType*> NodeList;
+ typedef google::dense_hash_map<SbkObjectType*, NodeList> Edges;
+
+ Edges m_edges;
+
+ Graph()
+ {
+ m_edges.set_empty_key(0);
+ }
+
+ 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<const void *>(sbkObj),
+ Py_TYPE(sbkObj)->tp_name,
+ int(reinterpret_cast<const PyObject *>(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;
+ m_d->wrapperMapper.set_empty_key((WrapperMap::key_type)0);
+ m_d->wrapperMapper.set_deleted_key((WrapperMap::key_type)1);
+
+#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<void*>(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<SbkObjectType*>(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<void*>((std::size_t) cptr + (*offset)));
+ offset++;
+ }
+ }
+}
+
+void BindingManager::releaseWrapper(SbkObject* sbkObj)
+{
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(Py_TYPE(sbkObj));
+ SbkObjectTypePrivate* d = sbkType->d;
+ int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(Py_TYPE(sbkObj)) : 1);
+
+ void** cptrs = reinterpret_cast<SbkObject*>(sbkObj)->d->cptr;
+ for (int i = 0; i < numBases; ++i) {
+ unsigned char *cptr = reinterpret_cast<unsigned char *>(cptrs[i]);
+ m_d->releaseWrapper(cptr, sbkObj);
+ if (d && d->mi_offsets) {
+ int* offset = d->mi_offsets;
+ while (*offset != -1) {
+ if (*offset > 0)
+ m_d->releaseWrapper(reinterpret_cast<void *>((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<const PyObject *>(wrapper)->ob_refcnt == 0)
+ return 0;
+
+ if (wrapper->ob_dict) {
+ PyObject* method = PyDict_GetItemString(wrapper->ob_dict, methodName);
+ if (method) {
+ Py_INCREF(reinterpret_cast<PyObject *>(method));
+ return method;
+ }
+ }
+
+ PyObject* pyMethodName = Shiboken::String::fromCString(methodName);
+ PyObject *method = PyObject_GetAttr(reinterpret_cast<PyObject *>(wrapper), pyMethodName);
+
+ if (method && PyMethod_Check(method)
+ && reinterpret_cast<PyMethodObject*>(method)->im_self == reinterpret_cast<PyObject*>(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<PyTypeObject*>(PyTuple_GET_ITEM(mro, i));
+ if (parent->tp_dict) {
+ defaultMethod = PyDict_GetItem(parent->tp_dict, pyMethodName);
+ if (defaultMethod && reinterpret_cast<PyMethodObject*>(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<PyObject*> BindingManager::getAllPyObjects()
+{
+ std::set<PyObject*> pyObjects;
+ const WrapperMap& wrappersMap = m_d->wrapperMapper;
+ WrapperMap::const_iterator it = wrappersMap.begin();
+ for (; it != wrappersMap.end(); ++it)
+ pyObjects.insert(reinterpret_cast<PyObject*>(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 <set>
+#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<PyObject*> 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 <limits>
+#include <typeinfo>
+
+#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<typename T>
+PyTypeObject* SbkType()
+{
+ return 0;
+}
+
+template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; }
+template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; }
+
+/**
+ * Convenience template to create wrappers using the proper Python type for a given C++ class instance.
+ */
+template<typename T>
+inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool isExactType = false)
+{
+ const char* typeName = 0;
+ if (!isExactType)
+ typeName = typeid(*const_cast<T*>(cppobj)).name();
+ return Object::newObject(reinterpret_cast<SbkObjectType*>(SbkType<T>()),
+ const_cast<T*>(cppobj), hasOwnership, isExactType, typeName);
+}
+
+// Base Conversions ----------------------------------------------------------
+// The basic converter must be empty to avoid object types being converted by value.
+template <typename T> struct Converter {};
+
+// Pointer conversion specialization for value types.
+template <typename T>
+struct Converter<T*>
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return Converter<T>::checkType(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>());
+ }
+
+ static PyObject* toPython(const T* cppobj)
+ {
+ if (!cppobj)
+ Py_RETURN_NONE;
+ PyObject* pyobj = reinterpret_cast<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj));
+ if (pyobj)
+ Py_INCREF(pyobj);
+ else
+ pyobj = createWrapper<T>(cppobj);
+ return pyobj;
+ }
+
+ static T* toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, SbkType<T>()))
+ return reinterpret_cast<T *>(Object::cppPointer(reinterpret_cast<SbkObject *>(pyobj), SbkType<T>()));
+ else if (Converter<T>::isConvertible(pyobj))
+ return new T(Converter<T>::toCpp(pyobj));
+ else if (pyobj == Py_None)
+ return 0;
+
+ assert(false);
+ return 0;
+ }
+};
+template <typename T> struct Converter<const T*> : Converter<T*> {};
+
+// Specialization for reference conversions.
+template <typename T>
+struct Converter<T&>
+{
+ static inline bool checkType(PyObject* pyObj) { return Converter<T>::checkType(pyObj); }
+ static inline bool isConvertible(PyObject* pyObj) { return Converter<T>::isConvertible(pyObj); }
+ static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); }
+ static inline T& toCpp(PyObject* pyobj) { return *Converter<T*>::toCpp(pyobj); }
+};
+
+// Void pointer conversions.
+template<>
+struct Converter<void*>
+{
+ 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<PyObject *>(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<ValueTypeClass> : ValueTypeConverter<ValueTypeClass>"
+template <typename T>
+struct ValueTypeConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+
+ // 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<T>()))
+ return true;
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>());
+ return ObjectType::isExternalConvertible(shiboType, pyobj);
+ }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(cppobj)); }
+ static inline PyObject* toPython(const T& cppobj)
+ {
+ PyObject* obj = createWrapper<T>(new T(cppobj), true, true);
+// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo<T>::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<T>())) {
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(SbkType<T>());
+ if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) {
+ T* cptr = reinterpret_cast<T*>(ObjectType::callExternalCppConversion(shiboType, pyobj));
+ const T result = *cptr;
+ delete cptr;
+ return result;
+ }
+ assert(false);
+ }
+ return *reinterpret_cast<T*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<T>()));
+ }
+};
+
+// 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<AbstractClass*> : ObjectTypeConverter<AbstractClass>"
+template <typename T>
+struct ObjectTypeConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ /// 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<T>()); }
+ /// Convenience overload that calls "toPython(const T*)" method.
+ static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast<T*>(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<PyObject*>(BindingManager::instance().retrieveWrapper(cppobj));
+ if (pyobj)
+ Py_INCREF(pyobj);
+ else
+ pyobj = createWrapper<T>(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<SbkObject *>(pyobj);
+ SbkObjectType* shiboType = reinterpret_cast<SbkObjectType*>(pyobj->ob_type);
+ if (ObjectType::hasCast(shiboType))
+ return reinterpret_cast<T*>(ObjectType::cast(shiboType, sbkObj, SbkType<T>()));
+ return reinterpret_cast<T *>(Object::cppPointer(sbkObj, SbkType<T>()));
+ }
+};
+
+template <typename T>
+struct ObjectTypeReferenceConverter : ObjectTypeConverter<T>
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<T>()); }
+ static inline PyObject* toPython(const T& cppobj) { return Converter<T*>::toPython(&cppobj); }
+ static inline T& toCpp(PyObject* pyobj)
+ {
+ T* t = Converter<T*>::toCpp(pyobj);
+ assert(t);
+ return *t;
+ }
+};
+
+// PyObject* specialization to avoid converting what doesn't need to be converted.
+template<>
+struct Converter<PyObject*> : ObjectTypeConverter<PyObject*>
+{
+ static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; }
+};
+
+// Primitive Conversions ------------------------------------------------------
+template <>
+struct Converter<bool>
+{
+ 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<bool*>(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<typename T, bool isSigned = std::numeric_limits<T>::is_signed >
+struct OverFlowChecker;
+
+template<typename T>
+struct OverFlowChecker<T, true>
+{
+ static bool check(const PY_LONG_LONG& value)
+ {
+ return value < std::numeric_limits<T>::min() || value > std::numeric_limits<T>::max();
+ }
+};
+
+template<typename T>
+struct OverFlowChecker<T, false>
+{
+ static bool check(const PY_LONG_LONG& value)
+ {
+ return value < 0 || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max();
+ }
+};
+
+template<>
+struct OverFlowChecker<PY_LONG_LONG, true>
+{
+ static bool check(const PY_LONG_LONG &)
+ {
+ return false;
+ }
+};
+
+template<>
+struct OverFlowChecker<double, true>
+{
+ static bool check(const double &)
+ {
+ return false;
+ }
+};
+
+template<>
+struct OverFlowChecker<float, true>
+{
+ static bool check(const double& value)
+ {
+ return value < std::numeric_limits<float>::min() || value > std::numeric_limits<float>::max();
+ }
+};
+
+template <typename PyIntEquiv>
+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<PyIntEquiv*>(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<PyIntEquiv>::check(d_result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return static_cast<PyIntEquiv>(d_result);
+ } else {
+ PY_LONG_LONG result = PyLong_AsLongLong(pyobj);
+ if (OverFlowChecker<PyIntEquiv>::check(result))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ return static_cast<PyIntEquiv>(result);
+ }
+ }
+};
+
+template <typename T>
+struct Converter_PyULongInt : Converter_PyInt<T>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<T*>(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 <typename CharType>
+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<CharType*>(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<CharType>::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<unsigned long> : Converter_PyULongInt<unsigned long> {};
+template <> struct Converter<unsigned int> : Converter_PyULongInt<unsigned int> {};
+template <> struct Converter<char> : CharConverter<char>
+{
+ // Should we really return a string?
+ using CharConverter<char>::toPython;
+ using CharConverter<char>::isConvertible;
+ using CharConverter<char>::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<char>::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<signed char> : CharConverter<signed char> {};
+template <> struct Converter<unsigned char> : CharConverter<unsigned char> {};
+template <> struct Converter<int> : Converter_PyInt<int> {};
+template <> struct Converter<short> : Converter_PyInt<short> {};
+template <> struct Converter<unsigned short> : Converter_PyInt<unsigned short> {};
+template <> struct Converter<long> : Converter_PyInt<long> {};
+
+template <>
+struct Converter<PY_LONG_LONG>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<PY_LONG_LONG*>(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<unsigned PY_LONG_LONG>
+{
+ static inline PyObject* toPython(void* cppobj)
+ {
+ return toPython(*reinterpret_cast<unsigned PY_LONG_LONG*>(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 <typename PyFloatEquiv>
+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<PyFloatEquiv*>(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<float> : Converter_PyFloat<float> {};
+template <> struct Converter<double> : Converter_PyFloat<double> {};
+
+// PyEnum Conversions ---------------------------------------------------------
+template <typename CppEnum>
+struct EnumConverter
+{
+ static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); }
+ static inline bool isConvertible(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType<CppEnum>()); }
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<CppEnum*>(cppobj)); }
+ static inline PyObject* toPython(CppEnum cppenum)
+ {
+ return Shiboken::Enum::newItem(Shiboken::SbkType<CppEnum>(), (long) cppenum);
+ }
+ static inline CppEnum toCpp(PyObject* pyObj)
+ {
+ return (CppEnum) Shiboken::Enum::getValue(pyObj);;
+ }
+};
+
+// C Sting Types --------------------------------------------------------------
+template <typename CString>
+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<CString>(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<const char*> : Converter_CString<const char*> {};
+
+template <> struct Converter<std::string> : Converter_CString<std::string>
+{
+ static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast<std::string*>(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<typename T> struct Converter<std::list<T> > : StdListConverter<std::list<T> > {};
+
+// And this for a std::map:
+// template<typename KT, typename VT>
+// struct Converter<std::map<KT, VT> > : StdMapConverter<std::map<KT, VT> > {};
+
+template <typename StdList>
+struct StdListConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdList>()))
+ 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<StdList>() && 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<typename StdList::value_type>::isConvertible(item))
+ return false;
+ }
+ return true;
+ }
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdList*>(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<typename StdList::value_type>::toPython(vh));
+ }
+ return result;
+ }
+ static StdList toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, SbkType<StdList>()))
+ return *reinterpret_cast<StdList*>(Object::cppPointer(reinterpret_cast<SbkObject*>(pyobj), SbkType<StdList>()));
+
+ StdList result;
+ for (int i = 0; i < PySequence_Size(pyobj); i++) {
+ AutoDecRef pyItem(PySequence_GetItem(pyobj, i));
+ result.push_back(Converter<typename StdList::value_type>::toCpp(pyItem));
+ }
+ return result;
+ }
+};
+
+template <typename StdPair>
+struct StdPairConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdPair>()))
+ return true;
+ if ((SbkType<StdPair>() && 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<typename StdPair::first_type>::isConvertible(item1)
+ && !Converter<typename StdPair::second_type>::isConvertible(item2)) {
+ return false;
+ }
+ return true;
+ }
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdPair*>(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<typename StdPair::first_type>::toPython(first));
+ PyTuple_SET_ITEM(tuple, 1, Converter<typename StdPair::second_type>::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<typename StdPair::first_type>::toCpp(pyFirst);
+ result.second = Converter<typename StdPair::second_type>::toCpp(pySecond);
+ return result;
+ }
+};
+
+template <typename StdMap>
+struct StdMapConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, SbkType<StdMap>()))
+ return true;
+ if ((SbkType<StdMap>() && 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<typename StdMap::key_type>::isConvertible(key)
+ || !Converter<typename StdMap::mapped_type>::isConvertible(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<StdMap*>(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<typename StdMap::key_type>::toPython(it->first),
+ Converter<typename StdMap::mapped_type>::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<typename StdMap::key_type>::toCpp(key),
+ Converter<typename StdMap::mapped_type>::toCpp(value)));
+ }
+ return result;
+ }
+};
+
+
+// class used to translate python objects to another type
+template <typename T> 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 <crtdbg.h>
+#include <windows.h>
+#endif
+
+#ifdef __GLIBC__
+#include <malloc.h>
+#endif
+
+#ifdef __APPLE__
+#include <malloc/malloc.h>
+#include <mach/mach.h>
+#include <mach/mach_vm.h>
+#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<PyObject *>(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 <shibokenmacros.h>
+#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 <stdarg.h>
+
+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<typename A>
+inline PyObject* makeTuple(const A& a)
+{
+ return PyTuple_Pack(1, AutoDecRef(Converter<A>::toPython(a)).object());
+}
+
+template<typename A, typename B>
+inline PyObject* makeTuple(const A& a, const B& b)
+{
+ return PyTuple_Pack(2, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object());
+}
+
+template<typename A, typename B, typename C>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c)
+{
+ return PyTuple_Pack(3, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object());
+}
+
+template<typename A, typename B, typename C, typename D>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d)
+{
+ return PyTuple_Pack(4, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object(),
+ AutoDecRef(Converter<D>::toPython(d)).object());
+}
+
+template<typename A, typename B, typename C, typename D, typename E>
+inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const E& e)
+{
+ return PyTuple_Pack(5, AutoDecRef(Converter<A>::toPython(a)).object(),
+ AutoDecRef(Converter<B>::toPython(b)).object(),
+ AutoDecRef(Converter<C>::toPython(c)).object(),
+ AutoDecRef(Converter<D>::toPython(d)).object(),
+ AutoDecRef(Converter<E>::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 T>
+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 <Python.h>
+#include <cstring>
+
+/*
+ *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..e7e9995b4
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkconverter.cpp
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** 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 "google/dense_hash_map"
+#include "autodecref.h"
+#include "sbkdbg.h"
+#include "helper.h"
+
+static SbkConverter** PrimitiveTypeConverters;
+
+typedef google::dense_hash_map<std::string, SbkConverter*> ConvertersMap;
+static ConvertersMap converters;
+
+namespace Shiboken {
+namespace Conversions {
+
+void init()
+{
+ static SbkConverter* primitiveTypeConverters[] = {
+ Primitive<PY_LONG_LONG>::createConverter(),
+ Primitive<bool>::createConverter(),
+ Primitive<char>::createConverter(),
+ Primitive<const char*>::createConverter(),
+ Primitive<double>::createConverter(),
+ Primitive<float>::createConverter(),
+ Primitive<int>::createConverter(),
+ Primitive<long>::createConverter(),
+ Primitive<short>::createConverter(),
+ Primitive<signed char>::createConverter(),
+ Primitive<std::string>::createConverter(),
+ Primitive<unsigned PY_LONG_LONG>::createConverter(),
+ Primitive<unsigned char>::createConverter(),
+ Primitive<unsigned int>::createConverter(),
+ Primitive<unsigned long>::createConverter(),
+ Primitive<unsigned short>::createConverter(),
+ Primitive<void*>::createConverter()
+ };
+ PrimitiveTypeConverters = primitiveTypeConverters;
+
+ assert(converters.empty());
+ converters.set_empty_key("");
+ converters.set_deleted_key("?");
+ 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<PyTypeObject *>(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<PyObject *>(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<SbkObjectType *>(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<void **>(cppOut) = pyIn == Py_None
+ ? 0
+ : cppPointer(reinterpret_cast<PyTypeObject *>(type), reinterpret_cast<SbkObject *>(pyIn));
+}
+
+void pythonToCppPointer(const SbkConverter *converter, PyObject *pyIn, void *cppOut)
+{
+ assert(converter);
+ assert(pyIn);
+ assert(cppOut);
+ *reinterpret_cast<void **>(cppOut) = pyIn == Py_None
+ ? 0
+ : cppPointer(reinterpret_cast<PyTypeObject *>(converter->pythonType), reinterpret_cast<SbkObject *>(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 <limits>
+#include <string>
+
+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<typename T> SbkConverter* PrimitiveTypeConverter() { return 0; }
+template<> inline SbkConverter* PrimitiveTypeConverter<PY_LONG_LONG>() { return primitiveTypeConverter(SBK_PY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<bool>() { return primitiveTypeConverter(SBK_BOOL_IDX_1); }
+template<> inline SbkConverter* PrimitiveTypeConverter<char>() { return primitiveTypeConverter(SBK_CHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<const char*>() { return primitiveTypeConverter(SBK_CONSTCHARPTR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<double>() { return primitiveTypeConverter(SBK_DOUBLE_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<float>() { return primitiveTypeConverter(SBK_FLOAT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<int>() { return primitiveTypeConverter(SBK_INT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<long>() { return primitiveTypeConverter(SBK_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<short>() { return primitiveTypeConverter(SBK_SHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<signed char>() { return primitiveTypeConverter(SBK_SIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<std::string>() { return primitiveTypeConverter(SBK_STD_STRING_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned PY_LONG_LONG>() { return primitiveTypeConverter(SBK_UNSIGNEDPY_LONG_LONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned char>() { return primitiveTypeConverter(SBK_UNSIGNEDCHAR_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned int>() { return primitiveTypeConverter(SBK_UNSIGNEDINT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned long>() { return primitiveTypeConverter(SBK_UNSIGNEDLONG_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<unsigned short>() { return primitiveTypeConverter(SBK_UNSIGNEDSHORT_IDX); }
+template<> inline SbkConverter* PrimitiveTypeConverter<void*>() { 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 <list>
+#include <limits>
+#include <typeinfo>
+#include <sstream>
+#include <iostream>
+
+#include "sbkdbg.h"
+
+extern "C"
+{
+
+typedef std::pair<IsConvertibleToCppFunc, PythonToCppFunc> ToCppConversion;
+typedef std::list<ToCppConversion> 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<typename T, typename MaxLimitType, bool isSigned>
+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<typename T, typename MaxLimitType = PY_LONG_LONG,
+ bool isSigned = std::numeric_limits<T>::is_signed >
+struct OverFlowChecker;
+
+template<typename T, typename MaxLimitType>
+struct OverFlowChecker<T, MaxLimitType, true> :
+ public OverFlowCheckerBase<T, MaxLimitType, true> {
+ static bool check(const MaxLimitType& value, PyObject *pyIn)
+ {
+ std::string valueAsString;
+ const bool isOverflow =
+ OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString)
+ || value < std::numeric_limits<T>::min()
+ || value > std::numeric_limits<T>::max();
+ if (isOverflow)
+ OverFlowChecker::formatOverFlowMessage(value, &valueAsString);
+ return isOverflow;
+ }
+};
+
+template<typename T, typename MaxLimitType>
+struct OverFlowChecker<T, MaxLimitType, false>
+ : public OverFlowCheckerBase<T, MaxLimitType, false> {
+ static bool check(const MaxLimitType& value, PyObject *pyIn)
+ {
+ std::string valueAsString;
+ const bool isOverflow =
+ OverFlowChecker::checkForInternalPyOverflow(pyIn, valueAsString)
+ || value < 0
+ || static_cast<unsigned long long>(value) > std::numeric_limits<T>::max();
+ if (isOverflow)
+ OverFlowChecker::formatOverFlowMessage(value, &valueAsString);
+ return isOverflow;
+ }
+};
+template<>
+struct OverFlowChecker<PY_LONG_LONG, PY_LONG_LONG, true> :
+ public OverFlowCheckerBase<PY_LONG_LONG, PY_LONG_LONG, true> {
+ 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<double, PY_LONG_LONG, true> {
+ static bool check(const double &, PyObject *) { return false; }
+};
+template<>
+struct OverFlowChecker<float, PY_LONG_LONG, true> :
+ public OverFlowCheckerBase<float, PY_LONG_LONG, true> {
+ static bool check(const double& value, PyObject *)
+ {
+ const bool result = value < std::numeric_limits<float>::min()
+ || value > std::numeric_limits<float>::max();
+ if (result)
+ formatOverFlowMessage(value);
+ return result;
+ }
+};
+
+// Basic primitive type converters ---------------------------------------------------------
+template<typename T> PyTypeObject* SbkType() { return 0; }
+template<> inline PyTypeObject* SbkType<PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<bool>() { return &PyBool_Type; }
+template<> inline PyTypeObject* SbkType<char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<const char*>() { return &PyString_Type; }
+template<> inline PyTypeObject* SbkType<double>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<float>() { return &PyFloat_Type; }
+template<> inline PyTypeObject* SbkType<int>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<short>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<signed char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned PY_LONG_LONG>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned char>() { return &PyInt_Type; }
+template<> inline PyTypeObject* SbkType<unsigned int>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned long>() { return &PyLong_Type; }
+template<> inline PyTypeObject* SbkType<unsigned short>() { return &PyInt_Type; }
+
+template <typename T> struct Primitive {};
+
+template <typename T>
+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<T>(), Primitive<T>::toPython);
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::toCpp, Primitive<T>::isConvertible);
+ return converter;
+ }
+};
+template <typename T>
+struct TwoPrimitive : OnePrimitive<T>
+{
+ static PythonToCppFunc isOtherConvertible(PyObject*) { return 0; }
+ static void otherToCpp(PyObject*, void*) {}
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = OnePrimitive<T>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, Primitive<T>::otherToCpp, Primitive<T>::isOtherConvertible);
+ return converter;
+ }
+};
+
+// Integers --------------------------------------------------------------------------------
+
+template <typename INT>
+struct IntPrimitive : TwoPrimitive<INT>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyInt_FromLong(*reinterpret_cast<const INT *>(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<INT>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(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<INT>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<INT * >(cppOut) = static_cast<INT>(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+template <> struct Primitive<int> : IntPrimitive<int> {};
+template <> struct Primitive<long> : IntPrimitive<long> {};
+template <> struct Primitive<short> : IntPrimitive<short> {};
+template <> struct Primitive<unsigned short> : IntPrimitive<unsigned short> {};
+
+// Unsigned Long Integers ------------------------------------------------------------------
+
+template <typename LONG>
+struct UnsignedLongPrimitive : IntPrimitive<LONG>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyLong_FromUnsignedLong(*reinterpret_cast<const LONG *>(cppIn));
+ }
+};
+template <> struct Primitive<unsigned int> : UnsignedLongPrimitive<unsigned int> {};
+template <> struct Primitive<unsigned long> : UnsignedLongPrimitive<unsigned long> {};
+
+// Big integers ----------------------------------------------------------------------------
+
+template <>
+struct Primitive<PY_LONG_LONG> : OnePrimitive<PY_LONG_LONG>
+{
+ 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<PY_LONG_LONG>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<PY_LONG_LONG * >(cppOut) = result;
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+};
+
+template <>
+struct Primitive<unsigned PY_LONG_LONG> : OnePrimitive<unsigned PY_LONG_LONG>
+{
+ 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<unsigned PY_LONG_LONG, unsigned PY_LONG_LONG>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<unsigned PY_LONG_LONG * >(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<unsigned PY_LONG_LONG>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<unsigned PY_LONG_LONG * >(cppOut) =
+ static_cast<unsigned PY_LONG_LONG>(result);
+ } else if (PyLong_Check(pyIn)) {
+ unsigned PY_LONG_LONG result = PyLong_AsUnsignedLongLong(pyIn);
+ if (OverFlowChecker<unsigned PY_LONG_LONG, unsigned PY_LONG_LONG>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<unsigned PY_LONG_LONG * >(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 <typename FLOAT>
+struct FloatPrimitive : TwoPrimitive<FLOAT>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyFloat_FromDouble(*reinterpret_cast<const FLOAT *>(cppIn));
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *reinterpret_cast<FLOAT *>(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<FLOAT *>(cppOut) = FLOAT(PyFloat_AsDouble(pyIn));
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+};
+template <> struct Primitive<float> : FloatPrimitive<float> {};
+template <> struct Primitive<double> : FloatPrimitive<double> {};
+
+// Boolean ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<bool> : OnePrimitive<bool>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ return PyBool_FromLong(*reinterpret_cast<const bool *>(cppIn));
+ }
+ static PythonToCppFunc isConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return toCpp;
+ return 0;
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *reinterpret_cast<bool *>(cppOut) = PyInt_AS_LONG(pyIn) != 0;
+ }
+};
+
+// Characters ------------------------------------------------------------------------------
+
+template <typename CHAR>
+struct CharPrimitive : IntPrimitive<CHAR>
+{
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ *reinterpret_cast<CHAR *>(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<CHAR>::check(result, pyIn))
+ PyErr_SetObject(PyExc_OverflowError, 0);
+ *reinterpret_cast<CHAR *>(cppOut) = CHAR(result);
+ }
+ static PythonToCppFunc isOtherConvertible(PyObject* pyIn)
+ {
+ if (SbkNumber_Check(pyIn))
+ return otherToCpp;
+ return 0;
+ }
+ static SbkConverter* createConverter()
+ {
+ SbkConverter* converter = IntPrimitive<CHAR>::createConverter();
+ Shiboken::Conversions::addPythonToCppValueConversion(converter, CharPrimitive<CHAR>::otherToCpp, CharPrimitive<CHAR>::isOtherConvertible);
+ return converter;
+ }
+
+};
+template <> struct Primitive<signed char> : CharPrimitive<signed char> {};
+template <> struct Primitive<unsigned char> : CharPrimitive<unsigned char> {};
+template <> struct Primitive<char> : CharPrimitive<char> {
+ using CharPrimitive<char>::toPython;
+ static PyObject* toPython(const void* cppIn) {
+ return Shiboken::String::fromCString((const char*)cppIn, 1);
+ }
+};
+
+
+
+// Strings ---------------------------------------------------------------------------------
+
+template <>
+struct Primitive<const char*> : TwoPrimitive<const char*>
+{
+ 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<std::string> : TwoPrimitive<std::string>
+{
+ 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<void*> : OnePrimitive<void*>
+{
+ static PyObject* toPython(const void* cppIn)
+ {
+ SbkDbg() << cppIn;
+ if (!cppIn)
+ Py_RETURN_NONE;
+ PyObject *result = reinterpret_cast<PyObject *>(const_cast<void *>(cppIn));
+ Py_INCREF(result);
+ return result;
+ }
+ static void toCpp(PyObject* pyIn, void* cppOut)
+ {
+ SbkDbg() << pyIn;
+ *reinterpret_cast<void **>(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 <iostream>
+
+#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 <typename T>
+ 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<void*>(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 <typename T>
+ 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..009d9ab2f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -0,0 +1,623 @@
+/****************************************************************************
+**
+** 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 <string.h>
+#include <cstring>
+#include <list>
+
+#define SBK_ENUM(ENUM) reinterpret_cast<SbkEnumObject*>(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<SbkEnumObject *>(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<SbkEnumObject *>(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<SbkEnumObject *>(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<PyObject*>(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<SbkEnumObject*>(pyObj)->ob_value;
+ if (val == -1)
+ val = -2;
+ return val;
+}
+
+static PyGetSetDef SbkEnumGetSetList[] = {
+ {const_cast<char*>("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<SbkEnumType*>(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<SbkEnumType*>(PyType_Type.tp_new(metatype, args, kwds));
+ if (!newType)
+ return 0;
+ return reinterpret_cast<PyObject*>(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<PyTypeObject*> 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<char*>("values"));
+
+ while (PyDict_Next(values, &pos, &key, &value)) {
+ SbkEnumObject *obj = reinterpret_cast<SbkEnumObject *>(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<int>(cppName);
+ if (shortName)
+ Shiboken::TypeResolver::createValueTypeResolver<int>(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<int>("Qt::WindowType");
+ Shiboken::TypeResolver::createValueTypeResolver<int>("WindowType");
+ if (enumType && PyModule_AddObject(module, name, reinterpret_cast<PyObject *>(enumType)) < 0)
+ return 0;
+ if (flagsType && PyModule_AddObject(module, flagsType->tp_name, reinterpret_cast<PyObject *>(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<PyObject *>(enumType)) < 0)
+ return 0;
+ if (flagsType && PyDict_SetItemString(scope->super.ht_type.tp_dict, flagsType->tp_name, reinterpret_cast<PyObject *>(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;
+ // @TODO This Py_DECREF causes crashes on exit with a debug Python interpreter, essentially
+ // causing a use-after-free in the GC. This is now commented out to cause a memory leak
+ // instead of a crash. Proper memory management of Enum types and items should be
+ // implemented. See PYSIDE-488. This will require proper allocation and deallocation of
+ // the underlying Enum PyHeapType, which is currently just deallocated at application exit.
+ // 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<SbkEnumObject*>(getEnumItemFromValue(enumType, itemValue));
+ if (enumObj)
+ return reinterpret_cast<PyObject*>(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<char*>("values"));
+ if (!values) {
+ values = PyDict_New();
+ PyDict_SetItemString(enumType->tp_dict, const_cast<char*>("values"), values);
+ Py_DECREF(values); // ^ values still alive, because setitemstring incref it
+ }
+ PyDict_SetItemString(values, itemName, reinterpret_cast<PyObject*>(enumObj));
+ }
+
+ return reinterpret_cast<PyObject*>(enumObj);
+}
+
+PyTypeObject* newType(const char* name)
+{
+ return newTypeWithName(name, "");
+}
+
+PyTypeObject* newTypeWithName(const char* name, const char* cppName)
+{
+ PyTypeObject* type = reinterpret_cast<PyTypeObject*>(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<SbkEnumType*>(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<SbkEnumType*>(enumType)->cppName;;
+}
+
+long int getValue(PyObject* enumItem)
+{
+ assert(Shiboken::Enum::check(enumItem));
+ return reinterpret_cast<SbkEnumObject*>(enumItem)->ob_value;
+}
+
+void setTypeConverter(PyTypeObject* enumType, SbkConverter* converter)
+{
+ //reinterpret_cast<SbkEnumType*>(enumType)->converter = converter;
+ SBK_CONVERTER(enumType) = converter;
+}
+
+SbkConverter* getTypeConverter(PyTypeObject* enumType)
+{
+ //return reinterpret_cast<SbkEnumType*>(enumType)->converter;
+ return SBK_CONVERTER(enumType);
+}
+
+} // namespace Enum
+
+DeclaredEnumTypes& DeclaredEnumTypes::instance()
+{
+ static DeclaredEnumTypes me;
+ return me;
+}
+
+DeclaredEnumTypes::DeclaredEnumTypes()
+{
+}
+
+DeclaredEnumTypes::~DeclaredEnumTypes()
+{
+ std::list<PyTypeObject*>::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..084e23efa
--- /dev/null
+++ b/sources/shiboken2/libshiboken/sbkmodule.cpp
@@ -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$
+**
+****************************************************************************/
+
+#include "sbkmodule.h"
+#include "basewrapper.h"
+#include "bindingmanager.h"
+
+// TODO: for performance reasons this should be a sparse_hash_map,
+// because there'll be very few modules as keys. The sparse_hash_map
+// is missing from the code added in ../ext/sparsehash/google directory.
+#include "google/dense_hash_map"
+
+/// This hash maps module objects to arrays of Python types.
+typedef google::dense_hash_map<PyObject*, PyTypeObject**> ModuleTypesMap;
+
+/// This hash maps module objects to arrays of converters.
+typedef google::dense_hash_map<PyObject*, SbkConverter**> ModuleConvertersMap;
+
+/// All types produced in imported modules are mapped here.
+static ModuleTypesMap moduleTypes;
+static ModuleConvertersMap moduleConverters;
+
+namespace Shiboken
+{
+namespace Module
+{
+
+void init()
+{
+ // Initializes type registry for modules.
+ moduleTypes.set_empty_key((ModuleTypesMap::key_type)0);
+ moduleTypes.set_deleted_key((ModuleTypesMap::key_type)1);
+ moduleConverters.set_empty_key((ModuleConvertersMap::key_type)0);
+ moduleConverters.set_deleted_key((ModuleConvertersMap::key_type)1);
+}
+
+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<PyMethodDef *>(moduleData));
+#else
+ return PyModule_Create(reinterpret_cast<PyModuleDef*>(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<PyObject *>(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 <cstdlib>
+#include <cstring>
+
+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<void*>(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<void*>(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 <b>read only</b> 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 <shibokenmacros.h>
+
+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 <limits>
+#include <Python.h>
+#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..3939fff5f
--- /dev/null
+++ b/sources/shiboken2/libshiboken/typeresolver.cpp
@@ -0,0 +1,162 @@
+/****************************************************************************
+**
+** 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 "google/dense_hash_map"
+#include "sbkdbg.h"
+#include <cstdlib>
+#include <string>
+#include "basewrapper_p.h"
+
+using namespace Shiboken;
+
+typedef google::dense_hash_map<std::string, TypeResolver*> 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());
+ typeResolverMap.set_empty_key("");
+ typeResolverMap.set_deleted_key("?");
+ 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<PyTypeObject*>(&SbkObject_Type))) {
+ SbkObjectType* sbkType = reinterpret_cast<SbkObjectType*>(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 <typename T>
+inline void pythonToValueType(PyObject* pyobj, void** data)
+{
+ *reinterpret_cast<T*>(*data) = Shiboken::Converter<T>::toCpp(pyobj);
+}
+
+template <typename T>
+inline void pythonToObjectType(PyObject* pyobj, void** data)
+{
+ *reinterpret_cast<T**>(*data) = Shiboken::Converter<T*>::toCpp(pyobj);
+}
+
+template <typename T>
+inline PyObject* objectTypeToPython(void* cptr)
+{
+ return Shiboken::Converter<T*>::toPython(*reinterpret_cast<T**>(cptr));
+}
+
+template <typename T>
+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<T&>::toPython(*reinterpret_cast<T*>(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<typename T>
+ static TypeResolver* createValueTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &Shiboken::Converter<T>::toPython, &pythonToValueType<T>, SbkType<T>());
+ }
+
+ template<typename T>
+ static TypeResolver* createObjectTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &objectTypeToPython<T>, &pythonToObjectType<T>, SbkType<T>());
+ }
+
+ /**
+ * This kind of type resolver is used only when we have a signal with a reference in their arguments
+ * like on QSqlTableModel::primeInsert.
+ */
+ template<typename T>
+ static TypeResolver* createReferenceTypeResolver(const char* typeName)
+ {
+ return createTypeResolver(typeName, &referenceTypeToPython<T>, &pythonToValueType<T>, SbkType<T>());
+ }
+
+ 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
--- /dev/null
+++ b/sources/shiboken2/shibokenmodule/nothing.h
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 @@
+<?xml version="1.0" ?>
+<typesystem package="shiboken2">
+ <custom-type name="PyObject" />
+ <custom-type name="PyType" />
+ <primitive-type name="bool" />
+ <primitive-type name="unsigned long" />
+ <primitive-type name="size_t" />
+ <add-function signature="isValid(PyObject*)" return-type="bool">
+ <inject-code>
+ bool isValid = Shiboken::Object::isValid(%1, false);
+ %PYARG_0 = %CONVERTTOPYTHON[bool](isValid);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="invalidate(PyObject*)">
+ <inject-code>
+ Shiboken::Object::invalidate(%1);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="wrapInstance(size_t, PyType)" return-type="PyObject*">
+ <inject-code>
+ 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.");
+ </inject-code>
+ </add-function>
+
+ <add-function signature="getCppPointer(PyObject*)" return-type="PyObject*">
+ <inject-code>
+ if (Shiboken::Object::checkType(%1)) {
+ std::vector&lt;void*> ptrs = Shiboken::Object::cppPointers((SbkObject*)%1);
+ %PYARG_0 = PyTuple_New(ptrs.size());
+ for (std::size_t i = 0; i &lt; ptrs.size(); ++i)
+ PyTuple_SET_ITEM(%PYARG_0, i, PyLong_FromVoidPtr(ptrs[i]));
+ } else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+ }
+ </inject-code>
+ </add-function>
+
+ <add-function signature="delete(PyObject*)">
+ <inject-code>
+ if (Shiboken::Object::checkType(%1)) {
+ Shiboken::Object::callCppDestructors((SbkObject*)%1);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "You need a shiboken-based type.");
+ }
+ </inject-code>
+ </add-function>
+
+ <add-function signature="ownedByPython(PyObject*)" return-type="bool">
+ <inject-code>
+ 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.");
+ }
+ </inject-code>
+ </add-function>
+
+ <add-function signature="createdByPython(PyObject*)" return-type="bool">
+ <inject-code>
+ 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.");
+ }
+ </inject-code>
+ </add-function>
+
+ <add-function signature="dump(PyObject*)" return-type="PyObject*">
+ <inject-code>
+ if (!Shiboken::Object::checkType(%1)) {
+ %PYARG_0 = Shiboken::String::fromCString("Ordinary Python type.");
+ } else {
+ std::string str = Shiboken::Object::info((SbkObject*)%1);
+ %PYARG_0 = Shiboken::String::fromCString(str.c_str());
+ }
+ </inject-code>
+ </add-function>
+
+ <add-function signature="getAllValidWrappers(void)" return-type="PyObject*">
+ <inject-code>
+ std::set&lt;PyObject*&gt; setAll = Shiboken::BindingManager::instance().getAllPyObjects();
+ PyObject* listAll = PyList_New(0);
+ if (listAll == NULL)
+ return NULL;
+
+ const std::set&lt;PyObject*&gt;::iterator end = setAll.end();
+ for (std::set&lt;PyObject*&gt;::iterator iter = setAll.begin(); iter != end; ++iter) {
+ if (*iter != NULL) {
+ if (PyList_Append(listAll, *iter) != 0) {
+ Py_DECREF(listAll);
+ return NULL;
+ }
+ }
+ }
+ return listAll;
+ </inject-code>
+ </add-function>
+
+ <extra-includes>
+ <include file-name="sbkversion.h" location="local"/>
+ </extra-includes>
+ <inject-code position="end">
+ // Add __version__ and __version_info__ attributes to the module
+ PyObject* version = PyTuple_New(5);
+ PyTuple_SET_ITEM(version, 0, 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);
+ </inject-code>
+</typesystem>
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..9e62faa16
--- /dev/null
+++ b/sources/shiboken2/tests/dumpcodemodel/main.cpp
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** 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 <abstractmetabuilder_p.h>
+#include <parser/codemodel.h>
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QCommandLineOption>
+#include <QtCore/QCommandLineParser>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+
+#include <iostream>
+
+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);
+ if (parser.positionalArguments().isEmpty())
+ parser.showHelp(1);
+
+ const QString sourceFileName = parser.positionalArguments().at(0);
+ QFile sourceFile(sourceFileName);
+ if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QString message = QLatin1String("Cannot open \"") + QDir::toNativeSeparators(sourceFileName)
+ + QLatin1String("\": ") + sourceFile.errorString();
+ std::cerr << qPrintable(message) << '\n';
+ return -1;
+ }
+
+ const FileModelItem dom = AbstractMetaBuilderPrivate::buildDom(&sourceFile);
+ sourceFile.close();
+ if (dom.isNull())
+ 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 <numeric>
+#include <cstdlib>
+#include "listuser.h"
+
+std::list<int>
+ListUser::createIntList(int num)
+{
+ std::list<int> retval;
+ for (int i = 0; i < num; ++i)
+ retval.push_back(i);
+ return retval;
+}
+
+int
+ListUser::sumIntList(std::list<int> intList)
+{
+ int total = 0;
+ for (std::list<int>::iterator iter = intList.begin(); iter != intList.end(); iter++)
+ total += *iter;
+ return total;
+}
+
+std::list<MinBool>
+ListUser::createMinBoolList(MinBool mb1, MinBool mb2)
+{
+ std::list<MinBool> retval;
+ retval.push_back(mb1);
+ retval.push_back(mb2);
+ return retval;
+}
+
+MinBool
+ListUser::oredMinBoolList(std::list<MinBool> minBoolList)
+{
+ MinBool result(false);
+ for (std::list<MinBool>::iterator iter = minBoolList.begin(); iter != minBoolList.end(); iter++)
+ result |= *iter;
+ return result;
+}
+
+std::list<Val>
+ListUser::createValList(int num)
+{
+ std::list<Val> retval;
+ for (int i = 0; i < num; ++i)
+ retval.push_back(Val(i));
+ return retval;
+}
+
+int
+ListUser::sumValList(std::list<Val> valList)
+{
+ int total = 0;
+ for (std::list<Val>::iterator iter = valList.begin(); iter != valList.end(); iter++)
+ total += iter->valId();
+ return total;
+}
+
+std::list<Obj*>
+ListUser::createObjList(Obj* o1, Obj* o2)
+{
+ std::list<Obj*> retval;
+ retval.push_back(o1);
+ retval.push_back(o2);
+ return retval;
+}
+
+int
+ListUser::sumObjList(std::list<Obj*> objList)
+{
+ int total = 0;
+ for (std::list<Obj*>::iterator iter = objList.begin(); iter != objList.end(); iter++)
+ total += (*iter)->objId();
+ return total;
+}
+
+std::list<std::list<int> >
+ListUser::createListOfIntLists(int num)
+{
+ std::list<std::list<int> > retval;
+ for (int i = 0; i < num; ++i)
+ retval.push_back(createIntList(num));
+ return retval;
+}
+
+int
+ListUser::sumListOfIntLists(std::list<std::list<int> > intListList)
+{
+ int total = 0;
+ for (std::list<std::list<int> >::iterator it0 = intListList.begin(); it0 != intListList.end(); it0++) {
+ for (std::list<int>::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 <list>
+#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<int> createIntList(int num);
+ std::list<int> callCreateIntList(int num) { return createIntList(num); }
+ virtual int sumIntList(std::list<int> intList);
+ int callSumIntList(std::list<int> intList) { return sumIntList(intList); }
+
+ // List of C++ MinBool objects used as primitives in Python
+ virtual std::list<MinBool> createMinBoolList(MinBool mb1, MinBool mb2);
+ std::list<MinBool> callCreateMinBoolList(MinBool mb1, MinBool mb2) { return createMinBoolList(mb1, mb2); }
+ virtual MinBool oredMinBoolList(std::list<MinBool> minBoolList);
+ MinBool callOredMinBoolList(std::list<MinBool> minBoolList) { return oredMinBoolList(minBoolList); }
+
+ // List of C++ value types
+ virtual std::list<Val> createValList(int num);
+ std::list<Val> callCreateValList(int num) { return createValList(num); }
+ virtual int sumValList(std::list<Val> valList);
+ int callSumValList(std::list<Val> valList) { return sumValList(valList); }
+
+ // List of C++ object types
+ virtual std::list<Obj*> createObjList(Obj* o1, Obj* o2);
+ std::list<Obj*> callCreateObjList(Obj* o1, Obj* o2) { return createObjList(o1, o2); }
+ virtual int sumObjList(std::list<Obj*> objList);
+ int callSumObjList(std::list<Obj*> objList) { return sumObjList(objList); }
+
+ // List of lists of C++ primitive type items
+ virtual std::list<std::list<int> > createListOfIntLists(int num);
+ std::list<std::list<int> > callCreateListOfIntLists(int num) { return createListOfIntLists(num); }
+ virtual int sumListOfIntLists(std::list<std::list<int> > intListList);
+ int callSumListOfIntLists(std::list<std::list<int> > 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<int> a)
+{
+ return a.empty();
+}
+
+bool arrayFuncIntTypedef(MyArray a)
+{
+ return arrayFuncInt(a);
+}
+
+std::vector<int> arrayFuncIntReturn(int size)
+{
+ return std::vector<int>(size);
+}
+
+MyArray arrayFuncIntReturnTypedef(int size)
+{
+ return arrayFuncIntReturn(size);
+}
+
+//
+// Test wrapping of a typedef of a typedef
+//
+bool arrayFunc(std::vector<int> a)
+{
+ return a.empty();
+}
+
+bool arrayFuncTypedef(MyArray a)
+{
+ return arrayFunc(a);
+}
+
+std::vector<int> arrayFuncReturn(int size)
+{
+ return std::vector<int>(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 <vector>
+
+// Test wrapping of a typedef
+typedef std::vector<int> MyArrayInt;
+
+LIBMINIMAL_API bool arrayFuncInt(std::vector<int> a);
+LIBMINIMAL_API bool arrayFuncIntTypedef(MyArrayInt a);
+
+LIBMINIMAL_API std::vector<int> 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<int> a);
+LIBMINIMAL_API bool arrayFuncTypedef(MyArray a);
+
+LIBMINIMAL_API std::vector<int> 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 <cstring>
+#include <sstream>
+
+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 <list>
+#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 <iostream>
+#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<int, ObjectType*> item(m_ticket, object);
+ m_objects.insert(item);
+ object->setParent(0);
+
+ return m_ticket;
+}
+
+ObjectType*
+BlackBox::retrieveObjectType(int ticket)
+{
+ map<int, ObjectType*>::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<int, Point*> item(m_ticket, point);
+ m_points.insert(item);
+
+ return m_ticket;
+}
+
+Point*
+BlackBox::retrievePoint(int ticket)
+{
+ map<int, Point*>::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<ObjectType*>
+BlackBox::objects()
+{
+ std::list<ObjectType*> l;
+ map<int, ObjectType*>::iterator it;
+
+ for ( it = m_objects.begin() ; it != m_objects.end(); it++ )
+ l.push_back((*it).second);
+
+ return l;
+}
+
+std::list<Point*>
+BlackBox::points()
+{
+ std::list<Point*> l;
+ map<int, Point*>::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 <map>
+#include "objecttype.h"
+#include "point.h"
+
+class LIBSAMPLE_API BlackBox
+{
+public:
+ typedef std::map<int, ObjectType*> ObjectTypeMap;
+ typedef std::map<int, Point*> 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<ObjectType*> objects();
+ std::list<Point*> 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 <iostream>
+
+#ifdef _WIN32 // _WIN32 is defined by all Windows 32 and 64 bit compilers, but not by others.
+#include <windows.h>
+#define SLEEP(x) Sleep(x)
+#else
+#include <unistd.h>
+#define SLEEP(x) usleep(x)
+#endif
+
+
+using namespace std;
+
+Bucket::Bucket() : m_locked(false)
+{
+}
+
+void Bucket::push(int x)
+{
+ m_data.push_back(x);
+}
+
+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 <list>
+
+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<int> 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 <cstring>
+#include "bytearray.h"
+
+ByteArray::ByteArray()
+{
+ m_data = std::vector<char>(1);
+ m_data[0] = '\0';
+}
+
+ByteArray::ByteArray(char c)
+{
+ m_data = std::vector<char>(2);
+ m_data[0] = c;
+ m_data[1] = '\0';
+}
+
+ByteArray::ByteArray(const char* data)
+{
+ size_t len = strlen(data);
+ m_data = std::vector<char>(len + 1);
+ memcpy(&m_data[0], data, len);
+ m_data[len] = '\0';
+}
+
+ByteArray::ByteArray(const char* data, int len)
+{
+ m_data = std::vector<char>(len + 1);
+ memcpy(&m_data[0], data, len);
+ m_data[len] = '\0';
+}
+
+ByteArray::ByteArray(const ByteArray& other)
+{
+ m_data = std::vector<char>(other.size() + 1);
+ memcpy(&m_data[0], &other.m_data[0], other.size());
+ m_data[other.size()] = '\0';
+}
+
+int
+ByteArray::size() const
+{
+ 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<char>& 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 <vector>
+
+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<char> m_data;
+ friend LIBSAMPLE_API bool operator==(const ByteArray& ba1, const char* ba2);
+ friend LIBSAMPLE_API bool operator==(const char* ba1, const ByteArray& ba2);
+ friend LIBSAMPLE_API bool operator!=(const ByteArray& ba1, const char* ba2);
+ friend LIBSAMPLE_API bool operator!=(const char* ba1, const ByteArray& ba2);
+
+ friend LIBSAMPLE_API 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<ObjectType::Identifier> 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 <list>
+#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<ObjectType::Identifier> items();
+ int size();
+
+private:
+ std::list<ObjectType::Identifier> 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 <iostream>
+#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 <list>
+#include "libsamplemacros.h"
+
+class CVValueType
+{
+ CVValueType();
+};
+
+typedef std::list<const CVValueType*> 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 <iostream>
+#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 <sstream>
+
+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 <string>
+
+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 <string>
+#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 <string>
+#include <list>
+
+#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<Filter> filters() const { return m_filters; }
+ void addFilter(const Filter& data) { m_filters.push_back(data); }
+
+private:
+ std::list<Filter> m_filters;
+};
+
+class LIBSAMPLE_API Intersection : public Filter
+{
+public:
+
+ Intersection(const Data&);
+ Intersection(const Union&);
+ Intersection() {};
+ Intersection(const Intersection&);
+
+ std::list<Filter> filters() const { return m_filters; }
+ void addFilter(const Filter& data) { m_filters.push_back(data); }
+
+private:
+ std::list<Filter> m_filters;
+};
+
+LIBSAMPLE_API Intersection operator&(const Intersection& a, const Intersection& b);
+
+#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 <string.h>
+#include <iostream>
+
+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<Complex>
+gimmeComplexList()
+{
+ std::list<Complex> 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<Complex, Complex> cpx_pair)
+{
+ return cpx_pair.first + cpx_pair.second;
+}
+
+double
+multiplyPair(std::pair<double, double> 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<void *>(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 <list>
+#include <utility>
+#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<double, double> pair);
+LIBSAMPLE_API std::list<Complex> gimmeComplexList();
+LIBSAMPLE_API Complex sumComplexPair(std::pair<Complex, Complex> cpx_pair);
+
+LIBSAMPLE_API int countCharacters(const char* text);
+LIBSAMPLE_API char* makeCString();
+LIBSAMPLE_API const char* returnCString();
+
+LIBSAMPLE_API 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 <sstream>
+
+using namespace std;
+
+InjectCode::InjectCode()
+{
+}
+
+InjectCode::~InjectCode()
+{
+}
+
+template<typename T>
+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 <utility>
+#include <string>
+
+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<typename T>
+ 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 <list>
+#include "libsamplemacros.h"
+#include "point.h"
+
+class ObjectType;
+
+template<class T>
+class List : public std::list<T>
+{
+};
+
+class IntList : public List<int>
+{
+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<int>(lst), m_ctorUsed(CopyCtor) {}
+ inline IntList(const List<int>& lst) : List<int>(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<Point>
+{
+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<Point>(lst), m_ctorUsed(CopyCtor) {}
+ inline PointValueList(const List<Point>& lst) : List<Point>(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<ObjectType*>
+{
+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<ObjectType*>(lst), m_ctorUsed(CopyCtor) {}
+ inline ObjectTypePtrList(const List<ObjectType*>& lst) : List<ObjectType*>(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 <numeric>
+#include <cstdlib>
+#include "listuser.h"
+
+using namespace std;
+
+std::list<int>
+ListUser::callCreateList()
+{
+ return createList();
+}
+
+std::list<int>
+ListUser::createList()
+{
+ std::list<int> retval;
+ for (int i = 0; i < 4; i++)
+ retval.push_front(rand());
+ return retval;
+}
+
+std::list<Complex>
+ListUser::createComplexList(Complex cpx0, Complex cpx1)
+{
+ std::list<Complex> retval;
+ retval.push_back(cpx0);
+ retval.push_back(cpx1);
+ return retval;
+}
+
+double
+ListUser::sumList(std::list<int> vallist)
+{
+ return std::accumulate(vallist.begin(), vallist.end(), 0.0);
+}
+
+double
+ListUser::sumList(std::list<double> vallist)
+{
+ return std::accumulate(vallist.begin(), vallist.end(), 0.0);
+}
+
+ListUser::ListOfSomething
+ListUser::listOfPoints(const std::list<Point>& pointlist)
+{
+ return ListOfPoint;
+}
+
+ListUser::ListOfSomething
+ListUser::listOfPoints(const std::list<PointF>& 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 <list>
+#include "complex.h"
+#include "point.h"
+#include "pointf.h"
+
+#include "libsamplemacros.h"
+
+class LIBSAMPLE_API ListUser
+{
+public:
+ typedef std::list<Point*> PointList;
+
+ enum ListOfSomething {
+ ListOfPoint,
+ ListOfPointF
+ };
+
+ ListUser() {}
+ ListUser(const ListUser& other) : m_lst(other.m_lst) {}
+ virtual ~ListUser() {}
+
+ virtual std::list<int> createList();
+ std::list<int> callCreateList();
+
+ static std::list<Complex> createComplexList(Complex cpx0, Complex cpx1);
+
+ double sumList(std::list<int> vallist);
+ double sumList(std::list<double> vallist);
+
+ static ListOfSomething listOfPoints(const std::list<Point>& pointlist);
+ static ListOfSomething listOfPoints(const std::list<PointF>& pointlist);
+
+ static void multiplyPointList(PointList& points, double multiplier);
+
+ inline void setList(std::list<int> lst) { m_lst = lst; }
+ inline std::list<int> getList() { return m_lst; }
+
+private:
+ std::list<int> 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 <iostream>
+#include <list>
+#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<int> intlist = lu.createList();
+ for (std::list<int>::iterator it = intlist.begin(); it != intlist.end(); it++) {
+ cout << "* " << *it << endl;
+ }
+
+ cout << "ListUser::createComplexList" << endl;
+ std::list<Complex> cpxlist = ListUser::createComplexList(Complex(1.1, 2.2), Complex(3.3, 4.4));
+ for (std::list<Complex>::iterator it = cpxlist.begin(); it != cpxlist.end(); it++) {
+ cout << "* ";
+ (*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 <iostream>
+#include "mapuser.h"
+
+using namespace std;
+
+std::map<std::string, std::pair<Complex, int> >
+MapUser::callCreateMap()
+{
+ return createMap();
+}
+
+
+std::map<std::string, std::pair<Complex, int> >
+MapUser::createMap()
+{
+ std::map<std::string, std::pair<Complex, int> > retval;
+
+ std::pair<std::string, std::pair<Complex, int> >
+ item0("zero", std::pair<Complex, int>(Complex(1.2, 3.4), 2));
+ retval.insert(item0);
+
+ std::pair<std::string, std::pair<Complex, int> >
+ item1("one", std::pair<Complex, int>(Complex(5.6, 7.8), 3));
+ retval.insert(item1);
+
+ std::pair<std::string, std::pair<Complex, int> >
+ item2("two", std::pair<Complex, int>(Complex(9.1, 2.3), 5));
+ retval.insert(item2);
+
+ return retval;
+}
+
+void
+MapUser::showMap(std::map<std::string, int> mapping)
+{
+ std::map<std::string, int>::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 <map>
+#include <list>
+#include <utility>
+#include <string>
+#include "complex.h"
+#include "bytearray.h"
+
+#include "libsamplemacros.h"
+
+class LIBSAMPLE_API MapUser
+{
+public:
+ MapUser() {}
+ virtual ~MapUser() {}
+
+ virtual std::map<std::string, std::pair<Complex, int> > createMap();
+ std::map<std::string, std::pair<Complex, int> > callCreateMap();
+
+ void showMap(std::map<std::string, int> mapping);
+
+ inline void setMap(std::map<std::string, std::list<int> > map) { m_map = map; }
+ inline std::map<std::string, std::list<int> > getMap() { return m_map; }
+
+ // Compile test
+ static void pointerToMap(std::map<std::string, std::string>* arg) {}
+ static void referenceToMap(std::map<std::string, std::string>& arg) {}
+
+ inline const std::map<int, ByteArray>& passMapIntValueType(const std::map<int, ByteArray>& arg) { return arg; }
+
+private:
+ std::map<std::string, std::list<int> > 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 <iostream>
+#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<double, double>
+Modifications::pointToPair(Point pt, bool* ok)
+{
+ std::pair<double, double> retval(pt.x(), pt.y());
+ *ok = true;
+ return retval;
+}
+
+double
+Modifications::multiplyPointCoordsPlusValue(bool* ok, Point pt, double value)
+{
+ double 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 <utility>
+#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<double, double> pointToPair(Point pt, bool* ok);
+
+ // same as 'pointToPair' except that this time 'ok' is the first argument
+ double multiplyPointCoordsPlusValue(bool* ok, Point pt, double value);
+
+ // 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 <no-null-pointer/> 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<MDerived1*>(self);
+ return ptr;
+}
+
+MDerived1*
+MDerived1::transformFromBase2(Base2* self)
+{
+ MDerived1* ptr = dynamic_cast<MDerived1*>(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 <string>
+
+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 <algorithm>
+#include <iostream>
+#include <string>
+#include <assert.h>
+
+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<std::size_t>(objectType);
+}
+
+unsigned char
+ObjectType::callWithEnum(const Str& prefix, Event::EventType type, unsigned char value){
+ return value*value;
+}
+
+unsigned char
+ObjectType::callWithEnum(const Str& 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 <list>
+#include "str.h"
+#include "null.h"
+
+#include "libsamplemacros.h"
+
+#include <stddef.h>
+
+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<ObjectType*> 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<Identifier>(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("<unk"), const Str& suffix = Str("nown>"));
+ void setObjectNameWithSize(const char*, int size=9, const Str& name = Str("<unknown>"));
+ void setObjectNameWithSize(const Str& name = Str("<unknown>"), int size=9);
+
+ //Function used to confuse the generator when two values accept Null as arg
+ void setObject(ObjectType *);
+ void setObject(const Null&);
+ 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 <list>
+#include "protected.h"
+
+class ObjectTypeByValue
+{
+public:
+ ObjectTypeByValue returnSomeKindOfMe() { return ObjectTypeByValue(); }
+ void acceptKindOfMeAsValue(ObjectTypeByValue kindOfMe) {}
+
+ void acceptListOfObjectTypeByValue(std::list<ObjectTypeByValue> 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 <iostream>
+
+using namespace std;
+
+void ObjectTypeLayout::addObject(ObjectType* obj)
+{
+ if (obj->isLayoutType()) {
+ ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(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<ObjectType*>::const_iterator it = m_objects.begin();
+ for (; it != m_objects.end(); ++it) {
+ if ((*it)->isLayoutType())
+ reinterpret_cast<ObjectTypeLayout*>(*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 <list>
+
+class ObjectType;
+
+class LIBSAMPLE_API ObjectTypeLayout : public ObjectType
+{
+public:
+ void addObject(ObjectType* obj);
+ std::list<ObjectType*> 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<ObjectType*> 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 <string>
+
+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<OnlyCopy>
+FriendOfOnlyCopy::createListOfOnlyCopy(int quantity)
+{
+ std::list<OnlyCopy> 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 <list>
+
+// 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<OnlyCopy> 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 <list>
+
+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<ImplicitBase> &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 <iostream>
+#include "pairuser.h"
+
+using namespace std;
+
+std::pair<int, int>
+PairUser::callCreatePair()
+{
+ return createPair();
+}
+
+std::pair<int, int>
+PairUser::createPair()
+{
+ return std::pair<int, int>(10, 20);
+}
+
+std::pair<Complex, Complex>
+PairUser::createComplexPair(Complex cpx0, Complex cpx1)
+{
+ return std::pair<Complex, Complex>(cpx0, cpx1);
+}
+
+double
+PairUser::sumPair(std::pair<int, double> 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 <utility>
+#include "complex.h"
+
+#include "libsamplemacros.h"
+
+class LIBSAMPLE_API PairUser
+{
+public:
+ PairUser() {}
+ virtual ~PairUser() {}
+
+ virtual std::pair<int, int> createPair();
+ std::pair<int, int> callCreatePair();
+ static std::pair<Complex, Complex> createComplexPair(Complex cpx0, Complex cpx1);
+ double sumPair(std::pair<int, double> pair);
+
+ inline void setPair(std::pair<int, int> pair) { m_pair = pair; }
+ inline std::pair<int, int> getPair() { return m_pair; }
+
+private:
+ std::pair<int, int> 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<ValueIdentity>& values)
+{
+ return values.size();
+}
+int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> >& 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 <list>
+#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 <class T> 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<ClassType CLASS_TYPE>
+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<CLASS_TYPE>* other) const { return m_value + other->m_value; }
+ inline int sumValueUsingReference(TemplateBase<CLASS_TYPE>& other) const { return m_value + other.m_value; }
+
+ inline std::list<TemplateBase<CLASS_TYPE> > getListOfThisTemplateBase()
+ {
+ std::list<TemplateBase<CLASS_TYPE> > objs;
+ objs.push_back(*this);
+ objs.push_back(*this);
+ return objs;
+ }
+
+ static inline TemplateBase<CLASS_TYPE>* passPointerThrough(TemplateBase<CLASS_TYPE>* 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<IdentityType>;
+template class LIBSAMPLE_API TemplateBase<DuplicatorType>;
+#endif
+
+typedef TemplateBase<IdentityType> ValueIdentity;
+typedef TemplateBase<DuplicatorType> ValueDuplicator;
+
+LIBSAMPLE_API int callCalculateForValueDuplicatorPointer(ValueDuplicator* value);
+LIBSAMPLE_API int callCalculateForValueDuplicatorReference(ValueDuplicator& value);
+LIBSAMPLE_API int countValueIdentities(const std::list<ValueIdentity>& values);
+LIBSAMPLE_API int countValueDuplicators(const std::list<TemplateBase<DuplicatorType> >& values);
+
+// This simulates an internal error (SEGV) caused by 'noexcept' in
+// boost::intrusive_ptr before support for 'noexcept' was added. The ENTIRE
+// code below is needed to trigger the exception; it isn't seen with just a
+// 'noexcept' following a declaration.
+//
+// NOTE: For reasons that should be fairly obvious, this test unfortunately can
+// only be "run" when building in C++11 mode.
+#if __cplusplus >= 201103L || (defined(_MSC_VER) && _MSC_VER >= 1900)
+# define PHOTON_NOEXCEPT noexcept
+#else
+# define PHOTON_NOEXCEPT
+#endif
+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 <iostream>
+#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 <utility>
+
+#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 <iostream>
+#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 <utility>
+
+#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 <iostream>
+#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 <list>
+#include "point.h"
+
+#include "libsamplemacros.h"
+
+class LIBSAMPLE_API Polygon
+{
+public:
+ typedef std::list<Point> 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 <string>
+#include <list>
+
+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<int> 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 <iostream>
+#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 <iostream>
+#include <cstdlib>
+#include <time.h>
+#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 <list>
+#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<SomeInnerClass> 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 <stdlib.h>
+#include <string.h>
+#include <fstream>
+#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 <stdio.h>
+
+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 <iostream>
+#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 <stdio.h>
+
+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 <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <sstream>
+
+using namespace std;
+
+Str::Str(const Str& s)
+{
+ init(s.cstring());
+}
+
+Str::Str(char c)
+{
+ char str[2] = { c, 0 };
+ init(str);
+}
+
+Str::Str(const char* cstr)
+{
+ 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 <string>
+
+#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<Str>& 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 <list>
+#include "str.h"
+
+#include "libsamplemacros.h"
+
+class LIBSAMPLE_API StrList : public std::list<Str>
+{
+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<Str>(lst), m_ctorUsed(CopyCtor) {}
+ inline StrList(const std::list<Str>& lst) : std::list<Str>(lst), m_ctorUsed(ListOfStrCtor) {}
+
+ inline void append(Str str) { push_back(str); }
+ Str join(const Str& sep) const;
+
+ bool operator==(const std::list<Str>& other) const;
+ inline bool operator!=(const std::list<Str>& other) const { return !(*this == other); }
+
+ 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<std::pair<BlackBox *, BlackBox *> > & 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 <utility>
+#include <list>
+#include "libsamplemacros.h"
+#include "blackbox.h"
+
+class LIBSAMPLE_API TemplatePtr
+{
+public:
+ void dummy(std::list<std::pair<BlackBox *, BlackBox *> > & 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 <math.h>
+#include <float.h>
+static inline bool isfinite(double a) { return _finite(a); }
+#else
+#include <cmath>
+#endif
+
+using namespace std;
+
+Point applyHomogeneousTransform(
+ const Point& in,
+ double m11, double m12, double m13,
+ double m21, double m22, double m23,
+ double m31, double m32, double m33,
+ bool* okay)
+{
+ 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<Str> callStrListToStdList(const StrList& strList) { return strListToStdList(strList); }
+ virtual std::list<Str> strListToStdList(const StrList& strList ) { return strList; }
+
+ void setMargins(int left, int top, int right, int bottom)
+ {
+ 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> Obj::giveSharedPtrToObj()
+{
+ SharedPtr<Obj> o(new Obj);
+ return o;
+}
+
+SharedPtr<Integer> Obj::giveSharedPtrToInteger()
+{
+ SharedPtr<Integer> o(new Integer);
+ return o;
+}
+
+int Obj::takeSharedPtrToObj(SharedPtr<Obj> pObj)
+{
+ pObj->printObj();
+ return pObj->m_integer;
+}
+
+int Obj::takeSharedPtrToInteger(SharedPtr<Integer> 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 &registry;
+}
+
+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<int>(m_objects.size());
+}
+
+int Registry::countIntegers() const
+{
+ return static_cast<int>(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 <algorithm>
+#include <iostream>
+#include <vector>
+
+#include "libsmartmacros.h"
+
+// Forward declarations.
+template <class T>
+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<Obj *> m_objects;
+ std::vector<Integer *> m_integers;
+};
+
+template <class T>
+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 T>
+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<T>(v);
+ }
+
+ SharedPtr(const SharedPtr<T> &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<T> &operator=(const SharedPtr<T>& 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<T> *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<Obj> giveSharedPtrToObj();
+ SharedPtr<Integer> giveSharedPtrToInteger();
+ int takeSharedPtrToObj(SharedPtr<Obj> pObj);
+ int takeSharedPtrToInteger(SharedPtr<Integer> 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 @@
+<?xml version="1.0"?>
+<typesystem package="minimal">
+ <primitive-type name="bool"/>
+ <primitive-type name="int"/>
+
+ <primitive-type name="MinBool" target-lang-api-name="PyBool" default-constructor="MinBool(false)">
+ <include file-name="minbool.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ return PyBool_FromLong(%in.value());
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyBool" check="PyBool_Check(%in)">
+ %out = %OUTTYPE(%in == Py_True);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <container-type name="std::list" type="list">
+ <include file-name="list" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ 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;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0));
+ for (int i = 0; i &lt; 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);
+ }
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+
+ <object-type name="Obj"/>
+ <value-type name="Val">
+ <enum-type name="ValEnum"/>
+ </value-type>
+ <value-type name="ListUser"/>
+ <value-type name="MinBoolUser"/>
+
+ <container-type name="std::vector" type="vector">
+ <include file-name="vector" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ %INTYPE::size_type vectorSize = %in.size();
+ PyObject* %out = PyList_New((int) vectorSize);
+ for (%INTYPE::size_type idx = 0; idx &lt; vectorSize; ++idx) {
+ %INTYPE_0 cppItem(%in[idx]);
+ PyList_SET_ITEM(%out, idx, %CONVERTTOPYTHON[%INTYPE_0](cppItem));
+ }
+ return %out;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0));
+ int vectorSize = PySequence_Fast_GET_SIZE(seq.object());
+ %out.reserve(vectorSize);
+ for (int idx = 0; idx &lt; vectorSize; ++idx ) {
+ PyObject* pyItem = PySequence_Fast_GET_ITEM(seq.object(), idx);
+ %OUTTYPE_0 cppItem = %CONVERTTOCPP[%OUTTYPE_0](pyItem);
+ %out.push_back(cppItem);
+ }
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+ <!-- Test wrapping of a typedef -->
+ <function signature="arrayFuncInt(std::vector&lt;int&gt;)" />
+ <!-- Note manual expansion of the typedef -->
+ <function signature="arrayFuncIntTypedef(std::vector&lt;int&gt;)" />
+
+ <function signature="arrayFuncIntReturn(int)" />
+ <function signature="arrayFuncIntReturnTypedef(int)" />
+
+ <!-- Test wrapping of a typedef of a typedef -->
+ <function signature="arrayFunc(std::vector&lt;int&gt;)" />
+ <!-- Note manual expansion of the typedef -->
+ <function signature="arrayFuncTypedef(std::vector&lt;int&gt;)" />
+
+ <function signature="arrayFuncReturn(int)" />
+ <function signature="arrayFuncReturnTypedef(int)" />
+</typesystem>
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 @@
+<?xml version="1.0"?>
+<typesystem package="other">
+ <load-typesystem name="typesystem_sample.xml" generate="no" />
+
+ <object-type name="OtherObjectType" />
+ <object-type name="OtherDerived" />
+ <object-type name="OtherMultipleDerived" />
+
+ <value-type name="ExtendsNoImplicitConversion" />
+ <value-type name="Number" />
+
+ <suppress-warning text="signature 'operator!=(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
+ <suppress-warning text="signature 'operator+(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
+ <suppress-warning text="signature 'operator==(ByteArray,const char*)' for function modification in 'ByteArray' not found." />
+</typesystem>
diff --git a/sources/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<void*>(const_cast<char*>(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 <add-function> 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<int, const ByteArray>&)'''
+ 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(), "<un") # use name='unknown' default argument
+
+ o.setObjectSplittedName("")
+ self.assertEqual(o.objectName(), "<unknown>") # user prefix='<unk' and suffix='nown>'
+
+
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/shiboken2/tests/samplebinding/objecttypebyvalue_test.py b/sources/shiboken2/tests/samplebinding/objecttypebyvalue_test.py
new file mode 100644
index 000000000..a9938b8af
--- /dev/null
+++ b/sources/shiboken2/tests/samplebinding/objecttypebyvalue_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 sample import *
+import unittest
+
+class ObjectTypeByValueTest (unittest.TestCase):
+ def testIt(self):
+ factory = ObjectTypeByValue()
+ obj = factory.returnSomeKindOfMe()
+ # This should crash!
+ obj.prop.protectedValueTypeProperty.setX(1.0)
+ # just to make sure it will segfault
+ obj.prop.protectedValueTypeProperty.setY(2.0)
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/sources/shiboken2/tests/samplebinding/objecttypelayout_test.py b/sources/shiboken2/tests/samplebinding/objecttypelayout_test.py
new file mode 100644
index 000000000..4d0e8cab7
--- /dev/null
+++ b/sources/shiboken2/tests/samplebinding/objecttypelayout_test.py
@@ -0,0 +1,302 @@
+#!/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 ObjectTypeLayout class.'''
+
+import sys
+import unittest
+
+from sample import *
+
+
+class ObjectTypeLayoutTest(unittest.TestCase):
+ '''Test cases for ObjectTypeLayout class.'''
+
+ def testOwnershipOverride(self):
+ l = ObjectTypeLayout()
+
+ o1 = ObjectType(l)
+ o1.setObjectName('o1')
+
+ self.assertEqual(sys.getrefcount(o1), 3)
+ l.takeChild('o1')
+ self.assertEqual(sys.getrefcount(o1), 2)
+
+
+ def testSetNullLayout(self):
+ '''ObjectType.setLayout(0).'''
+ o2 = ObjectType()
+ o2.setLayout(None)
+
+ def testSetNullLayoutToObjectTypeCreatedInCpp(self):
+ '''ObjectType.setLayout(0) to object created in C++.'''
+ o1 = ObjectType.create()
+ o1.setLayout(None)
+
+ def testObjectTypeLayout(self):
+ '''ObjectType.setLayout.'''
+ p1 = ObjectType()
+ c1 = ObjectType()
+ c2 = ObjectType()
+ c3 = ObjectType()
+ layout = ObjectTypeLayout()
+ layout.addObject(c1)
+ layout.addObject(c2)
+ layout.addObject(c3)
+ self.assertEqual(c1.parent(), None)
+ self.assertEqual(c2.parent(), None)
+ self.assertEqual(c3.parent(), None)
+
+ p1.setLayout(layout)
+ del p1 # This must kill c1, c2 and c3
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, layout.objectName)
+
+ def testObjectTypeLayoutWithObjectsCreatedInCpp(self):
+ '''ObjectType.setLayout with objects created in C++.'''
+ p1 = ObjectType.create()
+ c1 = ObjectType.create()
+ c2 = ObjectType.create()
+ c3 = ObjectType.create()
+ layout = ObjectTypeLayout()
+ layout.addObject(c1)
+ layout.addObject(c2)
+ layout.addObject(c3)
+ self.assertEqual(c1.parent(), None)
+ self.assertEqual(c2.parent(), None)
+ self.assertEqual(c3.parent(), None)
+
+ p1.setLayout(layout)
+ del p1 # This must kill c1, c2 and c3
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, layout.objectName)
+
+ def testObjectTypeLayoutTransference(self):
+ '''Transfer a layout from one ObjectType to another, so that all the items in the layout get reparented.'''
+ p1 = ObjectType()
+ p2 = ObjectType()
+ c1 = ObjectType()
+ c2 = ObjectType()
+
+ layout = ObjectTypeLayout()
+ layout.addObject(c1)
+ layout.addObject(c2)
+
+ p1.setLayout(layout)
+
+ self.assertEqual(len(p2.children()), 0)
+ self.assertEqual(c1.parent(), p1)
+ self.assertEqual(c2.parent(), p1)
+ self.assertEqual(set(p1.children()), set([c1, c2, layout]))
+
+ p2.setLayout(layout)
+
+ self.assertEqual(len(p1.children()), 0)
+ self.assertEqual(c1.parent(), p2)
+ self.assertEqual(c2.parent(), p2)
+ self.assertEqual(set(p2.children()), set([c1, c2, layout]))
+
+ def testObjectTypeLayoutInsideAnotherLayout(self):
+ '''Adds one ObjectTypeLayout to another and sets the parent to an ObjectType.'''
+ p1 = ObjectType()
+
+ l1 = ObjectTypeLayout()
+ c1 = ObjectType()
+ l1.addObject(c1)
+ c2 = ObjectType()
+ l1.addObject(c2)
+
+ l2 = ObjectTypeLayout()
+ c3 = ObjectType()
+ l2.addObject(c3)
+ c4 = ObjectType()
+ l2.addObject(c4)
+
+ l1.addObject(l2)
+
+ p1.setLayout(l1)
+
+ self.assertEqual(c1.parent(), p1)
+ self.assertEqual(c2.parent(), p1)
+ self.assertEqual(c3.parent(), p1)
+ self.assertEqual(c4.parent(), p1)
+ self.assertEqual(l1.parent(), p1)
+ self.assertEqual(l2.parent(), l1)
+
+ del p1
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, c4.objectName)
+ self.assertRaises(RuntimeError, l1.objectName)
+ self.assertRaises(RuntimeError, l2.objectName)
+
+ def testObjectTypeLayoutInsideAnotherLayoutAndEveryoneCreatedInCpp(self):
+ '''Adds one ObjectTypeLayout to another and sets the parent to an ObjectType. All the objects are created in C++.'''
+ p1 = ObjectType.create()
+
+ l1 = ObjectTypeLayout.create()
+ c1 = ObjectType.create()
+ l1.addObject(c1)
+ c2 = ObjectType.create()
+ l1.addObject(c2)
+
+ l2 = ObjectTypeLayout.create()
+ c3 = ObjectType.create()
+ l2.addObject(c3)
+ c4 = ObjectType.create()
+ l2.addObject(c4)
+
+ l1.addObject(l2)
+
+ p1.setLayout(l1)
+
+ self.assertEqual(c1.parent(), p1)
+ self.assertEqual(c2.parent(), p1)
+ self.assertEqual(c3.parent(), p1)
+ self.assertEqual(c4.parent(), p1)
+ self.assertEqual(l1.parent(), p1)
+ self.assertEqual(l2.parent(), l1)
+
+ del p1
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, c4.objectName)
+ self.assertRaises(RuntimeError, l1.objectName)
+ self.assertRaises(RuntimeError, l2.objectName)
+
+ def testTransferNestedLayoutsBetweenObjects(self):
+ '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType and then transfer it to another object.'''
+ p1 = ObjectType()
+ p2 = ObjectType()
+
+ l1 = ObjectTypeLayout()
+ c1 = ObjectType()
+ l1.addObject(c1)
+ c2 = ObjectType()
+ l1.addObject(c2)
+
+ l2 = ObjectTypeLayout()
+ c3 = ObjectType()
+ l2.addObject(c3)
+ c4 = ObjectType()
+ l2.addObject(c4)
+
+ l1.addObject(l2)
+
+ p1.setLayout(l1)
+
+ self.assertEqual(c1.parent(), p1)
+ self.assertEqual(c2.parent(), p1)
+ self.assertEqual(c3.parent(), p1)
+ self.assertEqual(c4.parent(), p1)
+ self.assertEqual(l1.parent(), p1)
+ self.assertEqual(l2.parent(), l1)
+
+ p2.setLayout(l1)
+ del p1
+
+ self.assertEqual(c1.parent(), p2)
+ self.assertEqual(c2.parent(), p2)
+ self.assertEqual(c3.parent(), p2)
+ self.assertEqual(c4.parent(), p2)
+ self.assertEqual(l1.parent(), p2)
+ self.assertEqual(l2.parent(), l1)
+
+ del p2
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, c4.objectName)
+ self.assertRaises(RuntimeError, l1.objectName)
+ self.assertRaises(RuntimeError, l2.objectName)
+
+ def testTransferNestedLayoutsBetweenObjectsAndEveryoneCreatedInCpp(self):
+ '''Adds one ObjectTypeLayout to another, sets the parent to an ObjectType and then transfer it to another object.
+ All the objects are created in C++.'''
+ p1 = ObjectType.create()
+ p2 = ObjectType.create()
+
+ l1 = ObjectTypeLayout.create()
+ c1 = ObjectType.create()
+ l1.addObject(c1)
+ c2 = ObjectType.create()
+ l1.addObject(c2)
+
+ l2 = ObjectTypeLayout.create()
+ c3 = ObjectType.create()
+ l2.addObject(c3)
+ c4 = ObjectType.create()
+ l2.addObject(c4)
+
+ l1.addObject(l2)
+
+ p1.setLayout(l1)
+
+ self.assertEqual(c1.parent(), p1)
+ self.assertEqual(c2.parent(), p1)
+ self.assertEqual(c3.parent(), p1)
+ self.assertEqual(c4.parent(), p1)
+ self.assertEqual(l1.parent(), p1)
+ self.assertEqual(l2.parent(), l1)
+
+ p2.setLayout(l1)
+ del p1
+
+ self.assertEqual(c1.parent(), p2)
+ self.assertEqual(c2.parent(), p2)
+ self.assertEqual(c3.parent(), p2)
+ self.assertEqual(c4.parent(), p2)
+ self.assertEqual(l1.parent(), p2)
+ self.assertEqual(l2.parent(), l1)
+
+ del p2
+
+ self.assertRaises(RuntimeError, c1.objectName)
+ self.assertRaises(RuntimeError, c2.objectName)
+ self.assertRaises(RuntimeError, c3.objectName)
+ self.assertRaises(RuntimeError, c4.objectName)
+ self.assertRaises(RuntimeError, l1.objectName)
+ self.assertRaises(RuntimeError, l2.objectName)
+
+if __name__ == '__main__':
+ unittest.main()
+
diff --git a/sources/shiboken2/tests/samplebinding/objecttypeoperators_test.py b/sources/shiboken2/tests/samplebinding/objecttypeoperators_test.py
new file mode 100644
index 000000000..a8bcf1aa0
--- /dev/null
+++ b/sources/shiboken2/tests/samplebinding/objecttypeoperators_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$
+##
+#############################################################################
+
+import unittest
+from sample import *
+
+class ObjectTypeOperatorsTest(unittest.TestCase):
+
+ def testIt(self):
+ a = ObjectTypeOperators("a")
+ b = ObjectTypeOperators("b")
+ self.assertFalse(a == b)
+ self.assertEqual(a, a < b)
+
+ # this should change a.key() and return nothing.
+ self.assertEqual(None, a > 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 <add-function> 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<Str>.'''
+
+import unittest
+
+from sample import Str, StrList
+
+class StrListTest(unittest.TestCase):
+ '''Test cases for StrList class that inherits from std::list<Str>.'''
+
+ 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<Complex,int>')
+ self.assertEqual(pyType, list)
+
+ def testListContainerType(self):
+ pyType = sample.getPythonType('std::list<int>')
+ self.assertEqual(pyType, list)
+
+ def testMapContainerType(self):
+ pyType = sample.getPythonType('std::map<std::string,int>')
+ 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<int>'))
+ self.assertFalse(sample.cppTypeIsObjectType('std::list<int>'))
+
+
+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 @@
+<?xml version="1.0"?>
+<typesystem package="sample">
+ <suppress-warning text="Duplicate type entry: 'sample'" />
+ <suppress-warning text="Duplicate type entry: 'SampleNamespace'" />
+
+ <custom-type name="str"/>
+ <custom-type name="PyBytes"/>
+ <custom-type name="PyDate"/>
+ <custom-type name="PyObject"/>
+ <custom-type name="PyUnicode"/>
+
+ <primitive-type name="bool"/>
+ <primitive-type name="double"/>
+ <primitive-type name="real"/>
+ <primitive-type name="int"/>
+ <primitive-type name="short"/>
+ <primitive-type name="unsigned short"/>
+ <primitive-type name="ushort"/>
+ <primitive-type name="unsigned int" />
+ <primitive-type name="signed int" />
+ <primitive-type name="char"/>
+ <primitive-type name="unsigned char"/>
+ <primitive-type name="long"/>
+ <primitive-type name="unsigned long"/>
+ <primitive-type name="long long"/>
+ <primitive-type name="unsigned long long"/>
+ <primitive-type name="std::string"/>
+ <primitive-type name="ObjectType::Identifier"/>
+
+ <primitive-type name="Foo::HANDLE" target-lang-api-name="PyLong"/>
+
+ <primitive-type name="std::size_t" target-lang-api-name="PyLong">
+ <conversion-rule>
+ <native-to-target>
+ return PyLong_FromSize_t(%in);
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyLong">
+ %out = %OUTTYPE(PyLong_AsSsize_t(%in));
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <inject-code class="native" position="beginning">
+ static bool Check2TupleOfNumbers(PyObject* pyIn) {
+ if (!PySequence_Check(pyIn) || !(PySequence_Size(pyIn) == 2))
+ return false;
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(pyIn, 0));
+ if (!SbkNumber_Check(pyReal))
+ return false;
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(pyIn, 1));
+ if (!SbkNumber_Check(pyImag))
+ return false;
+ return true;
+ }
+ </inject-code>
+ <primitive-type name="Complex" target-lang-api-name="PyComplex">
+ <include file-name="complex.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ return PyComplex_FromDoubles(%in.real(), %in.imag());
+ </native-to-target>
+ <target-to-native>
+ <!-- The 'check' attribute can be derived from the 'type' attribute,
+ it is defined here to test the CHECKTYPE type system variable. -->
+ <add-conversion type="PyComplex" check="%CHECKTYPE[Complex](%in)">
+ double real = PyComplex_RealAsDouble(%in);
+ double imag = PyComplex_ImagAsDouble(%in);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+ <add-conversion type="PySequence" check="Check2TupleOfNumbers(%in)">
+ Shiboken::AutoDecRef pyReal(PySequence_GetItem(%in, 0));
+ Shiboken::AutoDecRef pyImag(PySequence_GetItem(%in, 1));
+ double real = %CONVERTTOCPP[double](pyReal);
+ double imag = %CONVERTTOCPP[double](pyImag);
+ %out = %OUTTYPE(real, imag);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <primitive-type name="Null">
+ <include file-name="null.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ SBK_UNUSED(%in);
+ Py_RETURN_NONE;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyObject" check="%in == 0 || %in == Py_None">
+ %out = %OUTTYPE(%in == 0);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <primitive-type name="HANDLE" target-lang-api-name="PyComplex">
+ <include file-name="handle.h" location="local"/>
+ <conversion-rule>
+ <native-to-target>
+ if (!%in)
+ Py_RETURN_NONE;
+ #ifdef IS_PY3K
+ return PyCapsule_New(%in, 0, 0);
+ #else
+ return PyCObject_FromVoidPtr(%in, 0);
+ #endif
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyNone">
+ %out = 0;
+ </add-conversion>
+ <add-conversion check="checkPyCapsuleOrPyCObject(%in)" type="PyObject">
+ void* ptr;
+ #ifdef IS_PY3K
+ ptr = PyCapsule_GetPointer(%in, 0);
+ #else
+ ptr = PyCObject_AsVoidPtr(%in);
+ #endif
+ %out = (%OUTTYPE)ptr;
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <inject-code class="native" position="beginning">
+ static bool checkPyCapsuleOrPyCObject(PyObject* pyObj)
+ {
+ #ifdef IS_PY3K
+ return PyCapsule_CheckExact(pyObj);
+ #else
+ return PyCObject_Check(pyObj);
+ #endif
+ }
+ </inject-code>
+
+ <primitive-type name="PrimitiveStructPtr">
+ <include file-name="handle.h" location="local"/>
+ <conversion-rule>
+ <native-to-target>
+ #ifdef IS_PY3K
+ return PyCapsule_New(&amp;%in, 0, 0);
+ #else
+ return PyCObject_FromVoidPtr(&amp;%in, 0);
+ #endif
+ </native-to-target>
+ <target-to-native>
+ <add-conversion check="checkPyCapsuleOrPyCObject(%in)" type="PyObject">
+ void* ptr;
+ #ifdef IS_PY3K
+ ptr = PyCapsule_GetPointer(%in, 0);
+ #else
+ ptr = PyCObject_AsVoidPtr(%in);
+ #endif
+ %out = *((%OUTTYPE*)ptr);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <primitive-type name="OddBool" target-lang-api-name="PyBool" default-constructor="OddBool(false)">
+ <include file-name="oddbool.h" location="global"/>
+ <include file-name="complex.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ return PyBool_FromLong(%in.value());
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyBool">
+ // Tests CONVERTTOCPP macro with C++ primitive type.
+ bool b = %CONVERTTOCPP[bool](%in);
+ %out = %OUTTYPE(b);
+ </add-conversion>
+ <add-conversion type="PyComplex">
+ // Tests CONVERTTOCPP macro with user's primitive type.
+ Complex cpx = %CONVERTTOCPP[Complex](%in);
+ %out = %OUTTYPE(cpx.real() != 0.0 || cpx.imag() != 0.0);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <primitive-type name="PStr">
+ <include file-name="str.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ return Shiboken::String::fromCString(%in.cstring(), %in.size());
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyUnicode" check="Shiboken::String::check(%in)">
+ const char* str = %CONVERTTOCPP[const char*](%in);
+ %out = %OUTTYPE(str);
+ </add-conversion>
+ <add-conversion type="Py_None">
+ %out = %OUTTYPE();
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <function signature="changePStr(PStr*, const char*)">
+ <!--
+ Comment out these modifications and the Shiboken generator
+ will issue a fatal error, because it can't handle a pointer
+ to a primitive type (PStr*) without help from the binding
+ developer.
+ -->
+ <modify-function signature="changePStr(PStr*, const char*)">
+ <modify-argument index="1">
+ <replace-type modified-type="PStr"/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ %FUNCTION_NAME(&amp;%1, %2);
+ %PYARG_0 = %CONVERTTOPYTHON[PStr](%1);
+ </inject-code>
+ </modify-function>
+ </function>
+
+ <function signature="duplicatePStr(PStr*)">
+ <modify-function signature="duplicatePStr(PStr*)">
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject"/>
+ </modify-argument>
+ <modify-argument index="1">
+ <replace-type modified-type="PStr"/>
+ <remove-default-expression/>
+ <replace-default-expression with="PStr()"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ %FUNCTION_NAME(&amp;%1);
+ %PYARG_0 = %CONVERTTOPYTHON[PStr](%1);
+ </inject-code>
+ </modify-function>
+ </function>
+
+ <primitive-type name="PStrList">
+ <include file-name="strlist.h" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ 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;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ %OUTTYPE&amp; list = %out;
+ Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0));
+ for (int i = 0; i &lt; 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);
+ }
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </primitive-type>
+
+ <add-function signature="createPStrList(PStr, PStr)" return-type="PyObject">
+ <inject-code class="target">
+ PStrList %0;
+ %0.push_back(%1);
+ %0.push_back(%2);
+ %PYARG_0 = %CONVERTTOPYTHON[PStrList](%0);
+ </inject-code>
+ </add-function>
+ <add-function signature="createListOfPStr(PStr, PStr)" return-type="PyObject">
+ <inject-code class="target">
+ std::list&lt;PStr&gt; %0;
+ %0.push_back(%1);
+ %0.push_back(%2);
+ %PYARG_0 = %CONVERTTOPYTHON[std::list&lt;PStr&gt;](%0);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="getPythonType(const char*)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = (PyObject*) Shiboken::Conversions::getPythonTypeObject(%1);
+ if (!%PYARG_0)
+ %PYARG_0 = Py_None;
+ Py_INCREF(%PYARG_0);
+ </inject-code>
+ </add-function>
+
+ <template name="cpp_type_is_object_or_value_type">
+ SbkConverter* converter = Shiboken::Conversions::getConverter(%1);
+ if (converter) {
+ if (Shiboken::Conversions::pythonTypeIs$TYPEType(converter))
+ %PYARG_0 = Py_True;
+ else
+ %PYARG_0 = Py_False;
+ Py_INCREF(%PYARG_0);
+ } else {
+ PyErr_Format(PyExc_ValueError, "Type '%s' has no converter associated to it", %1);
+ }
+ </template>
+ <add-function signature="cppTypeIsObjectType(const char*)" return-type="bool">
+ <inject-code class="target" position="beginning">
+ <insert-template name="cpp_type_is_object_or_value_type">
+ <replace from="$TYPE" to="Object" />
+ </insert-template>
+ </inject-code>
+ </add-function>
+ <add-function signature="cppTypeIsValueType(const char*)" return-type="bool">
+ <inject-code class="target" position="beginning">
+ <insert-template name="cpp_type_is_object_or_value_type">
+ <replace from="$TYPE" to="Value" />
+ </insert-template>
+ </inject-code>
+ </add-function>
+
+ <add-function signature="getConversionTypeString(const char*)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ 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);
+ </inject-code>
+ </add-function>
+
+ <inject-code class="native" position="beginning">
+ static PyObject* __convertCppValuesToPython(const char** typeName, void** values, int size)
+ {
+ PyObject* result = PyTuple_New(size);
+ for (int i = 0; i &lt; size; ++i) {
+ Shiboken::Conversions::SpecificConverter converter(typeName[i]);
+ PyTuple_SET_ITEM(result, i, converter.toPython(values[i]));
+ }
+ return result;
+ }
+ </inject-code>
+ <add-function signature="convertValueTypeToCppAndThenToPython(Point,Point*,Point&amp;)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ const char* typeNames[] = { "Point", "Point*", "Point&amp;" };
+ void* values[] = { &amp;%1, &amp;%2, &amp;(%3) };
+ %PYARG_0 = __convertCppValuesToPython(typeNames, values, 3);
+ </inject-code>
+ </add-function>
+ <add-function signature="convertObjectTypeToCppAndThenToPython(ObjectType*,ObjectType&amp;)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ const char* typeNames[] = { "ObjectType*", "ObjectType&amp;" };
+ void* values[] = { &amp;%1, &amp;(%2) };
+ %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2);
+ </inject-code>
+ </add-function>
+ <add-function signature="convertListOfIntegersToCppAndThenToPython(std::list&lt;int&gt;)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ const char* typeNames[] = { "std::list&lt;int&gt;" };
+ void* values[] = { &amp;%1 };
+ %PYARG_0 = __convertCppValuesToPython(typeNames, values, 1);
+ </inject-code>
+ </add-function>
+ <add-function signature="convertIntegersToCppAndThenToPython(int,int)" return-type="PyObject">
+ <inject-code class="target" position="beginning">
+ const char* typeNames[] = { "int", "int" };
+ void* values[] = { &amp;%1, &amp;%2 };
+ %PYARG_0 = __convertCppValuesToPython(typeNames, values, 2);
+ </inject-code>
+ </add-function>
+
+ <container-type name="std::pair" type="pair">
+ <include file-name="utility" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ 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;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ %out.first = %CONVERTTOCPP[%OUTTYPE_0](PySequence_Fast_GET_ITEM(%in, 0));
+ %out.second = %CONVERTTOCPP[%OUTTYPE_1](PySequence_Fast_GET_ITEM(%in, 1));
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+ <template name="cpplist_to_pylist_convertion">
+ 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;
+ </template>
+ <template name="pyseq_to_cpplist_convertion">
+ Shiboken::AutoDecRef seq(PySequence_Fast(%in, 0));
+ for (int i = 0; i &lt; 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);
+ }
+ </template>
+ <container-type name="std::list" type="list">
+ <include file-name="list" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ <insert-template name="cpplist_to_pylist_convertion"/>
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ <insert-template name="pyseq_to_cpplist_convertion"/>
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+ <container-type name="List" type="list">
+ <include file-name="list" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ <insert-template name="cpplist_to_pylist_convertion"/>
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PySequence">
+ <insert-template name="pyseq_to_cpplist_convertion"/>
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+ <container-type name="std::map" type="map">
+ <include file-name="map" location="global"/>
+ <conversion-rule>
+ <native-to-target>
+ PyObject* %out = PyDict_New();
+ %INTYPE::const_iterator it = %in.begin();
+ for (; it != %in.end(); ++it) {
+ %INTYPE_0 key = it->first;
+ %INTYPE_1 value = it->second;
+ PyDict_SetItem(%out,
+ %CONVERTTOPYTHON[%INTYPE_0](key),
+ %CONVERTTOPYTHON[%INTYPE_1](value));
+ }
+ return %out;
+ </native-to-target>
+ <target-to-native>
+ <add-conversion type="PyDict">
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+ while (PyDict_Next(%in, &amp;pos, &amp;key, &amp;value)) {
+ %OUTTYPE_0 cppKey = %CONVERTTOCPP[%OUTTYPE_0](key);
+ %OUTTYPE_1 cppValue = %CONVERTTOCPP[%OUTTYPE_1](value);
+ %out.insert(%OUTTYPE::value_type(cppKey, cppValue));
+ }
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ </container-type>
+
+ <add-function signature="cacheSize()" return-type="int">
+ <inject-code class="target">
+ %RETURN_TYPE %0 = Shiboken::BindingManager::instance().getAllPyObjects().size();
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+
+ <namespace-type name="sample">
+ <value-type name="sample" />
+ </namespace-type>
+
+ <function signature="sumComplexPair(std::pair&lt;Complex, Complex>)" />
+ <function signature="gimmeComplexList()" />
+ <function signature="transmuteComplexIntoPoint(const Complex&amp;)" />
+ <function signature="transmutePointIntoComplex(const Point&amp;)" />
+ <function signature="sumComplexPair(std::pair&lt;Complex, Complex>)" />
+ <function signature="doubleUnsignedInt(unsigned int)" />
+ <function signature="doubleLongLong(long long)" />
+ <function signature="doubleUnsignedLongLong(unsigned long long)" />
+ <function signature="doubleShort(short)" />
+ <function signature="returnNullPrimitivePointer()" />
+ <function signature="returnNullValueTypePointer()" />
+ <function signature="returnNullObjectTypePointer()" />
+ <function signature="acceptInt(int)" />
+ <function signature="acceptUInt(unsigned int)" />
+ <function signature="acceptLong(long)" />
+ <function signature="acceptULong(unsigned long)" />
+ <function signature="acceptDouble(double)" />
+ <function signature="acceptIntReference(int&amp;)" />
+ <function signature="acceptOddBoolReference(OddBool&amp;)" />
+ <function signature="countCharacters(const char*)" />
+ <function signature="gimmeInt()" />
+ <function signature="gimmeDouble()" />
+ <function signature="makeCString()" />
+ <function signature="multiplyPair(std::pair&lt;double, double>)" />
+ <function signature="returnCString()" />
+ <function signature="overloadedFunc(double)" />
+ <function signature="overloadedFunc(int)" />
+
+ <value-type name="ClassWithFunctionPointer">
+ <suppress-warning text="skipping function 'ClassWithFunctionPointer::callFunctionPointer', unmatched parameter type 'void (*)(void*)'" />
+ </value-type>
+
+ <enum-type name="OverloadedFuncEnum"/>
+ <!-- BUG:
+ renaming the ICOverloadedFuncEnum to the same name
+ of a global enum causes the generator to confuse the
+ two types.
+ -->
+ <enum-type name="GlobalEnum"/>
+ <enum-type name="GlobalOverloadFuncEnum"/>
+
+ <enum-type identified-by-value="AnonymousGlobalEnum_Value0"/>
+
+ <namespace-type name="Invisible" generate="no">
+ <enum-type name="EnumOnNamespace" />
+ </namespace-type>
+
+ <namespace-type name="SampleNamespace">
+ <enum-type name="Option"/>
+ <enum-type name="InValue"/>
+ <enum-type name="OutValue"/>
+ <enum-type identified-by-value="AnonymousClassEnum_Value1"/>
+
+ <object-type name="DerivedFromNamespace">
+ <enum-type name="SampleNamespace"/>
+ </object-type>
+ <value-type name="SomeClass">
+ <value-type name="SomeInnerClass">
+ <object-type name="OkThisIsRecursiveEnough">
+ <enum-type name="NiceEnum" />
+ </object-type>
+ <enum-type name="ProtectedEnum"/>
+ </value-type>
+ <value-type name="SomeOtherInnerClass"/>
+ <enum-type name="ProtectedEnum"/>
+ </value-type>
+
+ <modify-function signature="doSomethingWithArray(const unsigned char*, unsigned int, const char*)">
+ <modify-argument index="1">
+ <replace-type modified-type="const char*"/>
+ <conversion-rule class="native">
+ const unsigned char* %out = reinterpret_cast&lt;const unsigned char*>(Shiboken::String::toCString(%PYARG_1));
+ </conversion-rule>
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument/>
+ <conversion-rule class="native">
+ unsigned int %out = static_cast&lt;unsigned int>(Shiboken::String::len(%PYARG_1));
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <add-function signature="ImInsideANamespace(int, int)" return-type="int">
+ <inject-code class="target">
+ %RETURN_TYPE %0 = %1 + %2;
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ <add-function signature="passReferenceToValueType(Point&amp;)" return-type="double">
+ <inject-code>
+ %RETURN_TYPE %0 = %1.x() + %1.y();
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+
+ <!-- Do change the argument from pointer to reference to comply with the C++ overload
+ of this function. The generator must be able to deal with this for Object Types. -->
+ <add-function signature="passReferenceToObjectType(ObjectType*)" return-type="int">
+ <inject-code>
+ // The dot in "%1." must be replaced with a "->" by the generator.
+ %RETURN_TYPE %0 = %1.objectName().size();
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </namespace-type>
+
+ <namespace-type name="RemovedNamespace1" generate='no'>
+ <enum-type name="RemovedNamespace1_Enum" />
+ <namespace-type name="RemovedNamespace2" generate='no'>
+ <enum-type name="RemovedNamespace2_Enum" />
+ </namespace-type>
+ <enum-type identified-by-value="RemovedNamespace1_AnonymousEnum_Value0" />
+ </namespace-type>
+
+ <namespace-type name="UnremovedNamespace">
+ <namespace-type name="RemovedNamespace3" generate='no'>
+ <enum-type name="RemovedNamespace3_Enum" />
+ <enum-type identified-by-value="RemovedNamespace3_AnonymousEnum_Value0" />
+ </namespace-type>
+ </namespace-type>
+
+ <namespace-type name="Photon">
+ <enum-type name="ClassType"/>
+ <value-type name="Base"/>
+ <value-type name="TemplateBase" generate="no"/>
+ <value-type name="ValueIdentity"/>
+ <value-type name="ValueDuplicator"/>
+ </namespace-type>
+
+ <value-type name="CVValueType"/>
+ <value-type name="CVListUser"/>
+
+ <value-type name="IntList">
+ <enum-type name="CtorEnum"/>
+ </value-type>
+ <value-type name="PointValueList">
+ <enum-type name="CtorEnum"/>
+ </value-type>
+ <value-type name="ObjectTypePtrList">
+ <enum-type name="CtorEnum"/>
+ </value-type>
+
+ <object-type name="Abstract">
+ <enum-type name="Type"/>
+ <enum-type name="PrintFormat"/>
+ <modify-function signature="id()" rename="id_"/>
+ <modify-function signature="hideFunction(HideType*)" remove="all"/>
+ </object-type>
+
+ <object-type name="Derived" polymorphic-id-expression="%1->type() == Derived::TpDerived">
+ <enum-type name="OtherOverloadedFuncEnum"/>
+ <value-type name="SomeInnerClass" />
+ </object-type>
+
+ <object-type name="ModifiedConstructor">
+ <modify-function signature="ModifiedConstructor(int)">
+ <modify-argument index="1">
+ <replace-type modified-type="str"/>
+ </modify-argument>
+ <inject-code class='target' position='beginning'>
+ const char* tmpArg = %CONVERTTOCPP[const char*](%PYARG_1);
+ %0 = new %FUNCTION_NAME(atoi(tmpArg));
+ </inject-code>
+ </modify-function>
+ </object-type>
+
+ <object-type name="ObjectType" hash-function="objectTypeHash">
+ <modify-function signature="deprecatedFunction()" deprecated="yes" />
+ <!-- rename function to avoid Python signature conflit -->
+ <modify-function signature="setObject(const Null&amp;)" rename="setNullObject" />
+
+ <modify-function signature="getCppParent()">
+ <modify-argument index="this">
+ <parent index="return" action="add" />
+ </modify-argument>
+ <modify-argument index="return">
+ <define-ownership class="target" owner="default"/>
+ </modify-argument>
+ </modify-function>
+
+ <modify-function signature="event(Event*)">
+ <modify-argument index="1" invalidate-after-use="yes"/>
+ </modify-function>
+ <modify-function signature="invalidateEvent(Event*)">
+ <modify-argument index="1" invalidate-after-use="yes"/>
+ </modify-function>
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="createWithChild()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="setParent(ObjectType*)">
+ <modify-argument index="this">
+ <parent index="1" action="add"/>
+ </modify-argument>
+ </modify-function>
+ <inject-code class="native" position="beginning">
+ 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) &amp;&amp; !%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&amp; objChildren = var->objects();
+ ObjectTypeList::const_iterator it = objChildren.begin();
+ for (; it != objChildren.end(); ++it) {
+ if ((*it)->isLayoutType()) {
+ ObjectTypeLayout* l = reinterpret_cast&lt;ObjectTypeLayout*>(*it);
+ reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l));
+ Shiboken::Object::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l));
+ } else {
+ Shiboken::Object::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it));
+ }
+ }
+ }
+ </inject-code>
+ <modify-function signature="setLayout(ObjectTypeLayout*)">
+ <modify-argument index="1">
+ <parent index="this" action="add"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ if (%PYARG_1 != Py_None)
+ reparent_layout_items(%PYSELF, %PYARG_1);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="takeChild(ObjectType*)">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ <parent index="this" action="remove"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="takeChild(const Str&amp;)">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ <parent index="this" action="remove"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="findChild(const Str&amp;)">
+ <modify-argument index="return">
+ <parent index="this" action="add"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="children()const">
+ <modify-argument index="return">
+ <parent index="this" action="add"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="createChild(ObjectType*)">
+ <modify-argument index="return">
+ <define-ownership owner="c++" />
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="nextInFocusChain()">
+ <modify-argument index="return">
+ <parent index="this" action="add"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <object-type name="OtherBase" />
+ <object-type name="ObjectTypeDerived" />
+
+ <object-type name="ObjectTypeLayout">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <object-type name="ObjectView">
+ <modify-function signature="ObjectView(ObjectModel*, ObjectType*)">
+ <modify-argument index="1">
+ <reference-count action="set" variable-name="setModel(ObjectModel*)1"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="setModel(ObjectModel*)">
+ <modify-argument index="1">
+ <reference-count action="set"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <value-type name="ObjectTypeHolder"/>
+ <value-type name="OnlyCopy"/>
+ <value-type name="FriendOfOnlyCopy"/>
+
+ <object-type name="ObjectModel">
+ <enum-type name="MethodCalled" />
+ <modify-function signature="data() const">
+ <modify-argument index="return">
+ <define-ownership class="native" owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+ <value-type name="Event">
+ <enum-type name="EventType"/>
+ </value-type>
+
+ <value-type name="BlackBox">
+ <modify-function signature="keepObjectType(ObjectType*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="retrieveObjectType(int)">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="keepPoint(Point*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="retrievePoint(int)">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <value-type name="ProtectedNonPolymorphic">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="modifiedProtectedSum(int, int)">
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %2) * 10;
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="dataTypeName(void*) const" remove="all"/>
+ <modify-function signature="dataTypeName(int) const">
+ <modify-argument index="1">
+ <replace-default-expression with="0"/>
+ </modify-argument>
+ </modify-function>
+ <add-function signature="dataTypeName(PyObject*)const" return-type="const char*">
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%PYARG_1);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <value-type name="ProtectedPolymorphic">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <value-type name="ProtectedPolymorphicDaughter">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <value-type name="ProtectedPolymorphicGrandDaughter">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <object-type name="ProtectedVirtualDestructor">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+
+
+ <object-type name="ProtectedEnumClass">
+ <enum-type name="ProtectedEnum" />
+ <enum-type name="PublicEnum" />
+ </object-type>
+
+ <value-type name="ProtectedProperty" />
+
+ <function signature="createProtectedProperty()" />
+
+ <template name="boolptr_at_end_fix_beginning">
+ bool __ok__;
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%ARGUMENT_NAMES, &amp;__ok__);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </template>
+
+ <template name="boolptr_at_start_fix_beginning">
+ bool __ok__;
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(&amp;__ok__, %ARGUMENT_NAMES);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </template>
+
+ <template name="boolptr_at_start_and_one_arg_fix_beginning">
+ bool __ok__;
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(&amp;__ok__, %2);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </template>
+
+ <template name="boolptr_fix_end">
+ PyObject* _tuple_ = PyTuple_New(2);
+ PyTuple_SET_ITEM(_tuple_, 0, %PYARG_0);
+ PyObject* _item_ = %CONVERTTOPYTHON[bool](__ok__);
+ PyTuple_SET_ITEM(_tuple_, 1, _item_);
+ %PYARG_0 = _tuple_;
+ </template>
+
+ <template name="return_4_arguments_as_tuple">
+ %PYARG_0 = PyTuple_New(4);
+ PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%ARG1_TYPE](%1));
+ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG2_TYPE](%2));
+ PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[%ARG3_TYPE](%3));
+ PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[%ARG4_TYPE](%4));
+ </template>
+
+ <template name="return_5_arguments_as_tuple">
+ %PYARG_0 = PyTuple_New(5);
+ PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%ARG1_TYPE](%1));
+ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG2_TYPE](%2));
+ PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[%ARG3_TYPE](%3));
+ PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[%ARG4_TYPE](%4));
+ PyTuple_SET_ITEM(%PYARG_0, 4, %CONVERTTOPYTHON[%ARG5_TYPE](%5));
+ </template>
+
+ <template name="return_none">
+ %PYARG_0 = Py_None;
+ Py_INCREF(Py_None);
+ </template>
+
+ <object-type name="Modifications">
+ <enum-type name="OverloadedModFunc"/>
+
+ <modify-function signature="overloaded(int, bool, int, double)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, true, %3, %4);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="overloaded(int, bool, int, int)">
+ <modify-argument index="3">
+ <remove-argument/>
+ <replace-default-expression with="321"/>
+ </modify-argument>
+ <!--
+ <modify-argument index="4">
+ <remove-default-expression/>
+ </modify-argument>
+ -->
+ </modify-function>
+
+ <modify-function signature="argRemoval0(int, bool, int, int)">
+ <modify-argument index="3">
+ <remove-argument/>
+ <replace-default-expression with="321"/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_4_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval1(int, bool, Point, Point, int)">
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_5_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval1(int, bool, int, bool)">
+ <inject-code class="target" position="end">
+ <insert-template name="return_none"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval2(int, bool, Point, Point, int)">
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_5_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval3(int, Point, bool, Point, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_5_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval4(int, Point, bool, Point, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <replace-default-expression with="Point(6, 9)"/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_5_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval5(int, bool, Point, Point, int)">
+ <modify-argument index="1">
+ <remove-argument/>
+ <replace-default-expression with="100"/>
+ </modify-argument>
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_5_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="argRemoval5(int, bool, int, bool)">
+ <modify-argument index="1">
+ <remove-argument/>
+ <replace-default-expression with="200"/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ <insert-template name="return_4_arguments_as_tuple"/>
+ </inject-code>
+ </modify-function>
+
+ <!--
+ this alteration will trigger an interesting
+ compile time error on the binding
+ -->
+ <!--
+ <modify-function signature="overloaded(int, bool, Point, Point)">
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
+ -->
+
+ <!--
+ renaming this signature should remove it from the other
+ overloaded methods decision tree
+ -->
+ <modify-function signature="overloaded(int, bool, Point, Point)" rename="over"/>
+
+ <!--
+ '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
+ -->
+ <modify-function signature="pointToPair(Point, bool*)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="boolptr_at_end_fix_beginning"/>
+ </inject-code>
+ <inject-code class="target" position="end">
+ <insert-template name="boolptr_fix_end"/>
+ </inject-code>
+ </modify-function>
+
+ <!-- same as 'pointToPair' except that this time 'ok' is the first argument -->
+ <modify-function signature="multiplyPointCoordsPlusValue(bool*, Point, double)">
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="boolptr_at_start_fix_beginning"/>
+ </inject-code>
+ <inject-code class="target" position="end">
+ <insert-template name="boolptr_fix_end"/>
+ </inject-code>
+ </modify-function>
+
+ <!-- completely remove 'plus' from the Python side -->
+ <modify-function signature="doublePlus(int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ </modify-function>
+
+ <!-- the default value for both arguments must be changed in Python -->
+ <modify-function signature="power(int, int)">
+ <modify-argument index="1">
+ <replace-default-expression with="2"/>
+ </modify-argument>
+ <modify-argument index="2">
+ <replace-default-expression with="1"/>
+ </modify-argument>
+ </modify-function>
+
+ <!-- in Python set argument default value to 10 -->
+ <modify-function signature="timesTen(int)">
+ <modify-argument index="1">
+ <replace-default-expression with="10"/>
+ </modify-argument>
+ </modify-function>
+
+ <!-- in Python remove the argument default value -->
+ <modify-function signature="increment(int)">
+ <modify-argument index="1">
+ <remove-default-expression/>
+ </modify-argument>
+ </modify-function>
+
+ <!-- don't export this method to Python -->
+ <modify-function signature="exclusiveCppStuff()" remove="all"/>
+
+ <!-- change the name of this regular method -->
+ <modify-function signature="cppMultiply(int, int)" rename="calculateArea"/>
+
+ <!-- change the name of this virtual method -->
+ <modify-function signature="className()" rename="name"/>
+
+ <modify-function signature="sumPointArray(int, const Point*)">
+ <modify-argument index="1">
+ <remove-argument/>
+ <conversion-rule class="native">
+ int %out = PySequence_Size(%PYARG_1);
+ </conversion-rule>
+ </modify-argument>
+ <modify-argument index="2">
+ <replace-type modified-type="PySequence" />
+ <conversion-rule class="native">
+ Shiboken::AutoArrayPointer&lt;Point&gt; %out(%1);
+ for (int i = 0; i &lt; %1; ++i)
+ %out[i] = %CONVERTTOCPP[Point](PySequence_Fast_GET_ITEM(%PYARG_1, i));
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="getSize(const void*,int)">
+ <modify-argument index="1">
+ <replace-type modified-type="ByteArray&amp;"/>
+ </modify-argument>
+ <modify-argument index="2">
+ <replace-default-expression with="-1"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int size = (%2 &lt; 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);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="sumPointCoordinates(const Point*)">
+ <modify-argument index="1">
+ <no-null-pointer/>
+ </modify-argument>
+ </modify-function>
+ <template name="differenceOfPointCoordinates_arg2">
+ bool _status;
+ bool* %2 = &amp;_status;
+ </template>
+ <template name="differenceOfPointCoordinates_returnTarget">
+ %PYARG_0 = PyTuple_New(2);
+ PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[bool](*%2));
+ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%RETURN_TYPE](%0));
+ </template>
+ <modify-function signature="differenceOfPointCoordinates(const Point*, bool*)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <conversion-rule class="native">
+ <insert-template name="differenceOfPointCoordinates_arg2"/>
+ </conversion-rule>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PySequence"/>
+ <conversion-rule class="native">
+ Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0));
+ Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1));
+ *%2 = %CONVERTTOCPP[bool](_py_ok_);
+ %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ret_);
+ </conversion-rule>
+ <conversion-rule class="target">
+ <insert-template name="differenceOfPointCoordinates_returnTarget"/>
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="callDifferenceOfPointCoordinates(const Point*, bool*)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <conversion-rule class="native">
+ <insert-template name="differenceOfPointCoordinates_arg2"/>
+ </conversion-rule>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PySequence"/>
+ <conversion-rule class="target">
+ <insert-template name="differenceOfPointCoordinates_returnTarget"/>
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="nonConversionRuleForArgumentWithDefaultValue(ObjectType**)">
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="(status, object)"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ ObjectType* tmpObject = 0;
+ %BEGIN_ALLOW_THREADS
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(&amp;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));
+ </inject-code>
+ </modify-function>
+ <modify-function signature="passOddBool(OddBool)" rename="invertBoolean">
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = !%CPPSELF.%FUNCTION_NAME(%1);
+ %PYARG_0 = %CONVERTTOPYTHON[OddBool](%0);
+ </inject-code>
+ </modify-function>
+ </object-type>
+
+ <object-type name="AbstractModifications">
+ <!--
+ completely removing the pure virtual method from this
+ class will generate an #error directive.
+ -->
+ <!--
+ <modify-function signature="pointlessPureVirtualMethod()" remove="all"/>
+ -->
+ </object-type>
+
+ <value-type name="Reference">
+ <modify-function signature="returnMyFirstArg(Reference&amp;)">
+ <modify-argument index="return">
+ <replace-default-expression with="%1"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="returnMySecondArg(int, Reference&amp;)">
+ <modify-argument index="return">
+ <replace-default-expression with="%2"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+ <object-type name="ObjTypeReference">
+ <modify-function signature="returnMyFirstArg(ObjTypeReference&amp;)">
+ <modify-argument index="return">
+ <replace-default-expression with="%1"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="returnMySecondArg(int, ObjTypeReference&amp;)">
+ <modify-argument index="return">
+ <replace-default-expression with="%2"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="justAPureVirtualFunc(ObjTypeReference&amp;)">
+ <modify-argument index="return">
+ <replace-default-expression with="%1"/>
+ </modify-argument>
+ </modify-function>
+ </object-type>
+ <value-type name="ImplicitConv">
+ <enum-type name="CtorEnum"/>
+ <enum-type name="ICOverloadedFuncEnum"/>
+ </value-type>
+
+ <value-type name="VirtualMethods">
+ <modify-function signature="sum0(int, int, int)" rename="sumThree"/>
+ <modify-function signature="sum1(int, int, int)">
+ <modify-argument index="3">
+ <replace-default-expression with="1000"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="sum2(int, int, int)">
+ <modify-argument index="3">
+ <remove-argument/>
+ <replace-default-expression with="2000"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="sum3(int, int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, %1+%3, %3);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="sum4(int, int, int)">
+ <modify-argument index="2">
+ <remove-argument/>
+ <replace-default-expression with="3000"/>
+ </modify-argument>
+ <inject-code class="native" position="beginning">
+ PyObject* new_arg0 = PyInt_FromLong(PyInt_AS_LONG(%PYARG_1) - %2);
+ Py_DECREF(%PYARG_1);
+ %PYARG_1 = new_arg0;
+ </inject-code>
+ </modify-function>
+ <modify-function signature="name()">
+ <inject-code class="native" position="end">
+ %0.prepend(Str("Pimped"));
+ </inject-code>
+ </modify-function>
+ <modify-function signature="callMe()">
+ <inject-code class="native" position="end">
+ PyObject_Call(%PYTHON_METHOD_OVERRIDE, %PYTHON_ARGUMENTS, NULL);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="createStr(const char*, Str*&amp;)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PySequence"/>
+ <conversion-rule class="native">
+ Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0));
+ Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1));
+ %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ok_);
+ %2 = %CONVERTTOCPP[Str*](_py_ret_);
+ </conversion-rule>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ Str* _str_arg_ = 0;
+ %RETURN_TYPE %0 = %CPPSELF.%TYPE::%FUNCTION_NAME(%1, _str_arg_);
+ </inject-code>
+ <inject-code class="target" position="end">
+ %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_);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="callCreateStr(const char*, Str*&amp;)">
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PySequence"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ Str* _str_arg_ = 0;
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, _str_arg_);
+ </inject-code>
+ <inject-code class="target" position="end">
+ %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_);
+ </inject-code>
+ </modify-function>
+ <template name="fix_int*,int*,int*,int*">
+ int a0, a1, a2, a3;
+ %BEGIN_ALLOW_THREADS
+ %CPPSELF->::%TYPE::%FUNCTION_NAME(&amp;a0, &amp;a1, &amp;a2, &amp;a3);
+ %END_ALLOW_THREADS
+ %PYARG_0 = PyTuple_New(4);
+ PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[int](a0));
+ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[int](a1));
+ PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[int](a2));
+ PyTuple_SET_ITEM(%PYARG_0, 3, %CONVERTTOPYTHON[int](a3));
+ </template>
+ <template name="fix_native_return_int*,int*,int*,int*">
+ PyObject* _obj = %PYARG_0.object();
+ if (!PySequence_Check(_obj)
+ || PySequence_Fast_GET_SIZE(_obj) != 4
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 0))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 1))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 2))
+ || !SbkNumber_Check(PySequence_Fast_GET_ITEM(_obj, 3))) {
+ PyErr_SetString(PyExc_TypeError, "Sequence of 4 numbers expected");
+ } else {
+ *%1 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 0));
+ *%2 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 1));
+ *%3 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 2));
+ *%4 = %CONVERTTOCPP[int](PySequence_Fast_GET_ITEM(_obj, 3));
+ }
+ </template>
+ <modify-function signature="getMargins(int*,int*,int*,int*)const">
+ <modify-argument index="0">
+ <replace-type modified-type="PyObject" />
+ </modify-argument>
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ <remove-default-expression/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="fix_int*,int*,int*,int*"/>
+ </inject-code>
+ <inject-code class="native" position="end">
+ <insert-template name="fix_native_return_int*,int*,int*,int*"/>
+ </inject-code>
+ </modify-function>
+ <modify-function signature="callGetMargins(int*,int*,int*,int*)const">
+ <modify-argument index="0">
+ <replace-type modified-type="PyObject" />
+ </modify-argument>
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="3">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="4">
+ <remove-argument/>
+ <remove-default-expression/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="fix_int*,int*,int*,int*"/>
+ </inject-code>
+ </modify-function>
+ <modify-function signature="recursionOnModifiedVirtual(Str)const">
+ <inject-code class="target" position="beginning">
+ %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);
+ </inject-code>
+ </modify-function>
+ </value-type>
+ <value-type name="VirtualDaughter" />
+
+ <value-type name="VirtualDtor">
+ <modify-function signature="create()">
+ <modify-argument index="return">
+ <define-ownership owner="target"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <value-type name="PointerHolder">
+ <modify-function signature="PointerHolder(void*)" remove="all"/>
+ <add-function signature="PointerHolder(PyObject*)">
+ <inject-code class="target" position="beginning">
+ %0 = new %TYPE(%PYARG_1);
+ </inject-code>
+ </add-function>
+ <modify-function signature="pointer() const">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = reinterpret_cast&lt;PyObject*>(%CPPSELF.%FUNCTION_NAME());
+ if (!%PYARG_0)
+ %PYARG_0 = Py_None;
+ Py_INCREF(%PYARG_0);
+ </inject-code>
+ </modify-function>
+ </value-type>
+
+ <function signature="applyHomogeneousTransform(Point,double,double,double,double,double,double,double,double,double,bool*)">
+ <!--
+ Tests handling of the '%#' substitution for # > 9.
+ -->
+ <modify-function signature="applyHomogeneousTransform(Point,double,double,double,double,double,double,double,double,double,bool*)">
+ <modify-argument index="11">
+ <remove-argument/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ bool ok_;
+ %RETURN_TYPE retval_ =
+ %FUNCTION_NAME(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, &amp;ok_);
+ if (!ok_)
+ %PYARG_0 = Py_None;
+ else
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](retval_);
+ </inject-code>
+ </modify-function>
+ </function>
+
+ <!-- Tests add-function for nested template types -->
+ <add-function signature="sum2d(std::list&lt;std::list&lt;int&gt; &gt;)" return-type="int">
+ <inject-code class="target" position="beginning">
+ typedef std::list&lt;int&gt; Inner;
+ typedef std::list&lt;Inner&gt; Outer;
+
+ int result = 0;
+
+ Outer::const_iterator oiter, oend = %1.end();
+ for (oiter = %1.begin(); oiter != oend; ++oiter) {
+ const Inner&amp; inner = *oiter;
+ Inner::const_iterator iiter, iend = inner.end();
+ for (iiter = inner.begin(); iiter != iend; ++iiter)
+ result += *iiter;
+ }
+
+ %PYARG_0 = %CONVERTTOPYTHON[int](result);
+ </inject-code>
+ </add-function>
+
+ <!-- Tests add-function for nested template types -->
+ <add-function signature="sumproduct(std::list&lt;std::pair&lt;int, int&gt; &gt;)" return-type="int">
+ <inject-code class="target" position="beginning">
+ typedef std::pair&lt;int, int&gt; Pair;
+ typedef std::list&lt;Pair&gt; 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);
+ </inject-code>
+ </add-function>
+
+
+ <value-type name="InjectCode">
+ <!--
+ Various tests for inject codes.
+ Note: Some uses of inject code here are used just for testing purposes, consider using the add-function tag.
+ -->
+
+ <modify-function signature="sumArrayAndLength(int *) const">
+ <modify-argument index="1">
+ <replace-type modified-type="PyObject"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int* array = NULL;
+ bool errorOccurred = false;
+
+ if (PySequence_Check(%PYARG_1)) {
+ if((array = Shiboken::sequenceToIntArray(%PYARG_1, true)) == NULL &amp;&amp; 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);
+ }
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="arrayMethod(int, int*) const">
+ <modify-argument index="1">
+ <remove-argument/>
+ <conversion-rule class="native">
+ int %out = PySequence_Size(%PYARG_1);
+ </conversion-rule>
+ </modify-argument>
+ <modify-argument index="2">
+ <replace-type modified-type="PySequence"/>
+ <conversion-rule class="native">
+ int numItems = PySequence_Size(%PYARG_1);
+ Shiboken::AutoArrayPointer&lt;int&gt; %out(numItems);
+ for (int i = 0; i &lt; 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;
+ }
+ </conversion-rule>
+ <conversion-rule class="target">
+ PyObject* %out = PyList_New(count);
+ for (int i = 0; i &lt; count; ++i)
+ PyList_SET_ITEM(%out, i, %CONVERTTOPYTHON[int](%in[i]));
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+
+ <modify-function signature="callArrayMethod(int, int*) const">
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="2">
+ <replace-type modified-type="PySequence"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int numItems = PySequence_Size(%PYARG_1);
+ int *cppItems = new int[numItems];
+ for (int i = 0; i &lt; 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;
+ </inject-code>
+ </modify-function>
+
+ <!--
+ Inject the tp_str method using this alternative way
+ Tested in InjectCodeTest.testTypeNativeBeginning_TypeTargetBeginning:
+ -->
+ <inject-code class="native" position="beginning">
+ PyObject* InjectCode_tpstr(PyObject*) { return Shiboken::String::fromCString("Hi! I'm the inject code dummy class."); }
+ </inject-code>
+ <!--
+ Register our tp_str class using another inject code
+ Tested in InjectCodeTest.testTypeNativeBeginning_TypeTargetBeginning:
+ -->
+ <inject-code class="target" position="beginning">
+ %PYTHONTYPEOBJECT.tp_str = InjectCode_tpstr;
+ </inject-code>
+
+ <!-- Tested in InjectCodeTest.testFunctionTargetBeginning_FunctionTargetEnd -->
+ <modify-function signature="simpleMethod1(int, int)">
+ <inject-code class="target" position="beginning">
+ %1 += 1;
+ </inject-code>
+ <inject-code class="target" position="end">
+ PyObject* tmp = Shiboken::String::fromCString("end");
+ Shiboken::String::concat(&amp;%PYARG_0, tmp);
+ Py_DECREF(tmp);
+ </inject-code>
+ </modify-function>
+
+ <!-- Tested in InjectCodeTest.testFunctionTargetBeginning -->
+ <modify-function signature="simpleMethod2()">
+ <inject-code class="target" position="end">
+ PyObject* tmp = Shiboken::String::fromCString("end");
+ Shiboken::String::concat(&amp;%PYARG_0, tmp);
+ Py_DECREF(tmp);
+ </inject-code>
+ </modify-function>
+
+ <!-- Tested in InjectCodeTest.testArgsModification -->
+ <modify-function signature="overloadedMethod(int, char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int argc;
+ char** argv;
+ if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &amp;argc, &amp;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 &lt; argc; ++i)
+ free(argv[i]);
+ delete[] argv;
+ </inject-code>
+ </modify-function>
+
+ <!-- Tested in InjectCodeTest.testArgsModification2 -->
+ <modify-function signature="simpleMethod3(int, char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ </modify-argument>
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ int argc;
+ char** argv;
+ if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &amp;argc, &amp;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 &lt; argc; ++i)
+ free(argv[i]);
+ delete[] argv;
+ </inject-code>
+ </modify-function>
+ </value-type>
+
+ <value-type name="ImplicitBase"/>
+ <value-type name="SortedOverload">
+ <add-function signature="overload(PyObject *)" return-type="const char *">
+ <inject-code class="target" position="beginning">
+ return Shiboken::String::fromCString("PyObject");
+ </inject-code>
+ </add-function>
+
+ <add-function signature="overloadDeep(int, PyObject *)" return-type="const char *">
+ <inject-code class="target" position="beginning">
+ return Shiboken::String::fromCString("PyObject");
+ </inject-code>
+ </add-function>
+ <modify-function signature="pyObjOverload(unsigned char*, int)">
+ <modify-argument index="1">
+ <replace-type modified-type="PyObject" />
+ <conversion-rule class="native">
+ unsigned char* %out = 0;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+ <value-type name="ImplicitTarget"/>
+
+ <value-type name="Point">
+ <add-function signature="__str__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ 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);
+ </inject-code>
+ </add-function>
+ <add-function signature="__repr__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ 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("&lt;Point object at %p: (%d.%d, %d.%d)&gt;", %CPPSELF, x1, x2, y1, y2);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="__reduce__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ PyObject* type = PyObject_Type(%PYSELF);
+ PyObject* args = NULL;
+
+ args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y());
+
+ %PYARG_0 = Py_BuildValue("(OO)", type, args);
+ </inject-code>
+ </add-function>
+
+ <modify-function signature="midpoint(const Point&amp;, Point*)const">
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="Point" />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ Point _midpoint;
+ // The test consists in *NOT* using the ARGUMENT_NAMES type system variable.
+ %CPPSELF.%FUNCTION_NAME(%1, &amp;_midpoint);
+ %PYARG_0 = %CONVERTTOPYTHON[Point](_midpoint);
+ </inject-code>
+ </modify-function>
+
+ <template name="return_self">
+ %PYARG_0 = %PYARG_1;
+ Py_INCREF(%PYARG_1);
+ </template>
+ <add-function signature="operator-(PyUnicode)">
+ <inject-code>
+ <insert-template name="return_self" />
+ </inject-code>
+ </add-function>
+ <!-- A reverse operator -->
+ <add-function signature="operator-(PyUnicode, Point)">
+ <inject-code>
+ <insert-template name="return_self" />
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <value-type name="PointF">
+ <add-function signature="__str__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ 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);
+ </inject-code>
+ </add-function>
+ <add-function signature="__repr__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ 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("&lt;PointF object at %p: (%d.%d, %d.%d)&gt;", %CPPSELF, x1, x2, y1, y2);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="__reduce__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ PyObject *type = PyObject_Type(%PYSELF);
+ PyObject *args = NULL;
+
+ args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y());
+
+ %PYARG_0 = Py_BuildValue("(OO)", type, args);
+ </inject-code>
+ </add-function>
+
+ <modify-function signature="midpoint(const PointF&amp;, PointF*)const">
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PointF" />
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ PointF _midpoint;
+ // The test consists in using the ARGUMENT_NAMES type system variable.
+ %CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, &amp;_midpoint);
+ %PYARG_0 = %CONVERTTOPYTHON[PointF](_midpoint);
+ </inject-code>
+ </modify-function>
+ </value-type>
+
+ <value-type name="Rect" />
+ <value-type name="RectF" />
+
+ <value-type name="Polygon">
+ <modify-function signature="stealOwnershipFromPython(Point*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="stealOwnershipFromPython(Polygon*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <value-type name="Time">
+ <extra-includes>
+ <include file-name="datetime.h" location="global"/>
+ </extra-includes>
+ <enum-type name="NumArgs"/>
+ <add-function signature="operator!=(const PyObject*)" return-type="PyObject">
+ <inject-code>
+ 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()) &amp;&amp;
+ (pyM == %CPPSELF.minute()) &amp;&amp;
+ (pyS == %CPPSELF.second()))
+ %PYARG_0 = Py_False;
+ else
+ %PYARG_0 = Py_True;
+ }
+ </inject-code>
+ </add-function>
+ <add-function signature="operator==(const PyObject*)" return-type="PyObject">
+ <inject-code>
+ 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()) &amp;&amp;
+ (pyM == %CPPSELF.minute()) &amp;&amp;
+ (pyS == %CPPSELF.second()))
+ %PYARG_0 = Py_True;
+ else
+ %PYARG_0 = Py_False;
+ }
+ </inject-code>
+ </add-function>
+
+ </value-type>
+ <value-type name="Size">
+ <add-function signature="Size(const char*)">
+ <inject-code class="target" position="beginning">
+ %0 = new %TYPE();
+ </inject-code>
+ <inject-code class="target" position="end">
+ Shiboken::AutoDecRef result(PyObject_CallMethod(%PYSELF, const_cast&lt;char*>("setHeight"), const_cast&lt;char*>("i"), 2));
+ </inject-code>
+ </add-function>
+ </value-type>
+ <value-type name="SizeF"/>
+ <value-type name="MapUser"/>
+ <value-type name="PairUser"/>
+ <value-type name="ListUser">
+ <enum-type name="ListOfSomething"/>
+ </value-type>
+ <value-type name="NoImplicitConversion" />
+ <value-type name="NonDefaultCtor" />
+ <value-type name="OddBoolUser" />
+ <object-type name="Overload">
+ <enum-type name="FunctionEnum"/>
+ <enum-type name="ParamEnum"/>
+ <modify-function signature="intOverloads(int, int, double)">
+ <modify-argument index="2">
+ <remove-argument />
+ </modify-argument>
+ <inject-code class="target">
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1, 2, %3);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </modify-function>
+ <modify-function signature="singleOverload(Point*)">
+ <modify-argument index="1">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="acceptSequence(const char**)">
+ <modify-argument index="1">
+ <replace-type modified-type="PySequence" />
+ <conversion-rule class="native">
+ {
+ 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 &lt; 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;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <modify-function signature="acceptSequence(void*)">
+ <modify-argument index="1">
+ <replace-type modified-type="PyObject" />
+ <conversion-rule class="native">
+ void* %out = 0;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+
+ <template name="buffer_argument">
+ unsigned char* %out = (unsigned char*) Shiboken::Buffer::getPointer(%PYARG_1);
+ </template>
+
+ <modify-function signature="strBufferOverloads(unsigned char*,int)">
+ <modify-argument index="1">
+ <replace-type modified-type="PyBuffer"/>
+ <conversion-rule class="native">
+ <insert-template name="buffer_argument" />
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ <!--
+ This added function simulates the solution given to PySide's QImage
+ constructor problem, as seen in PySide/bbba1cc4, and described in
+ bug #489 [http://bugs.pyside.org/show_bug.cgi?id=489].
+ This is not the best solution, just one that works. The proper way
+ to handle it would be to fix the overload decisor.
+ -->
+ <add-function signature="strBufferOverloads(Str&amp;,int)" return-type="Overload::FunctionEnum">
+ <inject-code class="target" position="beginning">
+ <insert-template name="buffer_argument">
+ <replace from="%out" to="argOut" />
+ </insert-template>
+ %BEGIN_ALLOW_THREADS
+ %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(argOut, %2);
+ %END_ALLOW_THREADS
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </object-type>
+ <object-type name="Overload2" />
+
+ <object-type name="Collector" stream="yes"/>
+
+ <value-type name="IntWrapper" />
+
+ <value-type name="Str" hash-function="strHash">
+ <add-function signature="__str__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = Shiboken::String::fromCString(%CPPSELF.cstring());
+ </inject-code>
+ </add-function>
+ <add-function signature="__len__" >
+ <inject-code class="target" position="end">
+ return %CPPSELF.size();
+ </inject-code>
+ </add-function>
+ <add-function signature="__getitem__" >
+ <inject-code class="target" position="beginning">
+ if (_i &lt; 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);
+ }
+ </inject-code>
+ </add-function>
+ <add-function signature="__setitem__" >
+ <inject-code class="target" position="beginning">
+ 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;
+ </inject-code>
+ </add-function>
+ <modify-function signature="toInt(bool*, int)const">
+ <modify-argument index="1">
+ <remove-argument/>
+ </modify-argument>
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ <insert-template name="boolptr_at_start_and_one_arg_fix_beginning"/>
+ </inject-code>
+ <inject-code class="target" position="end">
+ <insert-template name="boolptr_fix_end"/>
+ </inject-code>
+ </modify-function>
+ </value-type>
+
+ <value-type name="ByteArray" hash-function="ByteArray::hash">
+ <conversion-rule>
+ <target-to-native>
+ <add-conversion type="Py_None">
+ %out = %OUTTYPE();
+ </add-conversion>
+ <add-conversion type="PyObject" check="Shiboken::String::check(%in) || PyBytes_Check(%in)">
+ Py_ssize_t len;
+ const char* str = Shiboken::String::toCString(%in, &amp;len);
+ %out = %OUTTYPE(str, len);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+
+ <modify-function signature="ByteArray(const char*,int)" remove="all" />
+ <modify-function signature="ByteArray(const char*)" remove="all" >
+ <!-- Keep \x00 bytes passed in Python strings. -->
+ <modify-argument index="1">
+ <replace-type modified-type="PyBytes"/>
+ </modify-argument>
+ <inject-code class="target" position="beginning">
+ 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);
+ </inject-code>
+ </modify-function>
+
+ <!-- buffer protocol -->
+ <inject-code class="native" position="beginning" file="bytearray_bufferprotocol.cpp" />
+ <inject-code class="target" position="end">
+ #if PY_VERSION_HEX &lt; 0x03000000
+ Shiboken::SbkType&lt;ByteArray&gt;()->tp_as_buffer = &amp;SbkByteArrayBufferProc;
+ Shiboken::SbkType&lt;ByteArray&gt;()->tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER;
+ #endif
+ </inject-code>
+
+ <modify-function signature="data() const">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = PyBytes_FromStringAndSize(%CPPSELF.%FUNCTION_NAME(), %CPPSELF.size());
+ </inject-code>
+ </modify-function>
+
+ <modify-function signature="hash(const ByteArray&amp;)" remove="all" />
+ <!-- Functions removed to proper deal with strings containing zeroes -->
+ <modify-function signature="append(const char*)" remove="all" />
+ <modify-function signature="append(const char*,int)" remove="all" />
+ <modify-function signature="operator==(const char*,ByteArray)" remove="all" />
+ <modify-function signature="operator==(ByteArray,const char*)" remove="all" />
+ <modify-function signature="operator!=(const char*,ByteArray)" remove="all" />
+ <modify-function signature="operator!=(ByteArray,const char*)" remove="all" />
+ <modify-function signature="operator+(ByteArray,const char*)" remove="all" />
+ <modify-function signature="operator+(const char*,ByteArray)" remove="all" />
+ <modify-function signature="operator+=(const char*)" remove="all" />
+ <modify-function signature="operator[](int)const" remove="all"/>
+
+ <add-function signature="operator+(PyUnicode)" return-type="ByteArray">
+ <inject-code>
+ 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);
+ }
+ </inject-code>
+ </add-function>
+ <add-function signature="operator+(PyUnicode,ByteArray)" return-type="ByteArray">
+ <inject-code>
+ 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);
+ }
+ </inject-code>
+ </add-function>
+ <add-function signature="operator+(PyBytes,ByteArray)">
+ <inject-code>
+ ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1));
+ ba = ba + *%CPPSELF;
+ %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba);
+ </inject-code>
+ </add-function>
+ <add-function signature="operator+(PyBytes)">
+ <inject-code>
+ ByteArray ba(PyBytes_AsString(%PYARG_1), PyBytes_GET_SIZE(%PYARG_1));
+ ba.append(*%CPPSELF);
+ %PYARG_0 = %CONVERTTOPYTHON[ByteArray](ba);
+ </inject-code>
+ </add-function>
+ <add-function signature="__repr__" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ 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());
+ </inject-code>
+ </add-function>
+
+ <add-function signature="__str__" return-type="str">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = Shiboken::String::fromStringAndSize(%CPPSELF.data(), %CPPSELF.size());
+ </inject-code>
+ </add-function>
+
+ <add-function signature="__len__">
+ <inject-code class="target" position="beginning">
+ return %CPPSELF.size();
+ </inject-code>
+ </add-function>
+ <add-function signature="__getitem__">
+ <inject-code class="target" position="beginning">
+ if (_i &lt; 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);
+ }
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <value-type name="StrList">
+ <enum-type name="CtorEnum"/>
+ <add-function signature="__len__" >
+ <inject-code class="target" position="end">
+ return %CPPSELF.size();
+ </inject-code>
+ </add-function>
+ <add-function signature="__getitem__" >
+ <inject-code class="target" position="beginning">
+ if (_i &lt; 0 || _i >= static_cast&lt;Py_ssize_t>(%CPPSELF.size())) {
+ PyErr_BadArgument();
+ return 0;
+ } else {
+ %TYPE::const_iterator it = %CPPSELF.begin();
+ for (Py_ssize_t i = 1; i &lt;= _i; i++)
+ ++it;
+ return %CONVERTTOPYTHON[Str](*it);
+ }
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <value-type name="SimpleFile">
+ <modify-function signature="open()">
+ <modify-argument index="return">
+ <remove-argument/>
+ </modify-argument>
+ <inject-code class="target" position="end" file="simplefile_glue.cpp"/>
+ </modify-function>
+ </value-type>
+
+ <value-type name="VoidHolder">
+ <modify-function signature="gimmeMeSomeVoidPointer()">
+ <modify-argument index="return">
+ <replace-type modified-type="PyObject*"/>
+ </modify-argument>
+ <inject-code class="target" position="end">
+ %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME();
+ %PYARG_0 = Shiboken::Object::newObject(&amp;SbkObject_Type, %0, false, false);
+ </inject-code>
+ </modify-function>
+ </value-type>
+
+ <object-type name="PrivateCtor" />
+ <object-type name="PrivateDtor" />
+
+ <object-type name="Base1"/>
+ <object-type name="Base2"/>
+ <object-type name="Base3"/>
+ <object-type name="Base4"/>
+ <object-type name="Base5"/>
+ <object-type name="Base6"/>
+ <object-type name="MDerived1"/>
+ <object-type name="MDerived2"/>
+ <object-type name="MDerived3"/>
+ <object-type name="MDerived4"/>
+ <object-type name="MDerived5"/>
+ <object-type name="SonOfMDerived1"/>
+
+ <object-type name="Bucket">
+ <modify-function signature="lock()" allow-thread="yes" />
+ <modify-function signature="virtualBlockerMethod()" allow-thread="yes"/>
+ <modify-function signature="callVirtualBlockerMethodButYouDontKnowThis()" allow-thread="yes"/>
+ </object-type>
+
+ <value-type name="Echo">
+ <add-function signature="echo(const char *)" return-type="PyObject*">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = Shiboken::String::fromCString(%1);
+ </inject-code>
+ </add-function>
+ <add-function signature="operator>(int)">
+ <inject-code>
+ // This should test if code injections works inside rich comparison operators
+ Py_INCREF(Py_True);
+ %PYARG_0 = Py_True;
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <value-type name="Color" />
+ <value-type name="Pen">
+ <enum-type identified-by-value="EnumCtor"/>
+ </value-type>
+
+ <value-type name="CtorConvRule">
+ <modify-function signature="CtorConvRule(long)">
+ <modify-argument index="1">
+ <!--<replace-type modified-type="long"/>-->
+ <conversion-rule class="native">
+ // Does nothing really, just test the code generation
+ // of constructors whose arguments where
+ long %out = PyInt_AS_LONG(%PYARG_1) + 1;
+ </conversion-rule>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+
+ <add-function signature="multiplyString(str, unsigned int)" return-type="const char*">
+ <inject-code class="target" position="beginning">
+ %PYARG_0 = Shiboken::String::fromCString("");
+ for (unsigned int i = 0; i &lt; %2; ++i)
+ Shiboken::String::concat(&amp;%PYARG_0, %PYARG_1);
+ </inject-code>
+ </add-function>
+
+ <add-function signature="countVarargs(int, ...)" return-type="int">
+ <inject-code class="target" position="beginning">
+ %RETURN_TYPE %0 = PyTuple_GET_SIZE(%PYARG_2);
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+
+ <value-type name="SbkDate">
+ <extra-includes>
+ <include file-name="datetime.h" location="global"/>
+ </extra-includes>
+ <inject-code class="native" position="beginning">
+ static bool PyDate_ImportAndCheck(PyObject* pyIn) {
+ if (!PyDateTimeAPI)
+ PyDateTime_IMPORT;
+ return PyDate_Check(pyIn);
+ }
+ </inject-code>
+ <conversion-rule>
+ <target-to-native>
+ <add-conversion type="PyDate" check="PyDate_ImportAndCheck(%in)">
+ int day = PyDateTime_GET_DAY(%in);
+ int month = PyDateTime_GET_MONTH(%in);
+ int year = PyDateTime_GET_YEAR(%in);
+ %out = %OUTTYPE(day, month, year);
+ </add-conversion>
+ </target-to-native>
+ </conversion-rule>
+ <add-function signature="toPython()" return-type="PyDate">
+ <inject-code class="target">
+ if (!PyDateTimeAPI)
+ PyDateTime_IMPORT;
+ %PYARG_0 = PyDate_FromDate(%CPPSELF.day(), %CPPSELF.month(), %CPPSELF.year());
+ </inject-code>
+ </add-function>
+ </value-type>
+
+ <object-type name="HandleHolder" />
+ <value-type name="PrimitiveStructPointerHolder" />
+
+ <object-type name="ObjectTypeOperators">
+ <add-function signature="operator!=(std::string)" return-type="bool">
+ <inject-code class="target">
+ %RETURN_TYPE %0 = %CPPSELF.key() != %1;
+ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </object-type>
+
+ <value-type name="Filter" />
+ <value-type name="Data">
+ <enum-type name="Field" />
+ <add-function signature="operator&amp;(const Union&amp;)" return-type="Intersection">
+ <inject-code class="target">
+ %RETURN_TYPE %0 = *%CPPSELF &amp; %1;
+ return %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </value-type>
+ <value-type name="Union">
+ <add-function signature="operator&amp;(const Data&amp;)" return-type="Intersection">
+ <inject-code class="target">
+ %RETURN_TYPE %0 = *%CPPSELF &amp; %1;
+ return %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+ </inject-code>
+ </add-function>
+ </value-type>
+ <value-type name="Intersection" />
+
+ <!-- type used in abstract method -->
+ <object-type name="HideType" generate="no" />
+
+ <value-type name="Expression" />
+
+ <value-type name="ModelIndex" />
+ <value-type name="ReferentModelIndex">
+ <modify-function signature="operator const ModelIndex&amp;()const">
+ <modify-argument index="return">
+ <define-ownership owner="c++"/>
+ </modify-argument>
+ </modify-function>
+ </value-type>
+ <value-type name="PersistentModelIndex" />
+
+ <!-- test rejections using full signatures; this method is a template and
+ cannot be wrapped, but is otherwise recognized by shiboken and will
+ result in a compile error if the rejection is not matched -->
+ <rejection class="Photon::Base" function-name="isType()"/>
+
+ <value-type name="ValueAndVirtual" />
+
+ <object-type name="ObjectTypeByValue" />
+
+ <object-type name="TemplatePtr">
+ <modify-function signature="dummy(std::list&lt;std::pair&lt;BlackBox *, BlackBox *&gt; &gt; &amp;)" rename="dummy_method" />
+ </object-type>
+
+ <suppress-warning text="horribly broken type '__off64_t'" />
+ <suppress-warning text="enum '__codecvt_result' does not have a type entry or is not an enum" />
+ <suppress-warning text="Pure virtual method &quot;Abstract::hideFunction(HideType*)&quot; must be implement but was completely removed on typesystem." />
+ <suppress-warning text="hiding of function 'takeChild' in class 'ObjectType'" />
+ <suppress-warning text="Shadowing: MDerived2::castToBase3() and MDerived3::castToBase3()" />
+ <suppress-warning text="hiding of function 'takeChild' in class 'Bucket'" />
+ <suppress-warning text="visibility of function 'publicMethod' modified in class 'MDerived1'" />
+ <suppress-warning text="hiding of function 'doNothingInPublic3' in class 'Overload2'" />
+ <suppress-warning text="hiding of function 'takeChild' in class 'ObjectModel'" />
+ <suppress-warning text="hiding of function 'takeChild' in class 'ObjectView'" />
+ <suppress-warning text="visibility of function 'publicMethod' modified in class 'MDerived3'" />
+ <suppress-warning text="skipping function 'InjectCode::toStr', unmatched parameter type 'T const&amp;'" />
+
+ <!-- Do not fix this warning, the generator should be able to handle this situation for Object Types. -->
+ <suppress-warning text="Argument in position 1 of added function 'SampleNamespace::passReferenceToObjectType(ObjectType * arg__1)', has a type that is not a reference, while the argument in the corresponding position in C++ function 'SampleNamespace::passReferenceToObjectType(const ObjectType &amp; obj, int multiplier)' is a reference." />
+
+</typesystem>
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 @@
+<?xml version="1.0"?>
+<typesystem package="smart">
+ <primitive-type name="int" />
+ <primitive-type name="char" />
+ <primitive-type name="float" />
+ <primitive-type name="bool" />
+
+ <!-- Used in tests to check what C++ objects are allocated. -->
+ <object-type name="Registry" />
+
+ <!-- Current limitation: shared pointer python objects can only be instantiated from API usage,
+ like when they are returned as a result of a method, or passed as arguments. It is not
+ possible to explicitly instantiate a new shared pointer in python e.g. o = SharedPtr_Foo()
+ won't work.
+ -->
+ <smart-pointer-type name="SharedPtr" type="shared" getter="data" ref-count-method="useCount" />
+
+ <object-type name="Obj" />
+ <value-type name="Integer" />
+
+ <!-- Just used to silence the warnings that shiboken doens't know what to do with this type -->
+ <custom-type name="RefData" />
+</typesystem>
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 <QtTest/QTest>
+#include <QDebug>
+
+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 = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item>\
+ <para>1 1</para>\
+ </item>\
+ <item>\
+ <para>1 2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 1</para>\
+ </item>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ 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 = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item colspan=\"2\">\
+ <para>I'm a big text!</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 1</para>\
+ </item>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ 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 = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item rowspan=\"2\">\
+ <para>1.1</para>\
+ </item>\
+ <item>\
+ <para>1.2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ </row>\
+</table>";
+ 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 = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ <item>\
+ <para>Header 3</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item rowspan=\"2\">\
+ <para>1.1</para>\
+ </item>\
+ <item colspan=\"2\">\
+ <para>1.2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>2 2</para>\
+ </item>\
+ <item>\
+ <para>2 3</para>\
+ </item>\
+ </row>\
+</table>";
+ 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 = "\
+<table>\
+ <header>\
+ <item><para>h1</para></item>\
+ <item><para>h2</para></item>\
+ <item><para>h3</para></item>\
+ <item><para>h4</para></item>\
+ </header>\
+ <row>\
+ <item rowspan=\"6\"><para>A</para></item>\
+ <item rowspan=\"6\"><para>B</para></item>\
+ <item><para>C</para></item>\
+ <item><para>D</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+ <row>\
+ <item><para>E</para></item>\
+ <item><para>F</para></item>\
+ </row>\
+</table>";
+ 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 = "\
+<table>\
+ <header>\
+ <item>\
+ <para>Header 1</para>\
+ </item>\
+ <item>\
+ <para>Header 2</para>\
+ </item>\
+ </header>\
+ <row>\
+ <item>\
+ <para>1.1</para>\
+ </item>\
+ <item>\
+ <para>1.2</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item colspan=\"2\">\
+ <para>2 2</para>\
+ </item>\
+ <item>\
+ <para>2 3</para>\
+ </item>\
+ <item>\
+ <para>2 4</para>\
+ </item>\
+ <item>\
+ <para>2 5</para>\
+ </item>\
+ </row>\
+ <row>\
+ <item>\
+ <para>3 1</para>\
+ </item>\
+ <item>\
+ <para>3 2</para>\
+ </item>\
+ <item>\
+ <para>3 3</para>\
+ </item>\
+ </row>\
+</table>";
+ 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 <QObject>
+
+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..51d2b33da
--- /dev/null
+++ b/sources/shiboken2/tests/test_generator/dummygenerator.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 <iostream>
+#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<QString, QString>& args)
+{
+ if (args.contains("dump-arguments") && !args["dump-arguments"].isEmpty()) {
+ QFile logFile(args["dump-arguments"]);
+ logFile.open(QIODevice::WriteOnly | QIODevice::Text);
+ QTextStream out(&logFile);
+ foreach (const QString& key, args.keys()) {
+ 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<QString, QString>& 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 <QTemporaryFile>
+#include <QtTest/QTest>
+#include <QProcess>
+
+#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 <QObject>
+
+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 <QtCore>
+
+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 @@
+<typesystem package='dummy'>
+ <value-type name='Dummy'/>
+</typesystem>