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.txt90
-rw-r--r--sources/shiboken2/ApiExtractor/COPYING342
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp3459
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.h106
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h194
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp2784
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h1976
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h50
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.cpp317
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractor.h111
-rw-r--r--sources/shiboken2/ApiExtractor/apiextractormacros.h41
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp770
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h58
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp150
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h48
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp266
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangparser.h93
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp227
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangutils.h101
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp155
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/compilersupport.h40
-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/graph.cpp135
-rw-r--r--sources/shiboken2/ApiExtractor/graph.h72
-rw-r--r--sources/shiboken2/ApiExtractor/header_paths.h62
-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/codemodel.cpp1207
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h687
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_enums.h38
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_fwd.h82
-rw-r--r--sources/shiboken2/ApiExtractor/qtdocparser.cpp189
-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.txt74
-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.cpp130
-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.cpp75
-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.cpp117
-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.cpp139
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testreverseoperators.h41
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testtemplates.cpp439
-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.h78
-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.cpp745
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase.h186
-rw-r--r--sources/shiboken2/ApiExtractor/typedatabase_typedefs.h49
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.cpp318
-rw-r--r--sources/shiboken2/ApiExtractor/typeparser.h60
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp2737
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h1975
-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.h49
-rw-r--r--sources/shiboken2/CMakeLists.txt285
-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/generator/CMakeLists.txt40
-rw-r--r--sources/shiboken2/generator/generator.cpp864
-rw-r--r--sources/shiboken2/generator/generator.h448
-rw-r--r--sources/shiboken2/generator/main.cpp552
-rw-r--r--sources/shiboken2/generator/qtdoc/CMakeLists.txt21
-rw-r--r--sources/shiboken2/generator/qtdoc/qtdocgenerator.cpp1715
-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.cpp5755
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.h370
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.cpp569
-rw-r--r--sources/shiboken2/generator/shiboken2/headergenerator.h67
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.cpp1092
-rw-r--r--sources/shiboken2/generator/shiboken2/overloaddata.h163
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.cpp2728
-rw-r--r--sources/shiboken2/generator/shiboken2/shibokengenerator.h556
-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.txt69
-rw-r--r--sources/shiboken2/libshiboken/autodecref.h115
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.cpp1516
-rw-r--r--sources/shiboken2/libshiboken/basewrapper.h451
-rw-r--r--sources/shiboken2/libshiboken/basewrapper_p.h287
-rw-r--r--sources/shiboken2/libshiboken/bindingmanager.cpp341
-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.cpp571
-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.cpp618
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.h118
-rw-r--r--sources/shiboken2/libshiboken/sbkmodule.cpp111
-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.cpp160
-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.cpp82
-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.cpp70
-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
599 files changed, 91828 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..6cb3e0185
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt
@@ -0,0 +1,90 @@
+project(apiextractor)
+
+find_package(LibXml2 2.6.32)
+find_package(LibXslt 1.1.19)
+
+option(DISABLE_DOCSTRINGS "Disable documentation extraction." FALSE)
+
+if (NOT DISABLE_DOCSTRINGS)
+ if (NOT LIBXSLT_FOUND OR NOT LIBXML2_FOUND)
+ set(DISABLE_DOCSTRINGS TRUE CACHE BOOL "Disable doc strings" PARENT_SCOPE)
+ set(DISABLE_DOCSTRINGS TRUE)
+ message(WARNING "libxslt and/or libxml not found, disabling support for doc strings!")
+ endif()
+endif()
+
+if(NOT CMAKE_BUILD_TYPE)
+ set(CMAKE_BUILD_TYPE Release)
+endif()
+
+if(BUILD_TESTS)
+ set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/tests)
+endif ()
+
+set(QT_USE_QTCORE 1)
+set(QT_USE_QTXML 1)
+add_definitions(-DQT_PLUGIN)
+add_definitions(-DQT_SHARED)
+add_definitions(-DRXX_ALLOCATOR_INIT_0)
+
+set(apiextractor_SRC
+apiextractor.cpp
+abstractmetabuilder.cpp
+abstractmetalang.cpp
+fileout.cpp
+graph.cpp
+reporthandler.cpp
+typeparser.cpp
+typesystem.cpp
+include.cpp
+typedatabase.cpp
+# Clang
+clangparser/compilersupport.cpp
+clangparser/clangparser.cpp
+clangparser/clangbuilder.cpp
+clangparser/clangdebugutils.cpp
+clangparser/clangutils.cpp
+# Old parser
+parser/codemodel.cpp
+)
+
+set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES})
+set(APIEXTRACTOR_EXTRA_LIBRARIES ${CLANG_EXTRA_LIBRARIES})
+
+if (NOT DISABLE_DOCSTRINGS)
+ set(apiextractor_SRC
+ ${apiextractor_SRC}
+ docparser.cpp
+ doxygenparser.cpp
+ qtdocparser.cpp
+ )
+ set(APIEXTRACTOR_EXTRA_INCLUDES ${APIEXTRACTOR_EXTRA_INCLUDES} ${LIBXSLT_INCLUDE_DIR} ${LIBXML2_INCLUDE_DIR})
+ set(APIEXTRACTOR_EXTRA_LIBRARIES ${APIEXTRACTOR_EXTRA_LIBRARIES} ${LIBXSLT_LIBRARIES} ${LIBXML2_LIBRARIES})
+endif()
+
+set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
+
+set(CMAKE_AUTOMOC ON)
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_SOURCE_DIR}/parser
+ ${CMAKE_CURRENT_SOURCE_DIR}/parser/rpp
+ ${APIEXTRACTOR_EXTRA_INCLUDES}
+ ${Qt5Core_INCLUDE_DIRS}
+ ${Qt5Xml_INCLUDE_DIRS}
+ )
+
+add_library(apiextractor STATIC ${apiextractor_SRC} ${apiextractor_RCCS_SRC})
+target_link_libraries(apiextractor
+ ${Qt5Xml_LIBRARIES}
+ ${Qt5XmlPatterns_LIBRARIES}
+ ${APIEXTRACTOR_EXTRA_LIBRARIES}
+ )
+
+set_property(TARGET apiextractor PROPERTY CXX_STANDARD 11)
+
+if (BUILD_TESTS)
+ enable_testing()
+ add_subdirectory(tests)
+endif()
diff --git a/sources/shiboken2/ApiExtractor/COPYING b/sources/shiboken2/ApiExtractor/COPYING
new file mode 100644
index 000000000..4ccd71466
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/COPYING
@@ -0,0 +1,342 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <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..3b2ecf8e1
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
@@ -0,0 +1,3459 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractmetabuilder_p.h"
+#include "reporthandler.h"
+#include "typedatabase.h"
+
+#include <clangparser/clangbuilder.h>
+#include <clangparser/clangutils.h>
+
+#include "parser/codemodel.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QRegularExpression>
+#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();
+ const SingleTypeEntryHash entryHash = types->entries();
+
+ for (SingleTypeEntryHash::const_iterator it = entryHash.cbegin(), end = entryHash.cend(); it != end; ++it) {
+ const TypeEntry *entry = it.value();
+ if (!entry)
+ continue;
+ if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
+ continue;
+
+ const ComplexTypeEntry* centry = static_cast<const ComplexTypeEntry*>(entry);
+ FunctionModificationList modifications = centry->functionModifications();
+
+ for (const FunctionModification &modification : qAsConst(modifications)) {
+ QString signature = modification.signature;
+
+ QString name = signature.trimmed();
+ name.truncate(name.indexOf(QLatin1Char('(')));
+
+ AbstractMetaClass *clazz = AbstractMetaClass::findClass(m_metaClasses, centry->qualifiedCppName());
+ if (!clazz)
+ continue;
+
+ const AbstractMetaFunctionList functions = clazz->functions();
+ bool found = false;
+ QStringList possibleSignatures;
+ for (AbstractMetaFunction *function : functions) {
+ if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
+ found = true;
+ break;
+ }
+
+ if (function->originalName() == name) {
+ possibleSignatures.append(function->minimalSignature() + QLatin1String(" in ")
+ + function->implementingClass()->name());
+ }
+ }
+
+ if (!found) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
+ .arg(signature, clazz->qualifiedCppName(), possibleSignatures.join(QLatin1String(", ")));
+ }
+ }
+ }
+}
+
+AbstractMetaClass *AbstractMetaBuilderPrivate::argumentToClass(ArgumentModelItem argument)
+{
+ AbstractMetaClass* returned = 0;
+ bool ok = false;
+ AbstractMetaType* type = translateType(argument->type(), &ok);
+ if (ok && type && type->typeEntry() && type->typeEntry()->isComplex()) {
+ const TypeEntry *entry = type->typeEntry();
+ returned = AbstractMetaClass::findClass(m_metaClasses, entry->name());
+ }
+ delete type;
+ return returned;
+}
+
+AbstractMetaClass *AbstractMetaBuilder::createMetaClass()
+{
+ return new AbstractMetaClass();
+}
+
+AbstractMetaEnum *AbstractMetaBuilder::createMetaEnum()
+{
+ return new AbstractMetaEnum();
+}
+
+AbstractMetaEnumValue *AbstractMetaBuilder::createMetaEnumValue()
+{
+ return new AbstractMetaEnumValue();
+}
+
+AbstractMetaField *AbstractMetaBuilder::createMetaField()
+{
+ return new AbstractMetaField();
+}
+
+AbstractMetaFunction *AbstractMetaBuilder::createMetaFunction()
+{
+ return new AbstractMetaFunction();
+}
+
+AbstractMetaArgument *AbstractMetaBuilder::createMetaArgument()
+{
+ return new AbstractMetaArgument();
+}
+
+AbstractMetaType *AbstractMetaBuilder::createMetaType()
+{
+ return new AbstractMetaType();
+}
+
+/**
+ * Checks the argument of a hash function and flags the type if it is a complex type
+ */
+void AbstractMetaBuilderPrivate::registerHashFunction(FunctionModelItem function_item)
+{
+ ArgumentList arguments = function_item->arguments();
+ if (arguments.size() == 1) {
+ if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
+ cls->setHasHashFunction(true);
+ }
+}
+
+/**
+ * Check if a class has a debug stream operator that can be used as toString
+ */
+
+void AbstractMetaBuilderPrivate::registerToStringCapability(FunctionModelItem function_item)
+{
+ ArgumentList arguments = function_item->arguments();
+ if (arguments.size() == 2) {
+ if (arguments.at(0)->type().toString() == QLatin1String("QDebug")) {
+ ArgumentModelItem arg = arguments.at(1);
+ if (AbstractMetaClass *cls = argumentToClass(arg)) {
+ if (arg->type().indirections() < 2)
+ cls->setToStringCapability(true);
+ }
+ }
+ }
+}
+
+void AbstractMetaBuilderPrivate::traverseOperatorFunction(FunctionModelItem item)
+{
+ if (item->accessPolicy() != CodeModel::Public)
+ return;
+
+ ArgumentList arguments = item->arguments();
+ AbstractMetaClass* baseoperandClass;
+ bool firstArgumentIsSelf = true;
+ bool unaryOperator = false;
+
+ baseoperandClass = argumentToClass(arguments.at(0));
+
+ if (arguments.size() == 1) {
+ unaryOperator = true;
+ } else if (!baseoperandClass
+ || !(baseoperandClass->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)) {
+ baseoperandClass = argumentToClass(arguments.at(1));
+ firstArgumentIsSelf = false;
+ } else {
+ bool ok;
+ AbstractMetaType* type = translateType(item->type(), &ok);
+ const TypeEntry* retType = ok ? type->typeEntry() : 0;
+ AbstractMetaClass* otherArgClass = argumentToClass(arguments.at(1));
+ if (otherArgClass && retType
+ && (retType->isValue() || retType->isObject())
+ && retType != baseoperandClass->typeEntry()
+ && retType == otherArgClass->typeEntry()) {
+ baseoperandClass = AbstractMetaClass::findClass(m_metaClasses, retType);
+ firstArgumentIsSelf = false;
+ }
+ delete type;
+ }
+
+ if (baseoperandClass) {
+ AbstractMetaClass* oldCurrentClass = m_currentClass;
+ m_currentClass = baseoperandClass;
+ AbstractMetaFunction *metaFunction = traverseFunction(item);
+ if (metaFunction && !metaFunction->isInvalid()) {
+ // Strip away first argument, since that is the containing object
+ AbstractMetaArgumentList arguments = metaFunction->arguments();
+ if (firstArgumentIsSelf || unaryOperator) {
+ AbstractMetaArgument* first = arguments.takeFirst();
+ if (!unaryOperator && first->type()->indirections())
+ metaFunction->setPointerOperator(true);
+ delete first;
+ metaFunction->setArguments(arguments);
+ } else {
+ // If the operator method is not unary and the first operator is
+ // not of the same type of its owning class we suppose that it
+ // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)).
+ // All operator overloads that operate over a class are already
+ // being added as member functions of that class by the API Extractor.
+ AbstractMetaArgument* last = arguments.takeLast();
+ if (last->type()->indirections())
+ metaFunction->setPointerOperator(true);
+ delete last;
+
+ metaFunction->setArguments(arguments);
+ metaFunction->setReverseOperator(true);
+ }
+ metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction);
+ metaFunction->setVisibility(AbstractMetaFunction::Public);
+ metaFunction->setOriginalAttributes(metaFunction->attributes());
+ setupFunctionDefaults(metaFunction, baseoperandClass);
+ baseoperandClass->addFunction(metaFunction);
+ Q_ASSERT(!metaFunction->wasPrivate());
+ } else if (metaFunction) {
+ delete metaFunction;
+ }
+
+ m_currentClass = oldCurrentClass;
+ }
+}
+
+void AbstractMetaBuilderPrivate::traverseStreamOperator(FunctionModelItem item)
+{
+ ArgumentList arguments = item->arguments();
+ if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
+ AbstractMetaClass* streamClass = argumentToClass(arguments.at(0));
+ AbstractMetaClass* streamedClass = argumentToClass(arguments.at(1));
+
+ if (streamClass && streamedClass && (streamClass->isStream())) {
+ AbstractMetaClass *oldCurrentClass = m_currentClass;
+ m_currentClass = streamedClass;
+ AbstractMetaFunction *streamFunction = traverseFunction(item);
+
+ if (streamFunction && !streamFunction->isInvalid()) {
+ QString name = item->name();
+ streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
+ // Strip first argument, since that is the containing object
+ AbstractMetaArgumentList arguments = streamFunction->arguments();
+ if (!streamClass->typeEntry()->generateCode())
+ delete arguments.takeLast();
+ else
+ delete arguments.takeFirst();
+
+ streamFunction->setArguments(arguments);
+
+ *streamFunction += AbstractMetaAttributes::Final;
+ *streamFunction += AbstractMetaAttributes::Public;
+ streamFunction->setOriginalAttributes(streamFunction->attributes());
+
+// streamFunction->setType(0);
+
+ AbstractMetaClass *funcClass;
+
+ if (!streamClass->typeEntry()->generateCode()) {
+ AbstractMetaArgumentList reverseArgs = reverseList(streamFunction->arguments());
+ streamFunction->setArguments(reverseArgs);
+ streamFunction->setReverseOperator(true);
+ funcClass = streamedClass;
+ } else {
+ funcClass = streamClass;
+ }
+
+ setupFunctionDefaults(streamFunction, funcClass);
+ funcClass->addFunction(streamFunction);
+ if (funcClass == streamClass)
+ funcClass->typeEntry()->addExtraInclude(streamedClass->typeEntry()->include());
+ else
+ funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
+
+ m_currentClass = oldCurrentClass;
+ } else if (streamFunction) {
+ delete streamFunction;
+ }
+
+ }
+ }
+}
+
+void AbstractMetaBuilderPrivate::fixQObjectForScope(const FileModelItem &dom,
+ const TypeDatabase *types,
+ const NamespaceModelItem &scope)
+{
+ const ClassList &scopeClasses = scope->classes();
+ for (const ClassModelItem &item : scopeClasses) {
+ QString qualifiedName = item->qualifiedName().join(colonColon());
+ TypeEntry* entry = types->findType(qualifiedName);
+ if (entry) {
+ if (isQObject(dom, qualifiedName) && entry->isComplex())
+ ((ComplexTypeEntry*) entry)->setQObject(true);
+ }
+ }
+
+ const NamespaceList &namespaces = scope->namespaces();
+ for (const NamespaceModelItem &n : namespaces) {
+ if (scope != n)
+ fixQObjectForScope(dom, types, n);
+ }
+}
+
+void AbstractMetaBuilderPrivate::sortLists()
+{
+ for (AbstractMetaClass *cls : qAsConst(m_metaClasses))
+ cls->sortFunctions();
+}
+
+FileModelItem AbstractMetaBuilderPrivate::buildDom(const QByteArrayList &arguments,
+ unsigned clangFlags)
+{
+ clang::Builder builder;
+ FileModelItem result = clang::parse(arguments, clangFlags, builder)
+ ? builder.dom() : FileModelItem();
+ const clang::BaseVisitor::Diagnostics &diagnostics = builder.diagnostics();
+ if (const int diagnosticsCount = diagnostics.size()) {
+ QDebug d = qWarning();
+ d.nospace();
+ d.noquote();
+ d << "Clang: " << diagnosticsCount << " diagnostic messages:\n";
+ for (int i = 0; i < diagnosticsCount; ++i)
+ d << " " << diagnostics.at(i) << '\n';
+ }
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom)
+{
+ const TypeDatabase *types = TypeDatabase::instance();
+
+ pushScope(dom);
+
+ // fix up QObject's in the type system..
+ fixQObjectForScope(dom, types, dom);
+
+ // Start the generation...
+ const ClassList &typeValues = dom->classes();
+ ReportHandler::setProgressReference(typeValues);
+ for (const ClassModelItem &item : typeValues) {
+ ReportHandler::progress(QLatin1String("Generating class model..."));
+ AbstractMetaClass *cls = traverseClass(dom, item);
+ if (!cls)
+ continue;
+
+ addAbstractMetaClass(cls);
+ }
+
+ // We need to know all global enums
+ const EnumList &enums = dom->enums();
+ ReportHandler::setProgressReference(enums);
+ for (const EnumModelItem &item : enums) {
+ ReportHandler::progress(QLatin1String("Generating enum model..."));
+ AbstractMetaEnum *metaEnum = traverseEnum(item, 0, QSet<QString>());
+ if (metaEnum) {
+ if (metaEnum->typeEntry()->generateCode())
+ m_globalEnums << metaEnum;
+ }
+ }
+
+ const QSet<NamespaceModelItem> &namespaceTypeValues = dom->uniqueNamespaces();
+ ReportHandler::setProgressReference(namespaceTypeValues);
+ for (NamespaceModelItem item : namespaceTypeValues) {
+ ReportHandler::progress(QLatin1String("Generating namespace model..."));
+ AbstractMetaClass *metaClass = traverseNamespace(dom, item);
+ if (metaClass)
+ m_metaClasses << metaClass;
+ }
+
+ // Go through all typedefs to see if we have defined any
+ // specific typedefs to be used as classes.
+ const TypeDefList typeDefs = dom->typeDefs();
+ ReportHandler::setProgressReference(typeDefs);
+ for (const TypeDefModelItem &typeDef : typeDefs) {
+ ReportHandler::progress(QLatin1String("Resolving typedefs..."));
+ AbstractMetaClass* cls = traverseTypeDef(dom, typeDef);
+ addAbstractMetaClass(cls);
+ }
+
+ figureOutEnumValues();
+
+ for (const ClassModelItem &item : typeValues)
+ traverseClassMembers(item);
+
+ for (const NamespaceModelItem &item : namespaceTypeValues)
+ traverseNamespaceMembers(item);
+
+ // Global functions
+ const FunctionList &functions = dom->functions();
+ for (const FunctionModelItem &func : functions) {
+ if (func->accessPolicy() != CodeModel::Public || func->name().startsWith(QLatin1String("operator")))
+ continue;
+
+ FunctionTypeEntry* funcEntry = types->findFunctionType(func->name());
+ if (!funcEntry || !funcEntry->generateCode())
+ continue;
+
+ AbstractMetaFunction* metaFunc = traverseFunction(func);
+ if (!metaFunc)
+ continue;
+
+ if (!funcEntry->hasSignature(metaFunc->minimalSignature())) {
+ delete metaFunc;
+ continue;
+ }
+
+ applyFunctionModifications(metaFunc);
+
+ setInclude(funcEntry, func->fileName());
+ if (metaFunc->typeEntry())
+ delete metaFunc->typeEntry();
+
+ metaFunc->setTypeEntry(funcEntry);
+ m_globalFunctions << metaFunc;
+ }
+
+ ReportHandler::setProgressReference(m_metaClasses);
+ for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ ReportHandler::progress(QLatin1String("Fixing class inheritance..."));
+ if (!cls->isInterface() && !cls->isNamespace())
+ setupInheritance(cls);
+ }
+
+ ReportHandler::setProgressReference(m_metaClasses);
+ for (AbstractMetaClass *cls : qAsConst(m_metaClasses)) {
+ ReportHandler::progress(QLatin1String("Detecting inconsistencies in class model..."));
+ cls->fixFunctions();
+
+ if (!cls->typeEntry()) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("class '%1' does not have an entry in the type system")
+ .arg(cls->name());
+ } else {
+ bool couldAddDefaultCtors = !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace();
+ if (couldAddDefaultCtors) {
+ if (!cls->hasConstructors())
+ cls->addDefaultConstructor();
+ if (cls->typeEntry()->isValue() && !cls->isAbstract() && !cls->hasCopyConstructor())
+ cls->addDefaultCopyConstructor(ancestorHasPrivateCopyConstructor(cls));
+ }
+ }
+
+ if (cls->isAbstract() && !cls->isInterface())
+ cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + QLatin1String("$ConcreteWrapper"));
+ }
+ const TypeEntryHash allEntries = types->allEntries();
+ ReportHandler::progress(QLatin1String("Detecting inconsistencies in typesystem..."));
+ for (TypeEntryHash::const_iterator it = allEntries.cbegin(), end = allEntries.cend(); it != end; ++it) {
+ for (TypeEntry *entry : it.value()) {
+ if (entry->isPrimitive())
+ continue;
+
+ if ((entry->isValue() || entry->isObject())
+ && !entry->isString()
+ && !entry->isChar()
+ && !entry->isContainer()
+ && !entry->isCustom()
+ && !entry->isVariant()
+ && !AbstractMetaClass::findClass(m_metaClasses, entry->qualifiedCppName())) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
+ .arg(entry->qualifiedCppName());
+ } else if (entry->generateCode() && entry->type() == TypeEntry::FunctionType) {
+ const FunctionTypeEntry* fte = static_cast<const FunctionTypeEntry*>(entry);
+ const QStringList &signatures = fte->signatures();
+ for (const QString &signature : signatures) {
+ bool ok = false;
+ for (AbstractMetaFunction* func : qAsConst(m_globalFunctions)) {
+ if (signature == func->minimalSignature()) {
+ ok = true;
+ break;
+ }
+ }
+ if (!ok) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("Global function '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
+ .arg(signature);
+ }
+ }
+ } else if (entry->isEnum()) {
+ const QString name = ((EnumTypeEntry*) entry)->targetLangQualifier();
+ AbstractMetaClass *cls = AbstractMetaClass::findClass(m_metaClasses, name);
+
+ bool enumFound = false;
+ if (cls) {
+ enumFound = cls->findEnum(entry->targetLangName());
+ } else { // Global enum
+ for (AbstractMetaEnum *metaEnum : qAsConst(m_enums)) {
+ if (metaEnum->typeEntry() == entry) {
+ enumFound = true;
+ break;
+ }
+ }
+ }
+ if (!enumFound) {
+ entry->setCodeGeneration(TypeEntry::GenerateNothing);
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("enum '%1' is specified in typesystem, but not declared")
+ .arg(entry->qualifiedCppName());
+ }
+
+ }
+ }
+ }
+
+ {
+ const FunctionList &hashFunctions = dom->findFunctions(QLatin1String("qHash"));
+ for (const FunctionModelItem &item : hashFunctions)
+ registerHashFunction(item);
+ }
+
+ {
+ const FunctionList &streamOps = dom->findFunctions(QLatin1String("operator<<"));
+ for (const FunctionModelItem &item : streamOps)
+ registerToStringCapability(item);
+ }
+
+ {
+ FunctionList binaryOperators = dom->findFunctions(QStringLiteral("operator=="));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator!=")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator<=")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator>=")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator<")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator+")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator/")));
+ // Filter binary operators, skipping for example
+ // class Iterator { ... Value *operator*() ... };
+ const FunctionList potentiallyBinaryOperators =
+ dom->findFunctions(QStringLiteral("operator*"))
+ + dom->findFunctions(QStringLiteral("operator&"));
+ for (const FunctionModelItem &item : potentiallyBinaryOperators) {
+ if (!item->arguments().isEmpty())
+ binaryOperators.append(item);
+ }
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator-")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator&")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator|")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator^")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator~")));
+ binaryOperators.append(dom->findFunctions(QStringLiteral("operator>")));
+
+ for (const FunctionModelItem &item : qAsConst(binaryOperators))
+ traverseOperatorFunction(item);
+ }
+
+ {
+ const FunctionList streamOperators = dom->findFunctions(QLatin1String("operator<<"))
+ + dom->findFunctions(QLatin1String("operator>>"));
+ for (const FunctionModelItem &item : streamOperators)
+ traverseStreamOperator(item);
+ }
+
+ figureOutDefaultEnumArguments();
+ checkFunctionModifications();
+
+ // sort all classes topologically
+ m_metaClasses = classesTopologicalSorted();
+
+ for (AbstractMetaClass* cls : qAsConst(m_metaClasses)) {
+// setupEquals(cls);
+// setupComparable(cls);
+ setupClonable(cls);
+ setupExternalConversion(cls);
+
+ // sort all inner classes topologically
+ if (!cls->typeEntry()->codeGeneration() || cls->innerClasses().size() < 2)
+ continue;
+
+ cls->setInnerClasses(classesTopologicalSorted(cls));
+ }
+
+ dumpLog();
+
+ sortLists();
+
+ m_currentClass = 0;
+
+ // Functions added to the module on the type system.
+ const AddedFunctionList &globalUserFunctions = types->globalUserFunctions();
+ for (const AddedFunction &addedFunc : globalUserFunctions) {
+ AbstractMetaFunction* metaFunc = traverseFunction(addedFunc);
+ metaFunc->setFunctionType(AbstractMetaFunction::NormalFunction);
+ m_globalFunctions << metaFunc;
+ }
+
+ std::puts("");
+}
+
+bool AbstractMetaBuilder::build(const QByteArrayList &arguments, unsigned clangFlags)
+{
+ const FileModelItem dom = d->buildDom(arguments, clangFlags);
+ if (dom.isNull())
+ return false;
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug))
+ qCDebug(lcShiboken) << dom.data();
+ d->traverseDom(dom);
+ return true;
+}
+
+void AbstractMetaBuilder::setLogDirectory(const QString& logDir)
+{
+ d->m_logDirectory = logDir;
+ if (!d->m_logDirectory.endsWith(QDir::separator()))
+ d->m_logDirectory.append(QDir::separator());
+}
+
+void AbstractMetaBuilderPrivate::addAbstractMetaClass(AbstractMetaClass *cls)
+{
+ if (!cls)
+ return;
+
+ cls->setOriginalAttributes(cls->attributes());
+ if (cls->typeEntry()->isContainer()) {
+ m_templates << cls;
+ } else if (cls->typeEntry()->isSmartPointer()) {
+ m_smartPointers << cls;
+ } else {
+ m_metaClasses << cls;
+ if (cls->typeEntry()->designatedInterface()) {
+ AbstractMetaClass* interface = cls->extractInterface();
+ m_metaClasses << interface;
+ if (ReportHandler::isDebug(ReportHandler::SparseDebug))
+ qCDebug(lcShiboken) << QStringLiteral(" -> interface '%1'").arg(interface->name());
+ }
+ }
+}
+
+AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModelItem &dom,
+ const NamespaceModelItem &namespaceItem)
+{
+ QString namespaceName =
+ (!m_namespacePrefix.isEmpty() ? m_namespacePrefix + colonColon() : QString())
+ + namespaceItem->name();
+ NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespaceName);
+
+ if (TypeDatabase::instance()->isClassRejected(namespaceName)) {
+ m_rejectedClasses.insert(namespaceName, AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+
+ if (!type) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("namespace '%1' does not have a type entry").arg(namespaceName);
+ return 0;
+ }
+
+ AbstractMetaClass* metaClass = q->createMetaClass();
+ metaClass->setTypeEntry(type);
+
+ *metaClass += AbstractMetaAttributes::Public;
+
+ m_currentClass = metaClass;
+
+ if (ReportHandler::isDebug(ReportHandler::SparseDebug)) {
+ qCDebug(lcShiboken)
+ << QStringLiteral("namespace '%1.%2'").arg(metaClass->package(), namespaceItem->name());
+ }
+
+ traverseEnums(namespaceItem, metaClass, namespaceItem->enumsDeclarations());
+
+ pushScope(namespaceItem);
+ m_namespacePrefix = currentScope()->qualifiedName().join(colonColon());
+
+ const ClassList &classes = namespaceItem->classes();
+ for (const ClassModelItem &cls : classes) {
+ AbstractMetaClass* mjc = traverseClass(dom, cls);
+ if (mjc) {
+ metaClass->addInnerClass(mjc);
+ mjc->setEnclosingClass(metaClass);
+ addAbstractMetaClass(mjc);
+ }
+ }
+
+ // Go through all typedefs to see if we have defined any
+ // specific typedefs to be used as classes.
+ const TypeDefList typeDefs = namespaceItem->typeDefs();
+ for (const TypeDefModelItem &typeDef : typeDefs) {
+ AbstractMetaClass *cls = traverseTypeDef(dom, typeDef);
+ if (cls) {
+ metaClass->addInnerClass(cls);
+ cls->setEnclosingClass(metaClass);
+ addAbstractMetaClass(cls);
+ }
+ }
+
+ // Traverse namespaces recursively
+ const QSet<NamespaceModelItem> &innerNamespaces = namespaceItem->uniqueNamespaces();
+ for (const NamespaceModelItem &ni : innerNamespaces) {
+ AbstractMetaClass* mjc = traverseNamespace(dom, ni);
+ if (mjc) {
+ metaClass->addInnerClass(mjc);
+ mjc->setEnclosingClass(metaClass);
+ addAbstractMetaClass(mjc);
+ }
+ }
+
+ m_currentClass = 0;
+
+ popScope();
+ m_namespacePrefix = currentScope()->qualifiedName().join(colonColon());
+
+ if (!type->include().isValid())
+ setInclude(type, namespaceItem->fileName());
+
+ return metaClass;
+}
+
+struct Operator
+{
+ enum Type { Complement, Plus, ShiftRight, ShiftLeft, None };
+
+ Operator() : type(None) {}
+
+ int calculate(int x)
+ {
+ switch (type) {
+ case Complement: return ~value;
+ case Plus: return x + value;
+ case ShiftRight: return x >> value;
+ case ShiftLeft: return x << value;
+ case None: return x;
+ }
+ return x;
+ }
+
+ Type type;
+ int value;
+};
+
+
+
+Operator findOperator(QString* s)
+{
+ const char *names[] = {
+ "~",
+ "+",
+ ">>",
+ "<<"
+ };
+
+ for (int i = 0; i < Operator::None; ++i) {
+ QString name = QLatin1String(names[i]);
+ QString str = *s;
+ int splitPoint = str.indexOf(name);
+ if (splitPoint > -1) {
+ bool ok;
+ QString right = str.mid(splitPoint + name.length());
+ Operator op;
+
+ op.value = right.toInt(&ok);
+ if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u'))
+ op.value = right.left(right.length() - 1).toUInt(&ok, 0);
+
+ if (ok) {
+ op.type = Operator::Type(i);
+ if (splitPoint > 0)
+ *s = str.left(splitPoint).trimmed();
+ else
+ *s = QString();
+ return op;
+ }
+ }
+ }
+ return Operator();
+}
+
+int AbstractMetaBuilderPrivate::figureOutEnumValue(const QString &stringValue,
+ int oldValuevalue,
+ AbstractMetaEnum *metaEnum,
+ AbstractMetaFunction *metaFunction)
+{
+ if (stringValue.isEmpty())
+ return oldValuevalue;
+
+ QStringList stringValues = stringValue.split(QLatin1Char('|'));
+
+ int returnValue = 0;
+
+ bool matched = false;
+
+ for (int i = 0; i < stringValues.size(); ++i) {
+ QString s = stringValues.at(i).trimmed();
+
+ bool ok;
+ int v;
+
+ Operator op = findOperator(&s);
+
+ if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
+ v = s.toUInt(&ok, 0);
+ else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u'))
+ v = s.left(s.length() - 1).toUInt(&ok, 0);
+ else
+ v = s.toInt(&ok);
+
+ if (ok || s.isEmpty()) {
+ matched = true;
+ } else if (m_enumValues.contains(s)) {
+ v = m_enumValues[s]->value();
+ matched = true;
+ } else {
+ if (metaEnum) {
+ v = findOutValueFromString(s, matched);
+ if (!matched) {
+ QString enclosingClass = QString(metaEnum->enclosingClass() ? metaEnum->enclosingClass()->name() + colonColon() : QString());
+ qCWarning(lcShiboken).noquote().nospace()
+ << "unhandled enum value: " << s << " in "
+ << enclosingClass << metaEnum->name() << " from header '"
+ << metaEnum->typeEntry()->include().name() << '\'';
+ }
+ } else {
+ qCWarning(lcShiboken) << "unhandled enum value: Unknown enum";
+ }
+ }
+
+ if (matched)
+ returnValue |= op.calculate(v);
+ }
+
+ if (!matched) {
+ QString warn = QStringLiteral("unmatched enum %1").arg(stringValue);
+
+ if (metaFunction) {
+ warn += QStringLiteral(" when parsing default value of '%1' in class '%2'")
+ .arg(metaFunction->name(), metaFunction->implementingClass()->name());
+ }
+ warn += QLatin1String(" from header '") + metaEnum->typeEntry()->include().name()
+ + QLatin1Char('\'');
+
+ qCWarning(lcShiboken).noquote().nospace() << warn;
+ returnValue = oldValuevalue;
+ }
+
+ return returnValue;
+}
+
+void AbstractMetaBuilderPrivate::figureOutEnumValuesForClass(AbstractMetaClass *metaClass,
+ QSet<AbstractMetaClass *> *classes)
+{
+ AbstractMetaClass* base = metaClass->baseClass();
+
+ if (base && !classes->contains(base))
+ figureOutEnumValuesForClass(base, classes);
+
+ if (classes->contains(metaClass))
+ return;
+
+ const AbstractMetaEnumList &enums = metaClass->enums();
+ for (AbstractMetaEnum* e : enums) {
+ if (!e) {
+ qCWarning(lcShiboken).noquote().nospace() << "bad enum in class " << metaClass->name();
+ continue;
+ }
+ AbstractMetaEnumValueList lst = e->values();
+ int value = 0;
+ for (int i = 0; i < lst.size(); ++i) {
+ value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
+ lst.at(i)->setValue(value);
+ value++;
+ }
+ }
+
+ *classes += metaClass;
+}
+
+
+void AbstractMetaBuilderPrivate::figureOutEnumValues()
+{
+ // Keep a set of classes that we already traversed. We use this to
+ // enforce that we traverse base classes prior to subclasses.
+ QSet<AbstractMetaClass*> classes;
+ for (AbstractMetaClass *c : qAsConst(m_metaClasses))
+ figureOutEnumValuesForClass(c, &classes);
+
+ for (AbstractMetaEnum* metaEnum : qAsConst(m_globalEnums)) {
+ AbstractMetaEnumValueList enumValues = metaEnum->values();
+ int value = 0;
+ for (int i = 0; i < enumValues.size(); ++i) {
+ value = figureOutEnumValue(enumValues.at(i)->stringValue(), value, metaEnum);
+ enumValues.at(i)->setValue(value);
+ value++;
+ }
+ }
+}
+
+void AbstractMetaBuilderPrivate::figureOutDefaultEnumArguments()
+{
+ for (AbstractMetaClass* metaClass : qAsConst(m_metaClasses)) {
+ const AbstractMetaFunctionList &functions = metaClass->functions();
+ for (AbstractMetaFunction* metaFunction : functions) {
+ const AbstractMetaArgumentList &arguments = metaFunction->arguments();
+ for (AbstractMetaArgument *arg : arguments) {
+ QString expr = arg->defaultValueExpression();
+ if (expr.isEmpty())
+ continue;
+
+ if (!metaFunction->replacedDefaultExpression(metaFunction->implementingClass(),
+ arg->argumentIndex() + 1).isEmpty()) {
+ continue;
+ }
+
+ arg->setDefaultValueExpression(expr);
+ }
+ }
+ }
+}
+
+
+AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem,
+ AbstractMetaClass *enclosing,
+ const QSet<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();
+ const EnumeratorList &enums = enumItem->enumerators();
+ for (const EnumeratorModelItem& enumValue : enums) {
+ tmpQualifiedName.removeLast();
+ tmpQualifiedName << enumValue->name();
+ qualifiedName = tmpQualifiedName.join(colonColon());
+ typeEntry = TypeDatabase::instance()->findType(qualifiedName);
+ if (typeEntry)
+ break;
+ }
+ }
+
+ QString enumName = enumItem->name();
+
+ QString className;
+ if (m_currentClass)
+ className = m_currentClass->typeEntry()->qualifiedCppName();
+
+ QString rejectReason;
+ if (TypeDatabase::instance()->isEnumRejected(className, enumName, &rejectReason)) {
+ if (typeEntry)
+ typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
+ m_rejectedEnums.insert(qualifiedName + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+
+ if (!typeEntry || !typeEntry->isEnum()) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("enum '%1' does not have a type entry or is not an enum")
+ .arg(qualifiedName);
+ m_rejectedEnums.insert(qualifiedName, AbstractMetaBuilder::NotInTypeSystem);
+ return 0;
+ }
+
+ AbstractMetaEnum *metaEnum = q->createMetaEnum();
+ if (enumsDeclarations.contains(qualifiedName)
+ || enumsDeclarations.contains(enumName)) {
+ metaEnum->setHasQEnumsDeclaration(true);
+ }
+
+ metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry);
+ switch (enumItem->accessPolicy()) {
+ case CodeModel::Public:
+ *metaEnum += AbstractMetaAttributes::Public;
+ break;
+ case CodeModel::Protected:
+ *metaEnum += AbstractMetaAttributes::Protected;
+ break;
+ case CodeModel::Private:
+ *metaEnum += AbstractMetaAttributes::Private;
+ typeEntry->setCodeGeneration(TypeEntry::GenerateNothing);
+ break;
+ default:
+ break;
+ }
+
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug))
+ qCDebug(lcShiboken) << " - traversing enum " << metaEnum->fullName();
+
+ const EnumeratorList &enums = enumItem->enumerators();
+ for (const EnumeratorModelItem &value : enums) {
+
+ AbstractMetaEnumValue *metaEnumValue = q->createMetaEnumValue();
+ metaEnumValue->setName(value->name());
+ // Deciding the enum value...
+
+ metaEnumValue->setStringValue(value->value());
+ metaEnum->addEnumValue(metaEnumValue);
+
+ if (ReportHandler::isDebug(ReportHandler::FullDebug)) {
+ qCDebug(lcShiboken) << " - " << metaEnumValue->name() << " = "
+ << metaEnumValue->value() << " = " << metaEnumValue->value();
+ }
+
+ // Add into global register...
+ if (enclosing)
+ m_enumValues[enclosing->name() + colonColon() + metaEnumValue->name()] = metaEnumValue;
+ else
+ m_enumValues[metaEnumValue->name()] = metaEnumValue;
+ }
+
+ m_enums << metaEnum;
+
+ if (!metaEnum->typeEntry()->include().isValid())
+ setInclude(metaEnum->typeEntry(), enumItem->fileName());
+
+ metaEnum->setOriginalAttributes(metaEnum->attributes());
+
+ // Register all enum values on Type database
+ const EnumeratorList &enumerators = enumItem->enumerators();
+ for (EnumeratorModelItem e : enumItem->enumerators()) {
+ QString name;
+ if (enclosing) {
+ name += enclosing->name();
+ name += colonColon();
+ }
+ name += e->name();
+ EnumValueTypeEntry* enumValue = new EnumValueTypeEntry(name, e->value(), static_cast<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();
+ QVector<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();
+ for (const ClassModelItem &ci : innerClasses) {
+ AbstractMetaClass *cl = traverseClass(dom, ci);
+ if (cl) {
+ cl->setEnclosingClass(metaClass);
+ metaClass->addInnerClass(cl);
+ m_metaClasses << cl;
+ }
+ }
+
+ }
+
+ // Go through all typedefs to see if we have defined any
+ // specific typedefs to be used as classes.
+ const TypeDefList typeDefs = classItem->typeDefs();
+ for (const TypeDefModelItem &typeDef : typeDefs) {
+ AbstractMetaClass *cls = traverseTypeDef(dom, typeDef);
+ if (cls) {
+ cls->setEnclosingClass(metaClass);
+ addAbstractMetaClass(cls);
+ }
+ }
+
+
+ m_currentClass = oldCurrentClass;
+
+ // Set the default include file name
+ if (!type->include().isValid())
+ setInclude(type, classItem->fileName());
+
+ return metaClass;
+}
+
+void AbstractMetaBuilderPrivate::traverseScopeMembers(ScopeModelItem item,
+ AbstractMetaClass *metaClass)
+{
+ // Classes/Namespace members
+ traverseFields(item, metaClass);
+ traverseFunctions(item, metaClass);
+
+ // Inner classes
+ const ClassList &innerClasses = item->classes();
+ for (const ClassModelItem& ci : innerClasses)
+ traverseClassMembers(ci);
+}
+
+AbstractMetaClass* AbstractMetaBuilderPrivate::currentTraversedClass(ScopeModelItem item)
+{
+ QString className = stripTemplateArgs(item->name());
+ QString fullClassName = className;
+
+ // This is an inner class
+ if (m_currentClass)
+ fullClassName = stripTemplateArgs(m_currentClass->typeEntry()->qualifiedCppName()) + colonColon() + fullClassName;
+
+ AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, fullClassName);
+ if (!metaClass)
+ metaClass = AbstractMetaClass::findClass(m_templates, fullClassName);
+
+ if (!metaClass)
+ metaClass = AbstractMetaClass::findClass(m_smartPointers, fullClassName);
+ return metaClass;
+}
+
+void AbstractMetaBuilderPrivate::traverseClassMembers(ClassModelItem item)
+{
+ AbstractMetaClass* metaClass = currentTraversedClass(item);
+ if (!metaClass)
+ return;
+
+ AbstractMetaClass* oldCurrentClass = m_currentClass;
+ m_currentClass = metaClass;
+
+ // Class members
+ traverseScopeMembers(item, metaClass);
+
+ m_currentClass = oldCurrentClass;
+}
+
+void AbstractMetaBuilderPrivate::traverseNamespaceMembers(NamespaceModelItem item)
+{
+ AbstractMetaClass* metaClass = currentTraversedClass(item);
+ if (!metaClass)
+ return;
+
+ AbstractMetaClass* oldCurrentClass = m_currentClass;
+ m_currentClass = metaClass;
+
+ // Namespace members
+ traverseScopeMembers(item, metaClass);
+
+ // Inner namespaces
+ const QSet<NamespaceModelItem> &innerNamespaces = item->uniqueNamespaces();
+ for (const NamespaceModelItem &ni : innerNamespaces)
+ traverseNamespaceMembers(ni);
+
+ m_currentClass = oldCurrentClass;
+}
+
+static inline QString fieldSignatureWithType(VariableModelItem field)
+{
+ return field->name() + QStringLiteral(" -> ") + field->type().toString();
+}
+
+static inline QString qualifiedFieldSignatureWithType(const QString &className,
+ VariableModelItem field)
+{
+ return className + colonColon() + fieldSignatureWithType(field);
+}
+
+AbstractMetaField *AbstractMetaBuilderPrivate::traverseField(VariableModelItem field,
+ const AbstractMetaClass *cls)
+{
+ QString fieldName = field->name();
+ QString className = m_currentClass->typeEntry()->qualifiedCppName();
+
+ // Ignore friend decl.
+ if (field->isFriend())
+ return 0;
+
+ if (field->accessPolicy() == CodeModel::Private)
+ return 0;
+
+ QString rejectReason;
+ if (TypeDatabase::instance()->isFieldRejected(className, fieldName, &rejectReason)) {
+ m_rejectedFields.insert(qualifiedFieldSignatureWithType(className, field) + rejectReason,
+ AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+
+
+ AbstractMetaField *metaField = q->createMetaField();
+ metaField->setName(fieldName);
+ metaField->setEnclosingClass(cls);
+
+ bool ok;
+ TypeInfo fieldType = field->type();
+ AbstractMetaType *metaType = translateType(fieldType, &ok);
+
+ if (!metaType || !ok) {
+ const QString type = TypeInfo::resolveType(fieldType, currentScope()).qualifiedName().join(colonColon());
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("skipping field '%1::%2' with unmatched type '%3'")
+ .arg(m_currentClass->name(), fieldName, type);
+ delete metaField;
+ return 0;
+ }
+
+ metaField->setType(metaType);
+
+ AbstractMetaAttributes::Attributes attr = 0;
+ if (field->isStatic())
+ attr |= AbstractMetaAttributes::Static;
+
+ CodeModel::AccessPolicy policy = field->accessPolicy();
+ if (policy == CodeModel::Public)
+ attr |= AbstractMetaAttributes::Public;
+ else if (policy == CodeModel::Protected)
+ attr |= AbstractMetaAttributes::Protected;
+ else
+ attr |= AbstractMetaAttributes::Private;
+ metaField->setAttributes(attr);
+
+ return metaField;
+}
+
+void AbstractMetaBuilderPrivate::traverseFields(ScopeModelItem scope_item,
+ AbstractMetaClass *metaClass)
+{
+ const VariableList &variables = scope_item->variables();
+ for (const VariableModelItem &field : variables) {
+ AbstractMetaField* metaField = traverseField(field, metaClass);
+
+ if (metaField && !metaField->isModifiedRemoved()) {
+ metaField->setOriginalAttributes(metaField->attributes());
+ metaClass->addField(metaField);
+ }
+ }
+}
+
+void AbstractMetaBuilderPrivate::setupFunctionDefaults(AbstractMetaFunction *metaFunction,
+ AbstractMetaClass *metaClass)
+{
+ // Set the default value of the declaring class. This may be changed
+ // in fixFunctions later on
+ metaFunction->setDeclaringClass(metaClass);
+
+ // Some of the queries below depend on the implementing class being set
+ // to function properly. Such as function modifications
+ metaFunction->setImplementingClass(metaClass);
+
+ if (metaFunction->name() == QLatin1String("operator_equal"))
+ metaClass->setHasEqualsOperator(true);
+
+ if (!metaFunction->isFinalInTargetLang()
+ && metaFunction->isRemovedFrom(metaClass, TypeSystem::TargetLangCode)) {
+ *metaFunction += AbstractMetaAttributes::FinalInCpp;
+ }
+}
+
+void AbstractMetaBuilderPrivate::fixReturnTypeOfConversionOperator(AbstractMetaFunction *metaFunction)
+{
+ if (!metaFunction->isConversionOperator())
+ return;
+
+ TypeDatabase* types = TypeDatabase::instance();
+ static const QRegularExpression operatorRegExp(QStringLiteral("^operator "));
+ Q_ASSERT(operatorRegExp.isValid());
+ QString castTo = metaFunction->name().remove(operatorRegExp).trimmed();
+
+ if (castTo.endsWith(QLatin1Char('&')))
+ castTo.chop(1);
+ if (castTo.startsWith(QLatin1String("const ")))
+ castTo.remove(0, 6);
+
+ TypeEntry* retType = types->findType(castTo);
+ if (!retType)
+ return;
+
+ AbstractMetaType* metaType = q->createMetaType();
+ metaType->setTypeEntry(retType);
+ metaFunction->replaceType(metaType);
+}
+
+static bool _compareAbstractMetaTypes(const AbstractMetaType* type, const AbstractMetaType* other)
+{
+ if (!type && !other)
+ return true;
+ if (!type || !other)
+ return false;
+ return type->typeEntry() == other->typeEntry()
+ && type->isConstant() == other->isConstant()
+ && type->referenceType() == other->referenceType()
+ && type->indirections() == other->indirections();
+}
+
+static bool _compareAbstractMetaFunctions(const AbstractMetaFunction* func, const AbstractMetaFunction* other)
+{
+ if (!func && !other)
+ return true;
+ if (!func || !other)
+ return false;
+ if (func->arguments().count() != other->arguments().count()
+ || func->isConstant() != other->isConstant()
+ || func->isStatic() != other->isStatic()
+ || !_compareAbstractMetaTypes(func->type(), other->type())) {
+ return false;
+ }
+ for (int i = 0; i < func->arguments().count(); ++i) {
+ if (!_compareAbstractMetaTypes(func->arguments().at(i)->type(), other->arguments().at(i)->type()))
+ return false;
+ }
+ return true;
+}
+
+// Fix the arguments of template classes that take the class itself, for example:
+// "QList(const QList &)" to "QList(const QList<T> &)".
+static bool _fixFunctionModelItemTypes(FunctionModelItem& function, const AbstractMetaClass* metaClass)
+{
+ const QVector<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());
+ for (const FunctionModelItem &function : scopeFunctionList) {
+ if (AbstractMetaFunction *metaFunction = traverseFunction(function))
+ result.append(metaFunction);
+ }
+ return result;
+}
+
+// For template classes, entries with more specific types may exist from out-of-
+// line definitions. If there is a declaration which matches it after fixing
+// the parameters, remove it as duplicate. For example:
+// template class<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());
+ for (FunctionModelItem function : scopeFunctionList) {
+ // This fixes method's arguments and return types that are templates
+ // but the template variable wasn't declared in the C++ header.
+ const bool templateTypeFixed =_fixFunctionModelItemTypes(function, metaClass);
+ if (AbstractMetaFunction *metaFunction = traverseFunction(function)) {
+ result.append(metaFunction);
+ if (!templateTypeFixed)
+ unchangedFunctions.append(metaFunction);
+ }
+ }
+
+ const AbstractMetaFunctionList::ConstIterator unchangedBegin = unchangedFunctions.begin();
+ const AbstractMetaFunctionList::ConstIterator unchangedEnd = unchangedFunctions.end();
+ for (int i = result.size() - 1; i >= 0; --i) {
+ AbstractMetaFunction *function = result.at(i);
+ if (!unchangedFunctions.contains(function)
+ && unchangedEnd != std::find_if(unchangedBegin, unchangedEnd, DuplicatingFunctionPredicate(function))) {
+ delete result.takeAt(i);
+ }
+ }
+ return result;
+}
+
+void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem,
+ AbstractMetaClass *metaClass)
+{
+
+ const AbstractMetaFunctionList functions = metaClass->templateArguments().isEmpty()
+ ? classFunctionList(scopeItem)
+ : templateClassFunctionList(scopeItem, metaClass);
+
+ for (AbstractMetaFunction *metaFunction : functions){
+ metaFunction->setOriginalAttributes(metaFunction->attributes());
+ if (metaClass->isNamespace())
+ *metaFunction += AbstractMetaAttributes::Static;
+
+ QPropertySpec *read = 0;
+ if (!metaFunction->isSignal() && (read = metaClass->propertySpecForRead(metaFunction->name()))) {
+ // Property reader must be in the form "<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
+ const AddedFunctionList &addedFunctions = metaClass->typeEntry()->addedFunctions();
+ for (const AddedFunction &addedFunc : addedFunctions)
+ traverseFunction(addedFunc, metaClass);
+}
+
+void AbstractMetaBuilderPrivate::applyFunctionModifications(AbstractMetaFunction *func)
+{
+ const FunctionModificationList &mods = func->modifications(func->implementingClass());
+ AbstractMetaFunction& funcRef = *func;
+ for (const FunctionModification &mod : mods) {
+ if (mod.isRenameModifier()) {
+ func->setOriginalName(func->name());
+ func->setName(mod.renamedTo());
+ } else if (mod.isAccessModifier()) {
+ funcRef -= AbstractMetaAttributes::Public;
+ funcRef -= AbstractMetaAttributes::Protected;
+ funcRef -= AbstractMetaAttributes::Private;
+ funcRef -= AbstractMetaAttributes::Friendly;
+
+ if (mod.isPublic())
+ funcRef += AbstractMetaAttributes::Public;
+ else if (mod.isProtected())
+ funcRef += AbstractMetaAttributes::Protected;
+ else if (mod.isPrivate())
+ funcRef += AbstractMetaAttributes::Private;
+ else if (mod.isFriendly())
+ funcRef += AbstractMetaAttributes::Friendly;
+ }
+
+ if (mod.isFinal())
+ funcRef += AbstractMetaAttributes::FinalInTargetLang;
+ else if (mod.isNonFinal())
+ funcRef -= AbstractMetaAttributes::FinalInTargetLang;
+ }
+}
+
+bool AbstractMetaBuilderPrivate::setupInheritance(AbstractMetaClass *metaClass)
+{
+ Q_ASSERT(!metaClass->isInterface());
+
+ if (m_setupInheritanceDone.contains(metaClass))
+ return true;
+
+ m_setupInheritanceDone.insert(metaClass);
+
+ QStringList baseClasses = metaClass->baseClassNames();
+
+ // we only support our own containers and ONLY if there is only one baseclass
+ if (baseClasses.size() == 1 && baseClasses.first().contains(QLatin1Char('<'))) {
+ TypeParser::Info info;
+ ComplexTypeEntry* baseContainerType;
+ AbstractMetaClass* templ = findTemplateClass(baseClasses.first(), metaClass, &info, &baseContainerType);
+ if (templ) {
+ setupInheritance(templ);
+ inheritTemplate(metaClass, templ, info);
+ metaClass->typeEntry()->setBaseContainerType(templ->typeEntry());
+ return true;
+ }
+
+ if (baseContainerType) {
+ // Container types are not necessarily wrapped as 'real' classes,
+ // but there may still be classes derived from them. In such case,
+ // we still need to set the base container type in order to
+ // generate correct code for type conversion checking.
+ //
+ // Additionally, we consider this case as successfully setting up
+ // inheritance.
+ metaClass->typeEntry()->setBaseContainerType(baseContainerType);
+ return true;
+ }
+
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("template baseclass '%1' of '%2' is not known")
+ .arg(baseClasses.first(), metaClass->name());
+ return false;
+ }
+
+ TypeDatabase* types = TypeDatabase::instance();
+
+ int primary = -1;
+ int primaries = 0;
+ for (int i = 0; i < baseClasses.size(); ++i) {
+
+ if (types->isClassRejected(baseClasses.at(i)))
+ continue;
+
+ TypeEntry* baseClassEntry = types->findType(baseClasses.at(i));
+ if (!baseClassEntry) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("class '%1' inherits from unknown base class '%2'")
+ .arg(metaClass->name(), baseClasses.at(i));
+ } else if (!baseClassEntry->designatedInterface()) { // true for primary base class
+ primaries++;
+ primary = i;
+ }
+ }
+
+ if (primary >= 0) {
+ AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(primary));
+ if (!baseClass) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("unknown baseclass for '%1': '%2'")
+ .arg(metaClass->name(), baseClasses.at(primary));
+ return false;
+ }
+ metaClass->setBaseClass(baseClass);
+ }
+
+ for (int i = 0; i < baseClasses.size(); ++i) {
+ if (types->isClassRejected(baseClasses.at(i)))
+ continue;
+
+ if (i != primary) {
+ AbstractMetaClass *baseClass = AbstractMetaClass::findClass(m_metaClasses, baseClasses.at(i));
+ if (!baseClass) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("class not found for setup inheritance '%1'").arg(baseClasses.at(i));
+ return false;
+ }
+
+ setupInheritance(baseClass);
+
+ QString interfaceName = baseClass->isInterface() ? InterfaceTypeEntry::interfaceName(baseClass->name()) : baseClass->name();
+ AbstractMetaClass *iface = AbstractMetaClass::findClass(m_metaClasses, interfaceName);
+ if (!iface) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("unknown interface for '%1': '%2'").arg(metaClass->name(), interfaceName);
+ return false;
+ }
+ metaClass->addInterface(iface);
+
+ const AbstractMetaClassList &interfaces = iface->interfaces();
+ for (AbstractMetaClass* iface : interfaces)
+ metaClass->addInterface(iface);
+ }
+ }
+
+ return true;
+}
+
+void AbstractMetaBuilderPrivate::traverseEnums(ScopeModelItem scopeItem,
+ AbstractMetaClass *metaClass,
+ const QStringList &enumsDeclarations)
+{
+ const EnumList &enums = scopeItem->enums();
+ for (const EnumModelItem &enumItem : enums) {
+ AbstractMetaEnum* metaEnum = traverseEnum(enumItem, metaClass, QSet<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()));
+
+
+ QVector<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;
+ const FunctionModificationList &mods = func->modifications(m_currentClass);
+ for (const FunctionModification &mod : mods) {
+ for (const ArgumentModification &argMod : mod.argument_mods) {
+ if (!argMod.renamed_to.isEmpty()) {
+ AbstractMetaArgument* arg = func->arguments().at(argMod.index - 1);
+ arg->setOriginalName(arg->name());
+ arg->setName(argMod.renamed_to, false);
+ }
+ }
+ }
+
+ AbstractMetaArgumentList arguments = func->arguments();
+ for (int i = 0, size = arguments.size(); i < size; ++i) {
+ if (arguments.at(i)->name().isEmpty())
+ arguments[i]->setName(QLatin1String("arg__") + QString::number(i + 1), false);
+ }
+}
+
+static QString functionSignature(FunctionModelItem functionItem)
+{
+ QStringList args;
+ const ArgumentList &arguments = functionItem->arguments();
+ for (const ArgumentModelItem &arg : arguments)
+ args << arg->type().toString();
+ return functionItem->name() + QLatin1Char('(') + args.join(QLatin1Char(',')) + QLatin1Char(')');
+}
+
+static inline QString qualifiedFunctionSignatureWithType(const FunctionModelItem &functionItem,
+ const QString &className = QString())
+{
+ QString result = functionItem->type().toString() + QLatin1Char(' ');
+ if (!className.isEmpty())
+ result += className + colonColon();
+ result += functionSignature(functionItem);
+ return result;
+}
+
+static inline QString msgUnmatchedParameterType(const ArgumentModelItem &arg, int n)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "unmatched type '" << arg->type().toString() << "' in parameter #"
+ << (n + 1);
+ if (!arg->name().isEmpty())
+ str << " \"" << arg->name() << '"';
+ return result;
+}
+
+static inline QString msgVoidParameterType(const ArgumentModelItem &arg, int n)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "'void' encountered at parameter #" << (n + 1);
+ if (!arg->name().isEmpty())
+ str << " \"" << arg->name() << '"';
+ return result;
+}
+
+AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModelItem functionItem)
+{
+ if (!functionItem->templateParameters().isEmpty())
+ return nullptr;
+ QString functionName = functionItem->name();
+ QString className;
+ if (m_currentClass) {
+ // Clang: Skip qt_metacast(), qt_metacall(), expanded from Q_OBJECT
+ // and overridden metaObject(), QGADGET helpers
+ if (functionName == QLatin1String("qt_check_for_QGADGET_macro")
+ || functionName.startsWith(QLatin1String("qt_meta"))) {
+ return nullptr;
+ }
+ className = m_currentClass->typeEntry()->qualifiedCppName();
+ if (functionName == QLatin1String("metaObject") && className != QLatin1String("QObject"))
+ return nullptr;
+ }
+
+ // Store original signature with unresolved typedefs for message/log purposes
+ const QString originalQualifiedSignatureWithReturn =
+ qualifiedFunctionSignatureWithType(functionItem, className);
+
+ QString rejectReason;
+ if (TypeDatabase::instance()->isFunctionRejected(className, functionName, &rejectReason)) {
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+ else if (TypeDatabase::instance()->isFunctionRejected(className,
+ functionSignature(functionItem), &rejectReason)) {
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ return 0;
+ }
+
+ Q_ASSERT(functionItem->functionType() == CodeModel::Normal
+ || functionItem->functionType() == CodeModel::Signal
+ || functionItem->functionType() == CodeModel::Slot);
+
+ if (functionItem->isFriend())
+ return 0;
+
+ AbstractMetaFunction *metaFunction = q->createMetaFunction();
+ metaFunction->setConstant(functionItem->isConstant());
+
+ if (ReportHandler::isDebug(ReportHandler::MediumDebug))
+ qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()";
+
+ metaFunction->setName(functionName);
+ metaFunction->setOriginalName(functionItem->name());
+
+ if (functionItem->isAbstract())
+ *metaFunction += AbstractMetaAttributes::Abstract;
+
+ if (!metaFunction->isAbstract())
+ *metaFunction += AbstractMetaAttributes::Native;
+
+ if (!functionItem->isVirtual())
+ *metaFunction += AbstractMetaAttributes::Final;
+
+ if (functionItem->isInvokable())
+ *metaFunction += AbstractMetaAttributes::Invokable;
+
+ if (functionItem->isStatic()) {
+ *metaFunction += AbstractMetaAttributes::Static;
+ *metaFunction += AbstractMetaAttributes::Final;
+ }
+
+ // Access rights
+ if (functionItem->accessPolicy() == CodeModel::Public)
+ *metaFunction += AbstractMetaAttributes::Public;
+ else if (functionItem->accessPolicy() == CodeModel::Private)
+ *metaFunction += AbstractMetaAttributes::Private;
+ else
+ *metaFunction += AbstractMetaAttributes::Protected;
+
+
+ QString strippedClassName = className;
+ int cc_pos = strippedClassName.lastIndexOf(colonColon());
+ if (cc_pos > 0)
+ strippedClassName = strippedClassName.mid(cc_pos + 2);
+
+ TypeInfo functionType = functionItem->type();
+
+ if (TypeDatabase::instance()->isReturnTypeRejected(className, functionType.toString(), &rejectReason)) {
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ delete metaFunction;
+ return nullptr;
+ }
+
+ if (functionName.startsWith(QLatin1Char('~'))) {
+ metaFunction->setFunctionType(AbstractMetaFunction::DestructorFunction);
+ metaFunction->setInvalid(true);
+ } else if (stripTemplateArgs(functionName) == strippedClassName) {
+ metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction);
+ // Check for Copy/Move down below
+ metaFunction->setExplicit(functionItem->isExplicit());
+ metaFunction->setName(m_currentClass->name());
+ } else {
+ bool ok;
+ AbstractMetaType* type = translateType(functionType, &ok);
+
+ if (!ok) {
+ Q_ASSERT(type == 0);
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("skipping function '%1', unmatched return type '%2'")
+ .arg(originalQualifiedSignatureWithReturn,
+ functionItem->type().toString());
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn, AbstractMetaBuilder::UnmatchedReturnType);
+ metaFunction->setInvalid(true);
+ return metaFunction;
+ }
+
+ metaFunction->setType(type);
+
+ if (functionItem->functionType() == CodeModel::Signal)
+ metaFunction->setFunctionType(AbstractMetaFunction::SignalFunction);
+ else if (functionItem->functionType() == CodeModel::Slot)
+ metaFunction->setFunctionType(AbstractMetaFunction::SlotFunction);
+ }
+
+ ArgumentList arguments = functionItem->arguments();
+
+ if (arguments.size() == 1) {
+ ArgumentModelItem arg = arguments.at(0);
+ TypeInfo type = arg->type();
+ if (type.qualifiedName().first() == QLatin1String("void") && type.indirections() == 0)
+ arguments.pop_front();
+ }
+
+ AbstractMetaArgumentList metaArguments;
+
+ for (int i = 0; i < arguments.size(); ++i) {
+ ArgumentModelItem arg = arguments.at(i);
+
+ if (TypeDatabase::instance()->isArgumentTypeRejected(className, arg->type().toString(), &rejectReason)) {
+ m_rejectedFunctions.insert(originalQualifiedSignatureWithReturn + rejectReason, AbstractMetaBuilder::GenerationDisabled);
+ delete metaFunction;
+ return nullptr;
+ }
+
+ bool ok;
+ AbstractMetaType* metaType = translateType(arg->type(), &ok);
+ if (!ok) {
+ Q_ASSERT(metaType == 0);
+ const QString reason = msgUnmatchedParameterType(arg, i);
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("skipping function '%1', %2")
+ .arg(originalQualifiedSignatureWithReturn, reason);
+ const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
+ + QLatin1String(": ") + reason;
+ m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
+ metaFunction->setInvalid(true);
+ return metaFunction;
+ }
+
+ if (metaType == Q_NULLPTR) {
+ const QString reason = msgVoidParameterType(arg, i);
+ qCWarning(lcShiboken).noquote().nospace()
+ << QString::fromLatin1("skipping function '%1': %2")
+ .arg(originalQualifiedSignatureWithReturn, reason);
+ const QString rejectedFunctionSignature = originalQualifiedSignatureWithReturn
+ + QLatin1String(": ") + reason;
+ m_rejectedFunctions.insert(rejectedFunctionSignature, AbstractMetaBuilder::UnmatchedArgumentType);
+ metaFunction->setInvalid(true);
+ return metaFunction;
+ }
+
+ AbstractMetaArgument *metaArgument = q->createMetaArgument();
+
+ metaArgument->setType(metaType);
+ metaArgument->setName(arg->name());
+ metaArgument->setArgumentIndex(i);
+ metaArguments << metaArgument;
+ }
+
+ metaFunction->setArguments(metaArguments);
+
+ // Find the correct default values
+ for (int i = 0; i < arguments.size(); ++i) {
+ ArgumentModelItem arg = arguments.at(i);
+ AbstractMetaArgument* metaArg = metaArguments.at(i);
+
+ //use relace-default-expression for set default value
+ QString replacedExpression;
+ if (m_currentClass) {
+ replacedExpression = metaFunction->replacedDefaultExpression(m_currentClass, i + 1);
+ } else {
+ FunctionModificationList mods = TypeDatabase::instance()->functionModifications(metaFunction->minimalSignature());
+ if (!mods.isEmpty()) {
+ QVector<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();
+ for (const QString& candidate : qAsConst(candidates)) {
+ msg += QLatin1String(" ") + candidate + QLatin1Char('\n');
+ }
+ qFatal(qPrintable(msg), NULL);
+ }
+
+ AbstractMetaType *metaType = q->createMetaType();
+ metaType->setTypeEntry(type);
+ metaType->setIndirections(typeInfo.indirections);
+ if (typeInfo.isReference)
+ metaType->setReferenceType(LValueReference);
+ metaType->setConstant(typeInfo.isConstant);
+ if (isTemplate) {
+ for (const QString& templateArg : qAsConst(templateArgs)) {
+ AbstractMetaType* metaArgType = translateType(vr, AddedFunction::TypeInfo::fromSignature(templateArg));
+ metaType->addInstantiation(metaArgType);
+ }
+ metaType->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
+ }
+
+ return metaType;
+}
+
+static const TypeEntry* findTypeEntryUsingContext(const AbstractMetaClass* metaClass, const QString& qualifiedName)
+{
+ const TypeEntry* type = 0;
+ QStringList context = metaClass->qualifiedCppName().split(colonColon());
+ while(!type && (context.size() > 0) ) {
+ type = TypeDatabase::instance()->findType(context.join(colonColon()) + colonColon() + qualifiedName);
+ context.removeLast();
+ }
+ return type;
+}
+
+AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei,
+ bool *ok, bool resolveType,
+ bool resolveScope)
+{
+ Q_ASSERT(ok);
+ *ok = true;
+
+ // 1. Test the type info without resolving typedefs in case this is present in the
+ // type system
+ TypeInfo typei;
+ if (resolveType) {
+ bool ok;
+ AbstractMetaType* t = translateType(_typei, &ok, false, resolveScope);
+ if (t && ok)
+ return t;
+ Q_ASSERT(t == 0);
+ }
+
+ if (!resolveType) {
+ typei = _typei;
+ } else {
+ // Go through all parts of the current scope (including global namespace)
+ // to resolve typedefs. The parser does not properly resolve typedefs in
+ // the global scope when they are referenced from inside a namespace.
+ // This is a work around to fix this bug since fixing it in resolveType
+ // seemed non-trivial
+ int i = m_scopes.size() - 1;
+ while (i >= 0) {
+ typei = TypeInfo::resolveType(_typei, m_scopes.at(i--));
+ if (typei.qualifiedName().join(colonColon()) != _typei.qualifiedName().join(colonColon()))
+ break;
+ }
+
+ }
+
+ if (typei.isFunctionPointer()) {
+ *ok = false;
+ return 0;
+ }
+
+ QString errorMessage;
+ TypeParser::Info typeInfo = TypeParser::parse(typei.toString(), &errorMessage);
+ if (typeInfo.is_busted) {
+ qWarning().noquote().nospace() << "Unable to translate type \"" << _typei.toString()
+ << "\": " << errorMessage;
+ *ok = false;
+ return 0;
+ }
+
+ // 2. Handle pointers specified as arrays with unspecified size
+ bool arrayOfUnspecifiedSize = false;
+ if (typeInfo.arrays.size() > 0) {
+ arrayOfUnspecifiedSize = true;
+ for (int i = 0; i < typeInfo.arrays.size(); ++i)
+ arrayOfUnspecifiedSize = arrayOfUnspecifiedSize && typeInfo.arrays.at(i).isEmpty();
+
+ if (!arrayOfUnspecifiedSize) {
+ TypeInfo newInfo;
+ //newInfo.setArguments(typei.arguments());
+ newInfo.setIndirections(typei.indirections());
+ newInfo.setConstant(typei.isConstant());
+ newInfo.setFunctionPointer(typei.isFunctionPointer());
+ newInfo.setQualifiedName(typei.qualifiedName());
+ newInfo.setReferenceType(typei.referenceType());
+ newInfo.setVolatile(typei.isVolatile());
+
+ AbstractMetaType* elementType = translateType(newInfo, ok);
+ if (!(*ok))
+ return 0;
+
+ for (int i = typeInfo.arrays.size() - 1; i >= 0; --i) {
+ QString s = typeInfo.arrays.at(i);
+ bool _ok;
+ int elems = findOutValueFromString(s, _ok);
+
+ AbstractMetaType *arrayType = q->createMetaType();
+ arrayType->setArrayElementCount(elems);
+ arrayType->setArrayElementType(elementType);
+ arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version()));
+ decideUsagePattern(arrayType);
+
+ elementType = arrayType;
+ }
+
+ return elementType;
+ } else {
+ typeInfo.indirections += typeInfo.arrays.size();
+ }
+ }
+
+ QStringList qualifierList = typeInfo.qualified_name;
+ if (qualifierList.isEmpty()) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("horribly broken type '%1'").arg(_typei.toString());
+ *ok = false;
+ return 0;
+ }
+
+ QString qualifiedName = qualifierList.join(colonColon());
+ QString name = qualifierList.takeLast();
+
+ // 3. Special case 'void' type
+ if (name == QLatin1String("void") && !typeInfo.indirections)
+ return 0;
+
+ // 4. Special case QFlags (include instantiation in name)
+ if (qualifiedName == QLatin1String("QFlags"))
+ qualifiedName = typeInfo.toString();
+
+ const TypeEntry *type = 0;
+ // 5. Try to find the type
+
+ // 5.1 - Try first using the current scope
+ if (m_currentClass) {
+ type = findTypeEntryUsingContext(m_currentClass, qualifiedName);
+
+ // 5.1.1 - Try using the class parents' scopes
+ if (!type && !m_currentClass->baseClassNames().isEmpty()) {
+ const AbstractMetaClassList &baseClasses = getBaseClasses(m_currentClass);
+ for (const AbstractMetaClass *cls : baseClasses) {
+ type = findTypeEntryUsingContext(cls, qualifiedName);
+ if (type)
+ break;
+ }
+ }
+ }
+
+ // 5.2 - Try without scope
+ if (!type)
+ type = TypeDatabase::instance()->findType(qualifiedName);
+
+ // 6. No? Try looking it up as a flags type
+ if (!type)
+ type = TypeDatabase::instance()->findFlagsType(qualifiedName);
+
+ // 7. No? Try looking it up as a container type
+ if (!type)
+ type = TypeDatabase::instance()->findContainerType(name);
+
+ // 8. No? Check if the current class is a template and this type is one
+ // of the parameters.
+ if (!type && m_currentClass) {
+ const QVector<TypeEntry *> &template_args = m_currentClass->templateArguments();
+ for (TypeEntry *te : template_args) {
+ if (te->name() == qualifiedName)
+ type = te;
+ }
+ }
+
+ // 9. Try finding the type by prefixing it with the current
+ // context and all baseclasses of the current context
+ if (!type && !TypeDatabase::instance()->isClassRejected(qualifiedName) && m_currentClass && resolveScope) {
+ QStringList contexts;
+ contexts.append(m_currentClass->qualifiedCppName());
+ contexts.append(currentScope()->qualifiedName().join(colonColon()));
+
+
+ TypeInfo info = typei;
+ bool subclassesDone = false;
+ while (!contexts.isEmpty() && !type) {
+ type = TypeDatabase::instance()->findType(contexts.at(0) + colonColon() + qualifiedName);
+ contexts.pop_front();
+
+ // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
+ // enum types from there may be addressed without any scope resolution in properties.
+ if (!contexts.size() && !subclassesDone) {
+ contexts << QLatin1String("Qt");
+ subclassesDone = true;
+ }
+ }
+
+ }
+
+ if (!type) {
+ *ok = false;
+ return 0;
+ }
+
+ // Used to for diagnostics later...
+ m_usedTypes << type;
+
+ // These are only implicit and should not appear in code...
+ Q_ASSERT(!type->isInterface());
+
+ AbstractMetaType *metaType = q->createMetaType();
+ metaType->setTypeEntry(type);
+ metaType->setIndirections(typeInfo.indirections);
+ metaType->setReferenceType(typeInfo.referenceType);
+ metaType->setConstant(typeInfo.is_constant);
+ metaType->setOriginalTypeDescription(_typei.toString());
+
+ for (const TypeParser::Info &ta : qAsConst(typeInfo.template_instantiations)) {
+ TypeInfo info;
+ info.setConstant(ta.is_constant);
+ info.setReferenceType(ta.referenceType);
+ info.setIndirections(ta.indirections);
+
+ info.setFunctionPointer(false);
+ info.setQualifiedName(ta.instantiationName().split(colonColon()));
+
+ AbstractMetaType* targType = translateType(info, ok);
+ if (!(*ok)) {
+ delete metaType;
+ return 0;
+ }
+
+ metaType->addInstantiation(targType, true);
+ }
+
+ // The usage pattern *must* be decided *after* the possible template
+ // instantiations have been determined, or else the absence of
+ // such instantiations will break the caching scheme of
+ // AbstractMetaType::cppSignature().
+ decideUsagePattern(metaType);
+
+ return metaType;
+}
+
+
+int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok)
+{
+ int value = stringValue.toInt(&ok);
+ if (ok)
+ return value;
+
+ if (stringValue == QLatin1String("true") || stringValue == QLatin1String("false")) {
+ ok = true;
+ return (stringValue == QLatin1String("true"));
+ }
+
+ // This is a very lame way to handle expression evaluation,
+ // but it is not critical and will do for the time being.
+ static const QRegularExpression variableNameRegExp(QStringLiteral("^[a-zA-Z_][a-zA-Z0-9_]*$"));
+ Q_ASSERT(variableNameRegExp.isValid());
+ if (!variableNameRegExp.match(stringValue).hasMatch()) {
+ ok = true;
+ return 0;
+ }
+
+ AbstractMetaEnumValue *enumValue = AbstractMetaClass::findEnumValue(m_metaClasses, stringValue);
+ if (enumValue) {
+ ok = true;
+ return enumValue->value();
+ }
+
+ for (AbstractMetaEnum *metaEnum : qAsConst(m_globalEnums)) {
+ const AbstractMetaEnumValueList &values = metaEnum->values();
+ for (const AbstractMetaEnumValue *ev : values) {
+ if (ev->name() == stringValue) {
+ ok = true;
+ return ev->value();
+ }
+ }
+ }
+
+ ok = false;
+ return 0;
+}
+
+void AbstractMetaBuilderPrivate::decideUsagePattern(AbstractMetaType *metaType)
+{
+ metaType->decideUsagePattern();
+}
+
+QString AbstractMetaBuilderPrivate::fixDefaultValue(ArgumentModelItem item,
+ AbstractMetaType *type,
+ AbstractMetaFunction *fnc,
+ AbstractMetaClass *implementingClass,
+ int /* argumentIndex */)
+{
+ QString functionName = fnc->name();
+ QString className = implementingClass ? implementingClass->qualifiedCppName() : QString();
+
+ QString expr = item->defaultValueExpression();
+ if (type) {
+ if (type->isPrimitive()) {
+ if (type->name() == QLatin1String("boolean")) {
+ if (expr != QLatin1String("false") && expr != QLatin1String("true")) {
+ bool ok = false;
+ int number = expr.toInt(&ok);
+ if (ok && number)
+ expr = QLatin1String("true");
+ else
+ expr = QLatin1String("false");
+ }
+ } else {
+ // This can be an enum or flag so I need to delay the
+ // translation untill all namespaces are completly
+ // processed. This is done in figureOutEnumValues()
+ }
+ } else if (type->isFlags() || type->isEnum()) {
+ bool isNumber;
+ expr.toInt(&isNumber);
+ if (!isNumber && expr.indexOf(colonColon()) < 0) {
+ // Add the enum/flag scope to default value, making it usable
+ // from other contexts beside its owner class hierarchy
+ static const QRegularExpression typeRegEx(QStringLiteral("[^<]*[<]([^:]*::).*"));
+ Q_ASSERT(typeRegEx.isValid());
+ const QRegularExpressionMatch match = typeRegEx.match(type->minimalSignature());
+ if (match.hasMatch())
+ expr.prepend(match.captured(1));
+ }
+ } else if (type->isContainer() && expr.contains(QLatin1Char('<'))) {
+ static const QRegularExpression typeRegEx(QStringLiteral("[^<]*<(.*)>"));
+ Q_ASSERT(typeRegEx.isValid());
+ const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature());
+ static const QRegularExpression defaultRegEx(QLatin1String("([^<]*<).*(>[^>]*)"));
+ Q_ASSERT(defaultRegEx.isValid());
+ const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr);
+ if (typeMatch.hasMatch() && defaultMatch.hasMatch())
+ expr = defaultMatch.captured(1) + typeMatch.captured(1) + defaultMatch.captured(2);
+ } else {
+ // Here the default value is supposed to be a constructor,
+ // a class field, or a constructor receiving a class field
+ static const QRegularExpression defaultRegEx(QStringLiteral("([^\\(]*\\(|)([^\\)]*)(\\)|)"));
+ Q_ASSERT(defaultRegEx.isValid());
+ const QRegularExpressionMatch defaultMatch = defaultRegEx.match(expr);
+ QString defaultValueCtorName = defaultMatch.hasMatch() ? defaultMatch.captured(1) : QString();
+ if (defaultValueCtorName.endsWith(QLatin1Char('(')))
+ defaultValueCtorName.chop(1);
+
+ // Fix the scope for constructor using the already
+ // resolved argument type as a reference.
+ // The following regular expression extracts any
+ // use of namespaces/scopes from the type string.
+ static const QRegularExpression typeRegEx(QLatin1String("^(?:const[\\s]+|)([\\w:]*::|)([A-Za-z_]\\w*)\\s*[&\\*]?$"));
+ Q_ASSERT(typeRegEx.isValid());
+ const QRegularExpressionMatch typeMatch = typeRegEx.match(type->minimalSignature());
+
+ QString typeNamespace = typeMatch.hasMatch() ? typeMatch.captured(1) : QString();
+ QString typeCtorName = typeMatch.hasMatch() ? typeMatch.captured(2) : QString();
+ if (!typeNamespace.isEmpty() && defaultValueCtorName == typeCtorName)
+ expr.prepend(typeNamespace);
+
+ // Fix scope if the parameter is a field of the current class
+ if (implementingClass) {
+ const AbstractMetaFieldList &fields = implementingClass->fields();
+ for (const AbstractMetaField *field : fields) {
+ if (defaultMatch.hasMatch() && defaultMatch.captured(2) == field->name()) {
+ expr = defaultMatch.captured(1) + implementingClass->name()
+ + colonColon() + defaultMatch.captured(2) + defaultMatch.captured(3);
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("undefined type for default value '%3' of argument in function '%1', class '%2'")
+ .arg(functionName, className, item->defaultValueExpression());
+
+ expr = QString();
+ }
+
+ return expr;
+}
+
+bool AbstractMetaBuilderPrivate::isQObject(const FileModelItem &dom, const QString &qualifiedName)
+{
+ if (qualifiedName == QLatin1String("QObject"))
+ return true;
+
+ ClassModelItem classItem = dom->findClass(qualifiedName);
+
+ if (!classItem) {
+ QStringList names = qualifiedName.split(colonColon());
+ NamespaceModelItem ns = dom;
+ for (int i = 0; i < names.size() - 1 && ns; ++i)
+ ns = ns->findNamespace(names.at(i));
+ if (ns && names.size() >= 2)
+ classItem = ns->findClass(names.at(names.size() - 1));
+ }
+
+ bool isqobject = classItem && classItem->extendsClass(QLatin1String("QObject"));
+
+ if (classItem && !isqobject) {
+ QStringList baseClasses = classItem->baseClasses();
+ for (int i = 0; i < baseClasses.count(); ++i) {
+
+ isqobject = isQObject(dom, baseClasses.at(i));
+ if (isqobject)
+ break;
+ }
+ }
+
+ return isqobject;
+}
+
+
+bool AbstractMetaBuilderPrivate::isEnum(const FileModelItem &dom, const QStringList& qualified_name)
+{
+ CodeModelItem item = dom->model()->findItem(qualified_name, dom);
+ return item && item->kind() == _EnumModelItem::__node_kind;
+}
+
+AbstractMetaClass* AbstractMetaBuilderPrivate::findTemplateClass(const QString &name,
+ const AbstractMetaClass *context,
+ TypeParser::Info *info,
+ ComplexTypeEntry **baseContainerType) const
+{
+ TypeParser::Info localInfo;
+ if (!info)
+ info = &localInfo;
+
+ TypeDatabase* types = TypeDatabase::instance();
+
+ QStringList scope = context->typeEntry()->qualifiedCppName().split(colonColon());
+ QString errorMessage;
+ scope.removeLast();
+ for (int i = scope.size(); i >= 0; --i) {
+ QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join(colonColon()) + colonColon() : QString();
+ QString completeName = prefix + name;
+ const TypeParser::Info parsed = TypeParser::parse(completeName, &errorMessage);
+ if (parsed.is_busted) {
+ qWarning().noquote().nospace() << "Unable to parse type \"" << completeName
+ << "\" while looking for template \"" << name << "\": " << errorMessage;
+ continue;
+ }
+ *info = parsed;
+ QString qualifiedName = info->qualified_name.join(colonColon());
+
+ AbstractMetaClass* templ = 0;
+ for (AbstractMetaClass *c : qAsConst(m_templates)) {
+ if (c->typeEntry()->name() == qualifiedName) {
+ templ = c;
+ break;
+ }
+ }
+
+ if (!templ)
+ templ = AbstractMetaClass::findClass(m_metaClasses, qualifiedName);
+
+ if (templ)
+ return templ;
+
+ if (baseContainerType)
+ *baseContainerType = types->findContainerType(qualifiedName);
+ }
+
+ return 0;
+}
+
+AbstractMetaClassList AbstractMetaBuilderPrivate::getBaseClasses(const AbstractMetaClass *metaClass) const
+{
+ AbstractMetaClassList baseClasses;
+ const QStringList &baseClassNames = metaClass->baseClassNames();
+ for (const QString& parent : baseClassNames) {
+ AbstractMetaClass* cls = 0;
+ if (parent.contains(QLatin1Char('<')))
+ cls = findTemplateClass(parent, metaClass);
+ else
+ cls = AbstractMetaClass::findClass(m_metaClasses, parent);
+
+ if (cls)
+ baseClasses << cls;
+ }
+ return baseClasses;
+}
+
+bool AbstractMetaBuilderPrivate::ancestorHasPrivateCopyConstructor(const AbstractMetaClass *metaClass) const
+{
+ if (metaClass->hasPrivateCopyConstructor())
+ return true;
+ const AbstractMetaClassList &baseClasses = getBaseClasses(metaClass);
+ for (const AbstractMetaClass *cls : baseClasses) {
+ if (ancestorHasPrivateCopyConstructor(cls))
+ return true;
+ }
+ return false;
+}
+
+AbstractMetaType* AbstractMetaBuilderPrivate::inheritTemplateType(const QVector<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)
+{
+ QVector<TypeParser::Info> targs = info.template_instantiations;
+ QVector<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());
+ }
+
+ for (const TypeParser::Info &i : qAsConst(targs)) {
+ QString typeName = i.qualified_name.join(colonColon());
+ QStringList possibleNames;
+ possibleNames << subclass->qualifiedCppName() + colonColon() + typeName;
+ possibleNames << templateClass->qualifiedCppName() + colonColon() + typeName;
+ if (subclass->enclosingClass())
+ possibleNames << subclass->enclosingClass()->qualifiedCppName() + colonColon() + typeName;
+ possibleNames << typeName;
+
+ TypeDatabase* typeDb = TypeDatabase::instance();
+ TypeEntry* t = 0;
+ QString templateParamName;
+ for (const QString &possibleName : qAsConst(possibleNames)) {
+ t = typeDb->findType(possibleName);
+ if (t) {
+ QString templateParamName = possibleName;
+ break;
+ }
+ }
+
+ if (t) {
+ AbstractMetaType *temporaryType = q->createMetaType();
+ temporaryType->setTypeEntry(t);
+ temporaryType->setConstant(i.is_constant);
+ temporaryType->setReferenceType(i.referenceType);
+ temporaryType->setIndirections(i.indirections);
+ temporaryType->decideUsagePattern();
+ templateTypes << temporaryType;
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "Ignoring template parameter " << templateParamName << " from "
+ << info.instantiationName() << ", because I don't know what it is.";
+ }
+ }
+
+ AbstractMetaFunctionList funcs = subclass->functions();
+ const AbstractMetaFunctionList &templateClassFunctions = templateClass->functions();
+ for (const AbstractMetaFunction *function : templateClassFunctions) {
+ if (function->isModifiedRemoved(TypeSystem::All))
+ continue;
+
+ AbstractMetaFunction *f = function->copy();
+ f->setArguments(AbstractMetaArgumentList());
+
+ bool ok = true;
+ AbstractMetaType *ftype = function->type();
+ f->replaceType(inheritTemplateType(templateTypes, ftype, &ok));
+ if (!ok) {
+ delete f;
+ continue;
+ }
+
+ const AbstractMetaArgumentList &arguments = function->arguments();
+ for (AbstractMetaArgument *argument : arguments) {
+ AbstractMetaType* atype = argument->type();
+
+ AbstractMetaArgument *arg = argument->copy();
+ arg->replaceType(inheritTemplateType(templateTypes, atype, &ok));
+ if (!ok)
+ break;
+ f->addArgument(arg);
+ }
+
+ if (!ok) {
+ delete f;
+ continue;
+ }
+
+ // There is no base class in the target language to inherit from here, so
+ // the template instantiation is the class that implements the function.
+ f->setImplementingClass(subclass);
+
+ // We also set it as the declaring class, since the superclass is
+ // supposed to disappear. This allows us to make certain function modifications
+ // on the inherited functions.
+ f->setDeclaringClass(subclass);
+
+
+ if (f->isConstructor() && subclass->isTypeDef()) {
+ f->setName(subclass->name());
+ f->setOriginalName(subclass->name());
+ } else if (f->isConstructor()) {
+ delete f;
+ continue;
+ }
+
+ // if the instantiation has a function named the same as an existing
+ // function we have shadowing so we need to skip it.
+ bool found = false;
+ for (int i = 0; i < funcs.size(); ++i) {
+ if (funcs.at(i)->name() == f->name()) {
+ found = true;
+ continue;
+ }
+ }
+ if (found) {
+ delete f;
+ continue;
+ }
+
+ ComplexTypeEntry* te = subclass->typeEntry();
+ FunctionModificationList mods = function->modifications(templateClass);
+ for (int i = 0; i < mods.size(); ++i) {
+ FunctionModification mod = mods.at(i);
+ mod.signature = f->minimalSignature();
+
+ // If we ever need it... Below is the code to do
+ // substitution of the template instantation type inside
+ // injected code..
+#if 0
+ if (mod.modifiers & Modification::CodeInjection) {
+ for (int j = 0; j < template_types.size(); ++j) {
+ CodeSnip &snip = mod.snips.last();
+ QString code = snip.code();
+ code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
+ template_types.at(j)->typeEntry()->qualifiedCppName());
+ snip.codeList.clear();
+ snip.addCode(code);
+ }
+ }
+#endif
+ te->addFunctionModification(mod);
+ }
+
+ subclass->addFunction(f);
+ }
+
+ subclass->setTemplateBaseClass(templateClass);
+ subclass->setTemplateBaseClassInstantiations(templateTypes);
+ subclass->setInterfaces(templateClass->interfaces());
+ subclass->setBaseClass(templateClass->baseClass());
+
+ return true;
+}
+
+void AbstractMetaBuilderPrivate::parseQ_Property(AbstractMetaClass *metaClass,
+ const QStringList &declarations)
+{
+ for (int i = 0; i < declarations.size(); ++i) {
+ QString p = declarations.at(i);
+
+ QStringList l = p.split(QLatin1String(" "));
+
+
+ QStringList qualifiedScopeName = currentScope()->qualifiedName();
+ bool ok = false;
+ AbstractMetaType* type = 0;
+ QString scope;
+ for (int j = qualifiedScopeName.size(); j >= 0; --j) {
+ scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join(colonColon()) + colonColon() : QString();
+ TypeInfo info;
+ info.setQualifiedName((scope + l.at(0)).split(colonColon()));
+
+ type = translateType(info, &ok);
+ if (type && ok)
+ break;
+ }
+
+ if (!type || !ok) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("Unable to decide type of property: '%1' in class '%2'")
+ .arg(l.at(0), metaClass->name());
+ continue;
+ }
+
+ QString typeName = scope + l.at(0);
+
+ QPropertySpec* spec = new QPropertySpec(type->typeEntry());
+ spec->setName(l.at(1));
+ spec->setIndex(i);
+
+ for (int pos = 2; pos + 1 < l.size(); pos += 2) {
+ if (l.at(pos) == QLatin1String("READ"))
+ spec->setRead(l.at(pos + 1));
+ else if (l.at(pos) == QLatin1String("WRITE"))
+ spec->setWrite(l.at(pos + 1));
+ else if (l.at(pos) == QLatin1String("DESIGNABLE"))
+ spec->setDesignable(l.at(pos + 1));
+ else if (l.at(pos) == QLatin1String("RESET"))
+ spec->setReset(l.at(pos + 1));
+ }
+
+ metaClass->addPropertySpec(spec);
+ delete type;
+ }
+}
+
+static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls)
+{
+ AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::Invisible);
+ functions << cls->queryFunctions(AbstractMetaClass::Visible);
+
+ for (AbstractMetaFunction *f : qAsConst(functions)) {
+ const AbstractMetaFunction::FunctionType t = f->functionType();
+ if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction)
+ return f;
+ }
+ return 0;
+}
+
+void AbstractMetaBuilderPrivate::setupClonable(AbstractMetaClass *cls)
+{
+ bool result = true;
+
+ // find copy ctor for the current class
+ AbstractMetaFunction* copyCtor = findCopyCtor(cls);
+ if (copyCtor) { // if exists a copy ctor in this class
+ result = copyCtor->isPublic();
+ } else { // else... lets find one in the parent class
+ QQueue<AbstractMetaClass*> baseClasses;
+ if (cls->baseClass())
+ baseClasses.enqueue(cls->baseClass());
+ baseClasses << cls->interfaces().toList();
+
+ while (!baseClasses.isEmpty()) {
+ AbstractMetaClass* currentClass = baseClasses.dequeue();
+ baseClasses << currentClass->interfaces().toList();
+ if (currentClass->baseClass())
+ baseClasses.enqueue(currentClass->baseClass());
+
+ copyCtor = findCopyCtor(currentClass);
+ if (copyCtor) {
+ result = copyCtor->isPublic();
+ break;
+ }
+ }
+ }
+ cls->setHasCloneOperator(result);
+}
+
+void AbstractMetaBuilderPrivate::setupExternalConversion(AbstractMetaClass *cls)
+{
+ const AbstractMetaFunctionList &convOps = cls->operatorOverloads(AbstractMetaClass::ConversionOp);
+ for (AbstractMetaFunction *func : convOps) {
+ if (func->isModifiedRemoved())
+ continue;
+ AbstractMetaClass *metaClass = AbstractMetaClass::findClass(m_metaClasses, func->type()->typeEntry());
+ if (!metaClass)
+ continue;
+ metaClass->addExternalConversionOperator(func);
+ }
+ const AbstractMetaClassList &innerClasses = cls->innerClasses();
+ for (AbstractMetaClass *innerClass : innerClasses)
+ setupExternalConversion(innerClass);
+}
+
+static void writeRejectLogFile(const QString &name,
+ const QMap<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;
+ for (AbstractMetaClass *clazz : classList) {
+ if (map.contains(clazz->qualifiedCppName()))
+ continue;
+ map[clazz->qualifiedCppName()] = i;
+ reverseMap[i] = clazz;
+ i++;
+ }
+
+ Graph graph(map.count());
+
+ for (const Dependency &dep : additionalDependencies) {
+ const int parentIndex = map.value(dep.parent, -1);
+ const int childIndex = map.value(dep.child, -1);
+ if (parentIndex >= 0 && childIndex >= 0) {
+ graph.addEdge(parentIndex, childIndex);
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "AbstractMetaBuilder::classesTopologicalSorted(): Invalid additional dependency: "
+ << dep.child << " -> " << dep.parent << '.';
+ }
+ }
+
+ // TODO choose a better name to these regexs
+ static const QRegularExpression regex1(QStringLiteral("\\(.*\\)"));
+ Q_ASSERT(regex1.isValid());
+ static const QRegularExpression regex2(QStringLiteral("::.*"));
+ Q_ASSERT(regex2.isValid());
+ for (AbstractMetaClass *clazz : classList) {
+ if (clazz->enclosingClass() && map.contains(clazz->enclosingClass()->qualifiedCppName()))
+ graph.addEdge(map[clazz->enclosingClass()->qualifiedCppName()], map[clazz->qualifiedCppName()]);
+
+ const AbstractMetaClassList &bases = getBaseClasses(clazz);
+ for (AbstractMetaClass *baseClass : bases) {
+ // Fix polymorphic expression
+ if (clazz->baseClass() == baseClass)
+ clazz->setBaseClass(baseClass);
+
+ if (map.contains(baseClass->qualifiedCppName()))
+ graph.addEdge(map[baseClass->qualifiedCppName()], map[clazz->qualifiedCppName()]);
+ }
+
+ const AbstractMetaFunctionList &functions = clazz->functions();
+ for (AbstractMetaFunction *func : functions) {
+ const AbstractMetaArgumentList &arguments = func->arguments();
+ for (AbstractMetaArgument *arg : arguments) {
+ // check methods with default args
+ QString defaultExpression = arg->originalDefaultValueExpression();
+ if (!defaultExpression.isEmpty()) {
+ if (defaultExpression == QLatin1String("0") && arg->type()->isValue())
+ defaultExpression = arg->type()->name();
+
+ defaultExpression.remove(regex1);
+ defaultExpression.remove(regex2);
+ }
+ if (!defaultExpression.isEmpty()) {
+ QString exprClassName = clazz->qualifiedCppName() + colonColon() + defaultExpression;
+ if (!map.contains(exprClassName)) {
+ bool found = false;
+ for (AbstractMetaClass *baseClass : bases) {
+ exprClassName = baseClass->qualifiedCppName() + colonColon() + defaultExpression;
+ if (map.contains(exprClassName)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ if (map.contains(defaultExpression))
+ exprClassName = defaultExpression;
+ else
+ exprClassName.clear();
+ }
+ }
+ if (!exprClassName.isEmpty() && exprClassName != clazz->qualifiedCppName())
+ graph.addEdge(map[exprClassName], map[clazz->qualifiedCppName()]);
+ }
+ }
+ }
+ }
+
+ AbstractMetaClassList result;
+ unmappedResult = graph.topologicalSort();
+ if (unmappedResult.isEmpty() && graph.nodeCount()) {
+ QTemporaryFile tempFile;
+ tempFile.setAutoRemove(false);
+ tempFile.open();
+ QHash<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 {
+ for (int i : qAsConst(unmappedResult)) {
+ Q_ASSERT(reverseMap.contains(i));
+ if (!reverseMap[i]->isInterface())
+ result << reverseMap[i];
+ }
+ }
+
+ return result;
+}
+
+AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const AbstractMetaClass *cppClass,
+ const Dependencies &additionalDependencies) const
+{
+ return d->classesTopologicalSorted(cppClass, additionalDependencies);
+}
+
+AbstractMetaArgumentList AbstractMetaBuilderPrivate::reverseList(const AbstractMetaArgumentList &list)
+{
+ AbstractMetaArgumentList ret;
+
+ int index = list.size();
+ for (AbstractMetaArgument *arg : list) {
+ arg->setArgumentIndex(index);
+ ret.prepend(arg);
+ index--;
+ }
+
+ return ret;
+}
+
+void AbstractMetaBuilder::setGlobalHeader(const QString& globalHeader)
+{
+ d->m_globalHeader = QFileInfo(globalHeader);
+}
+
+void AbstractMetaBuilderPrivate::setInclude(TypeEntry *te, const QString &fileName) const
+{
+ QFileInfo info(fileName);
+ if (m_globalHeader.fileName() != info.fileName())
+ te->setInclude(Include(Include::IncludePath, info.fileName()));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+template <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..f7427d488
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTMETABUILDER_H
+#define ABSTRACTMETABUILDER_H
+
+#include "abstractmetalang_typedefs.h"
+#include "dependency.h"
+
+QT_FORWARD_DECLARE_CLASS(QIODevice)
+
+class AbstractMetaBuilderPrivate;
+class AbstractMetaClass;
+class AbstractMetaEnumValue;
+
+class AbstractMetaBuilder
+{
+public:
+ enum RejectReason {
+ NotInTypeSystem,
+ GenerationDisabled,
+ RedefinedToNotClass,
+ UnmatchedArgumentType,
+ UnmatchedReturnType,
+ ApiIncompatible,
+ NoReason
+ };
+
+ AbstractMetaBuilder();
+ virtual ~AbstractMetaBuilder();
+
+ AbstractMetaClassList classes() const;
+ AbstractMetaClassList templates() const;
+ AbstractMetaClassList smartPointers() const;
+ AbstractMetaFunctionList globalFunctions() const;
+ AbstractMetaEnumList globalEnums() const;
+ // QtScript
+ QSet<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(const QByteArrayList &arguments, unsigned clangFlags = 0);
+ void setLogDirectory(const QString& logDir);
+
+ /**
+ * AbstractMetaBuilder should know what's the global header being used,
+ * so any class declared under this header wont have the include file
+ * filled.
+ */
+ void setGlobalHeader(const QString& globalHeader);
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+protected:
+ virtual AbstractMetaClass *createMetaClass();
+ virtual AbstractMetaEnum *createMetaEnum();
+ virtual AbstractMetaEnumValue *createMetaEnumValue();
+ virtual AbstractMetaField *createMetaField();
+ virtual AbstractMetaFunction *createMetaFunction();
+ virtual AbstractMetaArgument *createMetaArgument();
+ virtual AbstractMetaType *createMetaType();
+
+private:
+ friend class AbstractMetaBuilderPrivate;
+ AbstractMetaBuilderPrivate *d;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const AbstractMetaBuilder &ab);
+#endif
+
+#endif // ABSTRACTMETBUILDER_H
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
new file mode 100644
index 000000000..96a6fdbfd
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h
@@ -0,0 +1,194 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTMETABUILDER_P_H
+#define ABSTRACTMETABUILDER_P_H
+
+#include "abstractmetabuilder.h"
+#include "parser/codemodel_fwd.h"
+#include "abstractmetalang.h"
+#include "typesystem.h"
+#include "typeparser.h"
+
+#include <QSet>
+#include <QFileInfo>
+
+class TypeDatabase;
+
+class AbstractMetaBuilderPrivate
+{
+public:
+ AbstractMetaBuilderPrivate();
+ ~AbstractMetaBuilderPrivate();
+
+ static FileModelItem buildDom(const QByteArrayList &arguments, unsigned clangFlags);
+ void traverseDom(const FileModelItem &dom);
+
+ void dumpLog() const;
+ AbstractMetaClassList classesTopologicalSorted(const AbstractMetaClass *cppClass = Q_NULLPTR,
+ const Dependencies &additionalDependencies = Dependencies()) const;
+ ScopeModelItem popScope() { return m_scopes.takeLast(); }
+
+ void pushScope(ScopeModelItem item) { m_scopes << item; }
+
+ ScopeModelItem currentScope() const { return m_scopes.last(); }
+
+ AbstractMetaClass *argumentToClass(ArgumentModelItem);
+
+ void figureOutEnumValuesForClass(AbstractMetaClass *metaClass, QSet<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 QVector<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..4fa009fd2
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -0,0 +1,2784 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "abstractmetalang.h"
+#include "reporthandler.h"
+#include "typedatabase.h"
+#include "typesystem.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+# include <QtCore/QMetaEnum>
+# include <QtCore/QMetaObject>
+#endif
+
+#include <QtCore/QRegularExpression>
+#include <QtCore/QStack>
+
+#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;
+
+ // Recursively iterate over the children / descendants of the type, to check if any of them
+ // corresponds to a template argument type.
+ while (!children.isEmpty()) {
+ AbstractMetaType *child = children.pop();
+ if (child->typeEntry()->isTemplateArgument())
+ return true;
+ children << child->m_children;
+ }
+
+ return false;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const AbstractMetaType *at)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaType(";
+ if (at)
+ d << at->name();
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+/*******************************************************************************
+ * AbstractMetaArgument
+ */
+AbstractMetaArgument *AbstractMetaArgument::copy() const
+{
+ return new AbstractMetaArgument(*this);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const AbstractMetaArgument *aa)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaArgument(";
+ if (aa)
+ d << aa->toString();
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+/*******************************************************************************
+ * AbstractMetaFunction
+ */
+AbstractMetaFunction::~AbstractMetaFunction()
+{
+ qDeleteAll(m_arguments);
+ delete m_type;
+}
+
+/*******************************************************************************
+ * Indicates that this function has a modification that removes it
+ */
+bool AbstractMetaFunction::isModifiedRemoved(int types) const
+{
+ const FunctionModificationList &mods = modifications(implementingClass());
+ for (const FunctionModification &mod : mods) {
+ if (!mod.isRemoveModifier())
+ continue;
+
+ if ((mod.removal & types) == types)
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::needsCallThrough() const
+{
+ if (ownerClass()->isInterface())
+ return false;
+ if (referenceCounts(implementingClass()).size() > 0)
+ return true;
+ if (argumentsHaveNativeId() || !isStatic())
+ return true;
+
+ for (const AbstractMetaArgument *arg : m_arguments) {
+ if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags())
+ return true;
+ }
+
+ if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags()))
+ return true;
+
+ for (int i = -1; i <= arguments().size(); ++i) {
+ TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i);
+ if (owner != TypeSystem::InvalidOwnership)
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::needsSuppressUncheckedWarning() const
+{
+ for (int i = -1; i <= arguments().size(); ++i) {
+ const QVector<ReferenceCount> &referenceCounts = this->referenceCounts(implementingClass(), i);
+ for (const ReferenceCount &referenceCount : referenceCounts) {
+ if (referenceCount.action != ReferenceCount::Set)
+ return true;
+ }
+ }
+ return false;
+}
+
+QString AbstractMetaFunction::marshalledName() const
+{
+ QString returned = QLatin1String("__qt_") + name();
+ for (const AbstractMetaArgument *arg : m_arguments) {
+ returned += QLatin1Char('_');
+ if (arg->type()->isNativePointer()) {
+ returned += QLatin1String("nativepointer");
+ } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) {
+ returned += QLatin1String("int");
+ } else {
+ QString a = arg->type()->name();
+ a.replace(QLatin1String("[]"), QLatin1String("_3"));
+ a.replace(QLatin1Char('.'), QLatin1Char('_'));
+ returned += a;
+ }
+ }
+ return returned;
+}
+
+bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const
+{
+ return compareTo(&other) & NameLessThan;
+}
+
+
+/*!
+ Returns a mask of CompareResult describing how this function is
+ compares to another function
+*/
+AbstractMetaFunction::CompareResult AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const
+{
+ CompareResult result = 0;
+
+ // Enclosing class...
+ if (ownerClass() == other->ownerClass())
+ result |= EqualImplementor;
+
+ // Attributes
+ if (attributes() == other->attributes())
+ result |= EqualAttributes;
+
+ // Compare types
+ AbstractMetaType *t = type();
+ AbstractMetaType *ot = other->type();
+ if ((!t && !ot) || ((t && ot && t->name() == ot->name())))
+ result |= EqualReturnType;
+
+ // Compare names
+ int cmp = originalName().compare(other->originalName());
+
+ if (cmp < 0)
+ result |= NameLessThan;
+ else if (!cmp)
+ result |= EqualName;
+
+ // compare name after modification...
+ cmp = modifiedName().compare(other->modifiedName());
+ if (!cmp)
+ result |= EqualModifiedName;
+
+ // Compare arguments...
+ AbstractMetaArgumentList minArguments;
+ AbstractMetaArgumentList maxArguments;
+ if (arguments().size() < other->arguments().size()) {
+ minArguments = arguments();
+ maxArguments = other->arguments();
+ } else {
+ minArguments = other->arguments();
+ maxArguments = arguments();
+ }
+
+ int minCount = minArguments.size();
+ int maxCount = maxArguments.size();
+ bool same = true;
+ for (int i = 0; i < maxCount; ++i) {
+ if (i < minCount) {
+ const AbstractMetaArgument *min_arg = minArguments.at(i);
+ const AbstractMetaArgument *max_arg = maxArguments.at(i);
+ if (min_arg->type()->name() != max_arg->type()->name()
+ && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) {
+ same = false;
+ break;
+ }
+ } else {
+ if (maxArguments.at(i)->defaultValueExpression().isEmpty()) {
+ same = false;
+ break;
+ }
+ }
+ }
+
+ if (same)
+ result |= minCount == maxCount ? EqualArguments : EqualDefaultValueOverload;
+
+ return result;
+}
+
+AbstractMetaFunction *AbstractMetaFunction::copy() const
+{
+ AbstractMetaFunction *cpy = new AbstractMetaFunction;
+ cpy->setName(name());
+ cpy->setOriginalName(originalName());
+ cpy->setOwnerClass(ownerClass());
+ cpy->setImplementingClass(implementingClass());
+ cpy->setFunctionType(functionType());
+ cpy->setAttributes(attributes());
+ cpy->setDeclaringClass(declaringClass());
+ if (type())
+ cpy->setType(type()->copy());
+ cpy->setConstant(isConstant());
+ cpy->setOriginalAttributes(originalAttributes());
+
+ for (AbstractMetaArgument *arg : m_arguments)
+ cpy->addArgument(arg->copy());
+
+ Q_ASSERT((!type() && !cpy->type())
+ || (type()->instantiations() == cpy->type()->instantiations()));
+
+ return cpy;
+}
+
+bool AbstractMetaFunction::usesRValueReferences() const
+{
+ if (m_functionType == MoveConstructorFunction || m_functionType == MoveAssignmentOperatorFunction)
+ return true;
+ if (m_type && m_type->referenceType() == RValueReference)
+ return true;
+ for (const AbstractMetaArgument *a : m_arguments) {
+ if (a->type()->referenceType() == RValueReference)
+ return true;
+ }
+ return false;
+}
+
+QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const
+{
+ AbstractMetaArgumentList arguments = this->arguments();
+ if (arguments.size() == resolvedArguments.size()) {
+ QString signature = name() + QLatin1Char('(') + resolvedArguments.join(QLatin1Char(',')) + QLatin1Char(')');
+ return QStringList(TypeDatabase::normalizedSignature(signature));
+ } else {
+ QStringList returned;
+
+ AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
+ QStringList minimalTypeSignature = argument->type()->minimalSignature().split(QLatin1String("::"));
+ for (int i = 0; i < minimalTypeSignature.size(); ++i) {
+ returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
+ << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join(QLatin1String("::")));
+ }
+
+ return returned;
+ }
+}
+
+QString AbstractMetaFunction::signature() const
+{
+ if (m_cachedSignature.isEmpty()) {
+ m_cachedSignature = m_originalName;
+
+ m_cachedSignature += QLatin1Char('(');
+
+ for (int i = 0; i < m_arguments.count(); ++i) {
+ AbstractMetaArgument *a = m_arguments.at(i);
+ AbstractMetaType *t = a->type();
+ if (t) {
+ if (i > 0)
+ m_cachedSignature += QLatin1String(", ");
+ m_cachedSignature += t->cppSignature();
+ // We need to have the argument names in the qdoc files
+ m_cachedSignature += QLatin1Char(' ');
+ m_cachedSignature += a->name();
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QString::fromLatin1("No abstract meta type found for argument '%1' while"
+ "constructing signature for function '%2'.")
+ .arg(a->name(), name());
+ }
+ }
+ m_cachedSignature += QLatin1Char(')');
+
+ if (isConstant())
+ m_cachedSignature += QLatin1String(" const");
+ }
+ return m_cachedSignature;
+}
+
+int AbstractMetaFunction::actualMinimumArgumentCount() const
+{
+ AbstractMetaArgumentList arguments = this->arguments();
+
+ int count = 0;
+ for (int i = 0; i < arguments.size(); ++i && ++count) {
+ if (argumentRemoved(i + 1))
+ --count;
+ else if (!arguments.at(i)->defaultValueExpression().isEmpty())
+ break;
+ }
+
+ return count;
+}
+
+// Returns reference counts for argument at idx, or all arguments if idx == -2
+QVector<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
+{
+ QVector<ReferenceCount> returned;
+
+ const FunctionModificationList &mods = this->modifications(cls);
+ for (const FunctionModification &mod : mods) {
+ for (const ArgumentModification &argumentMod : mod.argument_mods) {
+ if (argumentMod.index != idx && idx != -2)
+ continue;
+ returned += argumentMod.referenceCounts;
+ }
+ }
+
+ return returned;
+}
+
+
+ArgumentOwner AbstractMetaFunction::argumentOwner(const AbstractMetaClass *cls, int idx) const
+{
+ const FunctionModificationList &mods = this->modifications(cls);
+ for (const FunctionModification &mod : mods) {
+ for (const ArgumentModification &argumentMod : mod.argument_mods) {
+ if (argumentMod.index != idx)
+ continue;
+ return argumentMod.owner;
+ }
+ }
+ return ArgumentOwner();
+}
+
+
+QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key
+ && !argumentModification.replacedDefaultExpression.isEmpty()) {
+ return argumentModification.replacedDefaultExpression;
+ }
+ }
+ }
+
+ return QString();
+}
+
+bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key
+ && argumentModification.removedDefaultExpression) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::resetObjectAfterUse(int argumentIdx) const
+{
+ const AbstractMetaClass *cls = declaringClass();
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == argumentIdx && argumentModification.resetAfterUse)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argumentIdx) const
+{
+ Q_ASSERT(nullPointersDisabled(mainClass, argumentIdx));
+
+ const AbstractMetaClass *cls = mainClass;
+ if (!cls)
+ cls = implementingClass();
+
+ do {
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == argumentIdx
+ && argumentModification.noNullPointers) {
+ return argumentModification.nullPointerDefaultValue;
+ }
+ }
+ }
+ cls = cls->baseClass();
+ } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class
+
+ return QString();
+
+}
+
+bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argumentIdx) const
+{
+ const AbstractMetaClass *cls = mainClass;
+ if (!cls)
+ cls = implementingClass();
+
+ do {
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == argumentIdx
+ && argumentModification.noNullPointers) {
+ return true;
+ }
+ }
+ }
+
+ cls = cls->baseClass();
+ } while (cls && !mainClass); // Once when mainClass, or once for all base classes of implementing class
+
+ return false;
+}
+
+QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index != key)
+ continue;
+
+ for (const CodeSnip &snip : argumentModification.conversion_rules) {
+ if (snip.language == language && !snip.code().isEmpty())
+ return snip.code();
+ }
+ }
+ }
+
+ return QString();
+}
+
+QString AbstractMetaFunction::argumentReplaced(int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key && !argumentModification.replace_value.isEmpty())
+ return argumentModification.replace_value;
+ }
+ }
+
+ return QString();
+}
+
+// FIXME If we remove a arg. in the method at the base class, it will not reflect here.
+bool AbstractMetaFunction::argumentRemoved(int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key) {
+ if (argumentModification.removed)
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::isVirtualSlot() const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ if (modification.isVirtualSlot())
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
+{
+ typedef QHash<TypeSystem::Language, TypeSystem::Ownership>::const_iterator OwnershipMapIt;
+
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index != key)
+ continue;
+
+ for (OwnershipMapIt it = argumentModification.ownerships.cbegin(), end = argumentModification.ownerships.cend(); it != end; ++it) {
+ if (it.value() == TypeSystem::CppOwnership)
+ return true;
+ }
+
+ }
+ }
+
+ return false;
+}
+
+bool AbstractMetaFunction::isDeprecated() const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ if (modification.isDeprecated())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaFunction::isThread() const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ if (modification.isThread())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaFunction::allowThread() const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ if (modification.allowThread())
+ return true;
+ }
+ return false;
+}
+
+
+TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key)
+ return argumentModification.ownerships.value(language, TypeSystem::InvalidOwnership);
+ }
+ }
+
+ return TypeSystem::InvalidOwnership;
+}
+
+bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const
+{
+ return isRemovedFrom(cls, TypeSystem::All);
+}
+
+bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const
+{
+ const FunctionModificationList &modifications = this->modifications(cls);
+ for (const FunctionModification &modification : modifications) {
+ if ((modification.removal & language) == language)
+ return true;
+ }
+
+ return false;
+
+}
+
+QString AbstractMetaFunction::typeReplaced(int key) const
+{
+ const FunctionModificationList &modifications = this->modifications(declaringClass());
+ for (const FunctionModification &modification : modifications) {
+ for (const ArgumentModification &argumentModification : modification.argument_mods) {
+ if (argumentModification.index == key
+ && !argumentModification.modified_type.isEmpty()) {
+ return argumentModification.modified_type;
+ }
+ }
+ }
+
+ return QString();
+}
+
+QString AbstractMetaFunction::minimalSignature() const
+{
+ if (!m_cachedMinimalSignature.isEmpty())
+ return m_cachedMinimalSignature;
+
+ QString minimalSignature = originalName() + QLatin1Char('(');
+ AbstractMetaArgumentList arguments = this->arguments();
+
+ for (int i = 0; i < arguments.count(); ++i) {
+ AbstractMetaType *t = arguments.at(i)->type();
+ if (t) {
+ if (i > 0)
+ minimalSignature += QLatin1Char(',');
+ minimalSignature += t->minimalSignature();
+ } else {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QString::fromLatin1("No abstract meta type found for argument '%1' while constructing"
+ " minimal signature for function '%2'.")
+ .arg(arguments.at(i)->name(), name());
+ }
+ }
+ minimalSignature += QLatin1Char(')');
+ if (isConstant())
+ minimalSignature += QLatin1String("const");
+
+ minimalSignature = TypeDatabase::normalizedSignature(minimalSignature);
+ m_cachedMinimalSignature = minimalSignature;
+
+ return minimalSignature;
+}
+
+FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass* implementor) const
+{
+ if (!implementor)
+ implementor = ownerClass();
+
+ if (!implementor)
+ return TypeDatabase::instance()->functionModifications(minimalSignature());
+
+ FunctionModificationList mods;
+ while (implementor) {
+ mods += implementor->typeEntry()->functionModifications(minimalSignature());
+ if ((implementor == implementor->baseClass()) ||
+ (implementor == implementingClass() && (mods.size() > 0)))
+ break;
+ const AbstractMetaClassList &interfaces = implementor->interfaces();
+ for (const AbstractMetaClass *interface : interfaces)
+ mods += this->modifications(interface);
+ implementor = implementor->baseClass();
+ }
+ return mods;
+}
+
+bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const
+{
+ return !modifications(implementor).isEmpty();
+}
+
+QString AbstractMetaFunction::argumentName(int index,
+ bool /* create */,
+ const AbstractMetaClass * /* implementor */) const
+{
+ return m_arguments[--index]->name();
+}
+
+bool AbstractMetaFunction::isCallOperator() const
+{
+ return m_name == QLatin1String("operator()");
+}
+
+bool AbstractMetaFunction::hasInjectedCode() const
+{
+ const FunctionModificationList &mods = modifications(ownerClass());
+ for (const FunctionModification &mod : mods) {
+ if (mod.isCodeInjection())
+ return true;
+ }
+ return false;
+}
+
+CodeSnipList AbstractMetaFunction::injectedCodeSnips(TypeSystem::CodeSnipPosition position, TypeSystem::Language language) const
+{
+ CodeSnipList result;
+ const FunctionModificationList &mods = modifications(ownerClass());
+ for (const FunctionModification &mod : mods) {
+ if (mod.isCodeInjection()) {
+ for (const CodeSnip &snip : mod.snips) {
+ if ((snip.language & language) && (snip.position == position || position == TypeSystem::CodeSnipPositionAny))
+ result << snip;
+ }
+ }
+ }
+ return result;
+}
+
+bool AbstractMetaFunction::hasSignatureModifications() const
+{
+ const FunctionModificationList &mods = modifications();
+ for (const FunctionModification &mod : mods) {
+ if (mod.isRenameModifier())
+ return true;
+ for (const ArgumentModification &argmod : mod.argument_mods) {
+ // since zero represents the return type and we're
+ // interested only in checking the function arguments,
+ // it will be ignored.
+ if (argmod.index > 0)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool AbstractMetaFunction::isConversionOperator(QString funcName)
+{
+ static const QRegularExpression opRegEx(QStringLiteral("^operator(?:\\s+(?:const|volatile))?\\s+(\\w+\\s*)&?$"));
+ Q_ASSERT(opRegEx.isValid());
+ return opRegEx.match(funcName).hasMatch();
+}
+
+bool AbstractMetaFunction::isOperatorOverload(QString funcName)
+{
+ if (isConversionOperator(funcName))
+ return true;
+
+ static const QRegularExpression opRegEx(QLatin1String("^operator([+\\-\\*/%=&\\|\\^\\<>!][=]?"
+ "|\\+\\+|\\-\\-|&&|\\|\\||<<[=]?|>>[=]?|~"
+ "|\\[\\]|\\s+delete\\[?\\]?"
+ "|\\(\\)"
+ "|\\s+new\\[?\\]?)$"));
+ Q_ASSERT(opRegEx.isValid());
+ return opRegEx.match(funcName).hasMatch();
+}
+
+bool AbstractMetaFunction::isCastOperator() const
+{
+ return originalName().startsWith(QLatin1String("operator "));
+}
+
+bool AbstractMetaFunction::isArithmeticOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ QString name = originalName();
+
+ // It's a dereference operator!
+ if (name == QLatin1String("operator*") && m_arguments.isEmpty())
+ return false;
+
+ return name == QLatin1String("operator+") || name == QLatin1String("operator+=")
+ || name == QLatin1String("operator-") || name == QLatin1String("operator-=")
+ || name == QLatin1String("operator*") || name == QLatin1String("operator*=")
+ || name == QLatin1String("operator/") || name == QLatin1String("operator/=")
+ || name == QLatin1String("operator%") || name == QLatin1String("operator%=")
+ || name == QLatin1String("operator++") || name == QLatin1String("operator--");
+}
+
+bool AbstractMetaFunction::isBitwiseOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ QString name = originalName();
+ return name == QLatin1String("operator<<") || name == QLatin1String("operator<<=")
+ || name == QLatin1String("operator>>") || name == QLatin1String("operator>>=")
+ || name == QLatin1String("operator&") || name == QLatin1String("operator&=")
+ || name == QLatin1String("operator|") || name == QLatin1String("operator|=")
+ || name == QLatin1String("operator^") || name == QLatin1String("operator^=")
+ || name == QLatin1String("operator~");
+}
+
+bool AbstractMetaFunction::isComparisonOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ QString name = originalName();
+ return name == QLatin1String("operator<") || name == QLatin1String("operator<=")
+ || name == QLatin1String("operator>") || name == QLatin1String("operator>=")
+ || name == QLatin1String("operator==") || name == QLatin1String("operator!=");
+}
+
+bool AbstractMetaFunction::isLogicalOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ QString name = originalName();
+ return name == QLatin1String("operator!")
+ || name == QLatin1String("operator&&")
+ || name == QLatin1String("operator||");
+}
+
+bool AbstractMetaFunction::isSubscriptOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ return originalName() == QLatin1String("operator[]");
+}
+
+bool AbstractMetaFunction::isAssignmentOperator() const
+{
+ return m_functionType == AssignmentOperatorFunction
+ || m_functionType == MoveAssignmentOperatorFunction;
+}
+
+bool AbstractMetaFunction::isOtherOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ return !isArithmeticOperator()
+ && !isBitwiseOperator()
+ && !isComparisonOperator()
+ && !isLogicalOperator()
+ && !isConversionOperator()
+ && !isSubscriptOperator()
+ && !isAssignmentOperator();
+}
+
+int AbstractMetaFunction::arityOfOperator() const
+{
+ if (!isOperatorOverload() || isCallOperator())
+ return -1;
+
+ int arity = m_arguments.size();
+
+ // Operator overloads that are class members
+ // implicitly includes the instance and have
+ // one parameter less than their arity,
+ // so we increment it.
+ if (ownerClass() && arity < 2)
+ arity++;
+
+ return arity;
+}
+
+bool AbstractMetaFunction::isInplaceOperator() const
+{
+ if (!isOperatorOverload())
+ return false;
+
+ QString name = originalName();
+ return name == QLatin1String("operator+=") || name == QLatin1String("operator&=")
+ || name == QLatin1String("operator-=") || name == QLatin1String("operator|=")
+ || name == QLatin1String("operator*=") || name == QLatin1String("operator^=")
+ || name == QLatin1String("operator/=") || name == QLatin1String("operator<<=")
+ || name == QLatin1String("operator%=") || name == QLatin1String("operator>>=");
+}
+
+bool AbstractMetaFunction::isVirtual() const
+{
+ return !isFinal() && !isSignal() && !isStatic() && !isFinalInCpp() && !isConstructor();
+}
+
+QString AbstractMetaFunction::modifiedName() const
+{
+ if (m_cachedModifiedName.isEmpty()) {
+ const FunctionModificationList &mods = modifications(implementingClass());
+ for (const FunctionModification &mod : mods) {
+ if (mod.isRenameModifier()) {
+ m_cachedModifiedName = mod.renamedToName;
+ break;
+ }
+ }
+ if (m_cachedModifiedName.isEmpty())
+ m_cachedModifiedName = name();
+ }
+ return m_cachedModifiedName;
+}
+
+QString AbstractMetaFunction::targetLangSignature(bool minimal) const
+{
+ QString s;
+
+ // Attributes...
+ if (!minimal) {
+ // Return type
+ if (type())
+ s += type()->name() + QLatin1Char(' ');
+ else
+ s += QLatin1String("void ");
+ }
+
+ s += modifiedName();
+ s += QLatin1Char('(');
+
+ int j = 0;
+ for (int i = 0; i < m_arguments.size(); ++i) {
+ if (argumentRemoved(i + 1))
+ continue;
+ if (j) {
+ s += QLatin1Char(',');
+ if (!minimal)
+ s += QLatin1Char(' ');
+ }
+ s += m_arguments.at(i)->type()->name();
+
+ if (!minimal) {
+ s += QLatin1Char(' ');
+ s += m_arguments.at(i)->name();
+ }
+ ++j;
+ }
+
+ s += QLatin1Char(')');
+
+ return s;
+}
+
+
+bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
+{
+ return a->signature() < b->signature();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction *af)
+{
+ d << '"' << af->minimalSignature() << '"';
+}
+
+void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const
+{
+ d << m_functionType << ' ' << m_type << ' ' << m_name << '(';
+ for (int i = 0, count = m_arguments.size(); i < count; ++i) {
+ if (i)
+ d << ", ";
+ d << m_arguments.at(i);
+ }
+ d << "), signature=\"" << minimalSignature() << '"';
+ if (m_constant)
+ d << " [const]";
+ if (m_invalid)
+ d << " [invalid]";
+ if (m_reverse)
+ d << " [reverse]";
+ if (m_userAdded)
+ d << " [userAdded]";
+ if (m_explicit)
+ d << " [explicit]";
+ if (m_pointerOperator)
+ d << " [operator->]";
+ if (m_isCallOperator)
+ d << " [operator()]";
+ if (m_class)
+ d << " class: " << m_class->name();
+ if (m_implementingClass)
+ d << " implementing class: " << m_implementingClass->name();
+ if (m_declaringClass)
+ d << " declaring class: " << m_declaringClass->name();
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaFunction *af)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaFunction(";
+ if (af) {
+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ if (d.verbosity() > 2) {
+ af->formatDebugVerbose(d);
+ } else {
+#endif
+ d << "signature=";
+ formatMetaFunctionBrief(d, af);
+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ }
+#endif
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+/*******************************************************************************
+ * AbstractMetaClass
+ */
+AbstractMetaClass::~AbstractMetaClass()
+{
+ qDeleteAll(m_functions);
+ qDeleteAll(m_fields);
+ qDeleteAll(m_enums);
+ if (hasTemplateBaseClassInstantiations())
+ qDeleteAll(templateBaseClassInstantiations());
+}
+
+/*******************************************************************************
+ * Returns true if this class is a subclass of the given class
+ */
+bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
+{
+ Q_ASSERT(cls);
+
+ const AbstractMetaClass *clazz = this;
+ while (clazz) {
+ if (clazz == cls)
+ return true;
+
+ clazz = clazz->baseClass();
+ }
+
+ return false;
+}
+
+/*******************************************************************************
+ * Constructs an interface based on the functions and enums in this
+ * class and returns it...
+ */
+AbstractMetaClass *AbstractMetaClass::extractInterface()
+{
+ Q_ASSERT(typeEntry()->designatedInterface());
+
+ if (!m_extractedInterface) {
+ AbstractMetaClass *iface = new AbstractMetaClass;
+ iface->setAttributes(attributes());
+ iface->setBaseClass(0);
+
+ iface->setTypeEntry(typeEntry()->designatedInterface());
+
+ for (AbstractMetaFunction *function : qAsConst(m_functions)) {
+ if (!function->isConstructor())
+ iface->addFunction(function->copy());
+ }
+
+// iface->setEnums(enums());
+// setEnums(AbstractMetaEnumList());
+
+ for (const AbstractMetaField *field : qAsConst(m_fields)) {
+ if (field->isPublic()) {
+ AbstractMetaField *new_field = field->copy();
+ new_field->setEnclosingClass(iface);
+ iface->addField(new_field);
+ }
+ }
+
+ m_extractedInterface = iface;
+ addInterface(iface);
+ }
+
+ return m_extractedInterface;
+}
+
+/*******************************************************************************
+ * Returns a list of all the functions with a given name
+ */
+AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const
+{
+ AbstractMetaFunctionList returned;
+ for (AbstractMetaFunction *function : m_functions) {
+ if (function->name() == name)
+ returned.append(function);
+ }
+
+ return returned;
+}
+
+/*******************************************************************************
+ * Returns a list of all the functions retrieved during parsing which should
+ * be added to the API.
+ */
+AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const
+{
+ FunctionQueryOptions default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang;
+
+ // Interfaces don't implement functions
+ if (isInterface())
+ default_flags |= ClassImplements;
+
+ // Only public functions in final classes
+ // default_flags |= isFinal() ? WasPublic : 0;
+ FunctionQueryOptions public_flags;
+ if (isFinal())
+ public_flags |= WasPublic;
+
+ // Constructors
+ AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags);
+
+ // Final functions
+ returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
+
+ // Virtual functions
+ returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
+
+ // Static functions
+ returned += queryFunctions(StaticFunctions | default_flags | public_flags);
+
+ // Empty, private functions, since they aren't caught by the other ones
+ returned += queryFunctions(Empty | Invisible);
+
+ return returned;
+}
+
+AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const
+{
+ const AbstractMetaFunctionList &list = functionsInShellClass();
+
+ AbstractMetaFunctionList returned;
+ for (AbstractMetaFunction *f : list) {
+ if (!f->isFinalInCpp() || f->isVirtualSlot())
+ returned += f;
+ }
+
+ return returned;
+}
+
+AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const
+{
+ if (!hasCloneOperator() && !hasExternalConversionOperators())
+ return AbstractMetaFunctionList();
+
+ AbstractMetaFunctionList returned;
+ const AbstractMetaFunctionList list = queryFunctions(Constructors) + externalConversionOperators();
+
+ // Exclude anything that uses rvalue references, be it a move
+ // constructor "QPolygon(QPolygon &&)" or something else like
+ // "QPolygon(QVector<QPoint> &&)".
+ for (AbstractMetaFunction *f : list) {
+ if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator())
+ && !f->isExplicit()
+ && f->functionType() != AbstractMetaFunction::CopyConstructorFunction
+ && !f->usesRValueReferences()
+ && !f->isModifiedRemoved()
+ && (f->originalAttributes() & Public)) {
+ returned += f;
+ }
+ }
+ return returned;
+}
+
+AbstractMetaFunctionList AbstractMetaClass::operatorOverloads(OperatorQueryOptions query) const
+{
+ const AbstractMetaFunctionList &list = queryFunctions(OperatorOverloads | Visible);
+ AbstractMetaFunctionList returned;
+ for (AbstractMetaFunction *f : list) {
+ if (((query & ArithmeticOp) && f->isArithmeticOperator())
+ || ((query & BitwiseOp) && f->isBitwiseOperator())
+ || ((query & ComparisonOp) && f->isComparisonOperator())
+ || ((query & LogicalOp) && f->isLogicalOperator())
+ || ((query & SubscriptionOp) && f->isSubscriptOperator())
+ || ((query & AssignmentOp) && f->isAssignmentOperator())
+ || ((query & ConversionOp) && f->isConversionOperator())
+ || ((query & OtherOp) && f->isOtherOperator()))
+ returned += f;
+ }
+
+ return returned;
+}
+
+bool AbstractMetaClass::hasOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isOperatorOverload() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasArithmeticOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isArithmeticOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasBitwiseOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isBitwiseOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasComparisonOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isComparisonOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasLogicalOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isLogicalOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasSubscriptOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isSubscriptOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasAssignmentOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isAssignmentOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasConversionOperatorOverload() const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->ownerClass() == f->implementingClass() && f->isConversionOperator() && !f->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+/*******************************************************************************
+ * Returns a list of all functions that should be declared and implemented in
+ * the shell class which is generated as a wrapper on top of the actual C++ class
+ */
+AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const
+{
+ // Only functions and only protected and public functions
+ FunctionQueryOptions default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell;
+
+ // All virtual functions
+ AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags);
+
+ // All functions explicitly set to be implemented by the shell class
+ // (mainly superclass functions that are hidden by other declarations)
+ returned += queryFunctions(ForcedShellFunctions | default_flags);
+
+ // All functions explicitly set to be virtual slots
+ returned += queryFunctions(VirtualSlots | default_flags);
+
+ return returned;
+}
+
+/*******************************************************************************
+ * Returns a list of all functions that require a public override function to
+ * be generated in the shell class. This includes all functions that were originally
+ * protected in the superclass.
+ */
+AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const
+{
+ return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang)
+ + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang);
+}
+
+AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const
+{
+ return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) +
+ queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell);
+}
+
+void AbstractMetaClass::sortFunctions()
+{
+ qSort(m_functions.begin(), m_functions.end(), function_sorter);
+}
+
+void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
+{
+ m_functions = functions;
+
+ // Functions must be sorted by name before next loop
+ sortFunctions();
+
+ QString currentName;
+ bool hasVirtuals = false;
+ AbstractMetaFunctionList finalFunctions;
+ for (AbstractMetaFunction *f : qAsConst(m_functions)) {
+ f->setOwnerClass(this);
+
+ m_hasVirtualSlots = m_hasVirtualSlots || f->isVirtualSlot();
+ m_hasVirtuals = m_hasVirtuals || f->isVirtualSlot() || hasVirtualDestructor();
+ m_isPolymorphic = m_isPolymorphic || m_hasVirtuals;
+ m_hasNonpublic = m_hasNonpublic || !f->isPublic();
+
+ // If we have non-virtual overloads of a virtual function, we have to implement
+ // all the overloads in the shell class to override the hiding rule
+ if (currentName == f->name()) {
+ hasVirtuals = hasVirtuals || !f->isFinal();
+ if (f->isFinal())
+ finalFunctions += f;
+ } else {
+ if (hasVirtuals && finalFunctions.size() > 0) {
+ for (AbstractMetaFunction *final_function : qAsConst(finalFunctions)) {
+ *final_function += AbstractMetaAttributes::ForceShellImplementation;
+
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("hiding of function '%1' in class '%2'")
+ .arg(final_function->name(), name());
+ }
+ }
+
+ hasVirtuals = !f->isFinal();
+ finalFunctions.clear();
+ if (f->isFinal())
+ finalFunctions += f;
+ currentName = f->name();
+ }
+ }
+}
+
+bool AbstractMetaClass::hasFieldAccessors() const
+{
+ for (const AbstractMetaField *field : m_fields) {
+ if (field->getter() || field->setter())
+ return true;
+ }
+
+ return false;
+}
+
+bool AbstractMetaClass::hasDefaultToStringFunction() const
+{
+ const AbstractMetaFunctionList &funcs = queryFunctionsByName(QLatin1String("toString"));
+ for (const AbstractMetaFunction *f : funcs) {
+ if (!f->actualMinimumArgumentCount())
+ return true;
+ }
+ return false;
+}
+
+void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
+{
+ Q_ASSERT(!function->signature().startsWith(QLatin1Char('(')));
+ function->setOwnerClass(this);
+
+ if (!function->isDestructor())
+ m_functions << function;
+ else
+ Q_ASSERT(false); //memory leak
+
+ m_hasVirtualSlots |= function->isVirtualSlot();
+ m_hasVirtuals |= !function->isFinal() || function->isVirtualSlot() || hasVirtualDestructor();
+ m_isPolymorphic |= m_hasVirtuals;
+ m_hasNonpublic |= !function->isPublic();
+}
+
+bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
+{
+ if (!other->isSignal())
+ return false;
+
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName)
+ return other->modifiedName() == f->modifiedName();
+ }
+
+ return false;
+}
+
+
+QString AbstractMetaClass::name() const
+{
+ return QString(m_typeEntry->targetLangName()).split(QLatin1String("::")).last();
+}
+
+void AbstractMetaClass::setBaseClass(AbstractMetaClass *baseClass)
+{
+ m_baseClass = baseClass;
+ if (baseClass)
+ m_isPolymorphic |= baseClass->isPolymorphic();
+}
+
+QString AbstractMetaClass::package() const
+{
+ return m_typeEntry->targetLangPackage();
+}
+
+bool AbstractMetaClass::isInterface() const
+{
+ return m_typeEntry->isInterface();
+}
+
+bool AbstractMetaClass::isNamespace() const
+{
+ return m_typeEntry->isNamespace();
+}
+
+bool AbstractMetaClass::isQObject() const
+{
+ return m_typeEntry->isQObject();
+}
+
+QString AbstractMetaClass::qualifiedCppName() const
+{
+ return m_typeEntry->qualifiedCppName();
+}
+
+bool AbstractMetaClass::hasFunction(const QString &str) const
+{
+ return findFunction(str);
+}
+
+const AbstractMetaFunction* AbstractMetaClass::findFunction(const QString& functionName) const
+{
+ for (const AbstractMetaFunction *f : m_functions) {
+ if (f->name() == functionName)
+ return f;
+ }
+ return 0;
+}
+
+bool AbstractMetaClass::hasProtectedFunctions() const
+{
+ for (AbstractMetaFunction *func : m_functions) {
+ if (func->isProtected())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasProtectedFields() const
+{
+ for (const AbstractMetaField *field : m_fields) {
+ if (field->isProtected())
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasProtectedMembers() const
+{
+ return hasProtectedFields() || hasProtectedFunctions();
+}
+
+bool AbstractMetaClass::generateShellClass() const
+{
+ return m_forceShellClass ||
+ (!isFinal()
+ && (hasVirtualFunctions()
+ || hasProtectedFunctions()
+ || hasFieldAccessors()));
+}
+
+QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const
+{
+ for (int i = 0; i < m_propertySpecs.size(); ++i)
+ if (name == m_propertySpecs.at(i)->read())
+ return m_propertySpecs.at(i);
+ return 0;
+}
+
+QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const
+{
+ for (int i = 0; i < m_propertySpecs.size(); ++i)
+ if (name == m_propertySpecs.at(i)->write())
+ return m_propertySpecs.at(i);
+ return 0;
+}
+
+QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const
+{
+ for (int i = 0; i < m_propertySpecs.size(); ++i) {
+ if (name == m_propertySpecs.at(i)->reset())
+ return m_propertySpecs.at(i);
+ }
+ return 0;
+}
+
+typedef QHash<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)
+{
+ for (const AbstractMetaFunction *f : l) {
+ if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar)
+ return true;
+ }
+ return false;
+}
+
+AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0)
+{
+}
+
+AbstractMetaField::~AbstractMetaField()
+{
+ delete m_setter;
+ delete m_getter;
+}
+
+AbstractMetaField *AbstractMetaField::copy() const
+{
+ AbstractMetaField *returned = new AbstractMetaField;
+ returned->setEnclosingClass(0);
+ returned->setAttributes(attributes());
+ returned->setName(name());
+ returned->setType(type()->copy());
+ returned->setOriginalAttributes(originalAttributes());
+
+ return returned;
+}
+
+/*******************************************************************************
+ * Indicates that this field has a modification that removes it
+ */
+bool AbstractMetaField::isModifiedRemoved(int types) const
+{
+ const FieldModificationList &mods = modifications();
+ for (const FieldModification &mod : mods) {
+ if (!mod.isRemoveModifier())
+ continue;
+
+ if ((mod.removal & types) == types)
+ return true;
+ }
+
+ return false;
+}
+
+static QString upCaseFirst(const QString &str)
+{
+ Q_ASSERT(!str.isEmpty());
+ QString s = str;
+ s[0] = s.at(0).toUpper();
+ return s;
+}
+
+static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name,
+ AbstractMetaAttributes::Attributes type)
+{
+ AbstractMetaFunction *f = new AbstractMetaFunction;
+
+ f->setName(name);
+ f->setOriginalName(name);
+ f->setOwnerClass(g->enclosingClass());
+ f->setImplementingClass(g->enclosingClass());
+ f->setDeclaringClass(g->enclosingClass());
+
+ AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native
+ | AbstractMetaAttributes::Final
+ | type;
+ if (g->isStatic())
+ attr |= AbstractMetaAttributes::Static;
+ if (g->isPublic())
+ attr |= AbstractMetaAttributes::Public;
+ else if (g->isProtected())
+ attr |= AbstractMetaAttributes::Protected;
+ else
+ attr |= AbstractMetaAttributes::Private;
+ f->setAttributes(attr);
+ f->setOriginalAttributes(attr);
+
+ const FieldModificationList &mods = g->modifications();
+ for (const FieldModification &mod : mods) {
+ if (mod.isRenameModifier())
+ f->setName(mod.renamedTo());
+ if (mod.isAccessModifier()) {
+ if (mod.isPrivate())
+ f->setVisibility(AbstractMetaAttributes::Private);
+ else if (mod.isProtected())
+ f->setVisibility(AbstractMetaAttributes::Protected);
+ else if (mod.isPublic())
+ f->setVisibility(AbstractMetaAttributes::Public);
+ else if (mod.isFriendly())
+ f->setVisibility(AbstractMetaAttributes::Friendly);
+ }
+ }
+ return f;
+}
+
+FieldModificationList AbstractMetaField::modifications() const
+{
+ const FieldModificationList &mods = enclosingClass()->typeEntry()->fieldModifications();
+ FieldModificationList returned;
+
+ for (const FieldModification &mod : mods) {
+ if (mod.name == name())
+ returned += mod;
+ }
+
+ return returned;
+}
+
+const AbstractMetaFunction *AbstractMetaField::setter() const
+{
+ if (!m_setter) {
+ m_setter = createXetter(this,
+ QLatin1String("set") + upCaseFirst(name()),
+ AbstractMetaAttributes::SetterFunction);
+ AbstractMetaArgumentList arguments;
+ AbstractMetaArgument *argument = new AbstractMetaArgument;
+ argument->setType(type()->copy());
+ argument->setName(name());
+ arguments.append(argument);
+ m_setter->setArguments(arguments);
+ }
+ return m_setter;
+}
+
+const AbstractMetaFunction *AbstractMetaField::getter() const
+{
+ if (!m_getter) {
+ m_getter = createXetter(this,
+ name(),
+ AbstractMetaAttributes::GetterFunction);
+ m_getter->setType(type());
+ }
+
+ return m_getter;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+static void formatMetaAttributes(QDebug &d, AbstractMetaAttributes::Attributes value)
+{
+ static const int meIndex = AbstractMetaAttributes::staticMetaObject.indexOfEnumerator("Attribute");
+ Q_ASSERT(meIndex >= 0);
+ const QMetaEnum me = AbstractMetaAttributes::staticMetaObject.enumerator(meIndex);
+ d << me.valueToKeys(value);
+}
+
+static void formatMetaField(QDebug &d, const AbstractMetaField *af)
+{
+ formatMetaAttributes(d, af->attributes());
+ d << ' ' << af->type()->name() << " \"" << af->name() << '"';
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaField *af)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaField(";
+ if (af)
+ formatMetaField(d, af);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+
+static void formatMetaEnumValue(QDebug &d, const AbstractMetaEnumValue *v)
+{
+ const QString &name = v->stringValue();
+ if (!name.isEmpty())
+ d << name << '=';
+ d << v->value();
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaEnumValue *v)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaEnumValue(";
+ if (v)
+ formatMetaEnumValue(d, v);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+
+QDebug operator<<(QDebug d, const AbstractMetaEnum *ae)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaEnum(";
+ if (ae) {
+ d << ae->fullName() << '[';
+ const AbstractMetaEnumValueList &values = ae->values();
+ for (int i = 0, count = values.size(); i < count; ++i) {
+ if (i)
+ d << ' ';
+ formatMetaEnumValue(d, values.at(i));
+ }
+ d << ']';
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+bool AbstractMetaClass::hasConstructors() const
+{
+ return queryFunctions(Constructors).size();
+}
+
+bool AbstractMetaClass::hasCopyConstructor() const
+{
+ const AbstractMetaFunctionList &ctors = queryFunctions(Constructors);
+ for (const AbstractMetaFunction* ctor : ctors) {
+ if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction)
+ return true;
+ }
+ return false;
+}
+
+bool AbstractMetaClass::hasPrivateCopyConstructor() const
+{
+ const AbstractMetaFunctionList &ctors = queryFunctions(Constructors);
+ for (const AbstractMetaFunction *ctor : ctors) {
+ if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate())
+ return true;
+ }
+ return false;
+}
+
+void AbstractMetaClass::addDefaultConstructor()
+{
+ AbstractMetaFunction *f = new AbstractMetaFunction;
+ f->setOriginalName(name());
+ f->setName(name());
+ f->setOwnerClass(this);
+ f->setFunctionType(AbstractMetaFunction::ConstructorFunction);
+ f->setArguments(AbstractMetaArgumentList());
+ f->setDeclaringClass(this);
+
+ AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native;
+ attr |= AbstractMetaAttributes::Public;
+ attr |= AbstractMetaAttributes::Final;
+ f->setAttributes(attr);
+ f->setImplementingClass(this);
+ f->setOriginalAttributes(f->attributes());
+
+ addFunction(f);
+ this->setHasNonPrivateConstructor(true);
+}
+
+void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate)
+{
+ AbstractMetaFunction* f = new AbstractMetaFunction;
+ f->setOriginalName(name());
+ f->setName(name());
+ f->setOwnerClass(this);
+ f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction);
+ f->setDeclaringClass(this);
+
+ AbstractMetaType* argType = new AbstractMetaType;
+ argType->setTypeEntry(typeEntry());
+ argType->setReferenceType(LValueReference);
+ argType->setConstant(true);
+ argType->setTypeUsagePattern(AbstractMetaType::ValuePattern);
+
+ AbstractMetaArgument* arg = new AbstractMetaArgument;
+ arg->setType(argType);
+ arg->setName(name());
+ f->addArgument(arg);
+
+ AbstractMetaAttributes::Attributes attr = AbstractMetaAttributes::Native;
+ attr |= AbstractMetaAttributes::Final;
+ if (isPrivate)
+ attr |= AbstractMetaAttributes::Private;
+ else
+ attr |= AbstractMetaAttributes::Public;
+ f->setAttributes(attr);
+ f->setImplementingClass(this);
+ f->setOriginalAttributes(f->attributes());
+
+ addFunction(f);
+}
+
+bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
+{
+ return functions_contains(m_functions, f);
+}
+
+/* Goes through the list of functions and returns a list of all
+ functions matching all of the criteria in \a query.
+ */
+
+AbstractMetaFunctionList AbstractMetaClass::queryFunctions(FunctionQueryOptions query) const
+{
+ AbstractMetaFunctionList functions;
+
+ for (AbstractMetaFunction *f : m_functions) {
+
+ if ((query & VirtualSlots) && !f->isVirtualSlot())
+ continue;
+
+ if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode))
+ continue;
+
+ if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode))
+ continue;
+
+ if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode))
+ continue;
+
+ if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode))
+ continue;
+
+ if ((query & Visible) && f->isPrivate())
+ continue;
+
+ if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang())
+ continue;
+
+ if ((query & Invisible) && !f->isPrivate())
+ continue;
+
+ if ((query & Empty) && !f->isEmptyFunction())
+ continue;
+
+ if ((query & WasPublic) && !f->wasPublic())
+ continue;
+
+ if ((query & WasVisible) && f->wasPrivate())
+ continue;
+
+ if ((query & WasProtected) && !f->wasProtected())
+ continue;
+
+ if ((query & ClassImplements) && f->ownerClass() != f->implementingClass())
+ continue;
+
+ if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic()))
+ continue;
+
+ if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang())
+ continue;
+
+ if ((query & FinalInCppFunctions) && !f->isFinalInCpp())
+ continue;
+
+ if ((query & VirtualInCppFunctions) && f->isFinalInCpp())
+ continue;
+
+ if ((query & Signals) && (!f->isSignal()))
+ continue;
+
+ if ((query & ForcedShellFunctions) &&
+ (!f->isForcedShellImplementation() || !f->isFinal())) {
+ continue;
+ }
+
+ if ((query & Constructors) && (!f->isConstructor() || f->ownerClass() != f->implementingClass()))
+ continue;
+
+ if (!(query & Constructors) && f->isConstructor())
+ continue;
+
+ // Destructors are never included in the functions of a class currently
+ /*
+ if ((query & Destructors) && (!f->isDestructor()
+ || f->ownerClass() != f->implementingClass())
+ || f->isDestructor() && (query & Destructors) == 0) {
+ continue;
+ }*/
+
+ if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic()))
+ continue;
+
+ if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal()))
+ continue;
+
+ if ((query & NonStaticFunctions) && (f->isStatic()))
+ continue;
+
+ if ((query & NonEmptyFunctions) && (f->isEmptyFunction()))
+ continue;
+
+ if ((query & NormalFunctions) && (f->isSignal()))
+ continue;
+
+ if ((query & AbstractFunctions) && !f->isAbstract())
+ continue;
+
+ if ((query & OperatorOverloads) && !f->isOperatorOverload())
+ continue;
+
+ functions << f;
+ }
+
+ return functions;
+}
+
+bool AbstractMetaClass::hasSignals() const
+{
+ return cppSignalFunctions().size() > 0;
+}
+
+
+/**
+ * Adds the specified interface to this class by adding all the
+ * functions in the interface to this class.
+ */
+void AbstractMetaClass::addInterface(AbstractMetaClass *interface)
+{
+ Q_ASSERT(!m_interfaces.contains(interface));
+ m_interfaces << interface;
+
+ m_isPolymorphic |= interface->isPolymorphic();
+
+ if (m_extractedInterface && m_extractedInterface != interface)
+ m_extractedInterface->addInterface(interface);
+
+
+#if 0
+ const AbstractMetaFunctionList &funcs = interface->functions();
+ for (AbstractMetaFunction *function : funcs)
+ if (!hasFunction(function) && !function->isConstructor()) {
+ AbstractMetaFunction *cpy = function->copy();
+ cpy->setImplementingClass(this);
+
+ // Setup that this function is an interface class.
+ cpy->setInterfaceClass(interface);
+ *cpy += AbstractMetaAttributes::InterfaceFunction;
+
+ // Copy the modifications in interface into the implementing classes.
+ const FunctionModificationList &mods = function->modifications(interface);
+ for (const FunctionModification &mod : mods)
+ m_typeEntry->addFunctionModification(mod);
+
+ // It should be mostly safe to assume that when we implement an interface
+ // we don't "pass on" pure virtual functions to our sublcasses...
+// *cpy -= AbstractMetaAttributes::Abstract;
+
+ addFunction(cpy);
+ }
+#endif
+
+}
+
+
+void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
+{
+ m_interfaces = interfaces;
+ for (const AbstractMetaClass *interface : interfaces) {
+ if (interface)
+ m_isPolymorphic |= interface->isPolymorphic();
+ }
+}
+
+
+AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
+{
+ for (AbstractMetaEnum *e : qAsConst(m_enums)) {
+ if (e->name() == enumName)
+ return e;
+ }
+
+ if (typeEntry()->designatedInterface())
+ return extractInterface()->findEnum(enumName);
+
+ return 0;
+}
+
+
+
+
+/*! Recursivly searches for the enum value named \a enumValueName in
+ this class and its superclasses and interfaces. Values belonging to
+ \a meta_enum are excluded from the search.
+*/
+AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum)
+{
+ for (AbstractMetaEnum *e : qAsConst(m_enums)) {
+ if (e != meta_enum)
+ continue;
+ const AbstractMetaEnumValueList &values = e->values();
+ for (AbstractMetaEnumValue *v : values) {
+ if (v->name() == enumValueName)
+ return v;
+ }
+ }
+
+ if (typeEntry()->designatedInterface())
+ return extractInterface()->findEnumValue(enumValueName, meta_enum);
+
+ if (baseClass())
+ return baseClass()->findEnumValue(enumValueName, meta_enum);
+
+ return 0;
+}
+
+
+/*!
+ * Searches through all of this class' enums for a value matching the
+ * name \a enumValueName. The name is excluding the class/namespace
+ * prefix. The function recursivly searches interfaces and baseclasses
+ * of this class.
+ */
+AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName)
+{
+ for (AbstractMetaEnum *e : qAsConst(m_enums)) {
+ const AbstractMetaEnumValueList &values = e->values();
+ for (AbstractMetaEnumValue *v : values) {
+ if (v->name() == enumValueName)
+ return e;
+ }
+ }
+
+ if (typeEntry()->designatedInterface())
+ return extractInterface()->findEnumForValue(enumValueName);
+
+ if (baseClass())
+ return baseClass()->findEnumForValue(enumValueName);
+
+ return 0;
+}
+
+
+static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type)
+{
+ if (!type)
+ return;
+
+ Q_ASSERT(metaClass);
+ const TypeEntry *entry = (type ? type->typeEntry() : 0);
+ if (entry && entry->isComplex()) {
+ const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
+ ComplexTypeEntry *class_entry = metaClass->typeEntry();
+ if (class_entry && centry->include().isValid())
+ class_entry->addExtraInclude(centry->include());
+ }
+
+ if (type->hasInstantiations()) {
+ const AbstractMetaTypeList &instantiations = type->instantiations();
+ for (const AbstractMetaType *instantiation : instantiations)
+ addExtraIncludeForType(metaClass, instantiation);
+ }
+}
+
+static void addExtraIncludesForFunction(AbstractMetaClass *metaClass, const AbstractMetaFunction *meta_function)
+{
+ Q_ASSERT(metaClass);
+ Q_ASSERT(meta_function);
+ addExtraIncludeForType(metaClass, meta_function->type());
+
+ const AbstractMetaArgumentList &arguments = meta_function->arguments();
+ for (AbstractMetaArgument *argument : arguments)
+ addExtraIncludeForType(metaClass, argument->type());
+}
+
+void AbstractMetaClass::fixFunctions()
+{
+ if (m_functionsFixed)
+ return;
+ else
+ m_functionsFixed = true;
+
+ AbstractMetaClass *superClass = baseClass();
+ AbstractMetaFunctionList funcs = functions();
+
+ if (superClass)
+ superClass->fixFunctions();
+ int iface_idx = 0;
+ while (superClass || iface_idx < interfaces().size()) {
+ // Since we always traverse the complete hierarchy we are only
+ // interrested in what each super class implements, not what
+ // we may have propagated from their base classes again.
+ AbstractMetaFunctionList superFuncs;
+ if (superClass) {
+ // Super classes can never be final
+ if (superClass->isFinalInTargetLang()) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << "Final class '" << superClass->name() << "' set to non-final, as it is extended by other classes";
+ *superClass -= AbstractMetaAttributes::FinalInTargetLang;
+ }
+ superFuncs = superClass->queryFunctions(AbstractMetaClass::ClassImplements);
+ AbstractMetaFunctionList virtuals = superClass->queryFunctions(AbstractMetaClass::VirtualInCppFunctions);
+ superFuncs += virtuals;
+ } else {
+ superFuncs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions);
+ AbstractMetaFunctionList virtuals = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::VirtualInCppFunctions);
+ superFuncs += virtuals;
+ }
+
+ QSet<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;
+ const FunctionModificationList &mods = sf->modifications(sf->implementingClass());
+ for (const FunctionModification &mod : mods) {
+ if (mod.isNonFinal()) {
+ hasNonFinalModifier = true;
+ break;
+ } else if (mod.isPrivate()) {
+ isBaseImplPrivate = true;
+ break;
+ }
+ }
+
+ if (!hasNonFinalModifier && !isBaseImplPrivate) {
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("Shadowing: %1::%2 and %3::%4")
+ .arg(sf->implementingClass()->name(), sf->signature(),
+ f->implementingClass()->name(), f->signature());
+ }
+ }
+ }
+
+ }
+
+ if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
+ AbstractMetaArgumentList arguments;
+ if (f->arguments().size() < sf->arguments().size())
+ arguments = sf->arguments();
+ else
+ arguments = f->arguments();
+ //TODO: fix this
+ //for (int i=0; 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;
+ }
+
+ for (AbstractMetaFunction *f : qAsConst(funcsToAdd))
+ funcs << f->copy();
+
+ if (superClass)
+ superClass = superClass->baseClass();
+ else
+ iface_idx++;
+ }
+
+ bool hasPrivateConstructors = false;
+ bool hasPublicConstructors = false;
+ for (AbstractMetaFunction *func : qAsConst(funcs)) {
+ const FunctionModificationList &mods = func->modifications(this);
+ for (const FunctionModification &mod : mods) {
+ if (mod.isRenameModifier()) {
+ func->setName(mod.renamedTo());
+ }
+ }
+
+ // Make sure class is abstract if one of the functions is
+ if (func->isAbstract()) {
+ (*this) += AbstractMetaAttributes::Abstract;
+ (*this) -= AbstractMetaAttributes::Final;
+ }
+
+ if (func->isConstructor()) {
+ if (func->isPrivate())
+ hasPrivateConstructors = true;
+ else
+ hasPublicConstructors = true;
+ }
+
+
+
+ // Make sure that we include files for all classes that are in use
+
+ if (!func->isRemovedFrom(this, TypeSystem::ShellCode))
+ addExtraIncludesForFunction(this, func);
+ }
+
+ if (hasPrivateConstructors && !hasPublicConstructors) {
+ (*this) += AbstractMetaAttributes::Abstract;
+ (*this) -= AbstractMetaAttributes::Final;
+ }
+
+ for (AbstractMetaFunction *f1 : qAsConst(funcs)) {
+ for (AbstractMetaFunction *f2 : qAsConst(funcs)) {
+ if (f1 != f2) {
+ const AbstractMetaFunction::CompareResult cmp = f1->compareTo(f2);
+ if ((cmp & AbstractMetaFunction::EqualName)
+ && !f1->isFinalInCpp()
+ && f2->isFinalInCpp()) {
+ *f2 += AbstractMetaAttributes::FinalOverload;
+ }
+ }
+ }
+ }
+
+ setFunctions(funcs);
+}
+
+
+QString AbstractMetaType::minimalSignature() const
+{
+ QString minimalSignature;
+ if (isConstant())
+ minimalSignature += QLatin1String("const ");
+ minimalSignature += typeEntry()->qualifiedCppName();
+ if (hasInstantiations()) {
+ AbstractMetaTypeList instantiations = this->instantiations();
+ minimalSignature += QLatin1String("< ");
+ for (int i = 0; i < instantiations.size(); ++i) {
+ if (i > 0)
+ minimalSignature += QLatin1Char(',');
+ minimalSignature += instantiations[i]->minimalSignature();
+ }
+ minimalSignature += QLatin1String(" >");
+ }
+
+ for (int j = 0; j < indirections(); ++j)
+ minimalSignature += QLatin1Char('*');
+ switch (referenceType()) {
+ case NoReference:
+ break;
+ case LValueReference:
+ minimalSignature += QLatin1Char('&');
+ break;
+ case RValueReference:
+ minimalSignature += QLatin1String("&&");
+ break;
+ }
+
+ return minimalSignature;
+}
+
+bool AbstractMetaType::hasNativeId() const
+{
+ return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
+}
+
+bool AbstractMetaType::isTargetLangEnum() const
+{
+ return isEnum() && !static_cast<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 *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes,
+ const QString &name)
+{
+ QStringList lst = name.split(QLatin1String("::"));
+
+ if (lst.size() > 1) {
+ QString prefixName = lst.at(0);
+ QString enumName = lst.at(1);
+
+ AbstractMetaClass* cl = findClass(classes, prefixName);
+ if (cl)
+ return cl->findEnumValue(enumName, 0);
+ }
+
+ for (AbstractMetaClass *metaClass : classes) {
+ const AbstractMetaEnumList &enums = metaClass->enums();
+ for (AbstractMetaEnum *metaEnum : enums) {
+ AbstractMetaEnumValue* enumValue = metaClass->findEnumValue(name, metaEnum);
+ if (enumValue)
+ return enumValue;
+ }
+ }
+
+ qCWarning(lcShiboken).noquote().nospace()
+ << QStringLiteral("no matching enum '%1'").arg(name);
+ return 0;
+}
+
+/*!
+ * Searches the list after a class that mathces \a name; either as
+ * C++, Target language base name or complete Target language package.class name.
+ */
+
+AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
+ const QString &name)
+{
+ if (name.isEmpty())
+ return 0;
+
+ for (AbstractMetaClass *c : classes) {
+ if (c->qualifiedCppName() == name)
+ return c;
+ }
+
+ for (AbstractMetaClass *c : classes) {
+ if (c->fullName() == name)
+ return c;
+ }
+
+ for (AbstractMetaClass *c : classes) {
+ if (c->name() == name)
+ return c;
+ }
+
+ return 0;
+}
+
+AbstractMetaClass *AbstractMetaClass::findClass(const AbstractMetaClassList &classes,
+ const TypeEntry* typeEntry)
+{
+ for (AbstractMetaClass* c : classes) {
+ if (c->typeEntry() == typeEntry)
+ return c;
+ }
+ return 0;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const AbstractMetaClass *ac)
+{
+ QDebugStateSaver saver(d);
+ d.noquote();
+ d.nospace();
+ d << "AbstractMetaClass(";
+ if (ac) {
+ d << '"' << ac->fullName() << '"';
+ if (ac->m_baseClass)
+ d << ", inherits \"" << ac->m_baseClass->name() << '"';
+ const AbstractMetaEnumList &enums = ac->enums();
+ if (!enums.isEmpty())
+ d << ", enums[" << enums.size() << "]=" << enums;
+ const AbstractMetaFunctionList &functions = ac->functions();
+ if (!functions.isEmpty()) {
+ const int count = functions.size();
+ d << ", functions=[" << count << "](";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ d << ", ";
+#if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ if (d.verbosity() > 2)
+ d << functions.at(i);
+ else
+#endif
+ formatMetaFunctionBrief(d, functions.at(i));
+ }
+ d << ')';
+ }
+ const AbstractMetaFieldList &fields = ac->fields();
+ if (!fields.isEmpty()) {
+ const int count = fields.size();
+ d << ", fields=[" << count << "](";
+ for (int i = 0; i < count; ++i) {
+ if (i)
+ d << ", ";
+ formatMetaField(d, fields.at(i));
+ }
+ d << ')';
+ }
+ } else {
+ d << '0';
+ }
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+QString AbstractMetaEnum::name() const
+{
+ return m_typeEntry->targetLangName();
+}
+
+QString AbstractMetaEnum::qualifier() const
+{
+ return m_typeEntry->targetLangQualifier();
+}
+
+QString AbstractMetaEnum::package() const
+{
+ return m_typeEntry->targetLangPackage();
+}
+
+bool AbstractMetaEnum::isAnonymous() const
+{
+ return m_typeEntry->isAnonymous();
+}
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h
new file mode 100644
index 000000000..4d6d5fb1f
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h
@@ -0,0 +1,1976 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTMETALANG_H
+#define ABSTRACTMETALANG_H
+
+#include "abstractmetalang_typedefs.h"
+#include "typesystem_enums.h"
+#include "typesystem_typedefs.h"
+
+#include "parser/codemodel_enums.h"
+
+#include <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
+ {
+ for (const AbstractMetaArgument *arg : m_arguments) {
+ if (arg->type()->hasNativeId())
+ return true;
+ }
+
+ return false;
+ }
+
+ bool isModifiedRemoved(int types = TypeSystem::All) const;
+
+ AbstractMetaType *type() const
+ {
+ return m_type;
+ }
+ void setType(AbstractMetaType *type)
+ {
+ Q_ASSERT(m_type == 0);
+ m_type = type;
+ }
+
+ void replaceType(AbstractMetaType *type)
+ {
+ if (m_type)
+ delete m_type;
+ m_type = type;
+ }
+
+ // The class that has this function as a member.
+ const AbstractMetaClass *ownerClass() const
+ {
+ return m_class;
+ }
+ void setOwnerClass(const AbstractMetaClass *cls)
+ {
+ m_class = cls;
+ }
+
+ // The first class in a hierarchy that declares the function
+ const AbstractMetaClass *declaringClass() const
+ {
+ return m_declaringClass;
+ }
+ void setDeclaringClass(const AbstractMetaClass *cls)
+ {
+ m_declaringClass = cls;
+ }
+
+ // The class that actually implements this function
+ const AbstractMetaClass *implementingClass() const
+ {
+ return m_implementingClass;
+ }
+ void setImplementingClass(const AbstractMetaClass *cls)
+ {
+ m_implementingClass = cls;
+ }
+
+ bool needsCallThrough() const;
+
+ AbstractMetaArgumentList arguments() const
+ {
+ return m_arguments;
+ }
+ void setArguments(const AbstractMetaArgumentList &arguments)
+ {
+ m_arguments = arguments;
+ }
+ void addArgument(AbstractMetaArgument *argument)
+ {
+ m_arguments << argument;
+ }
+ int actualMinimumArgumentCount() const;
+
+ void setInvalid(bool on)
+ {
+ m_invalid = on;
+ }
+ bool isInvalid() const
+ {
+ return m_invalid;
+ }
+ bool isDeprecated() const;
+ bool isDestructor() const
+ {
+ return functionType() == DestructorFunction;
+ }
+ bool isConstructor() const
+ {
+ return m_functionType == ConstructorFunction || m_functionType == CopyConstructorFunction
+ || m_functionType == MoveConstructorFunction;
+ }
+ bool isNormal() const
+ {
+ return functionType() == NormalFunction || isSlot() || isInGlobalScope();
+ }
+ bool isInGlobalScope() const
+ {
+ return functionType() == GlobalScopeFunction;
+ }
+ bool isSignal() const
+ {
+ return functionType() == SignalFunction;
+ }
+ bool isSlot() const
+ {
+ return functionType() == SlotFunction;
+ }
+ bool isEmptyFunction() const
+ {
+ return functionType() == EmptyFunction;
+ }
+ FunctionType functionType() const
+ {
+ return m_functionType;
+ }
+ void setFunctionType(FunctionType type)
+ {
+ m_functionType = type;
+ }
+
+ bool usesRValueReferences() const;
+ QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const;
+ QString signature() const;
+ QString targetLangSignature(bool minimal = false) const;
+ bool shouldReturnThisObject() const
+ {
+ return QLatin1String("this") == argumentReplaced(0);
+ }
+ bool shouldIgnoreReturnValue() const
+ {
+ return QLatin1String("void") == argumentReplaced(0);
+ }
+
+ bool isConstant() const
+ {
+ return m_constant;
+ }
+ void setConstant(bool constant)
+ {
+ m_constant = constant;
+ }
+
+ /// Returns true if the AbstractMetaFunction was added by the user via the type system description.
+ bool isUserAdded() const
+ {
+ return m_userAdded;
+ }
+ void setUserAdded(bool userAdded)
+ {
+ m_userAdded = userAdded;
+ }
+
+ QString toString() const
+ {
+ return m_name;
+ }
+
+ CompareResult compareTo(const AbstractMetaFunction *other) const;
+
+ bool operator <(const AbstractMetaFunction &a) const;
+
+ AbstractMetaFunction *copy() const;
+
+ QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
+ bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
+ QString conversionRule(TypeSystem::Language language, int idx) const;
+ QVector<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 AbstractMetaEnum : public AbstractMetaAttributes
+{
+public:
+ AbstractMetaEnum() : m_typeEntry(0), m_class(0), m_hasQenumsDeclaration(false) {}
+ ~AbstractMetaEnum()
+ {
+ qDeleteAll(m_enumValues);
+ }
+
+ AbstractMetaEnumValueList values() const
+ {
+ return m_enumValues;
+ }
+
+ void addEnumValue(AbstractMetaEnumValue *enumValue)
+ {
+ m_enumValues << enumValue;
+ }
+
+ QString name() const;
+
+ QString qualifier() const;
+
+ QString package() const;
+
+ QString fullName() const
+ {
+ return package() + QLatin1Char('.') + qualifier() + QLatin1Char('.') + name();
+ }
+
+ // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class?
+ void setHasQEnumsDeclaration(bool on)
+ {
+ m_hasQenumsDeclaration = on;
+ }
+
+ bool hasQEnumsDeclaration() const
+ {
+ return m_hasQenumsDeclaration;
+ }
+
+ EnumTypeEntry *typeEntry() const
+ {
+ return m_typeEntry;
+ }
+
+ void setTypeEntry(EnumTypeEntry *entry)
+ {
+ m_typeEntry = entry;
+ }
+
+ AbstractMetaClass *enclosingClass() const
+ {
+ return m_class;
+ }
+
+ void setEnclosingClass(AbstractMetaClass *c)
+ {
+ m_class = c;
+ }
+
+ bool isAnonymous() const;
+
+private:
+ AbstractMetaEnumValueList m_enumValues;
+ EnumTypeEntry *m_typeEntry;
+ AbstractMetaClass *m_class;
+
+ uint m_hasQenumsDeclaration : 1;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const AbstractMetaEnum *ae);
+#endif
+
+class AbstractMetaClass : public AbstractMetaAttributes
+{
+ Q_GADGET
+public:
+ enum FunctionQueryOption {
+ Constructors = 0x0000001, // Only constructors
+ //Destructors = 0x0000002, // Only destructors. Not included in class.
+ VirtualFunctions = 0x0000004, // Only virtual functions (virtual in both TargetLang and C++)
+ FinalInTargetLangFunctions = 0x0000008, // Only functions that are non-virtual in TargetLang
+ FinalInCppFunctions = 0x0000010, // Only functions that are non-virtual in C++
+ ClassImplements = 0x0000020, // Only functions implemented by the current class
+ Inconsistent = 0x0000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++)
+ StaticFunctions = 0x0000080, // Only static functions
+ Signals = 0x0000100, // Only signals
+ NormalFunctions = 0x0000200, // Only functions that aren't signals
+ Visible = 0x0000400, // Only public and protected functions
+ ForcedShellFunctions = 0x0000800, // Only functions that are overridden to be implemented in the shell class
+ WasPublic = 0x0001000, // Only functions that were originally public
+ WasProtected = 0x0002000, // Only functions that were originally protected
+ NonStaticFunctions = 0x0004000, // No static functions
+ Empty = 0x0008000, // Empty overrides of abstract functions
+ Invisible = 0x0010000, // Only private functions
+ VirtualInCppFunctions = 0x0020000, // Only functions that are virtual in C++
+ NonEmptyFunctions = 0x0040000, // Only functions with target language API implementations
+ VirtualInTargetLangFunctions = 0x0080000, // Only functions which are virtual in TargetLang
+ AbstractFunctions = 0x0100000, // Only abstract functions
+ WasVisible = 0x0200000, // Only functions that were public or protected in the original code
+ NotRemovedFromTargetLang = 0x0400000, // Only functions that have not been removed from TargetLang
+ NotRemovedFromShell = 0x0800000, // Only functions that have not been removed from the shell class
+ VirtualSlots = 0x1000000, // Only functions that are set as virtual slots in the type system
+ OperatorOverloads = 0x2000000 // Only functions that are operator overloads
+ };
+ Q_DECLARE_FLAGS(FunctionQueryOptions, FunctionQueryOption)
+ Q_FLAG(FunctionQueryOption)
+
+ enum OperatorQueryOption {
+ ArithmeticOp = 0x01, // Arithmetic: +, -, *, /, %, +=, -=, *=, /=, %=, ++, --, unary+, unary-
+ BitwiseOp = 0x02, // Bitwise: <<, <<=, >>, >>=, ~, &, &=, |, |=, ^, ^=
+ ComparisonOp = 0x04, // Comparison: <, <=, >, >=, !=, ==
+ LogicalOp = 0x08, // Logical: !, &&, ||
+ ConversionOp = 0x10, // Conversion: operator [const] TYPE()
+ SubscriptionOp = 0x20, // Subscription: []
+ AssignmentOp = 0x40, // Assignment: =
+ OtherOp = 0x80, // The remaining operators: call(), etc
+ AllOperators = ArithmeticOp | BitwiseOp | ComparisonOp
+ | LogicalOp | ConversionOp | SubscriptionOp
+ | AssignmentOp | OtherOp
+ };
+ Q_DECLARE_FLAGS(OperatorQueryOptions, OperatorQueryOption)
+ Q_FLAG(OperatorQueryOption)
+
+ AbstractMetaClass()
+ : m_hasVirtuals(false),
+ m_isPolymorphic(false),
+ m_hasNonpublic(false),
+ m_hasVirtualSlots(false),
+ m_hasNonPrivateConstructor(false),
+ m_functionsFixed(false),
+ m_hasPrivateDestructor(false),
+ m_hasProtectedDestructor(false),
+ m_hasVirtualDestructor(false),
+ m_forceShellClass(false),
+ m_hasHashFunction(false),
+ m_hasEqualsOperator(false),
+ m_hasCloneOperator(false),
+ m_isTypeDef(false),
+ m_hasToStringCapability(false),
+ m_enclosingClass(0),
+ m_baseClass(0),
+ m_templateBaseClass(0),
+ m_extractedInterface(0),
+ m_typeEntry(0),
+ m_stream(false)
+ {
+ }
+
+ virtual ~AbstractMetaClass();
+
+ AbstractMetaClass *extractInterface();
+ void fixFunctions();
+
+ AbstractMetaFunctionList functions() const
+ {
+ return m_functions;
+ }
+
+ void setFunctions(const AbstractMetaFunctionList &functions);
+ void addFunction(AbstractMetaFunction *function);
+ bool hasFunction(const AbstractMetaFunction *f) const;
+ bool hasFunction(const QString &str) const;
+ const AbstractMetaFunction* findFunction(const QString& functionName) const;
+ bool hasSignal(const AbstractMetaFunction *f) const;
+
+ bool hasConstructors() const;
+ bool hasCopyConstructor() const;
+ bool hasPrivateCopyConstructor() const;
+
+ void addDefaultConstructor();
+ void addDefaultCopyConstructor(bool isPrivate = false);
+
+ bool hasNonPrivateConstructor() const
+ {
+ return m_hasNonPrivateConstructor;
+ }
+
+ void setHasNonPrivateConstructor(bool value)
+ {
+ m_hasNonPrivateConstructor = value;
+ }
+
+ bool hasPrivateDestructor() const
+ {
+ return m_hasPrivateDestructor;
+ }
+
+ void setHasPrivateDestructor(bool value)
+ {
+ m_hasPrivateDestructor = value;
+ }
+
+ bool hasProtectedDestructor() const
+ {
+ return m_hasProtectedDestructor;
+ }
+
+ void setHasProtectedDestructor(bool value)
+ {
+ m_hasProtectedDestructor = value;
+ }
+
+ bool hasVirtualDestructor() const
+ {
+ return m_hasVirtualDestructor;
+ }
+
+ void setHasVirtualDestructor(bool value)
+ {
+ m_hasVirtualDestructor = value;
+ }
+
+ AbstractMetaFunctionList queryFunctionsByName(const QString &name) const;
+ AbstractMetaFunctionList queryFunctions(FunctionQueryOptions query) const;
+ AbstractMetaFunctionList functionsInTargetLang() const;
+ AbstractMetaFunctionList functionsInShellClass() const;
+ inline AbstractMetaFunctionList cppSignalFunctions() const;
+ AbstractMetaFunctionList publicOverrideFunctions() const;
+ AbstractMetaFunctionList virtualOverrideFunctions() const;
+ AbstractMetaFunctionList virtualFunctions() const;
+ AbstractMetaFunctionList implicitConversions() const;
+
+ /**
+ * Retrieves all class' operator overloads that meet
+ * query criteria defined with the OperatorQueryOption
+ * enum.
+ * /param query composition of OperatorQueryOption enum values
+ * /return list of operator overload methods that meet the
+ * query criteria
+ */
+ AbstractMetaFunctionList operatorOverloads(OperatorQueryOptions query = AllOperators) const;
+
+ bool hasOperatorOverload() const;
+ bool hasArithmeticOperatorOverload() const;
+ bool hasBitwiseOperatorOverload() const;
+ bool hasComparisonOperatorOverload() const;
+ bool hasLogicalOperatorOverload() const;
+ bool hasSubscriptOperatorOverload() const;
+ bool hasAssignmentOperatorOverload() const;
+ bool hasConversionOperatorOverload() const;
+
+ AbstractMetaFieldList fields() const
+ {
+ return m_fields;
+ }
+
+ void setFields(const AbstractMetaFieldList &fields)
+ {
+ m_fields = fields;
+ }
+
+ void addField(AbstractMetaField *field)
+ {
+ m_fields << field;
+ }
+
+ AbstractMetaEnumList enums() const
+ {
+ return m_enums;
+ }
+ void setEnums(const AbstractMetaEnumList &enums)
+ {
+ m_enums = enums;
+ }
+
+ void addEnum(AbstractMetaEnum *e)
+ {
+ m_enums << e;
+ }
+
+ AbstractMetaEnum *findEnum(const QString &enumName);
+ AbstractMetaEnum *findEnumForValue(const QString &enumName);
+ AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum);
+
+ AbstractMetaClassList interfaces() const
+ {
+ return m_interfaces;
+ }
+ void addInterface(AbstractMetaClass *interface);
+ void setInterfaces(const AbstractMetaClassList &interface);
+
+ QString fullName() const
+ {
+ return package() + QLatin1Char('.') + name();
+ }
+
+ /**
+ * Retrieves the class name without any namespace/scope information.
+ * /return the class name without scope information
+ */
+ QString name() const;
+
+ QString baseClassName() const
+ {
+ return m_baseClass ? m_baseClass->name() : QString();
+ }
+
+ AbstractMetaClass *baseClass() const
+ {
+ return m_baseClass;
+ }
+
+ void setBaseClass(AbstractMetaClass *base_class);
+
+ const AbstractMetaClass *enclosingClass() const
+ {
+ return m_enclosingClass;
+ }
+
+ void setEnclosingClass(AbstractMetaClass *cl)
+ {
+ m_enclosingClass = cl;
+ }
+
+ const AbstractMetaClassList& innerClasses() const
+ {
+ return m_innerClasses;
+ }
+
+ void addInnerClass(AbstractMetaClass* cl)
+ {
+ m_innerClasses << cl;
+ }
+
+ void setInnerClasses(AbstractMetaClassList innerClasses)
+ {
+ m_innerClasses = innerClasses;
+ }
+
+ QString package() const;
+
+ bool isInterface() const;
+
+ bool isNamespace() const;
+
+ bool isQObject() const;
+
+ bool isQtNamespace() const
+ {
+ return isNamespace() && name() == QLatin1String("Qt");
+ }
+
+ QString qualifiedCppName() const;
+
+ bool hasSignals() const;
+ bool inheritsFrom(const AbstractMetaClass *other) const;
+
+ void setForceShellClass(bool on)
+ {
+ m_forceShellClass = on;
+ }
+
+ bool generateShellClass() const;
+
+ bool hasVirtualSlots() const
+ {
+ return m_hasVirtualSlots;
+ }
+
+ /**
+ * Says if a class has any virtual functions of its own.
+ * \return true if the class implements any virtual methods
+ */
+ bool hasVirtualFunctions() const
+ {
+ return !isFinal() && m_hasVirtuals;
+ }
+ /**
+ * Says if the class that declares or inherits a virtual function.
+ * \return true if the class implements or inherits any virtual methods
+ */
+ bool isPolymorphic() const
+ {
+ return m_isPolymorphic;
+ }
+
+ /**
+ * Tells if this class has one or more functions that are protected.
+ * \return true if the class has protected functions.
+ */
+ bool hasProtectedFunctions() const;
+
+ /**
+ * Tells if this class has one or more fields (member variables) that are protected.
+ * \return true if the class has protected fields.
+ */
+ bool hasProtectedFields() const;
+
+ /**
+ * Tells if this class has one or more members (functions or fields) that are protected.
+ * \return true if the class has protected members.
+ */
+ bool hasProtectedMembers() const;
+
+
+ QVector<TypeEntry *> templateArguments() const
+ {
+ return m_templateArgs;
+ }
+
+ void setTemplateArguments(const QVector<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;
+ }
+
+ QVector<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;
+ QVector<QPropertySpec *> m_propertySpecs;
+ AbstractMetaClassList m_innerClasses;
+
+ AbstractMetaFunctionList m_externalConversionOperators;
+
+ QStringList m_baseClassNames;
+ QVector<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..da8369895
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang_typedefs.h
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ABSTRACTMETALANG_TYPEDEFS_H
+#define ABSTRACTMETALANG_TYPEDEFS_H
+
+#include <QtCore/QVector>
+
+class AbstractMetaClass;
+class AbstractMetaField;
+class AbstractMetaArgument;
+class AbstractMetaEnum;
+class AbstractMetaEnumValue;
+class AbstractMetaFunction;
+class AbstractMetaType;
+
+typedef QVector<AbstractMetaArgument *> AbstractMetaArgumentList;
+typedef QVector<AbstractMetaClass *> AbstractMetaClassList;
+typedef QVector<AbstractMetaEnum *> AbstractMetaEnumList;
+typedef QVector<AbstractMetaEnumValue *> AbstractMetaEnumValueList;
+typedef QVector<AbstractMetaField *> AbstractMetaFieldList;
+typedef QVector<AbstractMetaFunction *> AbstractMetaFunctionList;
+typedef QVector<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..abb7c08b9
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/apiextractor.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "apiextractor.h"
+#include "abstractmetalang.h"
+
+#include <QDir>
+#include <QDebug>
+#include <QTemporaryFile>
+#include <algorithm>
+#include <iostream>
+#include <iterator>
+
+#include "reporthandler.h"
+#include "typesystem.h"
+#include "fileout.h"
+#include "abstractmetabuilder.h"
+#include "typedatabase.h"
+#include "typesystem.h"
+
+static bool appendFile(const QString& sourceFileName, QFile& targetFile)
+{
+ QFile sourceFile(sourceFileName);
+ if (!sourceFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ std::cerr << "Cannot open " << qPrintable(QDir::toNativeSeparators(sourceFileName))
+ << ": " << qPrintable(sourceFile.errorString()) << '\n';
+ return false;
+ }
+ targetFile.write(sourceFile.readAll());
+ return true;
+}
+
+ApiExtractor::ApiExtractor() : m_builder(0)
+{
+ // Environment TYPESYSTEMPATH
+ QString envTypesystemPaths = QFile::decodeName(getenv("TYPESYSTEMPATH"));
+ if (!envTypesystemPaths.isEmpty())
+ TypeDatabase::instance()->addTypesystemPath(envTypesystemPaths);
+}
+
+ApiExtractor::~ApiExtractor()
+{
+ delete m_builder;
+}
+
+void ApiExtractor::addTypesystemSearchPath (const QString& path)
+{
+ TypeDatabase::instance()->addTypesystemPath(path);
+}
+
+void ApiExtractor::addTypesystemSearchPath(const QStringList& paths)
+{
+ for (const QString &path : paths)
+ addTypesystemSearchPath(path);
+}
+
+void ApiExtractor::addIncludePath(const HeaderPath& path)
+{
+ m_includePaths << path;
+}
+
+void ApiExtractor::addIncludePath(const HeaderPaths& paths)
+{
+ m_includePaths << paths;
+}
+
+void ApiExtractor::setLogDirectory(const QString& logDir)
+{
+ m_logDirectory = logDir;
+}
+
+void ApiExtractor::setCppFileName(const QString& cppFileName)
+{
+ m_cppFileName = cppFileName;
+}
+
+void ApiExtractor::setTypeSystem(const QString& typeSystemFileName)
+{
+ m_typeSystemFileName = typeSystemFileName;
+}
+
+void ApiExtractor::setDebugLevel(ReportHandler::DebugLevel debugLevel)
+{
+ ReportHandler::setDebugLevel(debugLevel);
+}
+
+void ApiExtractor::setSuppressWarnings ( bool value )
+{
+ TypeDatabase::instance()->setSuppressWarnings(value);
+}
+
+void ApiExtractor::setSilent ( bool value )
+{
+ ReportHandler::setSilent(value);
+}
+
+bool ApiExtractor::setApiVersion(const QString& package, const QString &version)
+{
+ return TypeDatabase::instance()->setApiVersion(package, version);
+}
+
+void ApiExtractor::setDropTypeEntries(QString dropEntries)
+{
+ dropEntries.remove(QLatin1Char(' '));
+ QStringList entries = dropEntries.split(QLatin1Char(';'));
+ TypeDatabase::instance()->setDropTypeEntries(entries);
+}
+
+AbstractMetaEnumList ApiExtractor::globalEnums() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->globalEnums();
+}
+
+AbstractMetaFunctionList ApiExtractor::globalFunctions() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->globalFunctions();
+}
+
+AbstractMetaClassList ApiExtractor::classes() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->classes();
+}
+
+AbstractMetaClassList ApiExtractor::smartPointers() const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->smartPointers();
+}
+
+AbstractMetaClassList ApiExtractor::classesTopologicalSorted(const Dependencies &additionalDependencies) const
+{
+ Q_ASSERT(m_builder);
+ return m_builder->classesTopologicalSorted(Q_NULLPTR, additionalDependencies);
+}
+
+PrimitiveTypeEntryList ApiExtractor::primitiveTypes() const
+{
+ return TypeDatabase::instance()->primitiveTypes();
+}
+
+ContainerTypeEntryList ApiExtractor::containerTypes() const
+{
+ return TypeDatabase::instance()->containerTypes();
+}
+
+QSet<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;
+ for (const AbstractMetaClass* metaClass : qAsConst(metaClasses)) {
+ const AbstractMetaEnumList &enums = metaClass->enums();
+ for (const AbstractMetaEnum *metaEnum : enums) {
+ if (metaEnum->typeEntry() == typeEntry) {
+ result = metaEnum;
+ break;
+ }
+ }
+ if (result)
+ break;
+ result = findEnumOnClasses(metaClass->innerClasses(), typeEntry);
+ }
+ return result;
+}
+
+const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const EnumTypeEntry* typeEntry) const
+{
+ if (!typeEntry)
+ return 0;
+ const AbstractMetaEnumList &globalEnums = m_builder->globalEnums();
+ for (AbstractMetaEnum* metaEnum : globalEnums) {
+ if (metaEnum->typeEntry() == typeEntry)
+ return metaEnum;
+ }
+ return findEnumOnClasses(m_builder->classes(), typeEntry);
+}
+
+const AbstractMetaEnum* ApiExtractor::findAbstractMetaEnum(const TypeEntry* typeEntry) const
+{
+ if (!typeEntry)
+ return 0;
+ if (typeEntry->isFlags())
+ return findAbstractMetaEnum(reinterpret_cast<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;
+ }
+
+ const QString pattern = QDir::tempPath() + QLatin1Char('/') +
+ QFileInfo(m_cppFileName).baseName() + QStringLiteral("_XXXXXX.hpp");
+ QTemporaryFile ppFile(pattern);
+ bool autoRemove = !qEnvironmentVariableIsSet("KEEP_TEMP_FILES");
+ // make sure that a tempfile can be written
+ if (!ppFile.open()) {
+ std::cerr << "could not create tempfile " << qPrintable(pattern)
+ << ": " << qPrintable(ppFile.errorString()) << '\n';
+ return false;
+ }
+
+ if (!appendFile(m_cppFileName, ppFile))
+ return false;
+ const QString preprocessedCppFileName = ppFile.fileName();
+ ppFile.close();
+ m_builder = new AbstractMetaBuilder;
+ m_builder->setLogDirectory(m_logDirectory);
+ m_builder->setGlobalHeader(m_cppFileName);
+ QByteArrayList arguments;
+ arguments.reserve(m_includePaths.size() + 1);
+ for (const HeaderPath &headerPath : qAsConst(m_includePaths))
+ arguments.append(HeaderPath::includeOption(headerPath));
+ arguments.append(QFile::encodeName(preprocessedCppFileName));
+ qCDebug(lcShiboken) << __FUNCTION__ << arguments;
+ const bool result = m_builder->build(arguments);
+ if (!result)
+ autoRemove = false;
+ if (!autoRemove) {
+ ppFile.setAutoRemove(false);
+ std::cerr << "Keeping temporary file: " << qPrintable(QDir::toNativeSeparators(preprocessedCppFileName)) << '\n';
+ }
+ return result;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+template <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..ac90f5b2f
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/apiextractor.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APIEXTRACTOR_H
+#define APIEXTRACTOR_H
+
+#include "reporthandler.h"
+#include "dependency.h"
+#include "abstractmetalang_typedefs.h"
+#include "apiextractormacros.h"
+#include "header_paths.h"
+#include "typedatabase_typedefs.h"
+#include "typesystem_typedefs.h"
+#include <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 HeaderPath& path);
+ void addIncludePath(const HeaderPaths& paths);
+ HeaderPaths includePaths() const { return m_includePaths; }
+ void setLogDirectory(const QString& logDir);
+ bool setApiVersion(const QString& package, const QString& version);
+ void setDropTypeEntries(QString dropEntries);
+
+ AbstractMetaEnumList globalEnums() const;
+ AbstractMetaFunctionList globalFunctions() const;
+ AbstractMetaClassList classes() const;
+ AbstractMetaClassList smartPointers() const;
+ AbstractMetaClassList classesTopologicalSorted(const Dependencies &additionalDependencies = Dependencies()) const;
+ PrimitiveTypeEntryList primitiveTypes() const;
+ ContainerTypeEntryList containerTypes() const;
+ QSet<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;
+ HeaderPaths m_includePaths;
+ AbstractMetaBuilder* m_builder;
+ QString m_logDirectory;
+
+ // disable copy
+ ApiExtractor(const ApiExtractor&);
+ ApiExtractor& operator=(const ApiExtractor&);
+#ifndef QT_NO_DEBUG_STREAM
+ friend QDebug operator<<(QDebug d, const ApiExtractor &ae);
+#endif
+};
+
+#endif // APIEXTRACTOR_H
diff --git a/sources/shiboken2/ApiExtractor/apiextractormacros.h b/sources/shiboken2/ApiExtractor/apiextractormacros.h
new file mode 100644
index 000000000..41a710773
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/apiextractormacros.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef APIEXTRACTORMACROS_H
+#define APIEXTRACTORMACROS_H
+
+
+// APIEXTRACTOR_API is used for the public API symbols.
+#if defined _WIN32
+ #define APIEXTRACTOR_DEPRECATED(func) __declspec(deprecated) func
+#elif __GNUC__ >= 4
+ #define APIEXTRACTOR_DEPRECATED(func) func __attribute__ ((deprecated))
+#else
+ #define APIEXTRACTOR_DEPRECATED(func) func
+#endif
+#endif
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
new file mode 100644
index 000000000..dc0c59dd5
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp
@@ -0,0 +1,770 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clangbuilder.h"
+#include "compilersupport.h"
+#include "clangutils.h"
+
+#include <codemodel.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QHash>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStack>
+#include <QtCore/QVector>
+
+#include <string.h>
+
+#if QT_VERSION < 0x050800
+# define Q_FALLTHROUGH() (void)0
+#endif
+
+namespace clang {
+
+static inline QString colonColon() { return QStringLiteral("::"); }
+static inline QString templateBrackets() { return QStringLiteral("<>"); }
+
+static inline bool isClassCursor(const CXCursor &c)
+{
+ return c.kind == CXCursor_ClassDecl || c.kind == CXCursor_StructDecl
+ || c.kind == CXCursor_ClassTemplate
+ || c.kind == CXCursor_ClassTemplatePartialSpecialization;
+}
+
+static inline bool withinClassDeclaration(const CXCursor &cursor)
+{
+ return isClassCursor(clang_getCursorLexicalParent(cursor));
+}
+
+static QString fixTypeName(QString t)
+{
+ // Fix "Foo &" -> "Foo&", similarly "Bar **" -> "Bar**"
+ int pos = t.size() - 1;
+ for (; pos >= 0 && (t.at(pos) == QLatin1Char('&') || t.at(pos) == QLatin1Char('*')); --pos) {}
+ if (pos > 0 && t.at(pos) == QLatin1Char(' '))
+ t.remove(pos, 1);
+ return t;
+}
+
+// Insert template parameter to class name: "Foo<>" -> "Foo<T1>" -> "Foo<T1,T2>"
+// This needs to be done immediately when template parameters are encountered since
+// the class name "Foo<T1,T2>" is the scope for nested items.
+static bool insertTemplateParameterIntoClassName(const QString &parmName, QString *name)
+{
+ if (Q_UNLIKELY(!name->endsWith(QLatin1Char('>'))))
+ return false;
+ const bool needsComma = name->at(name->size() - 2) != QLatin1Char('<');
+ const int insertionPos = name->size() - 1;
+ name->insert(insertionPos, parmName);
+ if (needsComma)
+ name->insert(insertionPos, QLatin1Char(','));
+ return true;
+}
+
+static inline bool insertTemplateParameterIntoClassName(const QString &parmName,
+ const ClassModelItem &item)
+{
+ QString name = item->name();
+ const bool result = insertTemplateParameterIntoClassName(parmName, &name);
+ item->setName(name);
+ return result;
+}
+
+static inline CodeModel::AccessPolicy accessPolicy(CX_CXXAccessSpecifier access)
+{
+ CodeModel::AccessPolicy result = CodeModel::Public;
+ switch (access) {
+ case CX_CXXProtected:
+ result = CodeModel::Protected;
+ break;
+ case CX_CXXPrivate:
+ result = CodeModel::Private;
+ break;
+ default:
+ break;
+ }
+ return result;
+}
+
+static void setFileName(const CXCursor &cursor, _CodeModelItem *item)
+{
+ const SourceRange range = getCursorRange(cursor);
+ if (!range.first.file.isEmpty()) { // Has been observed to be 0 for invalid locations
+ item->setFileName(QDir::cleanPath(range.first.file));
+ item->setStartPosition(int(range.first.line), int(range.first.column));
+ item->setEndPosition(int(range.second.line), int(range.second.column));
+ }
+}
+
+class BuilderPrivate {
+public:
+ typedef QHash<CXCursor, ClassModelItem> CursorClassHash;
+ typedef QHash<CXCursor, TypeDefModelItem> CursorTypedefHash;
+
+ explicit BuilderPrivate(BaseVisitor *bv) : m_baseVisitor(bv), m_model(new CodeModel)
+ {
+ m_scopeStack.push(NamespaceModelItem(new _FileModelItem(m_model)));
+ }
+
+ // Determine scope from top item. Note that the scope list does not necessarily
+ // match the scope stack in case of forward-declared inner classes whose definition
+ // appears in the translation unit while the scope is the outer class.
+ void updateScope()
+ {
+ if (m_scopeStack.size() <= 1)
+ m_scope.clear();
+ else
+ m_scope = m_scopeStack.back()->scope() << m_scopeStack.back()->name();
+ }
+
+ void pushScope(const ScopeModelItem &i)
+ {
+ m_scopeStack.push(i);
+ updateScope();
+ }
+
+ void popScope()
+ {
+ m_scopeStack.pop();
+ updateScope();
+ }
+
+ bool addClass(const CXCursor &cursor, CodeModel::ClassType t);
+ FunctionModelItem createFunction(const CXCursor &cursor,
+ CodeModel::FunctionType t = CodeModel::Normal) const;
+ FunctionModelItem createMemberFunction(const CXCursor &cursor,
+ CodeModel::FunctionType t = CodeModel::Normal) const;
+ void qualifyConstructor(const CXCursor &cursor);
+ TypeInfo createTypeInfo(const CXType &type) const;
+ TypeInfo createTypeInfo(const CXCursor &cursor) const
+ { return createTypeInfo(clang_getCursorType(cursor)); }
+
+ TemplateParameterModelItem createTemplateParameter(const CXCursor &cursor) const;
+ TemplateParameterModelItem createNonTypeTemplateParameter(const CXCursor &cursor) const;
+ void addField(const CXCursor &cursor);
+
+ QString cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const;
+ void addBaseClass(const CXCursor &cursor);
+
+ template <class Item>
+ void qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const;
+
+ BaseVisitor *m_baseVisitor;
+ CodeModel *m_model;
+
+ QStack<ScopeModelItem> m_scopeStack;
+ QStringList m_scope;
+ // Store all classes by cursor so that base classes can be found and inner
+ // classes can be correctly parented in case of forward-declared inner classes
+ // (QMetaObject::Connection)
+ CursorClassHash m_cursorClassHash;
+ CursorTypedefHash m_cursorTypedefHash;
+
+ ClassModelItem m_currentClass;
+ EnumModelItem m_currentEnum;
+ FunctionModelItem m_currentFunction;
+ ArgumentModelItem m_currentArgument;
+ VariableModelItem m_currentField;
+
+ int m_anonymousEnumCount = 0;
+ CodeModel::FunctionType m_currentFunctionType = CodeModel::Normal;
+};
+
+bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t)
+{
+ QString className = getCursorSpelling(cursor);
+ m_currentClass.reset(new _ClassModelItem(m_model, className));
+ setFileName(cursor, m_currentClass.data());
+ m_currentClass->setClassType(t);
+ // Some inner class? Note that it does not need to be (lexically) contained in a
+ // class since it is possible to forward declare an inner class:
+ // class QMetaObject { class Connection; }
+ // class QMetaObject::Connection {}
+ const CXCursor semPar = clang_getCursorSemanticParent(cursor);
+ if (isClassCursor(semPar)) {
+ const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(semPar);
+ if (it == m_cursorClassHash.constEnd()) {
+ const QString message = QStringLiteral("Unable to find parent of inner class ") + className;
+ const Diagnostic d(message, cursor, CXDiagnostic_Error);
+ qWarning() << d;
+ m_baseVisitor->appendDiagnostic(d);
+ return false;
+ }
+ const ClassModelItem &containingClass = it.value();
+ containingClass->addClass(m_currentClass);
+ m_currentClass->setScope(containingClass->scope() << containingClass->name());
+ } else {
+ m_currentClass->setScope(m_scope);
+ m_scopeStack.back()->addClass(m_currentClass);
+ }
+ pushScope(m_currentClass);
+ m_cursorClassHash.insert(cursor, m_currentClass);
+ return true;
+}
+
+FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor,
+ CodeModel::FunctionType t) const
+{
+ QString name = getCursorSpelling(cursor);
+ // Apply type fixes to "operator X &" -> "operator X&"
+ if (name.startsWith(QLatin1String("operator ")))
+ name = fixTypeName(name);
+ FunctionModelItem result(new _FunctionModelItem(m_model, name));
+ setFileName(cursor, result.data());
+ result->setType(createTypeInfo(clang_getCursorResultType(cursor)));
+ result->setFunctionType(t);
+ result->setScope(m_scope);
+ result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static);
+ return result;
+}
+
+FunctionModelItem BuilderPrivate::createMemberFunction(const CXCursor &cursor,
+ CodeModel::FunctionType t) const
+{
+ FunctionModelItem result = createFunction(cursor, t);
+ result->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
+ result->setConstant(clang_CXXMethod_isConst(cursor) != 0);
+ result->setStatic(clang_CXXMethod_isStatic(cursor) != 0);
+ result->setVirtual(clang_CXXMethod_isVirtual(cursor) != 0);
+ result->setAbstract(clang_CXXMethod_isPureVirtual(cursor) != 0);
+ result->setFunctionType(m_currentFunctionType);
+ return result;
+}
+
+// For CXCursor_Constructor, on endToken().
+void BuilderPrivate::qualifyConstructor(const CXCursor &cursor)
+{
+ // Clang does not tell us whether a constructor is explicit, preventing it
+ // from being used for implicit conversions. Try to guess whether a
+ // constructor is explicit in the C++99 sense (1 parameter) by checking for
+ // isConvertingConstructor() == 0. Fixme: The notion of "isConvertingConstructor"
+ // should be used in the code model instead of "explicit"
+ if (clang_CXXConstructor_isDefaultConstructor(cursor) == 0
+ && m_currentFunction->arguments().size() == 1
+ && clang_CXXConstructor_isCopyConstructor(cursor) == 0
+ && clang_CXXConstructor_isMoveConstructor(cursor) == 0) {
+ m_currentFunction->setExplicit(clang_CXXConstructor_isConvertingConstructor(cursor) == 0);
+ }
+}
+
+TemplateParameterModelItem BuilderPrivate::createTemplateParameter(const CXCursor &cursor) const
+{
+ return TemplateParameterModelItem(new _TemplateParameterModelItem(m_model, getCursorSpelling(cursor)));
+}
+
+TemplateParameterModelItem BuilderPrivate::createNonTypeTemplateParameter(const CXCursor &cursor) const
+{
+ TemplateParameterModelItem result = createTemplateParameter(cursor);
+ result->setType(createTypeInfo(cursor));
+ return result;
+}
+
+// CXCursor_VarDecl, CXCursor_FieldDecl cursors
+void BuilderPrivate::addField(const CXCursor &cursor)
+{
+ VariableModelItem field(new _VariableModelItem(m_model, getCursorSpelling(cursor)));
+ field->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
+ field->setScope(m_scope);
+ field->setType(createTypeInfo(cursor));
+ field->setMutable(clang_CXXField_isMutable(cursor) != 0);
+ m_currentField = field;
+ m_scopeStack.back()->addVariable(field);
+}
+
+// Array helpers: Parse "a[2][4]" into a list of dimensions
+
+struct ArrayDimensionResult
+{
+ QVector<QStringRef> dimensions;
+ int position;
+};
+
+static ArrayDimensionResult arrayDimensions(const QString &typeName)
+{
+ ArrayDimensionResult result;
+ result.position = typeName.indexOf(QLatin1Char('['));
+ for (int openingPos = result.position; openingPos != -1; ) {
+ const int closingPos = typeName.indexOf(QLatin1Char(']'), openingPos + 1);
+ if (closingPos == -1)
+ break;
+ result.dimensions.append(typeName.midRef(openingPos + 1, closingPos - openingPos - 1));
+ openingPos = typeName.indexOf(QLatin1Char('['), closingPos + 1);
+ }
+ return result;
+}
+
+// Array helpers: Parse "a[2][4]" into a list of dimensions or "" for none
+static QStringList parseArrayArgs(const CXType &type, QString *typeName)
+{
+ const ArrayDimensionResult dimensions = arrayDimensions(*typeName);
+ Q_ASSERT(!dimensions.dimensions.isEmpty());
+
+ QStringList result;
+ // get first dimension from clang, preferably.
+ // "a[]" is seen as pointer by Clang, set special indicator ""
+ const long long size = clang_getArraySize(type);
+ result.append(size >= 0 ? QString::number(size) : QString());
+ // Parse out remaining dimensions
+ for (int i = 1, count = dimensions.dimensions.size(); i < count; ++i)
+ result.append(dimensions.dimensions.at(i).toString());
+ typeName->truncate(dimensions.position);
+ return result;
+}
+
+TypeInfo BuilderPrivate::createTypeInfo(const CXType &type) const
+{
+ if (type.kind == CXType_Pointer) { // Check for function pointers, first.
+ const CXType pointeeType = clang_getPointeeType(type);
+ const int argCount = clang_getNumArgTypes(pointeeType);
+ if (argCount >= 0) {
+ TypeInfo result = createTypeInfo(clang_getResultType(pointeeType));
+ result.setFunctionPointer(true);
+ for (int a = 0; a < argCount; ++a)
+ result.addArgument(createTypeInfo(clang_getArgType(pointeeType, unsigned(a))));
+ return result;
+ }
+ }
+
+ TypeInfo typeInfo;
+ QString typeName = fixTypeName(getTypeName(type));
+
+ int indirections = 0;
+ // "int **"
+ for ( ; typeName.endsWith(QLatin1Char('*')) ; ++indirections)
+ typeName.chop(1);
+ typeInfo.setIndirections(indirections);
+ // "int &&"
+ if (typeName.endsWith(QLatin1String("&&"))) {
+ typeName.chop(2);
+ typeInfo.setReferenceType(RValueReference);
+ } else if (typeName.endsWith(QLatin1Char('&'))) { // "int &"
+ typeName.chop(1);
+ typeInfo.setReferenceType(LValueReference);
+ }
+
+ // "int [3], int[]"
+ if (type.kind == CXType_ConstantArray || type.kind == CXType_IncompleteArray
+ || type.kind == CXType_VariableArray || type.kind == CXType_DependentSizedArray) {
+ typeInfo.setArrayElements(parseArrayArgs(type, &typeName));
+ }
+
+ bool isConstant = clang_isConstQualifiedType(type) != 0;
+ // A "char *const" parameter, is considered to be const-qualified by Clang, but
+ // not in the TypeInfo sense (corresponds to "char *" and not "const char *").
+ if (type.kind == CXType_Pointer && isConstant && typeName.endsWith(QLatin1String("const"))) {
+ typeName.chop(5);
+ typeName = typeName.trimmed();
+ isConstant = false;
+ }
+ // Clang has been observed to return false for "const int .."
+ if (!isConstant && typeName.startsWith(QLatin1String("const "))) {
+ typeName.remove(0, 6);
+ isConstant = true;
+ }
+ typeInfo.setConstant(isConstant);
+
+ // clang_isVolatileQualifiedType() returns true for "volatile int", but not for "volatile int *"
+ if (typeName.startsWith(QLatin1String("volatile "))) {
+ typeName.remove(0, 9);
+ typeInfo.setVolatile(true);
+ }
+
+ typeName = typeName.trimmed();
+
+ typeInfo.setQualifiedName(typeName.split(colonColon()));
+ // 3320:CINDEX_LINKAGE int clang_getNumArgTypes(CXType T); function ptr types?
+ return typeInfo;
+}
+
+// extract an expression from the cursor via source
+// CXCursor_EnumConstantDecl, ParmDecl (a = Flag1 | Flag2)
+QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &cursor) const
+{
+ BaseVisitor::CodeSnippet snippet = bv->getCodeSnippet(cursor);
+ const char *equalSign = std::find(snippet.first, snippet.second, '=');
+ if (equalSign == snippet.second)
+ return QString();
+ ++equalSign;
+ return QString::fromLocal8Bit(equalSign, int(snippet.second - equalSign)).trimmed();
+}
+
+// Add a base class to the current class from CXCursor_CXXBaseSpecifier
+void BuilderPrivate::addBaseClass(const CXCursor &cursor)
+{
+ const CXType inheritedType = clang_getCursorType(cursor); // Note spelling has "struct baseClass",
+ QString baseClassName = getTypeName(inheritedType); // use type.
+ const CXCursor declCursor = clang_getTypeDeclaration(inheritedType);
+ const CursorClassHash::const_iterator it = m_cursorClassHash.constFind(declCursor);
+ if (it == m_cursorClassHash.constEnd()) {
+ // Set unqualified name. This happens in cases like "class X : public std::list<...>"
+ // "template<class T> class Foo : public T" and standard types like true_type, false_type.
+ m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName);
+ return;
+ }
+ // Completely qualify the class name by looking it up and taking its scope
+ // plus the actual baseClass stripped off any scopes. Consider:
+ // namespace std {
+ // template <class T> class vector {};
+ // namespace n {
+ // class Foo : public vector<int> {};
+ // }
+ // }
+ // should have "std::vector<int>" as base class (whereas the type of the base class is
+ // "std::vector<T>").
+ const QStringList &baseScope = it.value()->scope();
+ if (!baseScope.isEmpty()) {
+ const int lastSep = baseClassName.lastIndexOf(colonColon());
+ if (lastSep >= 0)
+ baseClassName.remove(0, lastSep + colonColon().size());
+ baseClassName.prepend(colonColon());
+ baseClassName.prepend(baseScope.join(colonColon()));
+ }
+ m_currentClass->setBaseClasses(m_currentClass->baseClasses() << baseClassName);
+}
+
+static inline CXCursor definitionFromTypeRef(const CXCursor &typeRefCursor)
+{
+ Q_ASSERT(typeRefCursor.kind == CXCursor_TypeRef);
+ return clang_getTypeDeclaration(clang_getCursorType(typeRefCursor));
+}
+
+// Qualify function arguments or fields that are typedef'ed from another scope:
+// enum ConversionFlag {};
+// typedef QFlags<ConversionFlag> ConversionFlags;
+// class QTextCodec {
+// enum ConversionFlag {};
+// typedef QFlags<ConversionFlag> ConversionFlags;
+// struct ConverterState {
+// explicit ConverterState(ConversionFlags);
+// ^^ qualify to QTextCodec::ConversionFlags
+// ConversionFlags m_flags;
+// ^^ ditto
+
+template <class Item> // ArgumentModelItem, VariableModelItem
+void BuilderPrivate::qualifyTypeDef(const CXCursor &typeRefCursor, const QSharedPointer<Item> &item) const
+{
+ typedef typename CursorTypedefHash::const_iterator ConstIt;
+
+ TypeInfo type = item->type();
+ if (type.qualifiedName().size() == 1) { // item's type is unqualified.
+ const ConstIt it = m_cursorTypedefHash.constFind(definitionFromTypeRef(typeRefCursor));
+ if (it != m_cursorTypedefHash.constEnd() && !it.value()->scope().isEmpty()) {
+ type.setQualifiedName(it.value()->scope() + type.qualifiedName());
+ item->setType(type);
+ }
+ }
+}
+
+Builder::Builder()
+{
+ d = new BuilderPrivate(this);
+}
+
+Builder::~Builder()
+{
+ delete d;
+}
+
+bool Builder::visitLocation(const CXSourceLocation &location) const
+{
+ return !clang_Location_isInSystemHeader(location);
+}
+
+FileModelItem Builder::dom() const
+{
+ Q_ASSERT(!d->m_scopeStack.isEmpty());
+ return qSharedPointerDynamicCast<_FileModelItem>(d->m_scopeStack.constFirst());
+}
+
+static QString msgOutOfOrder(const CXCursor &cursor, const char *expectedScope)
+{
+ return getCursorKindName(cursor.kind) + QLatin1Char(' ')
+ + getCursorSpelling(cursor) + QLatin1String(" encountered outside ")
+ + QLatin1String(expectedScope) + QLatin1Char('.');
+}
+
+static CodeModel::ClassType codeModelClassTypeFromCursor(CXCursorKind kind)
+{
+ CodeModel::ClassType result = CodeModel::Class;
+ if (kind == CXCursor_UnionDecl)
+ result = CodeModel::Union;
+ else if (kind == CXCursor_StructDecl)
+ result = CodeModel::Struct;
+ return result;
+}
+
+BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor)
+{
+ switch (cursor.kind) {
+ case CXCursor_CXXAccessSpecifier:
+ d->m_currentFunctionType = CodeModel::Normal;
+ break;
+ case CXCursor_AnnotateAttr: {
+ const QString annotation = getCursorSpelling(cursor);
+ if (annotation == QLatin1String("qt_slot"))
+ d->m_currentFunctionType = CodeModel::Slot;
+ else if (annotation == QLatin1String("qt_signal"))
+ d->m_currentFunctionType = CodeModel::Signal;
+ else
+ d->m_currentFunctionType = CodeModel::Normal;
+ }
+ break;
+ case CXCursor_CXXBaseSpecifier:
+ if (d->m_currentClass.isNull()) {
+ const Diagnostic d(msgOutOfOrder(cursor, "class"), cursor, CXDiagnostic_Error);
+ qWarning() << d;
+ appendDiagnostic(d);
+ return Error;
+ }
+ d->addBaseClass(cursor);
+ break;
+ case CXCursor_ClassDecl:
+ case CXCursor_UnionDecl:
+ case CXCursor_StructDecl:
+ if (clang_isCursorDefinition(cursor) == 0)
+ return Skip;
+ if (!d->addClass(cursor, codeModelClassTypeFromCursor(cursor.kind)))
+ return Error;
+ break;
+ case CXCursor_ClassTemplate:
+ case CXCursor_ClassTemplatePartialSpecialization:
+ if (clang_isCursorDefinition(cursor) == 0)
+ return Skip;
+ d->addClass(cursor, CodeModel::Class);
+ d->m_currentClass->setName(d->m_currentClass->name() + templateBrackets());
+ d->m_scope.back() += templateBrackets();
+ break;
+ case CXCursor_EnumDecl: {
+ QString name = getCursorSpelling(cursor);
+ const bool anonymous = name.isEmpty();
+ if (anonymous)
+ name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount);
+ d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name));
+ setFileName(cursor, d->m_currentEnum.data());
+ d->m_currentEnum->setScope(d->m_scope);
+ d->m_currentEnum->setAnonymous(anonymous);
+ if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull())
+ d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor)));
+ d->m_scopeStack.back()->addEnum(d->m_currentEnum);
+ }
+ break;
+ case CXCursor_EnumConstantDecl: {
+ const QString name = getCursorSpelling(cursor);
+ if (d->m_currentEnum.isNull()) {
+ const Diagnostic d(msgOutOfOrder(cursor, "enum"), cursor, CXDiagnostic_Error);
+ qWarning() << d;
+ appendDiagnostic(d);
+ return Error;
+ }
+ EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name));
+ enumConstant->setValue(d->cursorValueExpression(this, cursor));
+ d->m_currentEnum->addEnumerator(enumConstant);
+ }
+ break;
+ case CXCursor_VarDecl:
+ // static class members are seen as CXCursor_VarDecl
+ if (!d->m_currentClass.isNull() && isClassCursor(clang_getCursorSemanticParent(cursor))) {
+ d->addField(cursor);
+ d->m_currentField->setStatic(true);
+ }
+ break;
+ case CXCursor_FieldDecl:
+ d->addField(cursor);
+ break;
+#if CINDEX_VERSION_MAJOR > 0 || CINDEX_VERSION_MINOR >= 37 // Clang 4.0
+ case CXCursor_FriendDecl:
+ return Skip;
+#endif
+ case CXCursor_Constructor:
+ case CXCursor_Destructor: // Note: Also use clang_CXXConstructor_is..Constructor?
+ case CXCursor_CXXMethod:
+ case CXCursor_ConversionFunction:
+ // Skip inline member functions outside class, only go by declarations inside class
+ if (!withinClassDeclaration(cursor))
+ return Skip;
+ d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal);
+ d->m_scopeStack.back()->addFunction(d->m_currentFunction);
+ break;
+ // Not fully supported, currently, seen as normal function
+ // Note: May appear inside class (member template) or outside (free template).
+ case CXCursor_FunctionTemplate: {
+ const CXCursor semParent = clang_getCursorSemanticParent(cursor);
+ if (isClassCursor(semParent)) {
+ if (semParent == clang_getCursorLexicalParent(cursor)) {
+ d->m_currentFunction = d->createMemberFunction(cursor, CodeModel::Normal);
+ d->m_scopeStack.back()->addFunction(d->m_currentFunction);
+ break;
+ } else {
+ return Skip; // inline member functions outside class
+ }
+ }
+ }
+ Q_FALLTHROUGH(); // fall through to free template function.
+ case CXCursor_FunctionDecl:
+ d->m_currentFunction = d->createFunction(cursor);
+ d->m_scopeStack.back()->addFunction(d->m_currentFunction);
+ break;
+ case CXCursor_Namespace: {
+ const QString name = getCursorSpelling(cursor);
+ const NamespaceModelItem parentNamespaceItem = qSharedPointerDynamicCast<_NamespaceModelItem>(d->m_scopeStack.back());
+ if (parentNamespaceItem.isNull()) {
+ const QString message = msgOutOfOrder(cursor, "namespace")
+ + QLatin1String(" (current scope: ") + d->m_scopeStack.back()->name() + QLatin1Char(')');
+ const Diagnostic d(message, cursor, CXDiagnostic_Error);
+ qWarning() << d;
+ appendDiagnostic(d);
+ return Error;
+ }
+ // If possible, continue existing namespace (as otherwise, all headers
+ // where a namespace is continued show up in the type database).
+ NamespaceModelItem namespaceItem = parentNamespaceItem->findNamespace(name);
+ if (namespaceItem.isNull()) {
+ namespaceItem.reset(new _NamespaceModelItem(d->m_model, name));
+ setFileName(cursor, namespaceItem.data());
+ namespaceItem->setScope(d->m_scope);
+ parentNamespaceItem->addNamespace(namespaceItem);
+ }
+ d->pushScope(namespaceItem);
+ }
+ break;
+ case CXCursor_ParmDecl:
+ // Skip in case of nested CXCursor_ParmDecls in case one parameter is a function pointer
+ // and function pointer typedefs.
+ if (d->m_currentArgument.isNull() && !d->m_currentFunction.isNull()) {
+ const QString name = getCursorSpelling(cursor);
+ d->m_currentArgument.reset(new _ArgumentModelItem(d->m_model, name));
+ d->m_currentArgument->setType(d->createTypeInfo(cursor));
+ d->m_currentFunction->addArgument(d->m_currentArgument);
+ QString defaultValueExpression = d->cursorValueExpression(this, cursor);
+ if (!defaultValueExpression.isEmpty()) {
+ d->m_currentArgument->setDefaultValueExpression(defaultValueExpression);
+ d->m_currentArgument->setDefaultValue(true);
+ }
+ } else {
+ return Skip;
+ }
+ break;
+ case CXCursor_TemplateTypeParameter:
+ case CXCursor_NonTypeTemplateParameter: {
+ const TemplateParameterModelItem tItem = cursor.kind == CXCursor_TemplateTemplateParameter
+ ? d->createTemplateParameter(cursor) : d->createNonTypeTemplateParameter(cursor);
+ // Apply to function/member template?
+ if (!d->m_currentFunction.isNull()) {
+ d->m_currentFunction->setTemplateParameters(d->m_currentFunction->templateParameters() << tItem);
+ } else if (!d->m_currentClass.isNull()) { // Apply to class
+ const QString &tplParmName = tItem->name();
+ if (Q_UNLIKELY(!insertTemplateParameterIntoClassName(tplParmName, d->m_currentClass)
+ || !insertTemplateParameterIntoClassName(tplParmName, &d->m_scope.back()))) {
+ const QString message = QStringLiteral("Error inserting template parameter \"") + tplParmName
+ + QStringLiteral("\" into ") + d->m_currentClass->name();
+ const Diagnostic d(message, cursor, CXDiagnostic_Error);
+ qWarning() << d;
+ appendDiagnostic(d);
+ return Error;
+ }
+ d->m_currentClass->setTemplateParameters(d->m_currentClass->templateParameters() << tItem);
+ }
+ }
+ break;
+ case CXCursor_TypeAliasDecl:
+ case CXCursor_TypeAliasTemplateDecl: // May contain nested CXCursor_TemplateTypeParameter
+ return Skip;
+ case CXCursor_TypedefDecl: {
+ const QString name = getCursorSpelling(cursor);
+ TypeDefModelItem item(new _TypeDefModelItem(d->m_model, name));
+ setFileName(cursor, item.data());
+ item->setType(d->createTypeInfo(clang_getTypedefDeclUnderlyingType(cursor)));
+ item->setScope(d->m_scope);
+ d->m_scopeStack.back()->addTypeDef(item);
+ d->m_cursorTypedefHash.insert(cursor, item);
+ }
+ break;
+ case CXCursor_TypeRef:
+ if (!d->m_currentFunction.isNull()) {
+ if (d->m_currentArgument.isNull())
+ d->qualifyTypeDef(cursor, d->m_currentFunction); // return type
+ else
+ d->qualifyTypeDef(cursor, d->m_currentArgument);
+ } else if (!d->m_currentField.isNull()) {
+ d->qualifyTypeDef(cursor, d->m_currentField);
+ }
+ break;
+ default:
+ break;
+ }
+ return BaseVisitor::Recurse;
+}
+
+bool Builder::endToken(const CXCursor &cursor)
+{
+ switch (cursor.kind) {
+ case CXCursor_UnionDecl:
+ case CXCursor_ClassDecl:
+ case CXCursor_StructDecl:
+ case CXCursor_ClassTemplate:
+ case CXCursor_ClassTemplatePartialSpecialization:
+ d->popScope();
+ // Continue in outer class after leaving inner class?
+ if (ClassModelItem lastClass = qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()))
+ d->m_currentClass = lastClass;
+ else
+ d->m_currentClass.clear();
+ d->m_currentFunctionType = CodeModel::Normal;
+ break;
+ case CXCursor_EnumDecl:
+ d->m_currentEnum.clear();
+ break;
+ case CXCursor_VarDecl:
+ case CXCursor_FieldDecl:
+ d->m_currentField.clear();
+ break;
+ case CXCursor_Constructor:
+ d->qualifyConstructor(cursor);
+ d->m_currentFunction.clear();
+ break;
+ case CXCursor_Destructor:
+ case CXCursor_CXXMethod:
+ case CXCursor_FunctionDecl:
+ case CXCursor_FunctionTemplate:
+ d->m_currentFunction.clear();
+ break;
+ case CXCursor_Namespace:
+ d->popScope();
+ break;
+ case CXCursor_ParmDecl:
+ d->m_currentArgument.clear();
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+} // namespace clang
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h
new file mode 100644
index 000000000..c97b7d2b7
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.h
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLANGBUILDER_H
+#define CLANGBUILDER_H
+
+#include "clangparser.h"
+
+#include <codemodel_fwd.h>
+
+namespace clang {
+
+class BuilderPrivate;
+
+class Builder : public BaseVisitor {
+public:
+ Builder();
+ ~Builder();
+
+ bool visitLocation(const CXSourceLocation &location) const override;
+
+ StartTokenResult startToken(const CXCursor &cursor) override;
+ bool endToken(const CXCursor &cursor) override;
+
+ FileModelItem dom() const;
+
+private:
+ BuilderPrivate *d;
+};
+
+} // namespace clang
+
+#endif // CLANGBUILDER_H
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp
new file mode 100644
index 000000000..8d0fd098a
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.cpp
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clangdebugutils.h"
+#include "clangutils.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+
+#include <string.h>
+
+#ifndef QT_NO_DEBUG_STREAM
+
+#ifdef Q_OS_WIN
+const char pathSep = '\\';
+#else
+const char pathSep = '/';
+#endif
+
+static const char *baseName(const char *fileName)
+{
+ const char *b = strrchr(fileName, pathSep);
+ return b ? b + 1 : fileName;
+}
+
+QDebug operator<<(QDebug s, const CXString &cs)
+{
+ s << clang_getCString(cs);
+ return s;
+}
+
+QDebug operator<<(QDebug s, CXCursorKind cursorKind) // Enum
+{
+ const CXString kindName = clang_getCursorKindSpelling(cursorKind);
+ s << kindName;
+ clang_disposeString(kindName);
+ return s;
+}
+
+static const char *accessSpecsStrings[]
+{
+ // CX_CXXInvalidAccessSpecifier, CX_CXXPublic, CX_CXXProtected, CX_CXXPrivate
+ "invalid", "public", "protected", "private"
+};
+
+QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac)
+{
+ s << accessSpecsStrings[ac];
+ return s;
+}
+
+QDebug operator<<(QDebug s, const CXType &t)
+{
+ CXString typeSpelling = clang_getTypeSpelling(t);
+ s << typeSpelling;
+ clang_disposeString(typeSpelling);
+ return s;
+}
+
+QDebug operator<<(QDebug s, const CXCursor &cursor)
+{
+ QDebugStateSaver saver(s);
+ s.nospace();
+ s.noquote();
+ const CXCursorKind kind = clang_getCursorKind(cursor);
+ s << kind;
+ if (kind >= CXCursor_FirstInvalid && kind <= CXCursor_LastInvalid)
+ return s;
+ const CXType type = clang_getCursorType(cursor);
+ switch (kind) {
+ case CXCursor_CXXAccessSpecifier:
+ s << ' ' << clang_getCXXAccessSpecifier(cursor);
+ break;
+ case CXCursor_CXXBaseSpecifier:
+ s << ", inherits=\"" << clang::getCursorSpelling(clang_getTypeDeclaration(type)) << '"';
+ break;
+ case CXCursor_CXXMethod:
+ case CXCursor_FunctionDecl:
+ case CXCursor_ConversionFunction:
+ s << ", result type=\"" << clang_getCursorResultType(cursor) << '"';
+ break;
+ case CXCursor_TypedefDecl:
+ s << ", underlyingType=\"" << clang_getTypedefDeclUnderlyingType(cursor) << '"';
+ break;
+ default:
+ break;
+ }
+
+ if (type.kind != CXType_Invalid)
+ s << ", type=\"" << type << '"';
+ if (clang_Cursor_hasAttrs(cursor))
+ s << ", [attrs]";
+
+ const QString cursorSpelling = clang::getCursorSpelling(cursor);
+ if (!cursorSpelling.isEmpty())
+ s << ", spelling=\"" << cursorSpelling << '"';
+ CXString cursorDisplay = clang_getCursorDisplayName(cursor);
+ if (const char *dpy = clang_getCString(cursorDisplay)) {
+ const QString display = QString::fromUtf8(dpy);
+ if (display != cursorSpelling)
+ s << ", display=\"" << dpy << '"';
+ }
+ clang_disposeString(cursorDisplay);
+ return s;
+}
+
+QDebug operator<<(QDebug s, const CXSourceLocation &location)
+{
+ QDebugStateSaver saver(s);
+ s.nospace();
+ CXFile file; // void *
+ unsigned line;
+ unsigned column;
+ unsigned offset;
+ clang_getExpansionLocation(location, &file, &line, &column, &offset);
+ const CXString cxFileName = clang_getFileName(file);
+ // Has been observed to be 0 for invalid locations
+ if (const char *cFileName = clang_getCString(cxFileName))
+ s << baseName(cFileName) << ':';
+ s << line << ':' << column;
+ clang_disposeString(cxFileName);
+ return s;
+}
+
+#endif // !QT_NO_DEBUG_STREAM
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h
new file mode 100644
index 000000000..323efdd2a
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangdebugutils.h
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLANGDEBUGUTILS_H
+#define CLANGDEBUGUTILS_H
+
+#include <QtCore/QtGlobal>
+
+#include <clang-c/Index.h>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+QT_FORWARD_DECLARE_CLASS(QString)
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug s, const CXString &cs);
+QDebug operator<<(QDebug s, CXCursorKind cursorKind);
+QDebug operator<<(QDebug s, CX_CXXAccessSpecifier ac);
+QDebug operator<<(QDebug s, const CXType &t);
+QDebug operator<<(QDebug s, const CXCursor &cursor);
+QDebug operator<<(QDebug s, const CXSourceLocation &location);
+#endif // !QT_NO_DEBUG_STREAM
+
+#endif // CLANGDEBUGUTILS_H
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
new file mode 100644
index 000000000..eb3be115c
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.cpp
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clangparser.h"
+#include "clangutils.h"
+#include "clangdebugutils.h"
+#include "compilersupport.h"
+
+#include <QtCore/QByteArrayList>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QScopedArrayPointer>
+#include <QtCore/QString>
+
+namespace clang {
+
+SourceFileCache::Snippet SourceFileCache::getCodeSnippet(const CXCursor &cursor)
+{
+ Snippet result(nullptr, nullptr);
+ const SourceRange range = getCursorRange(cursor);
+ if (range.first.file.isEmpty() || range.second.file != range.first.file)
+ return result;
+ FileBufferCache::Iterator it = m_fileBufferCache.find(range.first.file);
+ if (it == m_fileBufferCache.end()) {
+ QFile file(range.first.file);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning().noquote().nospace()
+ << "Can't open " << QDir::toNativeSeparators(range.first.file)
+ << ": " << file.errorString();
+ return result;
+ }
+ it = m_fileBufferCache.insert(range.first.file, file.readAll());
+ }
+
+ const unsigned pos = range.first.offset;
+ const unsigned end = range.second.offset;
+ const QByteArray &contents = it.value();
+ if (end >= unsigned(contents.size())) {
+ qWarning().noquote().nospace() << "Range end " << end << " is above size of "
+ << range.first.file << " (" << contents.size() << ')';
+ return result;
+ }
+ result.first = contents.constData() + pos;
+ result.second = contents.constData() + end;
+ return result;
+}
+
+BaseVisitor::BaseVisitor() = default;
+BaseVisitor::~BaseVisitor() = default;
+
+bool BaseVisitor::visitLocation(const CXSourceLocation &location) const
+{
+ return clang_Location_isFromMainFile(location) != 0;
+}
+
+BaseVisitor::StartTokenResult BaseVisitor::cbHandleStartToken(const CXCursor &cursor)
+{
+ switch (cursor.kind) {
+ default:
+ break;
+ }
+
+ return startToken(cursor);
+}
+
+bool BaseVisitor::cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult)
+{
+ const bool result = startResult != Recurse || endToken(cursor);
+ switch (cursor.kind) {
+ default:
+ break;
+ }
+
+ return result;
+}
+
+BaseVisitor::CodeSnippet BaseVisitor::getCodeSnippet(const CXCursor &cursor)
+{
+ CodeSnippet result = m_fileCache.getCodeSnippet(cursor);
+ if (result.first == nullptr)
+ appendDiagnostic(Diagnostic(QStringLiteral("Unable to retrieve code snippet."), cursor, CXDiagnostic_Error));
+ return result;
+}
+
+QString BaseVisitor::getCodeSnippetString(const CXCursor &cursor)
+{
+ CodeSnippet result = m_fileCache.getCodeSnippet(cursor);
+ return result.first != nullptr
+ ? QString::fromUtf8(result.first, int(result.second - result.first))
+ : QString();
+}
+
+static CXChildVisitResult
+ visitorCallback(CXCursor cursor, CXCursor /* parent */, CXClientData clientData)
+{
+ BaseVisitor *bv = reinterpret_cast<BaseVisitor *>(clientData);
+
+ const CXSourceLocation location = clang_getCursorLocation(cursor);
+ if (!bv->visitLocation(location))
+ return CXChildVisit_Continue;
+
+ const BaseVisitor::StartTokenResult startResult = bv->cbHandleStartToken(cursor);
+ switch (startResult) {
+ case clang::BaseVisitor::Error:
+ return CXChildVisit_Break;
+ case clang::BaseVisitor::Skip:
+ break;
+ case clang::BaseVisitor::Recurse:
+ clang_visitChildren(cursor, visitorCallback, clientData);
+ break;
+ }
+
+ if (!bv->cbHandleEndToken(cursor, startResult))
+ return CXChildVisit_Break;
+
+ return CXChildVisit_Continue;
+}
+
+BaseVisitor::Diagnostics BaseVisitor::diagnostics() const
+{
+ return m_diagnostics;
+}
+
+void BaseVisitor::setDiagnostics(const Diagnostics &d)
+{
+ m_diagnostics = d;
+}
+
+void BaseVisitor::appendDiagnostic(const Diagnostic &d)
+{
+ m_diagnostics.append(d);
+}
+
+static inline const char **byteArrayListToFlatArgV(const QByteArrayList &bl)
+{
+ const char **result = new const char *[bl.size() + 1];
+ result[bl.size()] = nullptr;
+ std::transform(bl.cbegin(), bl.cend(), result,
+ [] (const QByteArray &a) { return a.constData(); });
+ return result;
+}
+
+static QByteArray msgCreateTranslationUnit(const QByteArrayList clangArgs, unsigned flags)
+{
+ QByteArray result = "clang_parseTranslationUnit2(0x";
+ result += QByteArray::number(flags, 16);
+ const int count = clangArgs.size();
+ result += ", cmd[" + QByteArray::number(count) + "]=";
+ for (int i = 0; i < count; ++i) {
+ const QByteArray &arg = clangArgs.at(i);
+ if (i)
+ result += ' ';
+ const bool quote = arg.contains(' ') || arg.contains('(');
+ if (quote)
+ result += '"';
+ result += arg;
+ if (quote)
+ result += '"';
+ }
+ result += ')';
+ return result;
+}
+
+static CXTranslationUnit createTranslationUnit(CXIndex index,
+ const QByteArrayList &args,
+ unsigned flags = 0)
+{
+ // courtesy qdoc
+ const unsigned defaultFlags = CXTranslationUnit_SkipFunctionBodies
+ | CXTranslationUnit_Incomplete;
+
+ static const QByteArrayList defaultArgs = {
+ "-std=c++14", // ! otherwise, t.h is parsed as "C"
+ "-fPIC",
+ "-fno-exceptions", // Workaround for clang bug http://reviews.llvm.org/D17988
+#ifdef Q_OS_MACOS
+ "-Wno-expansion-to-defined", // Workaround for warnings in Darwin stdlib, see
+ // https://github.com/darlinghq/darling/issues/204
+#endif
+ "-Wno-constant-logical-operand"
+ };
+
+ const QByteArrayList clangArgs = emulatedCompilerOptions() + defaultArgs + args;
+ QScopedArrayPointer<const char *> argv(byteArrayListToFlatArgV(clangArgs));
+ qDebug().noquote().nospace() << msgCreateTranslationUnit(clangArgs, flags);
+
+ CXTranslationUnit tu;
+ CXErrorCode err = clang_parseTranslationUnit2(index, nullptr, argv.data(),
+ clangArgs.size(), nullptr, 0,
+ defaultFlags | flags, &tu);
+ if (err || !tu) {
+ qWarning().noquote().nospace() << "Could not parse "
+ << clangArgs.constLast().constData() << ", error code: " << err;
+ return nullptr;
+ }
+ return tu;
+}
+
+/* clangFlags are flags to clang_parseTranslationUnit2() such as
+ * CXTranslationUnit_KeepGoing (from CINDEX_VERSION_MAJOR/CINDEX_VERSION_MINOR 0.35)
+ */
+
+bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &bv)
+{
+ CXIndex index = clang_createIndex(0 /* excludeDeclarationsFromPCH */,
+ 1 /* displayDiagnostics */);
+ if (!index) {
+ qWarning() << "clang_createIndex() failed!";
+ return false;
+ }
+
+ CXTranslationUnit translationUnit = createTranslationUnit(index, clangArgs, clangFlags);
+ if (!translationUnit)
+ return false;
+
+ CXCursor rootCursor = clang_getTranslationUnitCursor(translationUnit);
+
+ clang_visitChildren(rootCursor, visitorCallback, reinterpret_cast<CXClientData>(&bv));
+
+ QVector<Diagnostic> diagnostics = getDiagnostics(translationUnit);
+ diagnostics.append(bv.diagnostics());
+ bv.setDiagnostics(diagnostics);
+
+ const bool ok = maxSeverity(diagnostics) < CXDiagnostic_Error;
+ if (!ok) {
+ QDebug debug = qWarning();
+ debug.noquote();
+ debug.nospace();
+ debug << "Errors in "
+ << QDir::toNativeSeparators(QFile::decodeName(clangArgs.constLast())) << ":\n";
+ for (const Diagnostic &diagnostic : diagnostics)
+ debug << diagnostic << '\n';
+ }
+
+ clang_disposeTranslationUnit(translationUnit);
+ clang_disposeIndex(index);
+ return ok;
+}
+
+} // namespace clang
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangparser.h b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h
new file mode 100644
index 000000000..ef1424f17
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangparser.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLANGPARSER_H
+#define CLANGPARSER_H
+
+#include <clang-c/Index.h>
+
+#include <QtCore/QByteArrayList>
+#include <QtCore/QHash>
+#include <QtCore/QPair>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+namespace clang {
+
+struct Diagnostic;
+
+class SourceFileCache {
+public:
+ typedef QPair<const char *, const char *> Snippet;
+
+ Snippet getCodeSnippet(const CXCursor &cursor);
+
+private:
+ typedef QHash<QString, QByteArray> FileBufferCache;
+
+ FileBufferCache m_fileBufferCache;
+};
+
+class BaseVisitor {
+ Q_DISABLE_COPY(BaseVisitor)
+public:
+ typedef QVector<Diagnostic> Diagnostics;
+ typedef SourceFileCache::Snippet CodeSnippet;
+
+ enum StartTokenResult { Error, Skip, Recurse };
+
+ BaseVisitor();
+ virtual ~BaseVisitor();
+
+ // Whether location should be visited.
+ // defaults to clang_Location_isFromMainFile()
+ virtual bool visitLocation(const CXSourceLocation &location) const;
+
+ virtual StartTokenResult startToken(const CXCursor &cursor) = 0;
+ virtual bool endToken(const CXCursor &cursor) = 0;
+
+ StartTokenResult cbHandleStartToken(const CXCursor &cursor);
+ bool cbHandleEndToken(const CXCursor &cursor, StartTokenResult startResult);
+
+ CodeSnippet getCodeSnippet(const CXCursor &cursor);
+ QString getCodeSnippetString(const CXCursor &cursor);
+
+ Diagnostics diagnostics() const;
+ void setDiagnostics(const Diagnostics &d);
+ void appendDiagnostic(const Diagnostic &d);
+
+private:
+ SourceFileCache m_fileCache;
+ Diagnostics m_diagnostics;
+};
+
+bool parse(const QByteArrayList &clangArgs, unsigned clangFlags, BaseVisitor &ctx);
+
+} // namespace clang
+
+#endif // !CLANGPARSER_H
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
new file mode 100644
index 000000000..fdc8d3312
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "clangutils.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QHashFunctions>
+#include <QtCore/QProcess>
+
+bool operator==(const CXCursor &c1, const CXCursor &c2)
+{
+ return c1.kind == c2.kind
+ && c1.xdata == c2.xdata
+ && std::equal(c1.data, c1.data + sizeof(c1.data) / sizeof(c1.data[0]), c2.data);
+}
+
+uint qHash(const CXCursor &c, uint seed)
+{
+ return qHash(c.kind) ^ qHash(c.xdata) ^ qHash(c.data[0])
+ ^ qHash(c.data[1]) ^ qHash(c.data[2]) ^ seed;
+}
+
+namespace clang {
+
+SourceLocation getExpansionLocation(const CXSourceLocation &location)
+{
+ SourceLocation result;
+ CXFile file; // void *
+ clang_getExpansionLocation(location, &file, &result.line, &result.column, &result.offset);
+ const CXString cxFileName = clang_getFileName(file);
+ // Has been observed to be 0 for invalid locations
+ if (const char *cFileName = clang_getCString(cxFileName))
+ result.file = QString::fromUtf8(cFileName);
+ clang_disposeString(cxFileName);
+ return result;
+}
+
+SourceLocation getCursorLocation(const CXCursor &cursor)
+{
+ const CXSourceRange extent = clang_getCursorExtent(cursor);
+ return getExpansionLocation(clang_getRangeStart(extent));
+}
+
+CXString getFileNameFromLocation(const CXSourceLocation &location)
+{
+ CXFile file;
+ unsigned line;
+ unsigned column;
+ unsigned offset;
+ clang_getExpansionLocation(location, &file, &line, &column, &offset);
+ return clang_getFileName(file);
+}
+
+SourceRange getCursorRange(const CXCursor &cursor)
+{
+ const CXSourceRange extent = clang_getCursorExtent(cursor);
+ return qMakePair(getExpansionLocation(clang_getRangeStart(extent)),
+ getExpansionLocation(clang_getRangeEnd(extent)));
+}
+
+QString getCursorKindName(CXCursorKind cursorKind)
+{
+ CXString kindName = clang_getCursorKindSpelling(cursorKind);
+ const QString result = QString::fromUtf8(clang_getCString(kindName));
+ clang_disposeString(kindName);
+ return result;
+}
+
+QString getCursorSpelling(const CXCursor &cursor)
+{
+ CXString cursorSpelling = clang_getCursorSpelling(cursor);
+ const QString result = QString::fromUtf8(clang_getCString(cursorSpelling));
+ clang_disposeString(cursorSpelling);
+ return result;
+}
+
+QString getCursorDisplayName(const CXCursor &cursor)
+{
+ CXString displayName = clang_getCursorDisplayName(cursor);
+ const QString result = QString::fromUtf8(clang_getCString(displayName));
+ clang_disposeString(displayName);
+ return result;
+}
+
+QString getTypeName(const CXType &type)
+{
+ CXString typeSpelling = clang_getTypeSpelling(type);
+ const QString result = QString::fromUtf8(clang_getCString(typeSpelling));
+ clang_disposeString(typeSpelling);
+ return result;
+}
+
+Diagnostic::Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s)
+ : message(m), location(getCursorLocation(c)), source(Other), severity(s)
+{
+}
+
+Diagnostic Diagnostic::fromCXDiagnostic(CXDiagnostic cd)
+{
+ Diagnostic result;
+ result.source = Clang;
+ CXString spelling = clang_getDiagnosticSpelling(cd);
+ result.message = QString::fromUtf8(clang_getCString(spelling));
+ clang_disposeString(spelling);
+ result.severity = clang_getDiagnosticSeverity(cd);
+ result.location = getExpansionLocation(clang_getDiagnosticLocation(cd));
+
+ CXDiagnosticSet childDiagnostics = clang_getChildDiagnostics(cd);
+ if (const unsigned childCount = clang_getNumDiagnosticsInSet(childDiagnostics)) {
+ result.childMessages.reserve(int(childCount));
+ const unsigned format = clang_defaultDiagnosticDisplayOptions();
+ for (unsigned i = 0; i < childCount; ++i) {
+ CXDiagnostic childDiagnostic = clang_getDiagnosticInSet(childDiagnostics, i);
+ CXString cdm = clang_formatDiagnostic(childDiagnostic, format);
+ result.childMessages.append(QString::fromUtf8(clang_getCString(cdm)));
+ clang_disposeString(cdm);
+ clang_disposeDiagnostic(childDiagnostic);
+ }
+ }
+
+ return result;
+}
+
+QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu)
+{
+ QVector<Diagnostic> result;
+ const unsigned count = clang_getNumDiagnostics(tu);
+ result.reserve(int(count));
+ for (unsigned i = 0; i < count; ++i) {
+ const CXDiagnostic d = clang_getDiagnostic(tu, i);
+ result.append(Diagnostic::fromCXDiagnostic(d));
+ clang_disposeDiagnostic(d);
+ }
+ return result;
+}
+
+CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds)
+{
+ CXDiagnosticSeverity result = CXDiagnostic_Ignored;
+ for (const Diagnostic d : ds) {
+ if (d.severity > result)
+ result = d.severity;
+ }
+ return result;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug s, const SourceLocation &l)
+{
+ QDebugStateSaver saver(s);
+ s.nospace();
+ s.noquote();
+ s << QDir::toNativeSeparators(l.file) << ':' << l.line;
+ if (l.column)
+ s << ':' << l.column;
+ return s;
+}
+
+// Roughly follow g++ format:
+// file.cpp:214:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
+QDebug operator<<(QDebug s, const Diagnostic &d)
+{
+ QDebugStateSaver saver(s);
+ s.nospace();
+ s.noquote();
+ s << d.location << ": ";
+ switch (d.severity) {
+ case CXDiagnostic_Ignored:
+ s << "ignored";
+ break;
+ case CXDiagnostic_Note:
+ s << "note";
+ break;
+ case CXDiagnostic_Warning:
+ s << "warning";
+ break;
+ case CXDiagnostic_Error:
+ s << "error";
+ break;
+ case CXDiagnostic_Fatal:
+ s << "fatal";
+ break;
+ }
+ s << ": " << d.message;
+
+ if (d.source != Diagnostic::Clang)
+ s << " [other]";
+
+ if (const int childMessagesCount = d.childMessages.size()) {
+ s << '\n';
+ for (int i = 0; i < childMessagesCount; ++i)
+ s << " " << d.childMessages.at(i) << '\n';
+ }
+
+ return s;
+}
+
+#endif // QT_NO_DEBUG_STREAM
+
+} // namespace clang
diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangutils.h b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
new file mode 100644
index 000000000..3437f51eb
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/clangutils.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CLANGUTILS_H
+#define CLANGUTILS_H
+
+#include <clang-c/Index.h>
+#include <QtCore/QPair>
+#include <QtCore/QString>
+#include <QtCore/QVector>
+
+QT_FORWARD_DECLARE_CLASS(QDebug)
+
+bool operator==(const CXCursor &c1, const CXCursor &c2);
+uint qHash(const CXCursor &c, uint seed = 0);
+
+namespace clang {
+
+QString getCursorKindName(CXCursorKind cursorKind);
+QString getCursorSpelling(const CXCursor &cursor);
+QString getCursorDisplayName(const CXCursor &cursor);
+QString getTypeName(const CXType &type);
+inline QString getCursorTypeName(const CXCursor &cursor)
+ { return getTypeName(clang_getCursorType(cursor)); }
+inline QString getCursorResultTypeName(const CXCursor &cursor)
+ { return getTypeName(clang_getCursorResultType(cursor)); }
+
+inline bool isCursorValid(const CXCursor &c)
+{
+ return c.kind < CXCursor_FirstInvalid || c.kind > CXCursor_LastInvalid;
+}
+
+struct SourceLocation
+{
+ int compare(const SourceLocation &rhs) const;
+
+ QString file;
+ unsigned line = 0;
+ unsigned column = 0;
+ unsigned offset = 0;
+};
+
+SourceLocation getExpansionLocation(const CXSourceLocation &location);
+
+typedef QPair<SourceLocation, SourceLocation> SourceRange;
+
+SourceLocation getCursorLocation(const CXCursor &cursor);
+CXString getFileNameFromLocation(const CXSourceLocation &location);
+SourceRange getCursorRange(const CXCursor &cursor);
+
+struct Diagnostic {
+ enum Source { Clang, Other };
+
+ Diagnostic() : source(Clang) {}
+ // Clang
+ static Diagnostic fromCXDiagnostic(CXDiagnostic cd);
+ // Other
+ explicit Diagnostic(const QString &m, const CXCursor &c, CXDiagnosticSeverity s = CXDiagnostic_Warning);
+
+ QString message;
+ QStringList childMessages;
+ SourceLocation location;
+ Source source;
+ CXDiagnosticSeverity severity;
+};
+
+QVector<Diagnostic> getDiagnostics(CXTranslationUnit tu);
+CXDiagnosticSeverity maxSeverity(const QVector<Diagnostic> &ds);
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const SourceLocation &);
+QDebug operator<<(QDebug, const Diagnostic &);
+#endif // QT_NO_DEBUG_STREAM
+} // namespace clang
+
+#endif // CLANGUTILS_H
diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
new file mode 100644
index 000000000..df82f9080
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.cpp
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "compilersupport.h"
+#include "header_paths.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+#include <QtCore/QStringList>
+
+#include <string.h>
+#include <algorithm>
+#include <iterator>
+
+namespace clang {
+
+static bool runProcess(const QString &program, const QStringList &arguments,
+ QByteArray *stdOutIn = nullptr, QByteArray *stdErrIn = nullptr)
+{
+ QProcess process;
+ process.start(program, arguments, QProcess::ReadWrite);
+ if (!process.waitForStarted()) {
+ qWarning().noquote().nospace() << "Unable to start "
+ << process.program() << ": " << process.errorString();
+ return false;
+ }
+ process.closeWriteChannel();
+ const bool finished = process.waitForFinished();
+ const QByteArray stdErr = process.readAllStandardError();
+ if (stdErrIn)
+ *stdErrIn = stdErr;
+ if (stdOutIn)
+ *stdOutIn = process.readAllStandardOutput();
+
+ if (!finished) {
+ qWarning().noquote().nospace() << process.program() << " timed out: " << stdErr;
+ process.kill();
+ return false;
+ }
+
+ if (process.exitStatus() != QProcess::NormalExit) {
+ qWarning().noquote().nospace() << process.program() << " crashed: " << stdErr;
+ return false;
+ }
+
+ if (process.exitCode() != 0) {
+ qWarning().noquote().nospace() << process.program() << " exited "
+ << process.exitCode() << ": " << stdErr;
+ return false;
+ }
+
+ return true;
+}
+
+#if defined(Q_CC_GNU)
+
+static QByteArray frameworkPath() { return QByteArrayLiteral(" (framework directory)"); }
+
+// Determine g++'s internal include paths from the output of
+// g++ -E -x c++ - -v </dev/null
+// Output looks like:
+// #include <...> search starts here:
+// /usr/local/include
+// /System/Library/Frameworks (framework directory)
+// End of search list.
+static HeaderPaths gppInternalIncludePaths(const QString &compiler)
+{
+ HeaderPaths result;
+ QStringList arguments;
+ arguments << QStringLiteral("-E") << QStringLiteral("-x") << QStringLiteral("c++")
+ << QStringLiteral("-") << QStringLiteral("-v");
+ QByteArray stdOut;
+ QByteArray stdErr;
+ if (!runProcess(compiler, arguments, &stdOut, &stdErr))
+ return result;
+ const QByteArrayList stdErrLines = stdErr.split('\n');
+ bool isIncludeDir = false;
+ for (const QByteArray &line : stdErrLines) {
+ if (isIncludeDir) {
+ if (line.startsWith(QByteArrayLiteral("End of search list"))) {
+ isIncludeDir = false;
+ } else {
+ HeaderPath headerPath(line.trimmed());
+ if (headerPath.path.endsWith(frameworkPath())) {
+ headerPath.m_isFramework = true;
+ headerPath.path.truncate(headerPath.path.size() - frameworkPath().size());
+ }
+ result.append(headerPath);
+ }
+ } else if (line.startsWith(QByteArrayLiteral("#include <...> search starts here"))) {
+ isIncludeDir = true;
+ }
+ }
+ return result;
+}
+#endif // Q_CC_MSVC
+
+// For MSVC, we set the MS compatibility version and let Clang figure out its own
+// options and include paths.
+// For the others, we pass "-nostdinc" since libclang tries to add it's own system
+// include paths, which together with the clang compiler paths causes some clash
+// which causes std types not being found and construct -I/-F options from the
+// include paths of the host compiler.
+
+static QByteArray noStandardIncludeOption() { return QByteArrayLiteral("-nostdinc"); }
+
+// Returns clang options needed for emulating the host compiler
+QByteArrayList emulatedCompilerOptions()
+{
+ QByteArrayList result;
+#if defined(Q_CC_MSVC)
+ const HeaderPaths headerPaths;
+ result.append(QByteArrayLiteral("-fms-compatibility-version=19"));
+#elif defined(Q_CC_CLANG)
+ const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("clang++"));
+ result.append(noStandardIncludeOption());
+#elif defined(Q_CC_GNU)
+ const HeaderPaths headerPaths = gppInternalIncludePaths(QStringLiteral("g++"));
+ result.append(noStandardIncludeOption());
+#else
+ const HeaderPaths headerPaths;
+#endif
+ std::transform(headerPaths.cbegin(), headerPaths.cend(),
+ std::back_inserter(result), [](const HeaderPath &p) {
+ return HeaderPath::includeOption(p, true);
+ });
+ return result;
+}
+
+} // namespace clang
diff --git a/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h
new file mode 100644
index 000000000..f556da551
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/clangparser/compilersupport.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef COMPILERSUPPORT_H
+#define COMPILERSUPPORT_H
+
+#include <QtCore/QByteArrayList>
+
+namespace clang {
+
+QByteArrayList emulatedCompilerOptions();
+
+} // namespace clang
+
+#endif // COMPILERSUPPORT_H
diff --git a/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake b/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake
new file mode 100644
index 000000000..df95fb9d8
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/cmake_uninstall.cmake
@@ -0,0 +1,21 @@
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+ MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+ IF(EXISTS "$ENV{DESTDIR}${file}")
+ EXEC_PROGRAM(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ IF(NOT "${rm_retval}" STREQUAL 0)
+ MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+ ENDIF(NOT "${rm_retval}" STREQUAL 0)
+ ELSE(EXISTS "$ENV{DESTDIR}${file}")
+ MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+ ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
diff --git a/sources/shiboken2/ApiExtractor/dependency.h b/sources/shiboken2/ApiExtractor/dependency.h
new file mode 100644
index 000000000..17fbffcce
--- /dev/null
+++ b/sources/shiboken2/ApiExtractor/dependency.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DEPENDENCY_H
+#define DEPENDENCY_H
+
+#include <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"