From 846c860b89ee5fbef4f1db583bd951f8a33e196a Mon Sep 17 00:00:00 2001 From: Luca Di Sera Date: Tue, 11 Apr 2023 14:38:38 +0200 Subject: QDoc: Move QDoc source files under a further "qdoc" directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QDoc development under the "qttools" repository is currently performed under the "src/qdoc" directory, which contains all source files and directories relevant to QDoc as direct children. Due to a slow restructuring of how QDoc works, what its dependencies are and certain possible architectural changes, the infrastructure that is expected to be required for the development of QDoc might increase. Some of that infrastructure, which might require some custom effort, is expected to be developed as "independent" "library-like" sub-projects, which QDoc depends on. Albeit developed "independently", such infrastructure would be developed specifically for QDoc and thus should live "adjacent" to it. To allow such a structure a new "qdoc" directory was added under the "src/qdoc" directory. All source files and directory that were previously children of the "src/qdoc" directory were moved under the new "qdoc" directory. This preserves the space for QDoc-related elements and the relative project structure while allowing some space for "adjacent" projects that are intended for QDoc specifically. To support the change, a new "CMakeLists.txt" file was introduced under "src/qdoc", which dispatches to the "CMakeLists.txt" file in the new "src/qdoc/qdoc" directory. QDoc is only built when certain dependencies are found. This is supported through the use of Qt features at the CMake level. The "CMakeLists.txt" file in "src", thus dispatched to the "src/qdoc" directory only when the required features were found. As "independent", "library-like", entities might not have the same requirements as QDoc, the "CMakeLists.txt" file in "src" was modified to always dispatch to the "src/qdoc" directory while the features-check was moved to the new "CMakeLists.txt" files in "src/qdoc", so as to allow non-QDoc but QDoc-specific project to have an independent configuration for building. Certain test projects in "test/auto/qdoc/" depends on QDoc-specific source-files to generate their CMake targets. Those dependencies were generally specified as relative paths. The additional level in the directory structure invalidated the paths and, hence, the relevant "CMakeLists.txt" files for those projects were modified to correctly refer to the new directory structure. Change-Id: I50c7106614428753544eaba5091e1e44d48fd31d Reviewed-by: Topi Reiniƶ --- src/CMakeLists.txt | 6 +- src/qdoc/CMakeLists.txt | 109 +- src/qdoc/access.h | 15 - src/qdoc/aggregate.cpp | 892 ---- src/qdoc/aggregate.h | 118 - src/qdoc/atom.cpp | 432 -- src/qdoc/atom.h | 218 - src/qdoc/boundaries/filesystem/directorypath.cpp | 126 - src/qdoc/boundaries/filesystem/directorypath.h | 17 - src/qdoc/boundaries/filesystem/filepath.cpp | 125 - src/qdoc/boundaries/filesystem/filepath.h | 17 - src/qdoc/boundaries/filesystem/resolvedfile.cpp | 96 - src/qdoc/boundaries/filesystem/resolvedfile.h | 20 - src/qdoc/boundaries/refined_typedef.h | 207 - .../boundaries/refined_typedef_members.qdocinc | 162 - src/qdoc/clangcodeparser.cpp | 1783 ------- src/qdoc/clangcodeparser.h | 55 - src/qdoc/classnode.cpp | 291 -- src/qdoc/classnode.h | 71 - src/qdoc/codechunk.cpp | 104 - src/qdoc/codechunk.h | 74 - src/qdoc/codemarker.cpp | 395 -- src/qdoc/codemarker.h | 67 - src/qdoc/codeparser.cpp | 139 - src/qdoc/codeparser.h | 131 - src/qdoc/collectionnode.cpp | 115 - src/qdoc/collectionnode.h | 107 - src/qdoc/config.cpp | 1401 ----- src/qdoc/config.h | 392 -- src/qdoc/cppcodemarker.cpp | 593 --- src/qdoc/cppcodemarker.h | 35 - src/qdoc/cppcodeparser.cpp | 977 ---- src/qdoc/cppcodeparser.h | 75 - src/qdoc/doc.cpp | 466 -- src/qdoc/doc.h | 92 - src/qdoc/doc/config/qdoc.qdocconf | 59 - src/qdoc/doc/corefeatures.qdoc | 11 - src/qdoc/doc/examples/cpp.qdoc.sample | 102 - src/qdoc/doc/examples/layoutmanagement.qdocinc | 13 - src/qdoc/doc/examples/main.cpp | 16 - src/qdoc/doc/examples/mainwindow.cpp | 213 - src/qdoc/doc/examples/minimum.qdocconf | 36 - src/qdoc/doc/examples/objectmodel.qdocinc | 11 - src/qdoc/doc/examples/qml.qdoc.sample | 90 - src/qdoc/doc/examples/samples.qdocinc | 85 - src/qdoc/doc/examples/signalandslots.qdocinc | 9 - src/qdoc/doc/files/basicqt.qdoc.sample | 64 - src/qdoc/doc/files/compat.qdocconf | 10 - src/qdoc/doc/files/qtgui.qdocconf | 45 - src/qdoc/doc/images/happy.gif | Bin 11526 -> 0 bytes src/qdoc/doc/images/happyguy.jpg | Bin 53442 -> 0 bytes src/qdoc/doc/images/link-to-qquickitem.png | Bin 46571 -> 0 bytes src/qdoc/doc/images/links-to-broken-links.png | Bin 16569 -> 0 bytes src/qdoc/doc/images/links-to-links.png | Bin 10042 -> 0 bytes src/qdoc/doc/images/qa-table.png | Bin 7057 -> 0 bytes src/qdoc/doc/images/qt-logo.png | Bin 1008 -> 0 bytes src/qdoc/doc/images/training.jpg | Bin 8368 -> 0 bytes src/qdoc/doc/images/windows-pushbutton.png | Bin 722 -> 0 bytes src/qdoc/doc/images/windows-toolbutton.png | Bin 771 -> 0 bytes src/qdoc/doc/qdoc-guide/qdoc-guide.qdoc | 670 --- src/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc | 163 - src/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc | 142 - src/qdoc/doc/qdoc-manual-cmdindex.qdoc | 133 - src/qdoc/doc/qdoc-manual-contextcmds.qdoc | 1075 ---- src/qdoc/doc/qdoc-manual-intro.qdoc | 299 -- src/qdoc/doc/qdoc-manual-markupcmds.qdoc | 4034 --------------- src/qdoc/doc/qdoc-manual-qdocconf.qdoc | 2033 -------- src/qdoc/doc/qdoc-manual-topiccmds.qdoc | 1666 ------ src/qdoc/doc/qdoc-manual.qdoc | 49 - src/qdoc/doc/qdoc-minimum-qdocconf.qdoc | 65 - src/qdoc/doc/qdoc-warnings.qdoc | 793 --- src/qdoc/doc/qtgui-qdocconf.qdoc | 260 - src/qdoc/docbookgenerator.cpp | 5344 -------------------- src/qdoc/docbookgenerator.h | 169 - src/qdoc/docparser.cpp | 2576 ---------- src/qdoc/docparser.h | 169 - src/qdoc/docprivate.cpp | 30 - src/qdoc/docprivate.h | 75 - src/qdoc/docutilities.h | 28 - src/qdoc/editdistance.cpp | 68 - src/qdoc/editdistance.h | 17 - src/qdoc/enumitem.h | 36 - src/qdoc/enumnode.cpp | 82 - src/qdoc/enumnode.h | 49 - src/qdoc/examplenode.h | 42 - src/qdoc/externalpagenode.cpp | 28 - src/qdoc/externalpagenode.h | 25 - src/qdoc/filesystem/fileresolver.cpp | 161 - src/qdoc/filesystem/fileresolver.h | 24 - src/qdoc/functionnode.cpp | 527 -- src/qdoc/functionnode.h | 206 - src/qdoc/generator.cpp | 2099 -------- src/qdoc/generator.h | 209 - src/qdoc/headernode.cpp | 43 - src/qdoc/headernode.h | 47 - src/qdoc/helpprojectwriter.cpp | 778 --- src/qdoc/helpprojectwriter.h | 107 - src/qdoc/htmlgenerator.cpp | 3711 -------------- src/qdoc/htmlgenerator.h | 176 - src/qdoc/importrec.h | 33 - src/qdoc/location.cpp | 423 -- src/qdoc/location.h | 92 - src/qdoc/macro.h | 27 - src/qdoc/main.cpp | 668 --- src/qdoc/manifestwriter.cpp | 391 -- src/qdoc/manifestwriter.h | 45 - src/qdoc/namespacenode.cpp | 190 - src/qdoc/namespacenode.h | 48 - src/qdoc/node.cpp | 1407 ------ src/qdoc/node.h | 337 -- src/qdoc/openedlist.cpp | 172 - src/qdoc/openedlist.h | 47 - src/qdoc/pagenode.cpp | 121 - src/qdoc/pagenode.h | 84 - src/qdoc/parameters.cpp | 542 -- src/qdoc/parameters.h | 113 - src/qdoc/propertynode.cpp | 135 - src/qdoc/propertynode.h | 93 - src/qdoc/proxynode.cpp | 54 - src/qdoc/proxynode.h | 23 - src/qdoc/puredocparser.cpp | 96 - src/qdoc/puredocparser.h | 33 - src/qdoc/qdoc/CMakeLists.txt | 109 + src/qdoc/qdoc/access.h | 15 + src/qdoc/qdoc/aggregate.cpp | 892 ++++ src/qdoc/qdoc/aggregate.h | 118 + src/qdoc/qdoc/atom.cpp | 432 ++ src/qdoc/qdoc/atom.h | 218 + .../qdoc/boundaries/filesystem/directorypath.cpp | 126 + .../qdoc/boundaries/filesystem/directorypath.h | 17 + src/qdoc/qdoc/boundaries/filesystem/filepath.cpp | 125 + src/qdoc/qdoc/boundaries/filesystem/filepath.h | 17 + .../qdoc/boundaries/filesystem/resolvedfile.cpp | 96 + src/qdoc/qdoc/boundaries/filesystem/resolvedfile.h | 20 + src/qdoc/qdoc/boundaries/refined_typedef.h | 207 + .../boundaries/refined_typedef_members.qdocinc | 162 + src/qdoc/qdoc/clangcodeparser.cpp | 1783 +++++++ src/qdoc/qdoc/clangcodeparser.h | 55 + src/qdoc/qdoc/classnode.cpp | 291 ++ src/qdoc/qdoc/classnode.h | 71 + src/qdoc/qdoc/codechunk.cpp | 104 + src/qdoc/qdoc/codechunk.h | 74 + src/qdoc/qdoc/codemarker.cpp | 395 ++ src/qdoc/qdoc/codemarker.h | 67 + src/qdoc/qdoc/codeparser.cpp | 139 + src/qdoc/qdoc/codeparser.h | 131 + src/qdoc/qdoc/collectionnode.cpp | 115 + src/qdoc/qdoc/collectionnode.h | 107 + src/qdoc/qdoc/config.cpp | 1401 +++++ src/qdoc/qdoc/config.h | 392 ++ src/qdoc/qdoc/cppcodemarker.cpp | 593 +++ src/qdoc/qdoc/cppcodemarker.h | 35 + src/qdoc/qdoc/cppcodeparser.cpp | 977 ++++ src/qdoc/qdoc/cppcodeparser.h | 75 + src/qdoc/qdoc/doc.cpp | 466 ++ src/qdoc/qdoc/doc.h | 92 + src/qdoc/qdoc/doc/config/qdoc.qdocconf | 59 + src/qdoc/qdoc/doc/corefeatures.qdoc | 11 + src/qdoc/qdoc/doc/examples/cpp.qdoc.sample | 102 + .../qdoc/doc/examples/layoutmanagement.qdocinc | 13 + src/qdoc/qdoc/doc/examples/main.cpp | 16 + src/qdoc/qdoc/doc/examples/mainwindow.cpp | 213 + src/qdoc/qdoc/doc/examples/minimum.qdocconf | 36 + src/qdoc/qdoc/doc/examples/objectmodel.qdocinc | 11 + src/qdoc/qdoc/doc/examples/qml.qdoc.sample | 90 + src/qdoc/qdoc/doc/examples/samples.qdocinc | 85 + src/qdoc/qdoc/doc/examples/signalandslots.qdocinc | 9 + src/qdoc/qdoc/doc/files/basicqt.qdoc.sample | 64 + src/qdoc/qdoc/doc/files/compat.qdocconf | 10 + src/qdoc/qdoc/doc/files/qtgui.qdocconf | 45 + src/qdoc/qdoc/doc/images/happy.gif | Bin 0 -> 11526 bytes src/qdoc/qdoc/doc/images/happyguy.jpg | Bin 0 -> 53442 bytes src/qdoc/qdoc/doc/images/link-to-qquickitem.png | Bin 0 -> 46571 bytes src/qdoc/qdoc/doc/images/links-to-broken-links.png | Bin 0 -> 16569 bytes src/qdoc/qdoc/doc/images/links-to-links.png | Bin 0 -> 10042 bytes src/qdoc/qdoc/doc/images/qa-table.png | Bin 0 -> 7057 bytes src/qdoc/qdoc/doc/images/qt-logo.png | Bin 0 -> 1008 bytes src/qdoc/qdoc/doc/images/training.jpg | Bin 0 -> 8368 bytes src/qdoc/qdoc/doc/images/windows-pushbutton.png | Bin 0 -> 722 bytes src/qdoc/qdoc/doc/images/windows-toolbutton.png | Bin 0 -> 771 bytes src/qdoc/qdoc/doc/qdoc-guide/qdoc-guide.qdoc | 670 +++ .../qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc | 163 + .../qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc | 142 + src/qdoc/qdoc/doc/qdoc-manual-cmdindex.qdoc | 133 + src/qdoc/qdoc/doc/qdoc-manual-contextcmds.qdoc | 1075 ++++ src/qdoc/qdoc/doc/qdoc-manual-intro.qdoc | 299 ++ src/qdoc/qdoc/doc/qdoc-manual-markupcmds.qdoc | 4034 +++++++++++++++ src/qdoc/qdoc/doc/qdoc-manual-qdocconf.qdoc | 2033 ++++++++ src/qdoc/qdoc/doc/qdoc-manual-topiccmds.qdoc | 1666 ++++++ src/qdoc/qdoc/doc/qdoc-manual.qdoc | 49 + src/qdoc/qdoc/doc/qdoc-minimum-qdocconf.qdoc | 65 + src/qdoc/qdoc/doc/qdoc-warnings.qdoc | 793 +++ src/qdoc/qdoc/doc/qtgui-qdocconf.qdoc | 260 + src/qdoc/qdoc/docbookgenerator.cpp | 5344 ++++++++++++++++++++ src/qdoc/qdoc/docbookgenerator.h | 169 + src/qdoc/qdoc/docparser.cpp | 2576 ++++++++++ src/qdoc/qdoc/docparser.h | 169 + src/qdoc/qdoc/docprivate.cpp | 30 + src/qdoc/qdoc/docprivate.h | 75 + src/qdoc/qdoc/docutilities.h | 28 + src/qdoc/qdoc/editdistance.cpp | 68 + src/qdoc/qdoc/editdistance.h | 17 + src/qdoc/qdoc/enumitem.h | 36 + src/qdoc/qdoc/enumnode.cpp | 82 + src/qdoc/qdoc/enumnode.h | 49 + src/qdoc/qdoc/examplenode.h | 42 + src/qdoc/qdoc/externalpagenode.cpp | 28 + src/qdoc/qdoc/externalpagenode.h | 25 + src/qdoc/qdoc/filesystem/fileresolver.cpp | 161 + src/qdoc/qdoc/filesystem/fileresolver.h | 24 + src/qdoc/qdoc/functionnode.cpp | 527 ++ src/qdoc/qdoc/functionnode.h | 206 + src/qdoc/qdoc/generator.cpp | 2099 ++++++++ src/qdoc/qdoc/generator.h | 209 + src/qdoc/qdoc/headernode.cpp | 43 + src/qdoc/qdoc/headernode.h | 47 + src/qdoc/qdoc/helpprojectwriter.cpp | 778 +++ src/qdoc/qdoc/helpprojectwriter.h | 107 + src/qdoc/qdoc/htmlgenerator.cpp | 3711 ++++++++++++++ src/qdoc/qdoc/htmlgenerator.h | 176 + src/qdoc/qdoc/importrec.h | 33 + src/qdoc/qdoc/location.cpp | 423 ++ src/qdoc/qdoc/location.h | 92 + src/qdoc/qdoc/macro.h | 27 + src/qdoc/qdoc/main.cpp | 668 +++ src/qdoc/qdoc/manifestwriter.cpp | 391 ++ src/qdoc/qdoc/manifestwriter.h | 45 + src/qdoc/qdoc/namespacenode.cpp | 190 + src/qdoc/qdoc/namespacenode.h | 48 + src/qdoc/qdoc/node.cpp | 1407 ++++++ src/qdoc/qdoc/node.h | 337 ++ src/qdoc/qdoc/openedlist.cpp | 172 + src/qdoc/qdoc/openedlist.h | 47 + src/qdoc/qdoc/pagenode.cpp | 121 + src/qdoc/qdoc/pagenode.h | 84 + src/qdoc/qdoc/parameters.cpp | 542 ++ src/qdoc/qdoc/parameters.h | 113 + src/qdoc/qdoc/propertynode.cpp | 135 + src/qdoc/qdoc/propertynode.h | 93 + src/qdoc/qdoc/proxynode.cpp | 54 + src/qdoc/qdoc/proxynode.h | 23 + src/qdoc/qdoc/puredocparser.cpp | 96 + src/qdoc/qdoc/puredocparser.h | 33 + src/qdoc/qdoc/qdoccommandlineparser.cpp | 177 + src/qdoc/qdoc/qdoccommandlineparser.h | 28 + src/qdoc/qdoc/qdocdatabase.cpp | 1721 +++++++ src/qdoc/qdoc/qdocdatabase.h | 395 ++ src/qdoc/qdoc/qdocindexfiles.cpp | 1452 ++++++ src/qdoc/qdoc/qdocindexfiles.h | 72 + src/qdoc/qdoc/qmlcodemarker.cpp | 175 + src/qdoc/qdoc/qmlcodemarker.h | 38 + src/qdoc/qdoc/qmlcodeparser.cpp | 143 + src/qdoc/qdoc/qmlcodeparser.h | 38 + src/qdoc/qdoc/qmlmarkupvisitor.cpp | 794 +++ src/qdoc/qdoc/qmlmarkupvisitor.h | 139 + src/qdoc/qdoc/qmlpropertynode.cpp | 125 + src/qdoc/qdoc/qmlpropertynode.h | 70 + src/qdoc/qdoc/qmltypenode.cpp | 153 + src/qdoc/qdoc/qmltypenode.h | 72 + src/qdoc/qdoc/qmlvisitor.cpp | 709 +++ src/qdoc/qdoc/qmlvisitor.h | 93 + src/qdoc/qdoc/quoter.cpp | 338 ++ src/qdoc/qdoc/quoter.h | 45 + src/qdoc/qdoc/relatedclass.cpp | 46 + src/qdoc/qdoc/relatedclass.h | 34 + src/qdoc/qdoc/sections.cpp | 990 ++++ src/qdoc/qdoc/sections.h | 206 + src/qdoc/qdoc/sharedcommentnode.cpp | 56 + src/qdoc/qdoc/sharedcommentnode.h | 51 + src/qdoc/qdoc/singleton.h | 32 + src/qdoc/qdoc/tagfilewriter.cpp | 306 ++ src/qdoc/qdoc/tagfilewriter.h | 33 + src/qdoc/qdoc/text.cpp | 306 ++ src/qdoc/qdoc/text.h | 77 + src/qdoc/qdoc/tokenizer.cpp | 788 +++ src/qdoc/qdoc/tokenizer.h | 179 + src/qdoc/qdoc/topic.h | 29 + src/qdoc/qdoc/tree.cpp | 1286 +++++ src/qdoc/qdoc/tree.h | 177 + src/qdoc/qdoc/typedefnode.cpp | 55 + src/qdoc/qdoc/typedefnode.h | 54 + src/qdoc/qdoc/utilities.cpp | 181 + src/qdoc/qdoc/utilities.h | 27 + src/qdoc/qdoc/variablenode.cpp | 23 + src/qdoc/qdoc/variablenode.h | 44 + src/qdoc/qdoc/webxmlgenerator.cpp | 909 ++++ src/qdoc/qdoc/webxmlgenerator.h | 60 + src/qdoc/qdoc/xmlgenerator.cpp | 493 ++ src/qdoc/qdoc/xmlgenerator.h | 54 + src/qdoc/qdoccommandlineparser.cpp | 177 - src/qdoc/qdoccommandlineparser.h | 28 - src/qdoc/qdocdatabase.cpp | 1721 ------- src/qdoc/qdocdatabase.h | 395 -- src/qdoc/qdocindexfiles.cpp | 1452 ------ src/qdoc/qdocindexfiles.h | 72 - src/qdoc/qmlcodemarker.cpp | 175 - src/qdoc/qmlcodemarker.h | 38 - src/qdoc/qmlcodeparser.cpp | 143 - src/qdoc/qmlcodeparser.h | 38 - src/qdoc/qmlmarkupvisitor.cpp | 794 --- src/qdoc/qmlmarkupvisitor.h | 139 - src/qdoc/qmlpropertynode.cpp | 125 - src/qdoc/qmlpropertynode.h | 70 - src/qdoc/qmltypenode.cpp | 153 - src/qdoc/qmltypenode.h | 72 - src/qdoc/qmlvisitor.cpp | 709 --- src/qdoc/qmlvisitor.h | 93 - src/qdoc/quoter.cpp | 338 -- src/qdoc/quoter.h | 45 - src/qdoc/relatedclass.cpp | 46 - src/qdoc/relatedclass.h | 34 - src/qdoc/sections.cpp | 990 ---- src/qdoc/sections.h | 206 - src/qdoc/sharedcommentnode.cpp | 56 - src/qdoc/sharedcommentnode.h | 51 - src/qdoc/singleton.h | 32 - src/qdoc/tagfilewriter.cpp | 306 -- src/qdoc/tagfilewriter.h | 33 - src/qdoc/text.cpp | 306 -- src/qdoc/text.h | 77 - src/qdoc/tokenizer.cpp | 788 --- src/qdoc/tokenizer.h | 179 - src/qdoc/topic.h | 29 - src/qdoc/tree.cpp | 1286 ----- src/qdoc/tree.h | 177 - src/qdoc/typedefnode.cpp | 55 - src/qdoc/typedefnode.h | 54 - src/qdoc/utilities.cpp | 181 - src/qdoc/utilities.h | 27 - src/qdoc/variablenode.cpp | 23 - src/qdoc/variablenode.h | 44 - src/qdoc/webxmlgenerator.cpp | 909 ---- src/qdoc/webxmlgenerator.h | 60 - src/qdoc/xmlgenerator.cpp | 493 -- src/qdoc/xmlgenerator.h | 54 - tests/auto/qdoc/config/CMakeLists.txt | 10 +- tests/auto/qdoc/qdoc/CMakeLists.txt | 10 +- .../auto/qdoc/qdoccommandlineparser/CMakeLists.txt | 6 +- tests/auto/qdoc/utilities/CMakeLists.txt | 4 +- 339 files changed, 57357 insertions(+), 57351 deletions(-) delete mode 100644 src/qdoc/access.h delete mode 100644 src/qdoc/aggregate.cpp delete mode 100644 src/qdoc/aggregate.h delete mode 100644 src/qdoc/atom.cpp delete mode 100644 src/qdoc/atom.h delete mode 100644 src/qdoc/boundaries/filesystem/directorypath.cpp delete mode 100644 src/qdoc/boundaries/filesystem/directorypath.h delete mode 100644 src/qdoc/boundaries/filesystem/filepath.cpp delete mode 100644 src/qdoc/boundaries/filesystem/filepath.h delete mode 100644 src/qdoc/boundaries/filesystem/resolvedfile.cpp delete mode 100644 src/qdoc/boundaries/filesystem/resolvedfile.h delete mode 100644 src/qdoc/boundaries/refined_typedef.h delete mode 100644 src/qdoc/boundaries/refined_typedef_members.qdocinc delete mode 100644 src/qdoc/clangcodeparser.cpp delete mode 100644 src/qdoc/clangcodeparser.h delete mode 100644 src/qdoc/classnode.cpp delete mode 100644 src/qdoc/classnode.h delete mode 100644 src/qdoc/codechunk.cpp delete mode 100644 src/qdoc/codechunk.h delete mode 100644 src/qdoc/codemarker.cpp delete mode 100644 src/qdoc/codemarker.h delete mode 100644 src/qdoc/codeparser.cpp delete mode 100644 src/qdoc/codeparser.h delete mode 100644 src/qdoc/collectionnode.cpp delete mode 100644 src/qdoc/collectionnode.h delete mode 100644 src/qdoc/config.cpp delete mode 100644 src/qdoc/config.h delete mode 100644 src/qdoc/cppcodemarker.cpp delete mode 100644 src/qdoc/cppcodemarker.h delete mode 100644 src/qdoc/cppcodeparser.cpp delete mode 100644 src/qdoc/cppcodeparser.h delete mode 100644 src/qdoc/doc.cpp delete mode 100644 src/qdoc/doc.h delete mode 100644 src/qdoc/doc/config/qdoc.qdocconf delete mode 100644 src/qdoc/doc/corefeatures.qdoc delete mode 100644 src/qdoc/doc/examples/cpp.qdoc.sample delete mode 100644 src/qdoc/doc/examples/layoutmanagement.qdocinc delete mode 100644 src/qdoc/doc/examples/main.cpp delete mode 100644 src/qdoc/doc/examples/mainwindow.cpp delete mode 100644 src/qdoc/doc/examples/minimum.qdocconf delete mode 100644 src/qdoc/doc/examples/objectmodel.qdocinc delete mode 100644 src/qdoc/doc/examples/qml.qdoc.sample delete mode 100644 src/qdoc/doc/examples/samples.qdocinc delete mode 100644 src/qdoc/doc/examples/signalandslots.qdocinc delete mode 100644 src/qdoc/doc/files/basicqt.qdoc.sample delete mode 100644 src/qdoc/doc/files/compat.qdocconf delete mode 100644 src/qdoc/doc/files/qtgui.qdocconf delete mode 100644 src/qdoc/doc/images/happy.gif delete mode 100644 src/qdoc/doc/images/happyguy.jpg delete mode 100644 src/qdoc/doc/images/link-to-qquickitem.png delete mode 100644 src/qdoc/doc/images/links-to-broken-links.png delete mode 100644 src/qdoc/doc/images/links-to-links.png delete mode 100644 src/qdoc/doc/images/qa-table.png delete mode 100644 src/qdoc/doc/images/qt-logo.png delete mode 100644 src/qdoc/doc/images/training.jpg delete mode 100644 src/qdoc/doc/images/windows-pushbutton.png delete mode 100644 src/qdoc/doc/images/windows-toolbutton.png delete mode 100644 src/qdoc/doc/qdoc-guide/qdoc-guide.qdoc delete mode 100644 src/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc delete mode 100644 src/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-cmdindex.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-contextcmds.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-intro.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-markupcmds.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-qdocconf.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual-topiccmds.qdoc delete mode 100644 src/qdoc/doc/qdoc-manual.qdoc delete mode 100644 src/qdoc/doc/qdoc-minimum-qdocconf.qdoc delete mode 100644 src/qdoc/doc/qdoc-warnings.qdoc delete mode 100644 src/qdoc/doc/qtgui-qdocconf.qdoc delete mode 100644 src/qdoc/docbookgenerator.cpp delete mode 100644 src/qdoc/docbookgenerator.h delete mode 100644 src/qdoc/docparser.cpp delete mode 100644 src/qdoc/docparser.h delete mode 100644 src/qdoc/docprivate.cpp delete mode 100644 src/qdoc/docprivate.h delete mode 100644 src/qdoc/docutilities.h delete mode 100644 src/qdoc/editdistance.cpp delete mode 100644 src/qdoc/editdistance.h delete mode 100644 src/qdoc/enumitem.h delete mode 100644 src/qdoc/enumnode.cpp delete mode 100644 src/qdoc/enumnode.h delete mode 100644 src/qdoc/examplenode.h delete mode 100644 src/qdoc/externalpagenode.cpp delete mode 100644 src/qdoc/externalpagenode.h delete mode 100644 src/qdoc/filesystem/fileresolver.cpp delete mode 100644 src/qdoc/filesystem/fileresolver.h delete mode 100644 src/qdoc/functionnode.cpp delete mode 100644 src/qdoc/functionnode.h delete mode 100644 src/qdoc/generator.cpp delete mode 100644 src/qdoc/generator.h delete mode 100644 src/qdoc/headernode.cpp delete mode 100644 src/qdoc/headernode.h delete mode 100644 src/qdoc/helpprojectwriter.cpp delete mode 100644 src/qdoc/helpprojectwriter.h delete mode 100644 src/qdoc/htmlgenerator.cpp delete mode 100644 src/qdoc/htmlgenerator.h delete mode 100644 src/qdoc/importrec.h delete mode 100644 src/qdoc/location.cpp delete mode 100644 src/qdoc/location.h delete mode 100644 src/qdoc/macro.h delete mode 100644 src/qdoc/main.cpp delete mode 100644 src/qdoc/manifestwriter.cpp delete mode 100644 src/qdoc/manifestwriter.h delete mode 100644 src/qdoc/namespacenode.cpp delete mode 100644 src/qdoc/namespacenode.h delete mode 100644 src/qdoc/node.cpp delete mode 100644 src/qdoc/node.h delete mode 100644 src/qdoc/openedlist.cpp delete mode 100644 src/qdoc/openedlist.h delete mode 100644 src/qdoc/pagenode.cpp delete mode 100644 src/qdoc/pagenode.h delete mode 100644 src/qdoc/parameters.cpp delete mode 100644 src/qdoc/parameters.h delete mode 100644 src/qdoc/propertynode.cpp delete mode 100644 src/qdoc/propertynode.h delete mode 100644 src/qdoc/proxynode.cpp delete mode 100644 src/qdoc/proxynode.h delete mode 100644 src/qdoc/puredocparser.cpp delete mode 100644 src/qdoc/puredocparser.h create mode 100644 src/qdoc/qdoc/CMakeLists.txt create mode 100644 src/qdoc/qdoc/access.h create mode 100644 src/qdoc/qdoc/aggregate.cpp create mode 100644 src/qdoc/qdoc/aggregate.h create mode 100644 src/qdoc/qdoc/atom.cpp create mode 100644 src/qdoc/qdoc/atom.h create mode 100644 src/qdoc/qdoc/boundaries/filesystem/directorypath.cpp create mode 100644 src/qdoc/qdoc/boundaries/filesystem/directorypath.h create mode 100644 src/qdoc/qdoc/boundaries/filesystem/filepath.cpp create mode 100644 src/qdoc/qdoc/boundaries/filesystem/filepath.h create mode 100644 src/qdoc/qdoc/boundaries/filesystem/resolvedfile.cpp create mode 100644 src/qdoc/qdoc/boundaries/filesystem/resolvedfile.h create mode 100644 src/qdoc/qdoc/boundaries/refined_typedef.h create mode 100644 src/qdoc/qdoc/boundaries/refined_typedef_members.qdocinc create mode 100644 src/qdoc/qdoc/clangcodeparser.cpp create mode 100644 src/qdoc/qdoc/clangcodeparser.h create mode 100644 src/qdoc/qdoc/classnode.cpp create mode 100644 src/qdoc/qdoc/classnode.h create mode 100644 src/qdoc/qdoc/codechunk.cpp create mode 100644 src/qdoc/qdoc/codechunk.h create mode 100644 src/qdoc/qdoc/codemarker.cpp create mode 100644 src/qdoc/qdoc/codemarker.h create mode 100644 src/qdoc/qdoc/codeparser.cpp create mode 100644 src/qdoc/qdoc/codeparser.h create mode 100644 src/qdoc/qdoc/collectionnode.cpp create mode 100644 src/qdoc/qdoc/collectionnode.h create mode 100644 src/qdoc/qdoc/config.cpp create mode 100644 src/qdoc/qdoc/config.h create mode 100644 src/qdoc/qdoc/cppcodemarker.cpp create mode 100644 src/qdoc/qdoc/cppcodemarker.h create mode 100644 src/qdoc/qdoc/cppcodeparser.cpp create mode 100644 src/qdoc/qdoc/cppcodeparser.h create mode 100644 src/qdoc/qdoc/doc.cpp create mode 100644 src/qdoc/qdoc/doc.h create mode 100644 src/qdoc/qdoc/doc/config/qdoc.qdocconf create mode 100644 src/qdoc/qdoc/doc/corefeatures.qdoc create mode 100644 src/qdoc/qdoc/doc/examples/cpp.qdoc.sample create mode 100644 src/qdoc/qdoc/doc/examples/layoutmanagement.qdocinc create mode 100644 src/qdoc/qdoc/doc/examples/main.cpp create mode 100644 src/qdoc/qdoc/doc/examples/mainwindow.cpp create mode 100644 src/qdoc/qdoc/doc/examples/minimum.qdocconf create mode 100644 src/qdoc/qdoc/doc/examples/objectmodel.qdocinc create mode 100644 src/qdoc/qdoc/doc/examples/qml.qdoc.sample create mode 100644 src/qdoc/qdoc/doc/examples/samples.qdocinc create mode 100644 src/qdoc/qdoc/doc/examples/signalandslots.qdocinc create mode 100644 src/qdoc/qdoc/doc/files/basicqt.qdoc.sample create mode 100644 src/qdoc/qdoc/doc/files/compat.qdocconf create mode 100644 src/qdoc/qdoc/doc/files/qtgui.qdocconf create mode 100644 src/qdoc/qdoc/doc/images/happy.gif create mode 100644 src/qdoc/qdoc/doc/images/happyguy.jpg create mode 100644 src/qdoc/qdoc/doc/images/link-to-qquickitem.png create mode 100644 src/qdoc/qdoc/doc/images/links-to-broken-links.png create mode 100644 src/qdoc/qdoc/doc/images/links-to-links.png create mode 100644 src/qdoc/qdoc/doc/images/qa-table.png create mode 100644 src/qdoc/qdoc/doc/images/qt-logo.png create mode 100644 src/qdoc/qdoc/doc/images/training.jpg create mode 100644 src/qdoc/qdoc/doc/images/windows-pushbutton.png create mode 100644 src/qdoc/qdoc/doc/images/windows-toolbutton.png create mode 100644 src/qdoc/qdoc/doc/qdoc-guide/qdoc-guide.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-cmdindex.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-contextcmds.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-intro.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-markupcmds.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-qdocconf.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual-topiccmds.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-manual.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-minimum-qdocconf.qdoc create mode 100644 src/qdoc/qdoc/doc/qdoc-warnings.qdoc create mode 100644 src/qdoc/qdoc/doc/qtgui-qdocconf.qdoc create mode 100644 src/qdoc/qdoc/docbookgenerator.cpp create mode 100644 src/qdoc/qdoc/docbookgenerator.h create mode 100644 src/qdoc/qdoc/docparser.cpp create mode 100644 src/qdoc/qdoc/docparser.h create mode 100644 src/qdoc/qdoc/docprivate.cpp create mode 100644 src/qdoc/qdoc/docprivate.h create mode 100644 src/qdoc/qdoc/docutilities.h create mode 100644 src/qdoc/qdoc/editdistance.cpp create mode 100644 src/qdoc/qdoc/editdistance.h create mode 100644 src/qdoc/qdoc/enumitem.h create mode 100644 src/qdoc/qdoc/enumnode.cpp create mode 100644 src/qdoc/qdoc/enumnode.h create mode 100644 src/qdoc/qdoc/examplenode.h create mode 100644 src/qdoc/qdoc/externalpagenode.cpp create mode 100644 src/qdoc/qdoc/externalpagenode.h create mode 100644 src/qdoc/qdoc/filesystem/fileresolver.cpp create mode 100644 src/qdoc/qdoc/filesystem/fileresolver.h create mode 100644 src/qdoc/qdoc/functionnode.cpp create mode 100644 src/qdoc/qdoc/functionnode.h create mode 100644 src/qdoc/qdoc/generator.cpp create mode 100644 src/qdoc/qdoc/generator.h create mode 100644 src/qdoc/qdoc/headernode.cpp create mode 100644 src/qdoc/qdoc/headernode.h create mode 100644 src/qdoc/qdoc/helpprojectwriter.cpp create mode 100644 src/qdoc/qdoc/helpprojectwriter.h create mode 100644 src/qdoc/qdoc/htmlgenerator.cpp create mode 100644 src/qdoc/qdoc/htmlgenerator.h create mode 100644 src/qdoc/qdoc/importrec.h create mode 100644 src/qdoc/qdoc/location.cpp create mode 100644 src/qdoc/qdoc/location.h create mode 100644 src/qdoc/qdoc/macro.h create mode 100644 src/qdoc/qdoc/main.cpp create mode 100644 src/qdoc/qdoc/manifestwriter.cpp create mode 100644 src/qdoc/qdoc/manifestwriter.h create mode 100644 src/qdoc/qdoc/namespacenode.cpp create mode 100644 src/qdoc/qdoc/namespacenode.h create mode 100644 src/qdoc/qdoc/node.cpp create mode 100644 src/qdoc/qdoc/node.h create mode 100644 src/qdoc/qdoc/openedlist.cpp create mode 100644 src/qdoc/qdoc/openedlist.h create mode 100644 src/qdoc/qdoc/pagenode.cpp create mode 100644 src/qdoc/qdoc/pagenode.h create mode 100644 src/qdoc/qdoc/parameters.cpp create mode 100644 src/qdoc/qdoc/parameters.h create mode 100644 src/qdoc/qdoc/propertynode.cpp create mode 100644 src/qdoc/qdoc/propertynode.h create mode 100644 src/qdoc/qdoc/proxynode.cpp create mode 100644 src/qdoc/qdoc/proxynode.h create mode 100644 src/qdoc/qdoc/puredocparser.cpp create mode 100644 src/qdoc/qdoc/puredocparser.h create mode 100644 src/qdoc/qdoc/qdoccommandlineparser.cpp create mode 100644 src/qdoc/qdoc/qdoccommandlineparser.h create mode 100644 src/qdoc/qdoc/qdocdatabase.cpp create mode 100644 src/qdoc/qdoc/qdocdatabase.h create mode 100644 src/qdoc/qdoc/qdocindexfiles.cpp create mode 100644 src/qdoc/qdoc/qdocindexfiles.h create mode 100644 src/qdoc/qdoc/qmlcodemarker.cpp create mode 100644 src/qdoc/qdoc/qmlcodemarker.h create mode 100644 src/qdoc/qdoc/qmlcodeparser.cpp create mode 100644 src/qdoc/qdoc/qmlcodeparser.h create mode 100644 src/qdoc/qdoc/qmlmarkupvisitor.cpp create mode 100644 src/qdoc/qdoc/qmlmarkupvisitor.h create mode 100644 src/qdoc/qdoc/qmlpropertynode.cpp create mode 100644 src/qdoc/qdoc/qmlpropertynode.h create mode 100644 src/qdoc/qdoc/qmltypenode.cpp create mode 100644 src/qdoc/qdoc/qmltypenode.h create mode 100644 src/qdoc/qdoc/qmlvisitor.cpp create mode 100644 src/qdoc/qdoc/qmlvisitor.h create mode 100644 src/qdoc/qdoc/quoter.cpp create mode 100644 src/qdoc/qdoc/quoter.h create mode 100644 src/qdoc/qdoc/relatedclass.cpp create mode 100644 src/qdoc/qdoc/relatedclass.h create mode 100644 src/qdoc/qdoc/sections.cpp create mode 100644 src/qdoc/qdoc/sections.h create mode 100644 src/qdoc/qdoc/sharedcommentnode.cpp create mode 100644 src/qdoc/qdoc/sharedcommentnode.h create mode 100644 src/qdoc/qdoc/singleton.h create mode 100644 src/qdoc/qdoc/tagfilewriter.cpp create mode 100644 src/qdoc/qdoc/tagfilewriter.h create mode 100644 src/qdoc/qdoc/text.cpp create mode 100644 src/qdoc/qdoc/text.h create mode 100644 src/qdoc/qdoc/tokenizer.cpp create mode 100644 src/qdoc/qdoc/tokenizer.h create mode 100644 src/qdoc/qdoc/topic.h create mode 100644 src/qdoc/qdoc/tree.cpp create mode 100644 src/qdoc/qdoc/tree.h create mode 100644 src/qdoc/qdoc/typedefnode.cpp create mode 100644 src/qdoc/qdoc/typedefnode.h create mode 100644 src/qdoc/qdoc/utilities.cpp create mode 100644 src/qdoc/qdoc/utilities.h create mode 100644 src/qdoc/qdoc/variablenode.cpp create mode 100644 src/qdoc/qdoc/variablenode.h create mode 100644 src/qdoc/qdoc/webxmlgenerator.cpp create mode 100644 src/qdoc/qdoc/webxmlgenerator.h create mode 100644 src/qdoc/qdoc/xmlgenerator.cpp create mode 100644 src/qdoc/qdoc/xmlgenerator.h delete mode 100644 src/qdoc/qdoccommandlineparser.cpp delete mode 100644 src/qdoc/qdoccommandlineparser.h delete mode 100644 src/qdoc/qdocdatabase.cpp delete mode 100644 src/qdoc/qdocdatabase.h delete mode 100644 src/qdoc/qdocindexfiles.cpp delete mode 100644 src/qdoc/qdocindexfiles.h delete mode 100644 src/qdoc/qmlcodemarker.cpp delete mode 100644 src/qdoc/qmlcodemarker.h delete mode 100644 src/qdoc/qmlcodeparser.cpp delete mode 100644 src/qdoc/qmlcodeparser.h delete mode 100644 src/qdoc/qmlmarkupvisitor.cpp delete mode 100644 src/qdoc/qmlmarkupvisitor.h delete mode 100644 src/qdoc/qmlpropertynode.cpp delete mode 100644 src/qdoc/qmlpropertynode.h delete mode 100644 src/qdoc/qmltypenode.cpp delete mode 100644 src/qdoc/qmltypenode.h delete mode 100644 src/qdoc/qmlvisitor.cpp delete mode 100644 src/qdoc/qmlvisitor.h delete mode 100644 src/qdoc/quoter.cpp delete mode 100644 src/qdoc/quoter.h delete mode 100644 src/qdoc/relatedclass.cpp delete mode 100644 src/qdoc/relatedclass.h delete mode 100644 src/qdoc/sections.cpp delete mode 100644 src/qdoc/sections.h delete mode 100644 src/qdoc/sharedcommentnode.cpp delete mode 100644 src/qdoc/sharedcommentnode.h delete mode 100644 src/qdoc/singleton.h delete mode 100644 src/qdoc/tagfilewriter.cpp delete mode 100644 src/qdoc/tagfilewriter.h delete mode 100644 src/qdoc/text.cpp delete mode 100644 src/qdoc/text.h delete mode 100644 src/qdoc/tokenizer.cpp delete mode 100644 src/qdoc/tokenizer.h delete mode 100644 src/qdoc/topic.h delete mode 100644 src/qdoc/tree.cpp delete mode 100644 src/qdoc/tree.h delete mode 100644 src/qdoc/typedefnode.cpp delete mode 100644 src/qdoc/typedefnode.h delete mode 100644 src/qdoc/utilities.cpp delete mode 100644 src/qdoc/utilities.h delete mode 100644 src/qdoc/variablenode.cpp delete mode 100644 src/qdoc/variablenode.h delete mode 100644 src/qdoc/webxmlgenerator.cpp delete mode 100644 src/qdoc/webxmlgenerator.h delete mode 100644 src/qdoc/xmlgenerator.cpp delete mode 100644 src/qdoc/xmlgenerator.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 466fca7a0..dc03e1c14 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -45,9 +45,9 @@ endif() if(QT_FEATURE_qtplugininfo) add_subdirectory(qtplugininfo) endif() -if(QT_FEATURE_qdoc AND QT_FEATURE_clangcpp) - add_subdirectory(qdoc) -endif() + +add_subdirectory(qdoc) + if(QT_FEATURE_qdbus) add_subdirectory(qdbus) endif() diff --git a/src/qdoc/CMakeLists.txt b/src/qdoc/CMakeLists.txt index ee3516e12..c25c4a8ee 100644 --- a/src/qdoc/CMakeLists.txt +++ b/src/qdoc/CMakeLists.txt @@ -1,109 +1,6 @@ -# Copyright (C) 2022 The Qt Company Ltd. +# Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -if(CMAKE_VERSION VERSION_LESS "3.19" AND MSVC AND CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") - message(WARNING "qdoc will not be built in this configuration.") - return() +if(QT_FEATURE_qdoc AND QT_FEATURE_clangcpp) + add_subdirectory(qdoc) endif() - -if (MINGW) - set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" PROPERTY _qt_skip_separate_debug_info ON) -endif() - - -##################################################################### -## qdoc Tool: -##################################################################### - -qt_get_tool_target_name(target_name qdoc) -qt_internal_add_tool(${target_name} - TARGET_DESCRIPTION "Qt Documentation Compiler" - TOOLS_TARGET Tools - USER_FACING - SOURCES - aggregate.cpp - atom.cpp - boundaries/filesystem/directorypath.cpp - boundaries/filesystem/filepath.cpp - boundaries/filesystem/resolvedfile.cpp - clangcodeparser.cpp - classnode.cpp - codechunk.cpp - codemarker.cpp - codeparser.cpp - collectionnode.cpp - config.cpp - cppcodemarker.cpp - cppcodeparser.cpp - doc.cpp - docbookgenerator.cpp - docparser.cpp - docprivate.cpp - editdistance.cpp - enumnode.cpp - externalpagenode.cpp - filesystem/fileresolver.cpp - functionnode.cpp - generator.cpp - headernode.cpp - helpprojectwriter.cpp - htmlgenerator.cpp - location.cpp - main.cpp - manifestwriter.cpp - namespacenode.cpp - node.cpp - openedlist.cpp - pagenode.cpp - parameters.cpp - propertynode.cpp - proxynode.cpp - puredocparser.cpp - qdoccommandlineparser.cpp - qdocdatabase.cpp - qdocindexfiles.cpp - qmlcodemarker.cpp - qmlcodeparser.cpp - qmlmarkupvisitor.cpp - qmlpropertynode.cpp - qmltypenode.cpp - qmlvisitor.cpp - quoter.cpp - relatedclass.cpp - sections.cpp - sharedcommentnode.cpp - tagfilewriter.cpp - text.cpp - tokenizer.cpp - tree.cpp - typedefnode.cpp - utilities.cpp - variablenode.cpp - webxmlgenerator.cpp - xmlgenerator.cpp - INCLUDE_DIRECTORIES - ${CMAKE_CURRENT_LIST_DIR} - LIBRARIES - Qt::QmlPrivate - WrapLibClang::WrapLibClang - DEFINES - #(CLANG_RESOURCE_DIR=\"/clang//include\") # special case remove - CLANG_RESOURCE_DIR=${QT_LIBCLANG_RESOURCE_DIR} - # To provide the ability to workaround version-specific Clang issues. - # A re-export of (LLVM|CLANG)_VERSION_MAJOR done in WrapLibClang.cmake - LIBCLANG_VERSION_MAJOR=${QT_LIB_CLANG_VERSION_MAJOR} - QDOC2_COMPAT -) -qt_internal_return_unless_building_tools() - -# If libclangTooling.a is not built with -fPIE enabled we cannot link it to qdoc. -# TODO: Re-enable PIE once clang is built with PIE in provisioning. -set_target_properties(${target_name} PROPERTIES POSITION_INDEPENDENT_CODE FALSE) - -qt_internal_extend_target(${target_name} CONDITION (WIN32 AND ICC) OR MSVC - LINK_OPTIONS - "/STACK:4194304" -) -qt_internal_add_docs(${target_name} - doc/config/qdoc.qdocconf -) diff --git a/src/qdoc/access.h b/src/qdoc/access.h deleted file mode 100644 index 96cad686b..000000000 --- a/src/qdoc/access.h +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include - -#ifndef ACCESS_H -#define ACCESS_H - -QT_BEGIN_NAMESPACE - -enum class Access : unsigned char { Public, Protected, Private }; - -QT_END_NAMESPACE - -#endif // ACCESS_H diff --git a/src/qdoc/aggregate.cpp b/src/qdoc/aggregate.cpp deleted file mode 100644 index 171e92a17..000000000 --- a/src/qdoc/aggregate.cpp +++ /dev/null @@ -1,892 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "aggregate.h" - -#include "functionnode.h" -#include "parameters.h" -#include "typedefnode.h" -#include "qdocdatabase.h" -#include "qmlpropertynode.h" -#include "qmltypenode.h" -#include "sharedcommentnode.h" - -QT_BEGIN_NAMESPACE - -/*! - \class Aggregate - */ - -/*! \fn Aggregate::Aggregate(NodeType type, Aggregate *parent, const QString &name) - The constructor should never be called directly. It is only called - by the constructors of subclasses of Aggregate. Those constructors - pass the node \a type they want to create, the \a parent of the new - node, and its \a name. - */ - -/*! - Recursively set all non-related members in the list of children to - \nullptr, after which each aggregate can safely delete all children - in their list. Aggregate's destructor calls this only on the root - namespace node. - */ -void Aggregate::dropNonRelatedMembers() -{ - for (auto &child : m_children) { - if (!child) - continue; - if (child->parent() != this) - child = nullptr; - else if (child->isAggregate()) - static_cast(child)->dropNonRelatedMembers(); - } -} - -/*! - Destroys this Aggregate; deletes each child. - */ -Aggregate::~Aggregate() -{ - // If this is the root, clear non-related children first - if (isNamespace() && name().isEmpty()) - dropNonRelatedMembers(); - - m_enumChildren.clear(); - m_nonfunctionMap.clear(); - m_functionMap.clear(); - qDeleteAll(m_children.begin(), m_children.end()); - m_children.clear(); -} - -/*! - If \a genus is \c{Node::DontCare}, find the first node in - this node's child list that has the given \a name. If this - node is a QML type, be sure to also look in the children - of its property group nodes. Return the matching node or \c nullptr. - - If \a genus is either \c{Node::CPP} or \c {Node::QML}, then - find all this node's children that have the given \a name, - and return the one that satisfies the \a genus requirement. - */ -Node *Aggregate::findChildNode(const QString &name, Node::Genus genus, int findFlags) const -{ - if (genus == Node::DontCare) { - Node *node = m_nonfunctionMap.value(name); - if (node) - return node; - } else { - const NodeList &nodes = m_nonfunctionMap.values(name); - for (auto *node : nodes) { - if (genus & node->genus()) { - if (findFlags & TypesOnly) { - if (!node->isTypedef() && !node->isClassNode() - && !node->isQmlType() && !node->isEnumType()) - continue; - } else if (findFlags & IgnoreModules && node->isModule()) - continue; - return node; - } - } - } - if (genus != Node::DontCare && !(genus & this->genus())) - return nullptr; - return m_functionMap.value(name); -} - -/*! - Find all the child nodes of this node that are named - \a name and return them in \a nodes. - */ -void Aggregate::findChildren(const QString &name, NodeVector &nodes) const -{ - nodes.clear(); - int nonfunctionCount = m_nonfunctionMap.count(name); - auto it = m_functionMap.find(name); - if (it != m_functionMap.end()) { - int functionCount = 0; - FunctionNode *fn = it.value(); - while (fn != nullptr) { - ++functionCount; - fn = fn->nextOverload(); - } - nodes.reserve(nonfunctionCount + functionCount); - fn = it.value(); - while (fn != nullptr) { - nodes.append(fn); - fn = fn->nextOverload(); - } - } else { - nodes.reserve(nonfunctionCount); - } - if (nonfunctionCount > 0) { - for (auto it = m_nonfunctionMap.find(name); - it != m_nonfunctionMap.end() && it.key() == name; ++it) { - nodes.append(it.value()); - } - } -} - -/*! - This function searches for a child node of this Aggregate, - such that the child node has the spacified \a name and the - function \a isMatch returns true for the node. The function - passed must be one of the isXxx() functions in class Node - that tests the node type. - */ -Node *Aggregate::findNonfunctionChild(const QString &name, bool (Node::*isMatch)() const) -{ - const NodeList &nodes = m_nonfunctionMap.values(name); - for (auto *node : nodes) { - if ((node->*(isMatch))()) - return node; - } - return nullptr; -} - -/*! - Find a function node that is a child of this node, such that - the function node has the specified \a name and \a parameters. - If \a parameters is empty but no matching function is found - that has no parameters, return the first non-internal primary - function or overload, whether it has parameters or not. - */ -FunctionNode *Aggregate::findFunctionChild(const QString &name, const Parameters ¶meters) -{ - auto it = m_functionMap.find(name); - if (it == m_functionMap.end()) - return nullptr; - FunctionNode *fn = it.value(); - - if (parameters.isEmpty() && fn->parameters().isEmpty() && !fn->isInternal()) - return fn; - - while (fn != nullptr) { - if (parameters.count() == fn->parameters().count() && !fn->isInternal()) { - if (parameters.isEmpty()) - return fn; - bool matched = true; - for (int i = 0; i < parameters.count(); i++) { - if (parameters.at(i).type() != fn->parameters().at(i).type()) { - matched = false; - break; - } - } - if (matched) - return fn; - } - fn = fn->nextOverload(); - } - - if (parameters.isEmpty()) { - for (fn = it.value(); fn != nullptr; fn = fn->nextOverload()) - if (!fn->isInternal()) - return fn; - return it.value(); - } - return nullptr; -} - -/*! - Find the function node that is a child of this node, such - that the function described has the same name and signature - as the function described by the function node \a clone. - */ -FunctionNode *Aggregate::findFunctionChild(const FunctionNode *clone) -{ - FunctionNode *fn = m_functionMap.value(clone->name()); - while (fn != nullptr) { - if (isSameSignature(clone, fn)) - return fn; - fn = fn->nextOverload(); - } - return nullptr; -} - -/*! - Mark all child nodes that have no documentation as having - private access and internal status. qdoc will then ignore - them for documentation purposes. - */ -void Aggregate::markUndocumentedChildrenInternal() -{ - for (auto *child : std::as_const(m_children)) { - if (!child->isSharingComment() && !child->hasDoc() && !child->isDontDocument()) { - if (!child->docMustBeGenerated()) { - if (child->isFunction()) { - if (static_cast(child)->hasAssociatedProperties()) - continue; - } else if (child->isTypedef()) { - if (static_cast(child)->hasAssociatedEnum()) - continue; - } - child->setAccess(Access::Private); - child->setStatus(Node::Internal); - } - } - if (child->isAggregate()) { - static_cast(child)->markUndocumentedChildrenInternal(); - } - } -} - -/*! - This is where we set the overload numbers for function nodes. - */ -void Aggregate::normalizeOverloads() -{ - /* - Ensure that none of the primary functions is inactive, private, - or marked \e {overload}. - */ - for (auto it = m_functionMap.begin(); it != m_functionMap.end(); ++it) { - FunctionNode *fn = it.value(); - if (fn->isOverload()) { - FunctionNode *primary = fn->findPrimaryFunction(); - if (primary) { - primary->setNextOverload(fn); - it.value() = primary; - fn = primary; - } - } - int count = 0; - fn->setOverloadNumber(0); // also clears the overload flag - FunctionNode *internalFn = nullptr; - while (fn != nullptr) { - FunctionNode *next = fn->nextOverload(); - if (next) { - if (next->isInternal()) { - // internal overloads are moved to a separate list - // and processed last - fn->setNextOverload(next->nextOverload()); - next->setNextOverload(internalFn); - internalFn = next; - } else { - next->setOverloadNumber(++count); - fn = fn->nextOverload(); - } - } else { - fn->setNextOverload(internalFn); - break; - } - } - while (internalFn) { - internalFn->setOverloadNumber(++count); - internalFn = internalFn->nextOverload(); - } - } - - for (auto *node : std::as_const(m_children)) { - if (node->isAggregate()) - static_cast(node)->normalizeOverloads(); - } -} - -/*! - Returns a const reference to the list of child nodes of this - aggregate that are not function nodes. Duplicate nodes are - removed from the list. - */ -const NodeList &Aggregate::nonfunctionList() -{ - m_nonfunctionList = m_nonfunctionMap.values(); - std::sort(m_nonfunctionList.begin(), m_nonfunctionList.end(), Node::nodeNameLessThan); - m_nonfunctionList.erase(std::unique(m_nonfunctionList.begin(), m_nonfunctionList.end()), - m_nonfunctionList.end()); - return m_nonfunctionList; -} - -/*! \fn bool Aggregate::isAggregate() const - Returns \c true because this node is an instance of Aggregate, - which means it can have children. - */ - -/*! - Finds the enum type node that has \a enumValue as one of - its enum values and returns a pointer to it. Returns 0 if - no enum type node is found that has \a enumValue as one - of its values. - */ -const EnumNode *Aggregate::findEnumNodeForValue(const QString &enumValue) const -{ - for (const auto *node : m_enumChildren) { - const auto *en = static_cast(node); - if (en->hasItem(enumValue)) - return en; - } - return nullptr; -} - -/*! - Compare \a f1 to \a f2 and return \c true if they have the same - signature. Otherwise return \c false. They must have the same - number of parameters, and all the parameter types must be the - same. The functions must have the same constness and refness. - This is a private function. - */ -bool Aggregate::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) -{ - if (f1->parameters().count() != f2->parameters().count()) - return false; - if (f1->isConst() != f2->isConst()) - return false; - if (f1->isRef() != f2->isRef()) - return false; - if (f1->isRefRef() != f2->isRefRef()) - return false; - - const Parameters &p1 = f1->parameters(); - const Parameters &p2 = f2->parameters(); - for (int i = 0; i < p1.count(); i++) { - if (p1.at(i).hasType() && p2.at(i).hasType()) { - QString t1 = p1.at(i).type(); - QString t2 = p2.at(i).type(); - - if (t1.size() < t2.size()) - qSwap(t1, t2); - - /* - ### hack for C++ to handle superfluous - "Foo::" prefixes gracefully - */ - if (t1 != t2 && t1 != (f2->parent()->name() + "::" + t2)) { - // Accept a difference in the template parametters of the type if one - // is omited (eg. "QAtomicInteger" == "QAtomicInteger") - auto ltLoc = t1.indexOf('<'); - auto gtLoc = t1.indexOf('>', ltLoc); - if (ltLoc < 0 || gtLoc < ltLoc) - return false; - t1.remove(ltLoc, gtLoc - ltLoc + 1); - if (t1 != t2) - return false; - } - } - } - return true; -} - -/*! - This function is only called by addChild(), when the child is a - FunctionNode. If the function map does not contain a function with - the name in \a fn, \a fn is inserted into the function map. If the - map already contains a function by that name, \a fn is appended to - that function's linked list of overloads. - - \note A function's overloads appear in the linked list in the same - order they were created. The first overload in the list is the first - overload created. This order is maintained in the numbering of - overloads. In other words, the first overload in the linked list has - overload number 1, and the last overload in the list has overload - number n, where n is the number of overloads not including the - function in the function map. - - \not Adding a function increments the aggregate's function count, - which is the total number of function nodes in the function map, - including the overloads. The overloads are not inserted into the map - but are in a linked list using the FunctionNode's m_nextOverload - pointer. - - \note The function's overload number and overload flag are set in - normalizeOverloads(). - - \note This is a private function. - - \sa normalizeOverloads() - */ -void Aggregate::addFunction(FunctionNode *fn) -{ - auto it = m_functionMap.find(fn->name()); - if (it == m_functionMap.end()) - m_functionMap.insert(fn->name(), fn); - else - it.value()->appendOverload(fn); -} - -/*! - When an Aggregate adopts a function \a fn that is a child of - another Aggregate, the function is inserted into this - Aggregate's function map. - - The function is also removed from the overload list - that's relative to the original parent \a firstParent. - - \note This is a private function. - */ -void Aggregate::adoptFunction(FunctionNode *fn, Aggregate *firstParent) -{ - auto *primary = firstParent->m_functionMap.value(fn->name()); - if (primary) { - if (primary != fn) - primary->removeOverload(fn); - else if (primary->nextOverload()) - firstParent->m_functionMap.insert(primary->name(), - primary->nextOverload()); - /* else...technically we should call - firstParent->m_functionMap.remove(primary->name()); - but we want to be able to still find global functions - from the global namespace, even after adopting them - elsewhere. - */ - } - fn->setNextOverload(nullptr); - addFunction(fn); -} - -/*! - Adds the \a child to this node's child map using \a title - as the key. The \a child is not added to the child list - again, because it is presumed to already be there. We just - want to be able to find the child by its \a title. - */ -void Aggregate::addChildByTitle(Node *child, const QString &title) -{ - m_nonfunctionMap.insert(title, child); -} - -/*! - Adds the \a child to this node's child list and sets the child's - parent pointer to this Aggregate. It then mounts the child with - mountChild(). - - The \a child is then added to this Aggregate's searchable maps - and lists. - - \note This function does not test the child's parent pointer - for null before changing it. If the child's parent pointer - is not null, then it is being reparented. The child becomes - a child of this Aggregate, but it also remains a child of - the Aggregate that is it's old parent. But the child will - only have one parent, and it will be this Aggregate. The is - because of the \c relates command. - - \sa mountChild(), dismountChild() - */ -void Aggregate::addChild(Node *child) -{ - m_children.append(child); - child->setParent(this); - child->setOutputSubdirectory(this->outputSubdirectory()); - child->setUrl(QString()); - child->setIndexNodeFlag(isIndexNode()); - - if (child->isFunction()) { - addFunction(static_cast(child)); - } else if (!child->name().isEmpty()) { - m_nonfunctionMap.insert(child->name(), child); - if (child->isEnumType()) - m_enumChildren.append(child); - } -} - -/*! - This Aggregate becomes the adoptive parent of \a child. The - \a child knows this Aggregate as its parent, but its former - parent continues to have pointers to the child in its child - list and in its searchable data structures. But the child is - also added to the child list and searchable data structures - of this Aggregate. - */ -void Aggregate::adoptChild(Node *child) -{ - if (child->parent() != this) { - m_children.append(child); - auto firstParent = child->parent(); - child->setParent(this); - if (child->isFunction()) { - adoptFunction(static_cast(child), firstParent); - } else if (!child->name().isEmpty()) { - m_nonfunctionMap.insert(child->name(), child); - if (child->isEnumType()) - m_enumChildren.append(child); - } - if (child->isSharedCommentNode()) { - auto *scn = static_cast(child); - for (Node *n : scn->collective()) - adoptChild(n); - } - } -} - -/*! - Recursively sets the output subdirectory for children - */ -void Aggregate::setOutputSubdirectory(const QString &t) -{ - Node::setOutputSubdirectory(t); - for (auto *node : std::as_const(m_children)) - node->setOutputSubdirectory(t); -} - -/*! - If this node has a child that is a QML property named \a n, return a - pointer to that child. Otherwise, return \nullptr. - */ -QmlPropertyNode *Aggregate::hasQmlProperty(const QString &n) const -{ - NodeType goal = Node::QmlProperty; - for (auto *child : std::as_const(m_children)) { - if (child->nodeType() == goal) { - if (child->name() == n) - return static_cast(child); - } - } - return nullptr; -} - -/*! - If this node has a child that is a QML property named \a n and that - also matches \a attached, return a pointer to that child. - */ -QmlPropertyNode *Aggregate::hasQmlProperty(const QString &n, bool attached) const -{ - NodeType goal = Node::QmlProperty; - for (auto *child : std::as_const(m_children)) { - if (child->nodeType() == goal) { - if (child->name() == n && child->isAttached() == attached) - return static_cast(child); - } - } - return nullptr; -} - -/*! - The FunctionNode \a fn is assumed to be a member function - of this Aggregate. The function's name is looked up in the - Aggregate's function map. It should be found because it is - assumed that \a fn is in this Aggregate's function map. But - in case it is not found, \c false is returned. - - Normally, the name will be found in the function map, and - the value of the iterator is used to get the value, which - is a pointer to another FunctionNode, which is not itself - an overload. If that function has a non-null overload - pointer, true is returned. Otherwise false is returned. - - This is a convenience function that you should not need to - use. - */ -bool Aggregate::hasOverloads(const FunctionNode *fn) const -{ - auto it = m_functionMap.find(fn->name()); - return !(it == m_functionMap.end()) && (it.value()->nextOverload() != nullptr); -} - -/* - When deciding whether to include a function in the function - index, if the function is marked private, don't include it. - If the function is marked obsolete, don't include it. If the - function is marked internal, don't include it. Or if the - function is a destructor or any kind of constructor, don't - include it. Otherwise include it. - */ -static bool keep(FunctionNode *fn) -{ - if (fn->isPrivate() || fn->isDeprecated() || fn->isInternal() || fn->isSomeCtor() || fn->isDtor()) - return false; - return true; -} - -/*! - Insert all functions declared in this aggregate into the - \a functionIndex. Call the function recursively for each - child that is an aggregate. - - Only include functions that are in the public API and - that are not constructors or destructors. - */ -void Aggregate::findAllFunctions(NodeMapMap &functionIndex) -{ - for (auto it = m_functionMap.constBegin(); it != m_functionMap.constEnd(); ++it) { - FunctionNode *fn = it.value(); - if (keep(fn)) - functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn); - fn = fn->nextOverload(); - while (fn != nullptr) { - if (keep(fn)) - functionIndex[fn->name()].insert(fn->parent()->fullDocumentName(), fn); - fn = fn->nextOverload(); - } - } - for (Node *node : std::as_const(m_children)) { - if (node->isAggregate() && !node->isPrivate() && !node->isDontDocument()) - static_cast(node)->findAllFunctions(functionIndex); - } -} - -/*! - For each child of this node, if the child is a namespace node, - insert the child into the \a namespaces multimap. If the child - is an aggregate, call this function recursively for that child. - - When the function called with the root node of a tree, it finds - all the namespace nodes in that tree and inserts them into the - \a namespaces multimap. - - The root node of a tree is a namespace, but it has no name, so - it is not inserted into the map. So, if this function is called - for each tree in the qdoc database, it finds all the namespace - nodes in the database. - */ -void Aggregate::findAllNamespaces(NodeMultiMap &namespaces) -{ - for (auto *node : std::as_const(m_children)) { - if (node->isAggregate() && !node->isPrivate()) { - if (node->isNamespace() && !node->name().isEmpty()) - namespaces.insert(node->name(), node); - static_cast(node)->findAllNamespaces(namespaces); - } - } -} - -/*! - Returns true if this aggregate contains at least one child - that is marked obsolete. Otherwise returns false. - */ -bool Aggregate::hasObsoleteMembers() const -{ - for (const auto *node : m_children) - if (!node->isPrivate() && node->isDeprecated()) { - if (node->isFunction() || node->isProperty() || node->isEnumType() || node->isTypedef() - || node->isTypeAlias() || node->isVariable() || node->isQmlProperty()) - return true; - } - return false; -} - -/*! - Finds all the obsolete C++ classes and QML types in this - aggregate and all the C++ classes and QML types with obsolete - members, and inserts them into maps used elsewhere for - generating documentation. - */ -void Aggregate::findAllObsoleteThings() -{ - for (auto *node : std::as_const(m_children)) { - if (!node->isPrivate()) { - if (node->isDeprecated()) { - if (node->isClassNode()) - QDocDatabase::obsoleteClasses().insert(node->qualifyCppName(), node); - else if (node->isQmlType()) - QDocDatabase::obsoleteQmlTypes().insert(node->qualifyQmlName(), node); - } else if (node->isClassNode()) { - auto *a = static_cast(node); - if (a->hasObsoleteMembers()) - QDocDatabase::classesWithObsoleteMembers().insert(node->qualifyCppName(), node); - } else if (node->isQmlType()) { - auto *a = static_cast(node); - if (a->hasObsoleteMembers()) - QDocDatabase::qmlTypesWithObsoleteMembers().insert(node->qualifyQmlName(), - node); - } else if (node->isAggregate()) { - static_cast(node)->findAllObsoleteThings(); - } - } - } -} - -/*! - Finds all the C++ classes, QML types, QML basic types, and examples - in this aggregate and inserts them into appropriate maps for later - use in generating documentation. - */ -void Aggregate::findAllClasses() -{ - for (auto *node : std::as_const(m_children)) { - if (!node->isPrivate() && !node->isInternal() && !node->isDontDocument() - && node->tree()->camelCaseModuleName() != QString("QDoc")) { - if (node->isClassNode()) { - QDocDatabase::cppClasses().insert(node->qualifyCppName().toLower(), node); - } else if (node->isQmlType()) { - QString name = node->name().toLower(); - QDocDatabase::qmlTypes().insert(name, node); - // also add to the QML basic type map - if (node->isQmlBasicType()) - QDocDatabase::qmlBasicTypes().insert(name, node); - } else if (node->isExample()) { - // use the module index title as key for the example map - QString title = node->tree()->indexTitle(); - if (!QDocDatabase::examples().contains(title, node)) - QDocDatabase::examples().insert(title, node); - } else if (node->isAggregate()) { - static_cast(node)->findAllClasses(); - } - } - } -} - -/*! - Find all the attribution pages in this node and insert them - into \a attributions. - */ -void Aggregate::findAllAttributions(NodeMultiMap &attributions) -{ - for (auto *node : std::as_const(m_children)) { - if (!node->isPrivate()) { - if (node->isPageNode() && static_cast(node)->isAttribution()) - attributions.insert(node->tree()->indexTitle(), node); - else if (node->isAggregate()) - static_cast(node)->findAllAttributions(attributions); - } - } -} - -/*! - Finds all the nodes in this node where a \e{since} command appeared - in the qdoc comment and sorts them into maps according to the kind - of node. - - This function is used for generating the "New Classes... in x.y" - section on the \e{What's New in Qt x.y} page. - */ -void Aggregate::findAllSince() -{ - for (auto *node : std::as_const(m_children)) { - if (node->isRelatedNonmember() && node->parent() != this) - continue; - QString sinceString = node->since(); - // Insert a new entry into each map for each new since string found. - if (node->isInAPI() && !sinceString.isEmpty()) { - // operator[] will insert a default-constructed value into the - // map if key is not found, which is what we want here. - auto &nsmap = QDocDatabase::newSinceMaps()[sinceString]; - auto &ncmap = QDocDatabase::newClassMaps()[sinceString]; - auto &nqcmap = QDocDatabase::newQmlTypeMaps()[sinceString]; - - if (node->isFunction()) { - // Insert functions into the general since map. - auto *fn = static_cast(node); - if (!fn->isDeprecated() && !fn->isSomeCtor() && !fn->isDtor()) - nsmap.insert(fn->name(), fn); - } else if (node->isClassNode()) { - // Insert classes into the since and class maps. - QString name = node->qualifyWithParentName(); - nsmap.insert(name, node); - ncmap.insert(name, node); - } else if (node->isQmlType()) { - // Insert QML elements into the since and element maps. - QString name = node->qualifyWithParentName(); - nsmap.insert(name, node); - nqcmap.insert(name, node); - } else if (node->isQmlProperty()) { - // Insert QML properties into the since map. - nsmap.insert(node->name(), node); - } else { - // Insert external documents into the general since map. - QString name = node->qualifyWithParentName(); - nsmap.insert(name, node); - } - } - // Enum values - a special case as EnumItem is not a Node subclass - if (node->isInAPI() && node->isEnumType()) { - for (const auto &val : static_cast(node)->items()) { - sinceString = val.since(); - if (sinceString.isEmpty()) - continue; - // Insert to enum value map - QDocDatabase::newEnumValueMaps()[sinceString].insert( - node->name() + "::" + val.name(), node); - // Ugly hack: Insert into general map with an empty key - - // we need something in there to mark the corresponding - // section populated. See Sections class constructor. - QDocDatabase::newSinceMaps()[sinceString].replace(QString(), node); - } - } - - // Recursively find child nodes with since commands. - if (node->isAggregate()) - static_cast(node)->findAllSince(); - } -} - -/*! - Resolves the inheritance information for all QML type children - of this aggregate. -*/ -void Aggregate::resolveQmlInheritance() -{ - NodeMap previousSearches; - for (auto *child : std::as_const(m_children)) { - if (!child->isQmlType()) - continue; - static_cast(child)->resolveInheritance(previousSearches); - } -} - -/*! - Returns a word representing the kind of Aggregate this node is. - Currently only works for class, struct, and union, but it can - easily be extended. If \a cap is true, the word is capitalised. - */ -QString Aggregate::typeWord(bool cap) const -{ - if (cap) { - switch (nodeType()) { - case Node::Class: - return QLatin1String("Class"); - case Node::Struct: - return QLatin1String("Struct"); - case Node::Union: - return QLatin1String("Union"); - default: - break; - } - } else { - switch (nodeType()) { - case Node::Class: - return QLatin1String("class"); - case Node::Struct: - return QLatin1String("struct"); - case Node::Union: - return QLatin1String("union"); - default: - break; - } - } - return QString(); -} - -/*! \fn int Aggregate::count() const - Returns the number of children in the child list. - */ - -/*! \fn const NodeList &Aggregate::childNodes() const - Returns a const reference to the child list. - */ - -/*! \fn NodeList::ConstIterator Aggregate::constBegin() const - Returns a const iterator pointing at the beginning of the child list. - */ - -/*! \fn NodeList::ConstIterator Aggregate::constEnd() const - Returns a const iterator pointing at the end of the child list. - */ - -/*! \fn QmlTypeNode *Aggregate::qmlBaseNode() const - If this Aggregate is a QmlTypeNode, this function returns a pointer to - the QmlTypeNode that is its base type. Otherwise it returns \c nullptr. - A QmlTypeNode doesn't always have a base type, so even when this Aggregate - is aQmlTypeNode, the pointer returned can be \c nullptr. - */ - -/*! \fn FunctionMap &Aggregate::functionMap() - Returns a reference to this Aggregate's function map, which - is a map of all the children of this Aggregate that are - FunctionNodes. - */ - -/*! \fn void Aggregate::appendToRelatedByProxy(const NodeList &t) - Appends the list of node pointers to the list of elements that are - related to this Aggregate but are documented in a different module. - - \sa relatedByProxy() - */ - -/*! \fn NodeList &Aggregate::relatedByProxy() - Returns a reference to a list of node pointers where each element - points to a node in an index file for some other module, such that - whatever the node represents was documented in that other module, - but it is related to this Aggregate, so when the documentation for - this Aggregate is written, it will contain links to elements in the - other module. - */ - -QT_END_NAMESPACE diff --git a/src/qdoc/aggregate.h b/src/qdoc/aggregate.h deleted file mode 100644 index eaa9ab635..000000000 --- a/src/qdoc/aggregate.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef AGGREGATE_H -#define AGGREGATE_H - -#include "pagenode.h" - -#include - -#include -#include - -QT_BEGIN_NAMESPACE - -class FunctionNode; -class QmlTypeNode; -class QmlPropertyNode; - -class Aggregate : public PageNode -{ -public: - [[nodiscard]] Node *findChildNode(const QString &name, Node::Genus genus, - int findFlags = 0) const; - Node *findNonfunctionChild(const QString &name, bool (Node::*)() const); - void findChildren(const QString &name, NodeVector &nodes) const; - FunctionNode *findFunctionChild(const QString &name, const Parameters ¶meters); - FunctionNode *findFunctionChild(const FunctionNode *clone); - - void normalizeOverloads(); - void markUndocumentedChildrenInternal(); - - [[nodiscard]] bool isAggregate() const override { return true; } - [[nodiscard]] const EnumNode *findEnumNodeForValue(const QString &enumValue) const; - - [[nodiscard]] qsizetype count() const { return m_children.size(); } - [[nodiscard]] const NodeList &childNodes() const { return m_children; } - const NodeList &nonfunctionList(); - [[nodiscard]] NodeList::ConstIterator constBegin() const { return m_children.constBegin(); } - [[nodiscard]] NodeList::ConstIterator constEnd() const { return m_children.constEnd(); } - - inline void setIncludeFile(const QString& include) { m_includeFile.emplace(include); } - // REMARK: Albeit not enforced at the API boundaries, - // downstream-user can assume that if there is a QString that was - // set, then that string is not empty. - [[nodiscard]] inline const std::optional& includeFile() const { return m_includeFile; } - - [[nodiscard]] QmlPropertyNode *hasQmlProperty(const QString &) const; - [[nodiscard]] QmlPropertyNode *hasQmlProperty(const QString &, bool attached) const; - virtual QmlTypeNode *qmlBaseNode() const { return nullptr; } - void addChildByTitle(Node *child, const QString &title); - void addChild(Node *child); - void adoptChild(Node *child); - void setOutputSubdirectory(const QString &t) override; - - FunctionMap &functionMap() { return m_functionMap; } - void findAllFunctions(NodeMapMap &functionIndex); - void findAllNamespaces(NodeMultiMap &namespaces); - void findAllAttributions(NodeMultiMap &attributions); - [[nodiscard]] bool hasObsoleteMembers() const; - void findAllObsoleteThings(); - void findAllClasses(); - void findAllSince(); - void resolveQmlInheritance(); - bool hasOverloads(const FunctionNode *fn) const; - void appendToRelatedByProxy(const NodeList &t) { m_relatedByProxy.append(t); } - NodeList &relatedByProxy() { return m_relatedByProxy; } - [[nodiscard]] QString typeWord(bool cap) const; - -protected: - Aggregate(NodeType type, Aggregate *parent, const QString &name) - : PageNode(type, parent, name) {} - ~Aggregate() override; - -private: - friend class Node; - void addFunction(FunctionNode *fn); - void adoptFunction(FunctionNode *fn, Aggregate *firstParent); - static bool isSameSignature(const FunctionNode *f1, const FunctionNode *f2); - void dropNonRelatedMembers(); - -protected: - NodeList m_children {}; - NodeList m_relatedByProxy {}; - FunctionMap m_functionMap {}; - -private: - // REMARK: The member indicates the name of a file where the - // aggregate can be found from, for example, an header file that - // declares a class. - // For aggregates such as classes we expect this to always be set - // to a non-empty string after the code-parsing phase. - // Indeed, currently, by default, QDoc always generates such a - // string using the name of the aggregate if no include file can - // be propagated from some of the parents. - // - // Nonetheless, we are still forced to make this an optional, as - // this will not be true for all Aggregates. - // - // For example, for namespaces, we don't seem to set an include - // file and indeed doing so wouldn't be particularly meaningful. - // - // It is possible to assume in later code, especially the - // generation phase, that at least some classes of aggregates - // always have a value set here but we should, for the moment, - // still check for the possibility of something not to be there, - // or warn if we decide to ignore that, to be compliant with the - // current interface, whose change would require deep changes to - // QDoc internal structures. - std::optional m_includeFile{}; - NodeList m_enumChildren {}; - NodeMultiMap m_nonfunctionMap {}; - NodeList m_nonfunctionList {}; -}; - -QT_END_NAMESPACE - -#endif // AGGREGATE_H diff --git a/src/qdoc/atom.cpp b/src/qdoc/atom.cpp deleted file mode 100644 index 69bf6fb9c..000000000 --- a/src/qdoc/atom.cpp +++ /dev/null @@ -1,432 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "atom.h" - -#include "location.h" -#include "qdocdatabase.h" - -#include - -#include - -QT_BEGIN_NAMESPACE - -/*! \class Atom - \brief The Atom class is the fundamental unit for representing - documents internally. - - Atoms have a \i type and are completed by a \i string whose - meaning depends on the \i type. For example, the string - \quotation - \i italic text looks nicer than \bold bold text - \endquotation - is represented by the following atoms: - \quotation - (FormattingLeft, ATOM_FORMATTING_ITALIC) - (String, "italic") - (FormattingRight, ATOM_FORMATTING_ITALIC) - (String, " text is more attractive than ") - (FormattingLeft, ATOM_FORMATTING_BOLD) - (String, "bold") - (FormattingRight, ATOM_FORMATTING_BOLD) - (String, " text") - \endquotation - - \also Text -*/ - -/*! \enum Atom::AtomType - - \value AnnotatedList - \value AutoLink - \value BaseName - \value BriefLeft - \value BriefRight - \value C - \value CaptionLeft - \value CaptionRight - \value Code - \value CodeBad - \value CodeQuoteArgument - \value CodeQuoteCommand - \value DivLeft - \value DivRight - \value EndQmlText - \value ExampleFileLink - \value ExampleImageLink - \value FormatElse - \value FormatEndif - \value FormatIf - \value FootnoteLeft - \value FootnoteRight - \value FormattingLeft - \value FormattingRight - \value GeneratedList - \value Image - \value ImageText - \value ImportantNote - \value InlineImage - \value Keyword - \value LineBreak - \value Link - \value LinkNode - \value ListLeft - \value ListItemNumber - \value ListTagLeft - \value ListTagRight - \value ListItemLeft - \value ListItemRight - \value ListRight - \value NavAutoLink - \value NavLink - \value Nop - \value Note - \value ParaLeft - \value ParaRight - \value Qml - \value QmlText - \value QuotationLeft - \value QuotationRight - \value RawString - \value SectionLeft - \value SectionRight - \value SectionHeadingLeft - \value SectionHeadingRight - \value SidebarLeft - \value SidebarRight - \value SinceList - \value SinceTagLeft - \value SinceTagRight - \value String - \value TableLeft - \value TableRight - \value TableHeaderLeft - \value TableHeaderRight - \value TableRowLeft - \value TableRowRight - \value TableItemLeft - \value TableItemRight - \value TableOfContents - \value Target - \value UnhandledFormat - \value UnknownCommand -*/ - -QString Atom::s_noError = QString(); - -static const struct -{ - const char *english; - int no; -} atms[] = { { "AnnotatedList", Atom::AnnotatedList }, - { "AutoLink", Atom::AutoLink }, - { "BaseName", Atom::BaseName }, - { "br", Atom::BR }, - { "BriefLeft", Atom::BriefLeft }, - { "BriefRight", Atom::BriefRight }, - { "C", Atom::C }, - { "CaptionLeft", Atom::CaptionLeft }, - { "CaptionRight", Atom::CaptionRight }, - { "Code", Atom::Code }, - { "CodeBad", Atom::CodeBad }, - { "CodeQuoteArgument", Atom::CodeQuoteArgument }, - { "CodeQuoteCommand", Atom::CodeQuoteCommand }, - { "DivLeft", Atom::DivLeft }, - { "DivRight", Atom::DivRight }, - { "EndQmlText", Atom::EndQmlText }, - { "ExampleFileLink", Atom::ExampleFileLink }, - { "ExampleImageLink", Atom::ExampleImageLink }, - { "FootnoteLeft", Atom::FootnoteLeft }, - { "FootnoteRight", Atom::FootnoteRight }, - { "FormatElse", Atom::FormatElse }, - { "FormatEndif", Atom::FormatEndif }, - { "FormatIf", Atom::FormatIf }, - { "FormattingLeft", Atom::FormattingLeft }, - { "FormattingRight", Atom::FormattingRight }, - { "GeneratedList", Atom::GeneratedList }, - { "hr", Atom::HR }, - { "Image", Atom::Image }, - { "ImageText", Atom::ImageText }, - { "ImportantLeft", Atom::ImportantLeft }, - { "ImportantRight", Atom::ImportantRight }, - { "InlineImage", Atom::InlineImage }, - { "Keyword", Atom::Keyword }, - { "LegaleseLeft", Atom::LegaleseLeft }, - { "LegaleseRight", Atom::LegaleseRight }, - { "LineBreak", Atom::LineBreak }, - { "Link", Atom::Link }, - { "LinkNode", Atom::LinkNode }, - { "ListLeft", Atom::ListLeft }, - { "ListItemNumber", Atom::ListItemNumber }, - { "ListTagLeft", Atom::ListTagLeft }, - { "ListTagRight", Atom::ListTagRight }, - { "ListItemLeft", Atom::ListItemLeft }, - { "ListItemRight", Atom::ListItemRight }, - { "ListRight", Atom::ListRight }, - { "NavAutoLink", Atom::NavAutoLink }, - { "NavLink", Atom::NavLink }, - { "Nop", Atom::Nop }, - { "NoteLeft", Atom::NoteLeft }, - { "NoteRight", Atom::NoteRight }, - { "ParaLeft", Atom::ParaLeft }, - { "ParaRight", Atom::ParaRight }, - { "Qml", Atom::Qml }, - { "QmlText", Atom::QmlText }, - { "QuotationLeft", Atom::QuotationLeft }, - { "QuotationRight", Atom::QuotationRight }, - { "RawString", Atom::RawString }, - { "SectionLeft", Atom::SectionLeft }, - { "SectionRight", Atom::SectionRight }, - { "SectionHeadingLeft", Atom::SectionHeadingLeft }, - { "SectionHeadingRight", Atom::SectionHeadingRight }, - { "SidebarLeft", Atom::SidebarLeft }, - { "SidebarRight", Atom::SidebarRight }, - { "SinceList", Atom::SinceList }, - { "SinceTagLeft", Atom::SinceTagLeft }, - { "SinceTagRight", Atom::SinceTagRight }, - { "SnippetCommand", Atom::SnippetCommand }, - { "SnippetIdentifier", Atom::SnippetIdentifier }, - { "SnippetLocation", Atom::SnippetLocation }, - { "String", Atom::String }, - { "TableLeft", Atom::TableLeft }, - { "TableRight", Atom::TableRight }, - { "TableHeaderLeft", Atom::TableHeaderLeft }, - { "TableHeaderRight", Atom::TableHeaderRight }, - { "TableRowLeft", Atom::TableRowLeft }, - { "TableRowRight", Atom::TableRowRight }, - { "TableItemLeft", Atom::TableItemLeft }, - { "TableItemRight", Atom::TableItemRight }, - { "TableOfContents", Atom::TableOfContents }, - { "Target", Atom::Target }, - { "UnhandledFormat", Atom::UnhandledFormat }, - { "WarningLeft", Atom::WarningLeft }, - { "WarningRight", Atom::WarningRight }, - { "UnknownCommand", Atom::UnknownCommand }, - { nullptr, 0 } }; - -/*! \fn Atom::Atom(AtomType type, const QString &string) - - Constructs an atom of the specified \a type with the single - parameter \a string and does not put the new atom in a list. -*/ - -/*! \fn Atom::Atom(AtomType type, const QString &p1, const QString &p2) - - Constructs an atom of the specified \a type with the two - parameters \a p1 and \a p2 and does not put the new atom - in a list. -*/ - -/*! \fn Atom(Atom *previous, AtomType type, const QString &string) - - Constructs an atom of the specified \a type with the single - parameter \a string and inserts the new atom into the list - after the \a previous atom. -*/ - -/*! \fn Atom::Atom(Atom *previous, AtomType type, const QString &p1, const QString &p2) - - Constructs an atom of the specified \a type with the two - parameters \a p1 and \a p2 and inserts the new atom into - the list after the \a previous atom. -*/ - -/*! \fn void Atom::appendChar(QChar ch) - - Appends \a ch to the string parameter of this atom. - - \also string() -*/ - -/*! \fn void Atom::appendString(const QString &string) - - Appends \a string to the string parameter of this atom. - - \also string() -*/ - -/*! \fn void Atom::chopString() - - \also string() -*/ - -/*! \fn Atom *Atom::next() - Return the next atom in the atom list. - \also type(), string() -*/ - -/*! - Return the next Atom in the list if it is of AtomType \a t. - Otherwise return 0. - */ -const Atom *Atom::next(AtomType t) const -{ - return (m_next && (m_next->type() == t)) ? m_next : nullptr; -} - -/*! - Return the next Atom in the list if it is of AtomType \a t - and its string part is \a s. Otherwise return 0. - */ -const Atom *Atom::next(AtomType t, const QString &s) const -{ - return (m_next && (m_next->type() == t) && (m_next->string() == s)) ? m_next : nullptr; -} - -/*! \fn const Atom *Atom::next() const - Return the next atom in the atom list. - \also type(), string() -*/ - -/*! \fn AtomType Atom::type() const - Return the type of this atom. - \also string(), next() -*/ - -/*! - Return the type of this atom as a string. Return "Invalid" if - type() returns an impossible value. - - This is only useful for debugging. - - \also type() -*/ -QString Atom::typeString() const -{ - static bool deja = false; - - if (!deja) { - int i = 0; - while (atms[i].english != nullptr) { - if (atms[i].no != i) - Location::internalError(QStringLiteral("QDoc::Atom: atom %1 missing").arg(i)); - ++i; - } - deja = true; - } - - int i = static_cast(type()); - if (i < 0 || i > static_cast(Last)) - return QLatin1String("Invalid"); - return QLatin1String(atms[i].english); -} - -/*! \fn const QString &Atom::string() const - - Returns the string parameter that together with the type - characterizes this atom. - - \also type(), next() -*/ - -/*! - For a link atom, returns the string representing the link text - if one exist in the list of atoms. -*/ -QString Atom::linkText() const -{ - Q_ASSERT(m_type == Atom::Link); - QString result; - - if (next() && next()->string() == ATOM_FORMATTING_LINK) { - auto *atom = next()->next(); - while (atom && atom->type() != Atom::FormattingRight) { - result += atom->string(); - atom = atom->next(); - } - return result; - } - - return string(); -} - -/*! - The only constructor for LinkAtom. It creates an Atom of - type Atom::Link. \a p1 being the link target. \a p2 is the - parameters in square brackets. Normally there is just one - word in the square brackets, but there can be up to three - words separated by spaces. The constructor splits \a p2 on - the space character. - */ -LinkAtom::LinkAtom(const QString &p1, const QString &p2) - : Atom(Atom::Link, p1), - m_resolved(false), - m_genus(Node::DontCare), - m_domain(nullptr), - m_squareBracketParams(p2) -{ - // nada. -} - -/*! - This function resolves the parameters that were enclosed in - square brackets. If the parameters have already been resolved, - it does nothing and returns immediately. - */ -void LinkAtom::resolveSquareBracketParams() -{ - if (m_resolved) - return; - const QStringList params = m_squareBracketParams.toLower().split(QLatin1Char(' ')); - for (const auto ¶m : params) { - if (!m_domain) { - m_domain = QDocDatabase::qdocDB()->findTree(param); - if (m_domain) { - continue; - } - } - - if (param == "qml") { - m_genus = Node::QML; - continue; - } - if (param == "cpp") { - m_genus = Node::CPP; - continue; - } - if (param == "doc") { - m_genus = Node::DOC; - continue; - } - if (param == "api") { - m_genus = Node::API; - continue; - } - m_error = m_squareBracketParams; - break; - } - m_resolved = true; -} - -/*! - Standard copy constructor of LinkAtom \a t. - */ -LinkAtom::LinkAtom(const LinkAtom &t) - : Atom(Link, t.string()), - m_resolved(t.m_resolved), - m_genus(t.m_genus), - m_domain(t.m_domain), - m_error(t.m_error), - m_squareBracketParams(t.m_squareBracketParams) -{ - // nothing -} - -/*! - Special copy constructor of LinkAtom \a t, where - where the new LinkAtom will not be the first one - in the list. - */ -LinkAtom::LinkAtom(Atom *previous, const LinkAtom &t) - : Atom(previous, Link, t.string()), - m_resolved(t.m_resolved), - m_genus(t.m_genus), - m_domain(t.m_domain), - m_error(t.m_error), - m_squareBracketParams(t.m_squareBracketParams) -{ - previous->m_next = this; -} - -QT_END_NAMESPACE diff --git a/src/qdoc/atom.h b/src/qdoc/atom.h deleted file mode 100644 index 1dc3806c9..000000000 --- a/src/qdoc/atom.h +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef ATOM_H -#define ATOM_H - -#include "node.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class Tree; -class LinkAtom; - -class Atom -{ -public: - enum AtomType { - AnnotatedList, - AutoLink, - BaseName, - BR, - BriefLeft, - BriefRight, - C, - CaptionLeft, - CaptionRight, - Code, - CodeBad, - CodeQuoteArgument, - CodeQuoteCommand, - DivLeft, - DivRight, - EndQmlText, - ExampleFileLink, - ExampleImageLink, - FootnoteLeft, - FootnoteRight, - FormatElse, - FormatEndif, - FormatIf, - FormattingLeft, - FormattingRight, - GeneratedList, - HR, - Image, - ImageText, - ImportantLeft, - ImportantRight, - InlineImage, - Keyword, - LegaleseLeft, - LegaleseRight, - LineBreak, - Link, - LinkNode, - ListLeft, - ListItemNumber, - ListTagLeft, - ListTagRight, - ListItemLeft, - ListItemRight, - ListRight, - NavAutoLink, - NavLink, - Nop, - NoteLeft, - NoteRight, - ParaLeft, - ParaRight, - Qml, - QmlText, - QuotationLeft, - QuotationRight, - RawString, - SectionLeft, - SectionRight, - SectionHeadingLeft, - SectionHeadingRight, - SidebarLeft, - SidebarRight, - SinceList, - SinceTagLeft, - SinceTagRight, - SnippetCommand, - SnippetIdentifier, - SnippetLocation, - String, - TableLeft, - TableRight, - TableHeaderLeft, - TableHeaderRight, - TableRowLeft, - TableRowRight, - TableItemLeft, - TableItemRight, - TableOfContents, - Target, - UnhandledFormat, - WarningLeft, - WarningRight, - UnknownCommand, - Last = UnknownCommand - }; - - friend class LinkAtom; - - explicit Atom(AtomType type, const QString &string = "") : m_type(type), m_strs(string) { } - - Atom(AtomType type, const QString &p1, const QString &p2) : m_type(type), m_strs(p1) - { - if (!p2.isEmpty()) - m_strs << p2; - } - - Atom(Atom *previous, AtomType type, const QString &string) - : m_next(previous->m_next), m_type(type), m_strs(string) - { - previous->m_next = this; - } - - Atom(Atom *previous, AtomType type, const QString &p1, const QString &p2) - : m_next(previous->m_next), m_type(type), m_strs(p1) - { - if (!p2.isEmpty()) - m_strs << p2; - previous->m_next = this; - } - - virtual ~Atom() = default; - - void appendChar(QChar ch) { m_strs[0] += ch; } - void appendString(const QString &string) { m_strs[0] += string; } - void chopString() { m_strs[0].chop(1); } - void setString(const QString &string) { m_strs[0] = string; } - Atom *next() { return m_next; } - void setNext(Atom *newNext) { m_next = newNext; } - - [[nodiscard]] const Atom *next() const { return m_next; } - [[nodiscard]] const Atom *next(AtomType t) const; - [[nodiscard]] const Atom *next(AtomType t, const QString &s) const; - [[nodiscard]] AtomType type() const { return m_type; } - [[nodiscard]] QString typeString() const; - [[nodiscard]] const QString &string() const { return m_strs[0]; } - [[nodiscard]] const QString &string(int i) const { return m_strs[i]; } - [[nodiscard]] qsizetype count() const { return m_strs.size(); } - [[nodiscard]] QString linkText() const; - [[nodiscard]] const QStringList &strings() const { return m_strs; } - - [[nodiscard]] virtual bool isLinkAtom() const { return false; } - virtual Node::Genus genus() { return Node::DontCare; } - virtual Tree *domain() { return nullptr; } - virtual const QString &error() { return s_noError; } - virtual void resolveSquareBracketParams() {} - -protected: - static QString s_noError; - Atom *m_next = nullptr; - AtomType m_type {}; - QStringList m_strs {}; -}; - -class LinkAtom : public Atom -{ -public: - LinkAtom(const QString &p1, const QString &p2); - LinkAtom(const LinkAtom &t); - LinkAtom(Atom *previous, const LinkAtom &t); - ~LinkAtom() override = default; - - [[nodiscard]] bool isLinkAtom() const override { return true; } - Node::Genus genus() override - { - resolveSquareBracketParams(); - return m_genus; - } - Tree *domain() override - { - resolveSquareBracketParams(); - return m_domain; - } - const QString &error() override { return m_error; } - void resolveSquareBracketParams() override; - -protected: - bool m_resolved {}; - Node::Genus m_genus {}; - Tree *m_domain {}; - QString m_error {}; - QString m_squareBracketParams {}; -}; - -#define ATOM_FORMATTING_BOLD "bold" -#define ATOM_FORMATTING_INDEX "index" -#define ATOM_FORMATTING_ITALIC "italic" -#define ATOM_FORMATTING_LINK "link" -#define ATOM_FORMATTING_PARAMETER "parameter" -#define ATOM_FORMATTING_SPAN "span " -#define ATOM_FORMATTING_SUBSCRIPT "subscript" -#define ATOM_FORMATTING_SUPERSCRIPT "superscript" -#define ATOM_FORMATTING_TELETYPE "teletype" -#define ATOM_FORMATTING_UICONTROL "uicontrol" -#define ATOM_FORMATTING_UNDERLINE "underline" - -#define ATOM_LIST_BULLET "bullet" -#define ATOM_LIST_TAG "tag" -#define ATOM_LIST_VALUE "value" -#define ATOM_LIST_LOWERALPHA "loweralpha" -#define ATOM_LIST_LOWERROMAN "lowerroman" -#define ATOM_LIST_NUMERIC "numeric" -#define ATOM_LIST_UPPERALPHA "upperalpha" -#define ATOM_LIST_UPPERROMAN "upperroman" - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/boundaries/filesystem/directorypath.cpp b/src/qdoc/boundaries/filesystem/directorypath.cpp deleted file mode 100644 index 799582139..000000000 --- a/src/qdoc/boundaries/filesystem/directorypath.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "directorypath.h" - -/*! - * \class DirectoryPath - * - * \brief Represents a path to a directory that was known to exist on the - * filesystem. - * - * An instance of this type guarantees that, at the time of creation - * of the instance, the contained path represented an existing, - * readable, executable directory. - * - * The type is intended to be used whenever a user-provided path to a - * directory is encountered the first time, validating that it can be - * used later on for the duration of a QDoc execution and - * canonicalizing the original path. - * - * Such a usage example could be during the configuration process, - * when encountering the paths that defines where QDoc should search - * for images or other files. - * - * Similarly, it is intended to be used at the API boundaries, - * internally, to relieve the called element of the requirement to - * check the validity of a path when a directory is required and to - * ensure that a single format of the path is encountered. - * - * Do note that the guarantees provided by this type do not - * necessarily hold after the time of creation of an instance. - * Indeed, the underlying filesystem may have changed. - * - * It is possible to renew the contract by obtaining a new instance: - * - * \code - * DirectoryPath old... - * - * ... - * - * auto current{DirectoryPath:refine(old.value())}; - * \endcode - * - * QDoc itself will not generally perform destructive operations on - * its input files during an execution and, as such, it is never - * required to renew a contract. Ensuring that the underlying input - * files are indeed immutable is out-of-scope for QDoc and it is - * allowed to consider a case where the contract was invalidated as - * undefined behavior. - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {wrapped_type_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_equality_operator_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_less_than_operator_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_strictly_less_than_operator_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_greater_than_operator_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_strictly_greater_than_operator_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {refine_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {value_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {copy_constructor_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {copy_assignment_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {move_constructor_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {move_assignment_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {conversion_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_equal_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_unequal_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_less_than_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_less_than_or_equal_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_greater_than_documentation} {DirectoryPath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_greater_than_or_equal_documentation} {DirectoryPath} - */ diff --git a/src/qdoc/boundaries/filesystem/directorypath.h b/src/qdoc/boundaries/filesystem/directorypath.h deleted file mode 100644 index 7ec1dd415..000000000 --- a/src/qdoc/boundaries/filesystem/directorypath.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "../refined_typedef.h" - -#include - -#include -#include - -QDOC_REFINED_TYPEDEF(QString, DirectoryPath) { - QFileInfo info{value}; - - return (info.isDir() && info.isReadable() && info.isExecutable()) ? std::optional(DirectoryPath{info.canonicalFilePath()}) : std::nullopt; -} diff --git a/src/qdoc/boundaries/filesystem/filepath.cpp b/src/qdoc/boundaries/filesystem/filepath.cpp deleted file mode 100644 index d8964b6a6..000000000 --- a/src/qdoc/boundaries/filesystem/filepath.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "filepath.h" - -/*! - * \class FilePath - * - * \brief Represents a path to a file that was known to exist on the - * filesystem. - * - * An instance of this type guarantees that, at the time of creation - * of the instance, the contained path represented an existing, - * readable file. - * - * The type is intended to be used whenever a user-provided path to a - * file is encountered the first time, validating that it can be - * used later on for the duration of a QDoc execution and - * canonicalizing the original path. - * - * Such a usage example could be when resolving a file whose path is - * provided by the user. - * - * Similarly, it is intended to be used at the API boundaries, - * internally, to relieve the called element of the requirement to - * check the validity of a path when a file is required and to - * ensure that a single format of the path is encountered. - * - * Do note that the guarantees provided by this type do not - * necessarily hold after the time of creation of an instance. - * Indeed, the underlying filesystem may have changed. - * - * It is possible to renew the contract by obtaining a new instance: - * - * \code - * FilePath old... - * - * ... - * - * auto current{FilePath::refine(old.value())}; - * \endcode - * - * QDoc itself will not generally perform destructive operations on - * its input files during an execution and, as such, it is never - * required to renew a contract. Ensuring that the underlying input - * files are indeed immutable is out-of-scope for QDoc and it is - * allowed to consider a case where the contract was invalidated as - * undefined behavior. - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {wrapped_type_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_equality_operator_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_less_than_operator_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_strictly_less_than_operator_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_greater_than_operator_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {has_strictly_greater_than_operator_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {refine_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {value_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {copy_constructor_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {copy_assignment_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {move_constructor_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {move_assignment_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {conversion_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_equal_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_unequal_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_less_than_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_less_than_or_equal_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_greater_than_documentation} {FilePath} - */ - -/*! - * \include boundaries/refined_typedef_members.qdocinc {operator_greater_than_or_equal_documentation} {FilePath} - */ diff --git a/src/qdoc/boundaries/filesystem/filepath.h b/src/qdoc/boundaries/filesystem/filepath.h deleted file mode 100644 index 0b315ccc2..000000000 --- a/src/qdoc/boundaries/filesystem/filepath.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "boundaries/refined_typedef.h" - -#include - -#include -#include - -QDOC_REFINED_TYPEDEF(QString, FilePath) { - QFileInfo info{value}; - - return (info.isFile() && info.isReadable()) ? std::optional(FilePath{info.canonicalFilePath()}) : std::nullopt; -} diff --git a/src/qdoc/boundaries/filesystem/resolvedfile.cpp b/src/qdoc/boundaries/filesystem/resolvedfile.cpp deleted file mode 100644 index 4d5eca512..000000000 --- a/src/qdoc/boundaries/filesystem/resolvedfile.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "resolvedfile.h" - -/*! - * \class ResolvedFile - * - * \brief Represents a file that is reachable by QDoc based on its - * current configuration. - * - * Instances of this type are, generally, intended to be generated by - * any process that needs to query the filesystem for the presence of - * some files based on a user-inputted path to ensure their - * availability. - * - * Such an example might be when QDoc is searching for a file whose - * path is provided by the user, such as the one in a snippet command, - * that should represent a file that is reachable with the current - * configuration. - * - * On the other side, logic that requires access to files that are - * known to be user-provided, such as the quoting of snippets, can use - * this type at the API boundary to signal that the file should be - * accessible so that they avoid the need to search for the file - * themselves. - * - * Do note that, semantically, this type doesn't actually guarantee - * anything about its origin and only guarantees whatever its members - * guarantee. - * - * The reasoning behind this lack of enforcement is to allow for an - * easier testing. - * As many parts of QDoc might require the presence of an instance of - * this type, we want to be able to construct those instances without - * the need to pass trough whichever valid generator for them. - * - * Nonetheless, inside QDoc, any boundary that requires an instance of - * this type can consider it guaranteed that the instance was - * generated trough some appropriate logic, and consider it a bug if - * such is not the case. - * - * An instance of this type provides two pieces of information. - * - * The path to the file that is considered resolved, accessible trough - * the get_path() method and the string that was used to resolve the - * file in the first place, accessible trough the get_query() method. - * - * The first should be used by consumer who needs to interact with the - * file itself, such as reading from it or copying it. - * - * The second is provided for context and can be used when consumers - * need to know what the user-inputted path was in the first place, - * for example when presenting debug information. - * - * It is not semantically guaranteed that this two pieces of - * information are actually related. Any such instance for which this - * is true should be considered malformed. Inside QDoc, tough, - * consumer of this type can consider it guaranteed that no malformed - * instance will be passed to them, and consider it a bug if it - * happens otherwise. - */ - -/*! - * \fn ResolvedFile::ResolvedFile(QString query, FilePath filepath) - * - * Constructs an instance of this type from \a query and \a filepath. - * - * \a query should represent the user-inputted path that was used to - * resolve the file that this instance represents. - * - * \a filepath should represent the file that is found querying the - * filesystem trough \a query using an appropriate logic for resolving - * files. - * - * An instance that is built from \a query and \a filepath is - * guaranteed to return a value that is equivalent to \a query when - * get_query() is called and a value that is equivalent to \a - * filepath.value() when get_path() is called. - */ - -/*! - * \fn const QString& ResolvedFile::get_query() const - * - * Returns a string representing the user-inputted path that was used - * to resolve the file. - */ - -/*! - * \fn const QString& ResolvedFile::get_path() const - * - * Returns a string representing the canonicalized path to the file - * that was resolved. - * - * Access to this file is to be considered guranteed to be available. - */ diff --git a/src/qdoc/boundaries/filesystem/resolvedfile.h b/src/qdoc/boundaries/filesystem/resolvedfile.h deleted file mode 100644 index 386ba3fce..000000000 --- a/src/qdoc/boundaries/filesystem/resolvedfile.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include "boundaries/filesystem/filepath.h" - -#include - -struct ResolvedFile { -public: - ResolvedFile(QString query, FilePath filepath) : query{query}, filepath{filepath} {} - - [[nodiscard]] const QString& get_query() const { return query; } - [[nodiscard]] const QString& get_path() const { return filepath.value(); } - -private: - QString query; - FilePath filepath; -}; diff --git a/src/qdoc/boundaries/refined_typedef.h b/src/qdoc/boundaries/refined_typedef.h deleted file mode 100644 index 4f3a13b7c..000000000 --- a/src/qdoc/boundaries/refined_typedef.h +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#pragma once - -#include - -#include -#include -#include - -// TODO: Express the documentation such that QDoc would be able to see -// it and process it correctly. This probably means that we would like -// to associate the definition with a namespace, albeit we could use -// the header file too, and put the documentation in an empty cpp -// file. This is delayed as there currently isn't much namespacing for -// anything in QDoc and such a namespacing should be added gradually -// and attentively. - -// TODO: Review the semantics for construction and optmize it. Should we copy the -// value? Should we only allow rvalues? - -// TODO: There is an high chance that we will need to "compose" -// refinitions later on when dealing, for example, with the basics of -// user-provided paths. -// For example, when requiring that each user-inputted path is purged -// as per QFileInfo definition of purging. -// For example, it might be that instead of passing QString around we -// might pass some Path type that is a purged QString. -// Then, any other refinement over paths will need to use that as a -// base type. -// To avoid the clutter that comes from that, if such will be the -// case, we will need to change the definition of refine and value if -// the passed in type was refined already. -// That is, such that if we have: -// -// QDOC_REFINE_TYPE(QString, Path) { ... } -// QDOC_REFINE_TYPE(Path, Foo) { ... } -// -// Foo refines a QString and Foo.value returns a QString. This should -// in general be trivial as long as we add a way to identify, such as -// a tag that refinements derive from, what type was declared through -// QDOC_REFINED_TYPEDEF and what type was not. - -// TODO: Provide a way to generate a standard documentation for all -// members of a type generated by QDOC_REFINED_TYPEDEF without having -// to copy-paste include command everywhere. -// The main problem of doing this is that the preprocessor strips -// comments away, making it impossible to generate comments, and hence -// QDoc documentation, with the preprocessor. - -/*! - * \macro QDOC_REFINED_TYPEDEF(_type, _name) - * \relates refined_typedef.hpp - * - * Declares a wrapper type for \c {_type}, with identifier \c {_name}, - * that represents a subset of \c {_type} for which some conditions - * hold. - * - * For example: - * - * \code - QDOC_REFINED_TYPEDEF(std::size_t, Fin5) { - return (value < 5) : std::make_optional{value} : std::nullopt; - } - * \endcode - * - * Represents the subset of \c {std::size_t} that contains the value 0, 1, - * 2, 3 and 4, that is, the general finite set of cardinality 5. - * - * As the example shows, usages of the macro require some type, an - * identifier and some code. - * - * The type that is provided is the type that will be wrapped. - * Do note that we expect a type with no-qualifiers and that is not a - * pointer type. Types passed with those kind of qualifiers will be - * simplified to their base type. - * - * That is, for example, \c {int*}, \c {const int}, \c {const int&}, - * \c {int&} all counts as \c {int}. - * - * The identifier that is passed is used as the name for the newly - * declared type that wraps the original type. - * - * The code block that is passed will be run when an instance of the - * newly created wrapper type is being obtained. - * If the wrapper type is T, the codeblock must return a \c - * {std::optional}. - * The code block should perform any check that ensures that the - * guarantees provided by the wrapper type holds and return a value if - * such is the case, otherwise returning \c {std::nullopt}. - * - * Inside the code block, the identifier \e {value} is implicitly - * bound to an element of the wrapped type that the instance is being - * built from and for which the guarantees provided by the wrapper - * type must hold. - * - * When a call to QDOC_REFINED_TYPEDEF is successful, a type with the - * provided identifier is declared. - * - * Let T be a type declared trough a call of QDOC_REFINED_TYPEDEF and - * W be the type that it wraps. - * - * An instance of T can be obtained by calling T::refine with an - * element of W. - * - * If the element of W respects the guarantees that T provides, then - * the call will return an optional that contains an instance of T, - * othewise it will return an empty optional. - * - * When an instance of T is obtained, it will wrap the element of W that - * was used to obtain it. - * - * The wrapped value can be accessed trough the \c {value} method. - * - * For example, considering \c {Fin5}, we could obtain an instance of - * it as follows: - * - * \code - * auto instance = *(Fin5::refine(std::size_t{1})); - * \endcode - * - * With that instance available we can retrieve the original value as - * follows: - * - * \code - * instance.value(); // The value 1 - * \endcode - */ - -#define QDOC_REFINED_TYPEDEF(_type, _name) \ - struct _name { \ - public: \ - using wrapped_type = std::remove_reference_t>>; \ - \ - inline static constexpr auto has_equality_operator_v = std::is_invocable_r_v, wrapped_type, wrapped_type>; \ - inline static constexpr auto has_less_than_operator_v = std::is_invocable_r_v, wrapped_type, wrapped_type>; \ - inline static constexpr auto has_strictly_less_than_operator_v = std::is_invocable_r_v, wrapped_type, wrapped_type>; \ - inline static constexpr auto has_greater_than_operator_v = std::is_invocable_r_v, wrapped_type, wrapped_type>; \ - inline static constexpr auto has_strictly_greater_than_operator_v = std::is_invocable_r_v, wrapped_type, wrapped_type>; \ - \ - public: \ - static std::optional<_name> refine(wrapped_type value); \ - \ - [[nodiscard]] const wrapped_type& value() const noexcept { return _value; } \ - \ - _name(const _name&) = default; \ - _name& operator=(const _name&) = default; \ - \ - _name(_name&&) = default; \ - _name& operator=(_name&&) = default; \ - \ - operator wrapped_type() const { return _value; } \ - \ - public: \ - \ - template< \ - typename = std::enable_if_t< \ - has_equality_operator_v \ - > \ - > \ - bool operator==(const _name& rhs) const noexcept { return _value == rhs._value; } \ - \ - template< \ - typename = std::enable_if_t< \ - has_equality_operator_v \ - > \ - > \ - bool operator!=(const _name& rhs) const noexcept { return !(_value == rhs._value); } \ - \ - template< \ - typename = std::enable_if_t< \ - has_less_than_operator_v \ - > \ - > \ - bool operator<=(const _name& rhs) const noexcept { return _value <= rhs._value; } \ - \ - \ - template< \ - typename = std::enable_if_t< \ - has_strictly_less_than_operator_v \ - > \ - > \ - bool operator<(const _name& rhs) const noexcept { return _value < rhs._value; } \ - \ - template< \ - typename = std::enable_if_t< \ - has_greater_than_operator_v \ - > \ - > \ - bool operator>=(const _name& rhs) const noexcept { return _value >= rhs._value; } \ - \ - template< \ - typename = std::enable_if_t< \ - has_strictly_greater_than_operator_v \ - > \ - > \ - bool operator>(const _name& rhs) const noexcept { return _value > rhs._value; } \ - \ - private: \ - _name(wrapped_type value) : _value{std::move(value)} {} \ - \ - private: \ - wrapped_type _value; \ - }; \ - \ - inline std::optional<_name> _name::refine(wrapped_type value) diff --git a/src/qdoc/boundaries/refined_typedef_members.qdocinc b/src/qdoc/boundaries/refined_typedef_members.qdocinc deleted file mode 100644 index ab956f49f..000000000 --- a/src/qdoc/boundaries/refined_typedef_members.qdocinc +++ /dev/null @@ -1,162 +0,0 @@ -//! [wrapped_type_documentation] -\typealias \1::wrapped_type - -The type that is wrapped by this type. - -This type is always deprived of qualifiers and is never a pointer -type. -//! [wrapped_type_documentation] - -//! [has_equality_operator_documentation] -\variable \1::has_equality_operator_v - -True when the wrapped_type can be compared for equality. - -When this is the case, \1 can be compared for equality and inequality. -//! [has_equality_operator_documentation] - -//! [has_less_than_operator_documentation] -\variable \1::has_less_than_operator_v - -True when the wrapped_type can be compared for lesserness. - -When this is the case, \1 can be compared for lesserness. -//! [has_less_than_operator_documentation] - -//! [has_strictly_less_than_operator_documentation] -\variable \1::has_strictly_less_than_operator_v - -True when the wrapped_type can be compared for strict lesserness. - -When this is the case, \1 can be compared for strict lesserness. -//! [has_stricly_less_than_operator_documentation] - -//! [has_greater_than_operator_documentation] -\variable \1::has_greater_than_operator_v - -True when the wrapped_type can be compared for greaterness. - -When this is the case, \1 can be compared for greaterness. -//! [has_less_than_operator_documentation] - -//! [has_strictly_greater_than_operator_documentation] -\variable \1::has_strictly_greater_than_operator_v - -True when the wrapped_type can be compared for strict greaterness. - -When this is the case, \1 can be compared for strict greaterness. -//! [has_stricly_greater_than_operator_documentation] - -//! [refine_documentation] -\fn static std::optional<\1> \1::refine(wrapped_type value) - -Returns an instance of \1 wrapping \a value if \a value respects the -guarantees that are required by \1. - -If such is not the case, \c {std::nullopt} is returned instead. -//! [refine_documentation] - -//! [value_documentation] -\fn const wrapped_type& \1::value() const noexcept - -Returns a const reference to the value that is wrapped by this -instance. -//! [value_documentation] - -//! [copy_constructor_documentation] -\fn \1::\1(const \1& other) - -Copy-constructs an instance of \1 from \a other. - -This constructor is generated by the compiler. -//! [copy_constructor_documentation] - -//! [copy_assignment_documentation] -\fn \1::operator=(const \1& other) - -Copy-assigns to this instance of \1 from \a other. - -This constructor is generated by the compiler. -//! [copy_assignment_documentation] - -//! [move_constructor_documentation] -\fn \1::\1(\1&& other) - -Move-constructs an instance of \1 from \a other. - -The only valid operations on an instance that was moved-from are -destruction and reassignment. - -This constructor is generated by the compiler. -//! [move_constructor_documentation] - -//! [move_assignment_documentation] -\fn \1::operator=(\1&& other) - -Move-assigns to this instance of \1 from \a other. - -The only valid operations on an instance that was moved-from are -destruction and reassignment. - -This constructor is generated by the compiler. -//! [move_assignment_documentation] - -//! [conversion_documentation] -\fn operator wrapped_type() const - -Converts this instance to its wrapped value. -//! [conversion_documentation] - -//! [operator_equal_documentation] -\fn bool operator=(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance and \a rhs compare -equal. - -Returns false otherwise. -//! [operator_equal_documentation] - -//! [operator_unequal_documentation] -\fn bool operator!=(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance and \a rhs do not -compare equal. - -Returns false otherwise. -//! [operator_unequal_documentation] - -//! [operator_less_than_documentation] -\fn bool operator<(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance compares less than -the value wrapped by \a rhs. - -Returns false otherwise. -//! [operator_less_than_documentation] - -//! [operator_less_than_or_equal_documentation] -\fn bool operator<=(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance compares less than -or equal than the value wrapped by \a rhs. - -Returns false otherwise. -//! [operator_less_than_or_equal_documentation] - -//! [operator_greater_than_documentation] -\fn bool operator>(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance compares greater -than the value wrapped by \a rhs. - -Returns false otherwise. -//! [operator_greater_than_documentation] - -//! [operator_greater_than_or_equal_documentation] -\fn bool operator>=(const \1& rhs) const noexcept - -Returns true if the value wrapped by this instance compares greater -than or equal or equal than the value wrapped by \a rhs. - -Returns false otherwise. -//! [operator_greater_than_or_equal_documentation] diff --git a/src/qdoc/clangcodeparser.cpp b/src/qdoc/clangcodeparser.cpp deleted file mode 100644 index 240e0759b..000000000 --- a/src/qdoc/clangcodeparser.cpp +++ /dev/null @@ -1,1783 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#include "clangcodeparser.h" - -#include "access.h" -#include "classnode.h" -#include "codechunk.h" -#include "config.h" -#include "enumnode.h" -#include "functionnode.h" -#include "namespacenode.h" -#include "propertynode.h" -#include "qdocdatabase.h" -#include "typedefnode.h" -#include "utilities.h" -#include "variablenode.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -const QStringList ClangCodeParser::accepted_header_file_extensions{ - "ch", "h", "h++", "hh", "hpp", "hxx" -}; - -// We're printing diagnostics in ClangCodeParser::printDiagnostics, -// so avoid clang itself printing them. -static const auto kClangDontDisplayDiagnostics = 0; - -static CXTranslationUnit_Flags flags_ = static_cast(0); -static CXIndex index_ = nullptr; - -QByteArray ClangCodeParser::s_fn; -constexpr const char fnDummyFileName[] = "/fn_dummyfile.cpp"; - -#ifndef QT_NO_DEBUG_STREAM -template -static QDebug operator<<(QDebug debug, const std::vector &v) -{ - QDebugStateSaver saver(debug); - debug.noquote(); - debug.nospace(); - const size_t size = v.size(); - debug << "std::vector<>[" << size << "]("; - for (size_t i = 0; i < size; ++i) { - if (i) - debug << ", "; - debug << v[i]; - } - debug << ')'; - return debug; -} -#endif // !QT_NO_DEBUG_STREAM - -/*! - Call clang_visitChildren on the given cursor with the lambda as a callback - T can be any functor that is callable with a CXCursor parameter and returns a CXChildVisitResult - (in other word compatible with function - */ -template -bool visitChildrenLambda(CXCursor cursor, T &&lambda) -{ - CXCursorVisitor visitor = [](CXCursor c, CXCursor, - CXClientData client_data) -> CXChildVisitResult { - return (*static_cast(client_data))(c); - }; - return clang_visitChildren(cursor, visitor, &lambda); -} - -/*! - convert a CXString to a QString, and dispose the CXString - */ -static QString fromCXString(CXString &&string) -{ - QString ret = QString::fromUtf8(clang_getCString(string)); - clang_disposeString(string); - return ret; -} - -static QString templateDecl(CXCursor cursor); - -/*! - Returns a list of template parameters at \a cursor. -*/ -static QStringList getTemplateParameters(CXCursor cursor) -{ - QStringList parameters; - visitChildrenLambda(cursor, [¶meters](CXCursor cur) { - QString name = fromCXString(clang_getCursorSpelling(cur)); - QString type; - - switch (clang_getCursorKind(cur)) { - case CXCursor_TemplateTypeParameter: - type = QStringLiteral("typename"); - break; - case CXCursor_NonTypeTemplateParameter: - type = fromCXString(clang_getTypeSpelling(clang_getCursorType(cur))); - // Hack: Omit QtPrivate template parameters from public documentation - if (type.startsWith(QLatin1String("QtPrivate"))) - return CXChildVisit_Continue; - break; - case CXCursor_TemplateTemplateParameter: - type = templateDecl(cur) + QLatin1String(" class"); - break; - default: - return CXChildVisit_Continue; - } - - if (!name.isEmpty()) - name.prepend(QLatin1Char(' ')); - - parameters << type + name; - return CXChildVisit_Continue; - }); - - return parameters; -} - -/*! - Gets the template declaration at specified \a cursor. - */ -static QString templateDecl(CXCursor cursor) -{ - QStringList params = getTemplateParameters(cursor); - return QLatin1String("template <") + params.join(QLatin1String(", ")) + QLatin1Char('>'); -} - -/*! - convert a CXSourceLocation to a qdoc Location - */ -static Location fromCXSourceLocation(CXSourceLocation location) -{ - unsigned int line, column; - CXString file; - clang_getPresumedLocation(location, &file, &line, &column); - Location l(fromCXString(std::move(file))); - l.setColumnNo(column); - l.setLineNo(line); - return l; -} - -/*! - convert a CX_CXXAccessSpecifier to Node::Access - */ -static Access fromCX_CXXAccessSpecifier(CX_CXXAccessSpecifier spec) -{ - switch (spec) { - case CX_CXXPrivate: - return Access::Private; - case CX_CXXProtected: - return Access::Protected; - case CX_CXXPublic: - return Access::Public; - default: - return Access::Public; - } -} - -/*! - Returns the spelling in the file for a source range - */ - -struct FileCacheEntry -{ - QByteArray fileName; - QByteArray content; -}; - -static inline QString fromCache(const QByteArray &cache, - unsigned int offset1, unsigned int offset2) -{ - return QString::fromUtf8(cache.mid(offset1, offset2 - offset1)); -} - -static QString readFile(CXFile cxFile, unsigned int offset1, unsigned int offset2) -{ - using FileCache = QList; - static FileCache cache; - - CXString cxFileName = clang_getFileName(cxFile); - const QByteArray fileName = clang_getCString(cxFileName); - clang_disposeString(cxFileName); - - for (const auto &entry : std::as_const(cache)) { - if (fileName == entry.fileName) - return fromCache(entry.content, offset1, offset2); - } - - // "fn_dummyfile.cpp" comes with varying cxFile values - if (fileName == fnDummyFileName) - return fromCache(ClangCodeParser::fn(), offset1, offset2); - - QFile file(QString::fromUtf8(fileName)); - if (file.open(QIODeviceBase::ReadOnly)) { // binary to match clang offsets - FileCacheEntry entry{fileName, file.readAll()}; - cache.prepend(entry); - while (cache.size() > 5) - cache.removeLast(); - return fromCache(entry.content, offset1, offset2); - } - return {}; -} - -static QString getSpelling(CXSourceRange range) -{ - auto start = clang_getRangeStart(range); - auto end = clang_getRangeEnd(range); - CXFile file1, file2; - unsigned int offset1, offset2; - clang_getFileLocation(start, &file1, nullptr, nullptr, &offset1); - clang_getFileLocation(end, &file2, nullptr, nullptr, &offset2); - - if (file1 != file2 || offset2 <= offset1) - return QString(); - - return readFile(file1, offset1, offset2); -} - -/*! - Returns the function name from a given cursor representing a - function declaration. This is usually clang_getCursorSpelling, but - not for the conversion function in which case it is a bit more complicated - */ -QString functionName(CXCursor cursor) -{ - if (clang_getCursorKind(cursor) == CXCursor_ConversionFunction) { - // For a CXCursor_ConversionFunction we don't want the spelling which would be something - // like "operator type-parameter-0-0" or "operator unsigned int". we want the actual name as - // spelled; - QString type = fromCXString(clang_getTypeSpelling(clang_getCursorResultType(cursor))); - if (type.isEmpty()) - return fromCXString(clang_getCursorSpelling(cursor)); - return QLatin1String("operator ") + type; - } - - QString name = fromCXString(clang_getCursorSpelling(cursor)); - - // Remove template stuff from constructor and destructor but not from operator< - auto ltLoc = name.indexOf('<'); - if (ltLoc > 0 && !name.startsWith("operator<")) - name = name.left(ltLoc); - return name; -} - -/*! - Reconstruct the qualified path name of a function that is - being overridden. - */ -static QString reconstructQualifiedPathForCursor(CXCursor cur) -{ - QString path; - auto kind = clang_getCursorKind(cur); - while (!clang_isInvalid(kind) && kind != CXCursor_TranslationUnit) { - switch (kind) { - case CXCursor_Namespace: - case CXCursor_StructDecl: - case CXCursor_ClassDecl: - case CXCursor_UnionDecl: - case CXCursor_ClassTemplate: - path.prepend("::"); - path.prepend(fromCXString(clang_getCursorSpelling(cur))); - break; - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - case CXCursor_CXXMethod: - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: - path = functionName(cur); - break; - default: - break; - } - cur = clang_getCursorSemanticParent(cur); - kind = clang_getCursorKind(cur); - } - return path; -} - -/*! - Find the node from the QDocDatabase \a qdb that corrseponds to the declaration - represented by the cursor \a cur, if it exists. - */ -static Node *findNodeForCursor(QDocDatabase *qdb, CXCursor cur) -{ - auto kind = clang_getCursorKind(cur); - if (clang_isInvalid(kind)) - return nullptr; - if (kind == CXCursor_TranslationUnit) - return qdb->primaryTreeRoot(); - - Node *p = findNodeForCursor(qdb, clang_getCursorSemanticParent(cur)); - if (p == nullptr) - return nullptr; - if (!p->isAggregate()) - return nullptr; - auto parent = static_cast(p); - - QString name = fromCXString(clang_getCursorSpelling(cur)); - switch (kind) { - case CXCursor_Namespace: - return parent->findNonfunctionChild(name, &Node::isNamespace); - case CXCursor_StructDecl: - case CXCursor_ClassDecl: - case CXCursor_UnionDecl: - case CXCursor_ClassTemplate: - return parent->findNonfunctionChild(name, &Node::isClassNode); - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - case CXCursor_CXXMethod: - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: { - NodeVector candidates; - parent->findChildren(functionName(cur), candidates); - if (candidates.isEmpty()) - return nullptr; - CXType funcType = clang_getCursorType(cur); - auto numArg = clang_getNumArgTypes(funcType); - bool isVariadic = clang_isFunctionTypeVariadic(funcType); - QVarLengthArray args; - for (Node *candidate : std::as_const(candidates)) { - if (!candidate->isFunction(Node::CPP)) - continue; - auto fn = static_cast(candidate); - const Parameters ¶meters = fn->parameters(); - if (parameters.count() != numArg + isVariadic) - continue; - if (fn->isConst() != bool(clang_CXXMethod_isConst(cur))) - continue; - if (isVariadic && parameters.last().type() != QLatin1String("...")) - continue; - if (fn->isRef() != (clang_Type_getCXXRefQualifier(funcType) == CXRefQualifier_LValue)) - continue; - if (fn->isRefRef() != (clang_Type_getCXXRefQualifier(funcType) == CXRefQualifier_RValue)) - continue; - - bool different = false; - for (int i = 0; i < numArg; ++i) { - CXType argType = clang_getArgType(funcType, i); - if (args.size() <= i) - args.append(fromCXString(clang_getTypeSpelling(argType))); - QString recordedType = parameters.at(i).type(); - QString typeSpelling = args.at(i); - auto p = parent; - while (p && recordedType != typeSpelling) { - QString parentScope = p->name() + QLatin1String("::"); - recordedType.remove(parentScope); - typeSpelling.remove(parentScope); - p = p->parent(); - } - different = recordedType != typeSpelling; - - // Retry with a canonical type spelling - if (different && (argType.kind == CXType_Typedef || argType.kind == CXType_Elaborated)) { - QStringView canonicalType = parameters.at(i).canonicalType(); - if (!canonicalType.isEmpty()) { - different = canonicalType != - fromCXString(clang_getTypeSpelling(clang_getCanonicalType(argType))); - } - } - if (different) { - break; - } - } - if (!different) - return fn; - } - return nullptr; - } - case CXCursor_EnumDecl: - return parent->findNonfunctionChild(name, &Node::isEnumType); - case CXCursor_FieldDecl: - case CXCursor_VarDecl: - return parent->findNonfunctionChild(name, &Node::isVariable); - case CXCursor_TypedefDecl: - return parent->findNonfunctionChild(name, &Node::isTypedef); - default: - return nullptr; - } -} - -static void setOverridesForFunction(FunctionNode *fn, CXCursor cursor) -{ - CXCursor *overridden; - unsigned int numOverridden = 0; - clang_getOverriddenCursors(cursor, &overridden, &numOverridden); - for (uint i = 0; i < numOverridden; ++i) { - QString path = reconstructQualifiedPathForCursor(overridden[i]); - if (!path.isEmpty()) { - fn->setOverride(true); - fn->setOverridesThis(path); - break; - } - } - clang_disposeOverriddenCursors(overridden); -} - -class ClangVisitor -{ -public: - ClangVisitor(QDocDatabase *qdb, const QMultiHash &allHeaders) - : qdb_(qdb), parent_(qdb->primaryTreeRoot()), allHeaders_(allHeaders) - { - } - - QDocDatabase *qdocDB() { return qdb_; } - - CXChildVisitResult visitChildren(CXCursor cursor) - { - auto ret = visitChildrenLambda(cursor, [&](CXCursor cur) { - auto loc = clang_getCursorLocation(cur); - if (clang_Location_isFromMainFile(loc)) - return visitSource(cur, loc); - CXFile file; - clang_getFileLocation(loc, &file, nullptr, nullptr, nullptr); - bool isInteresting = false; - auto it = isInterestingCache_.find(file); - if (it != isInterestingCache_.end()) { - isInteresting = *it; - } else { - QFileInfo fi(fromCXString(clang_getFileName(file))); - // Match by file name in case of PCH/installed headers - isInteresting = allHeaders_.contains(fi.fileName()); - isInterestingCache_[file] = isInteresting; - } - if (isInteresting) { - return visitHeader(cur, loc); - } - - return CXChildVisit_Continue; - }); - return ret ? CXChildVisit_Break : CXChildVisit_Continue; - } - - /* - Not sure about all the possibilities, when the cursor - location is not in the main file. - */ - CXChildVisitResult visitFnArg(CXCursor cursor, Node **fnNode, bool &ignoreSignature) - { - auto ret = visitChildrenLambda(cursor, [&](CXCursor cur) { - auto loc = clang_getCursorLocation(cur); - if (clang_Location_isFromMainFile(loc)) - return visitFnSignature(cur, loc, fnNode, ignoreSignature); - return CXChildVisit_Continue; - }); - return ret ? CXChildVisit_Break : CXChildVisit_Continue; - } - - Node *nodeForCommentAtLocation(CXSourceLocation loc, CXSourceLocation nextCommentLoc); - -private: - /*! - SimpleLoc represents a simple location in the main source file, - which can be used as a key in a QMap. - */ - struct SimpleLoc - { - unsigned int line {}, column {}; - friend bool operator<(const SimpleLoc &a, const SimpleLoc &b) - { - return a.line != b.line ? a.line < b.line : a.column < b.column; - } - }; - /*! - \variable ClangVisitor::declMap_ - Map of all the declarations in the source file so we can match them - with a documentation comment. - */ - QMap declMap_; - - QDocDatabase *qdb_; - Aggregate *parent_; - const QMultiHash allHeaders_; - QHash isInterestingCache_; // doing a canonicalFilePath is slow, so keep a cache. - - /*! - Returns true if the symbol should be ignored for the documentation. - */ - bool ignoredSymbol(const QString &symbolName) - { - if (symbolName == QLatin1String("QPrivateSignal")) - return true; - // Ignore functions generated by property macros - if (symbolName.startsWith("_qt_property_")) - return true; - // Ignore template argument deduction guides - if (symbolName.startsWith(" 'iterator' - */ - QString adjustTypeName(const QString &typeName) - { - auto parent = parent_->parent(); - if (parent && parent->isClassNode()) { - QStringView typeNameConstRemoved(typeName); - if (typeNameConstRemoved.startsWith(QLatin1String("const "))) - typeNameConstRemoved = typeNameConstRemoved.mid(6); - - auto parentName = parent->fullName(); - if (typeNameConstRemoved.startsWith(parentName) - && typeNameConstRemoved.mid(parentName.size(), 2) == QLatin1String("::")) { - QString result = typeName; - result.remove(typeName.indexOf(typeNameConstRemoved), parentName.size() + 2); - return result; - } - } - return typeName; - } - - CXChildVisitResult visitSource(CXCursor cursor, CXSourceLocation loc); - CXChildVisitResult visitHeader(CXCursor cursor, CXSourceLocation loc); - CXChildVisitResult visitFnSignature(CXCursor cursor, CXSourceLocation loc, Node **fnNode, - bool &ignoreSignature); - void processFunction(FunctionNode *fn, CXCursor cursor); - bool parseProperty(const QString &spelling, const Location &loc); - void readParameterNamesAndAttributes(FunctionNode *fn, CXCursor cursor); - Aggregate *getSemanticParent(CXCursor cursor); -}; - -/*! - Visits a cursor in the .cpp file. - This fills the declMap_ - */ -CXChildVisitResult ClangVisitor::visitSource(CXCursor cursor, CXSourceLocation loc) -{ - auto kind = clang_getCursorKind(cursor); - if (clang_isDeclaration(kind)) { - SimpleLoc l; - clang_getPresumedLocation(loc, nullptr, &l.line, &l.column); - declMap_.insert(l, cursor); - return CXChildVisit_Recurse; - } - return CXChildVisit_Continue; -} - -/*! - If the semantic and lexical parent cursors of \a cursor are - not the same, find the Aggregate node for the semantic parent - cursor and return it. Otherwise return the current parent. - */ -Aggregate *ClangVisitor::getSemanticParent(CXCursor cursor) -{ - CXCursor sp = clang_getCursorSemanticParent(cursor); - CXCursor lp = clang_getCursorLexicalParent(cursor); - if (!clang_equalCursors(sp, lp) && clang_isDeclaration(clang_getCursorKind(sp))) { - Node *spn = findNodeForCursor(qdb_, sp); - if (spn && spn->isAggregate()) { - return static_cast(spn); - } - } - return parent_; -} - -CXChildVisitResult ClangVisitor::visitFnSignature(CXCursor cursor, CXSourceLocation, Node **fnNode, - bool &ignoreSignature) -{ - switch (clang_getCursorKind(cursor)) { - case CXCursor_Namespace: - return CXChildVisit_Recurse; - case CXCursor_FunctionDecl: - case CXCursor_FunctionTemplate: - case CXCursor_CXXMethod: - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: { - ignoreSignature = false; - if (ignoredSymbol(functionName(cursor))) { - *fnNode = nullptr; - ignoreSignature = true; - } else { - *fnNode = findNodeForCursor(qdb_, cursor); - if (*fnNode) { - if ((*fnNode)->isFunction(Node::CPP)) { - auto *fn = static_cast(*fnNode); - readParameterNamesAndAttributes(fn, cursor); - } - } else { // Possibly an implicitly generated special member - QString name = functionName(cursor); - if (ignoredSymbol(name)) - return CXChildVisit_Continue; - Aggregate *semanticParent = getSemanticParent(cursor); - if (semanticParent && semanticParent->isClass()) { - auto *candidate = new FunctionNode(nullptr, name); - processFunction(candidate, cursor); - if (!candidate->isSpecialMemberFunction()) { - delete candidate; - return CXChildVisit_Continue; - } - candidate->setDefault(true); - semanticParent->addChild(*fnNode = candidate); - } - } - } - break; - } - default: - break; - } - return CXChildVisit_Continue; -} - -CXChildVisitResult ClangVisitor::visitHeader(CXCursor cursor, CXSourceLocation loc) -{ - auto kind = clang_getCursorKind(cursor); - QString templateString; - switch (kind) { - case CXCursor_TypeAliasTemplateDecl: - case CXCursor_TypeAliasDecl: { - QString aliasDecl = getSpelling(clang_getCursorExtent(cursor)).simplified(); - QStringList typeAlias = aliasDecl.split(QLatin1Char('=')); - if (typeAlias.size() == 2) { - typeAlias[0] = typeAlias[0].trimmed(); - const QLatin1String usingString("using "); - qsizetype usingPos = typeAlias[0].indexOf(usingString); - if (usingPos != -1) { - if (kind == CXCursor_TypeAliasTemplateDecl) - templateString = typeAlias[0].left(usingPos).trimmed(); - typeAlias[0].remove(0, usingPos + usingString.size()); - typeAlias[0] = typeAlias[0].split(QLatin1Char(' ')).first(); - typeAlias[1] = typeAlias[1].trimmed(); - auto *ta = new TypeAliasNode(parent_, typeAlias[0], typeAlias[1]); - ta->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - ta->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - ta->setTemplateDecl(templateString); - } - } - return CXChildVisit_Continue; - } - case CXCursor_StructDecl: - case CXCursor_UnionDecl: - if (fromCXString(clang_getCursorSpelling(cursor)).isEmpty()) // anonymous struct or union - return CXChildVisit_Continue; - Q_FALLTHROUGH(); - case CXCursor_ClassTemplate: - templateString = templateDecl(cursor); - Q_FALLTHROUGH(); - case CXCursor_ClassDecl: { - if (!clang_isCursorDefinition(cursor)) - return CXChildVisit_Continue; - - if (findNodeForCursor(qdb_, cursor)) // Was already parsed, probably in another TU - return CXChildVisit_Continue; - - QString className = fromCXString(clang_getCursorSpelling(cursor)); - - Aggregate *semanticParent = getSemanticParent(cursor); - if (semanticParent && semanticParent->findNonfunctionChild(className, &Node::isClassNode)) { - return CXChildVisit_Continue; - } - - CXCursorKind actualKind = (kind == CXCursor_ClassTemplate) ? - clang_getTemplateCursorKind(cursor) : kind; - - Node::NodeType type = Node::Class; - if (actualKind == CXCursor_StructDecl) - type = Node::Struct; - else if (actualKind == CXCursor_UnionDecl) - type = Node::Union; - - auto *classe = new ClassNode(type, semanticParent, className); - classe->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - classe->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - - if (kind == CXCursor_ClassTemplate) - classe->setTemplateDecl(templateString); - - QScopedValueRollback setParent(parent_, classe); - return visitChildren(cursor); - } - case CXCursor_CXXBaseSpecifier: { - if (!parent_->isClassNode()) - return CXChildVisit_Continue; - auto access = fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor)); - auto type = clang_getCursorType(cursor); - auto baseCursor = clang_getTypeDeclaration(type); - auto baseNode = findNodeForCursor(qdb_, baseCursor); - auto classe = static_cast(parent_); - if (baseNode == nullptr || !baseNode->isClassNode()) { - QString bcName = reconstructQualifiedPathForCursor(baseCursor); - classe->addUnresolvedBaseClass(access, - bcName.split(QLatin1String("::"), Qt::SkipEmptyParts)); - return CXChildVisit_Continue; - } - auto baseClasse = static_cast(baseNode); - classe->addResolvedBaseClass(access, baseClasse); - return CXChildVisit_Continue; - } - case CXCursor_Namespace: { - QString namespaceName = fromCXString(clang_getCursorDisplayName(cursor)); - NamespaceNode *ns = nullptr; - if (parent_) - ns = static_cast( - parent_->findNonfunctionChild(namespaceName, &Node::isNamespace)); - if (!ns) { - ns = new NamespaceNode(parent_, namespaceName); - ns->setAccess(Access::Public); - ns->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - } - QScopedValueRollback setParent(parent_, ns); - return visitChildren(cursor); - } - case CXCursor_FunctionTemplate: - templateString = templateDecl(cursor); - Q_FALLTHROUGH(); - case CXCursor_FunctionDecl: - case CXCursor_CXXMethod: - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: { - if (findNodeForCursor(qdb_, cursor)) // Was already parsed, probably in another TU - return CXChildVisit_Continue; - QString name = functionName(cursor); - if (ignoredSymbol(name)) - return CXChildVisit_Continue; - // constexpr constructors generate also a global instance; ignore - if (kind == CXCursor_Constructor && parent_ == qdb_->primaryTreeRoot()) - return CXChildVisit_Continue; - - auto *fn = new FunctionNode(parent_, name); - CXSourceRange range = clang_Cursor_getCommentRange(cursor); - if (!clang_Range_isNull(range)) { - QString comment = getSpelling(range); - if (comment.startsWith("//!")) { - qsizetype tag = comment.indexOf(QChar('[')); - if (tag > 0) { - qsizetype end = comment.indexOf(QChar(']'), ++tag); - if (end > 0) - fn->setTag(comment.mid(tag, end - tag)); - } - } - } - processFunction(fn, cursor); - fn->setTemplateDecl(templateString); - return CXChildVisit_Continue; - } -#if CINDEX_VERSION >= 36 - case CXCursor_FriendDecl: { - return visitChildren(cursor); - } -#endif - case CXCursor_EnumDecl: { - auto *en = static_cast(findNodeForCursor(qdb_, cursor)); - if (en && en->items().size()) - return CXChildVisit_Continue; // Was already parsed, probably in another TU - QString enumTypeName = fromCXString(clang_getCursorSpelling(cursor)); - if (enumTypeName.isEmpty()) { - enumTypeName = "anonymous"; - if (parent_ && (parent_->isClassNode() || parent_->isNamespace())) { - Node *n = parent_->findNonfunctionChild(enumTypeName, &Node::isEnumType); - if (n) - en = static_cast(n); - } - } - if (!en) { - en = new EnumNode(parent_, enumTypeName, clang_EnumDecl_isScoped(cursor)); - en->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - en->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - } - - // Enum values - visitChildrenLambda(cursor, [&](CXCursor cur) { - if (clang_getCursorKind(cur) != CXCursor_EnumConstantDecl) - return CXChildVisit_Continue; - - QString value; - visitChildrenLambda(cur, [&](CXCursor cur) { - if (clang_isExpression(clang_getCursorKind(cur))) { - value = getSpelling(clang_getCursorExtent(cur)); - return CXChildVisit_Break; - } - return CXChildVisit_Continue; - }); - if (value.isEmpty()) { - QLatin1String hex("0x"); - if (!en->items().isEmpty() && en->items().last().value().startsWith(hex)) { - value = hex + QString::number(clang_getEnumConstantDeclValue(cur), 16); - } else { - value = QString::number(clang_getEnumConstantDeclValue(cur)); - } - } - - en->addItem(EnumItem(fromCXString(clang_getCursorSpelling(cur)), value)); - return CXChildVisit_Continue; - }); - return CXChildVisit_Continue; - } - case CXCursor_FieldDecl: - case CXCursor_VarDecl: { - if (findNodeForCursor(qdb_, cursor)) // Was already parsed, probably in another TU - return CXChildVisit_Continue; - - auto access = fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor)); - auto var = new VariableNode(parent_, fromCXString(clang_getCursorSpelling(cursor))); - var->setAccess(access); - var->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - var->setLeftType(fromCXString(clang_getTypeSpelling(clang_getCursorType(cursor)))); - var->setStatic(kind == CXCursor_VarDecl && parent_->isClassNode()); - return CXChildVisit_Continue; - } - case CXCursor_TypedefDecl: { - if (findNodeForCursor(qdb_, cursor)) // Was already parsed, probably in another TU - return CXChildVisit_Continue; - auto *td = new TypedefNode(parent_, fromCXString(clang_getCursorSpelling(cursor))); - td->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - td->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - // Search to see if this is a Q_DECLARE_FLAGS (if the type is QFlags) - visitChildrenLambda(cursor, [&](CXCursor cur) { - if (clang_getCursorKind(cur) != CXCursor_TemplateRef - || fromCXString(clang_getCursorSpelling(cur)) != QLatin1String("QFlags")) - return CXChildVisit_Continue; - // Found QFlags - visitChildrenLambda(cursor, [&](CXCursor cur) { - if (clang_getCursorKind(cur) != CXCursor_TypeRef) - return CXChildVisit_Continue; - auto *en = - findNodeForCursor(qdb_, clang_getTypeDeclaration(clang_getCursorType(cur))); - if (en && en->isEnumType()) - static_cast(en)->setFlagsType(td); - return CXChildVisit_Break; - }); - return CXChildVisit_Break; - }); - return CXChildVisit_Continue; - } - default: - if (clang_isDeclaration(kind) && parent_->isClassNode()) { - // may be a property macro or a static_assert - // which is not exposed from the clang API - parseProperty(getSpelling(clang_getCursorExtent(cursor)), - fromCXSourceLocation(loc)); - } - return CXChildVisit_Continue; - } -} - -void ClangVisitor::readParameterNamesAndAttributes(FunctionNode *fn, CXCursor cursor) -{ - Parameters ¶meters = fn->parameters(); - // Visit the parameters and attributes - int i = 0; - visitChildrenLambda(cursor, [&](CXCursor cur) { - auto kind = clang_getCursorKind(cur); - if (kind == CXCursor_AnnotateAttr) { - QString annotation = fromCXString(clang_getCursorDisplayName(cur)); - if (annotation == QLatin1String("qt_slot")) { - fn->setMetaness(FunctionNode::Slot); - } else if (annotation == QLatin1String("qt_signal")) { - fn->setMetaness(FunctionNode::Signal); - } - if (annotation == QLatin1String("qt_invokable")) - fn->setInvokable(true); - } else if (kind == CXCursor_CXXOverrideAttr) { - fn->setOverride(true); - } else if (kind == CXCursor_ParmDecl) { - if (i >= parameters.count()) - return CXChildVisit_Break; // Attributes comes before parameters so we can break. - QString name = fromCXString(clang_getCursorSpelling(cur)); - if (!name.isEmpty()) { - parameters[i].setName(name); - // Find the default value - visitChildrenLambda(cur, [&](CXCursor cur) { - if (clang_isExpression(clang_getCursorKind(cur))) { - QString defaultValue = getSpelling(clang_getCursorExtent(cur)); - if (defaultValue.startsWith('=')) // In some cases, the = is part of the range. - defaultValue = QStringView{defaultValue}.mid(1).trimmed().toString(); - if (defaultValue.isEmpty()) - defaultValue = QStringLiteral("..."); - parameters[i].setDefaultValue(defaultValue); - return CXChildVisit_Break; - } - return CXChildVisit_Continue; - }); - } - ++i; - } - return CXChildVisit_Continue; - }); -} - -/*! - * Returns the underlying Decl that \a cursor represents. - * - * This can be used to drop back down from a LibClang's CXCursor to - * the underlying C++ AST that Clang provides. - * - * It should be used when LibClang does not expose certain - * functionalities that are available in the C++ AST. - * - * The CXCursor should represent a declaration. Usages of this - * function on CXCursors that do not represent a declaration may - * produce undefined results. - */ -static const clang::Decl* get_cursor_declaration(CXCursor cursor) { - assert(clang_isDeclaration(clang_getCursorKind(cursor))); - - return static_cast(cursor.data[0]); -} - -void ClangVisitor::processFunction(FunctionNode *fn, CXCursor cursor) -{ - CXCursorKind kind = clang_getCursorKind(cursor); - CXType funcType = clang_getCursorType(cursor); - fn->setAccess(fromCX_CXXAccessSpecifier(clang_getCXXAccessSpecifier(cursor))); - fn->setLocation(fromCXSourceLocation(clang_getCursorLocation(cursor))); - if (kind == CXCursor_Constructor - // a constructor template is classified as CXCursor_FunctionTemplate - || (kind == CXCursor_FunctionTemplate && fn->name() == parent_->name())) - fn->setMetaness(FunctionNode::Ctor); - else if (kind == CXCursor_Destructor) - fn->setMetaness(FunctionNode::Dtor); - else - fn->setReturnType(adjustTypeName( - fromCXString(clang_getTypeSpelling(clang_getResultType(funcType))))); - - fn->setStatic(clang_CXXMethod_isStatic(cursor)); - fn->setConst(clang_CXXMethod_isConst(cursor)); - fn->setVirtualness(!clang_CXXMethod_isVirtual(cursor) - ? FunctionNode::NonVirtual - : clang_CXXMethod_isPureVirtual(cursor) - ? FunctionNode::PureVirtual - : FunctionNode::NormalVirtual); - - // REMARK: We assume that the following operations and casts are - // generally safe. - // Callers of those methods will generally check at the LibClang - // level the kind of cursor we are dealing with and will pass on - // only valid cursors that are of a function kind and that are at - // least a declaration. - // - // Failure to do so implies a bug in the call chain and should be - // dealt with as such. - const clang::Decl* declaration = get_cursor_declaration(cursor); - const clang::FunctionDecl* function_declaration{nullptr}; - if (auto templated_decl = llvm::dyn_cast_or_null(declaration)) - function_declaration = templated_decl->getTemplatedDecl(); - else function_declaration = static_cast(declaration); - - assert(function_declaration); - - const clang::CXXConstructorDecl* constructor_declaration = llvm::dyn_cast(function_declaration); - - if (constructor_declaration && constructor_declaration->isCopyConstructor()) fn->setMetaness(FunctionNode::CCtor); - else if (constructor_declaration && constructor_declaration->isMoveConstructor()) fn->setMetaness(FunctionNode::MCtor); - - const clang::CXXConversionDecl* conversion_declaration = llvm::dyn_cast(function_declaration); - - if (function_declaration->isConstexpr()) fn->markConstexpr(); - if ( - (constructor_declaration && constructor_declaration->isExplicit()) || - (conversion_declaration && conversion_declaration->isExplicit()) - ) fn->markExplicit(); - - const clang::CXXMethodDecl* method_declaration = llvm::dyn_cast(function_declaration); - - if (method_declaration && method_declaration->isCopyAssignmentOperator()) fn->setMetaness(FunctionNode::CAssign); - else if (method_declaration && method_declaration->isMoveAssignmentOperator()) fn->setMetaness(FunctionNode::MAssign); - - const clang::FunctionType* function_type = function_declaration->getFunctionType(); - const clang::FunctionProtoType* function_prototype = static_cast(function_type); - - if (function_prototype) { - clang::FunctionProtoType::ExceptionSpecInfo exception_specification = function_prototype->getExceptionSpecInfo(); - - if (exception_specification.Type != clang::ExceptionSpecificationType::EST_None) { - clang::SourceManager& source_manager = function_declaration->getASTContext().getSourceManager(); - const clang::LangOptions& lang_options = function_declaration->getASTContext().getLangOpts(); - - fn->markNoexcept( - exception_specification.NoexceptExpr ? - QString::fromStdString(clang::Lexer::getSourceText(clang::CharSourceRange::getTokenRange(exception_specification.NoexceptExpr->getSourceRange()), source_manager, lang_options).str()) : - "" - ); - } - } - - CXRefQualifierKind refQualKind = clang_Type_getCXXRefQualifier(funcType); - if (refQualKind == CXRefQualifier_LValue) - fn->setRef(true); - else if (refQualKind == CXRefQualifier_RValue) - fn->setRefRef(true); - // For virtual functions, determine what it overrides - // (except for destructor for which we do not want to classify as overridden) - if (!fn->isNonvirtual() && kind != CXCursor_Destructor) - setOverridesForFunction(fn, cursor); - - Parameters ¶meters = fn->parameters(); - parameters.clear(); - parameters.reserve(function_declaration->getNumParams()); - - const clang::LangOptions& lang_options = function_declaration->getASTContext().getLangOpts(); - clang::PrintingPolicy p{lang_options}; - - for (clang::ParmVarDecl* const parameter_declaration : function_declaration->parameters()) { - clang::QualType parameter_type = parameter_declaration->getOriginalType(); - - parameters.append(adjustTypeName(QString::fromStdString(parameter_type.getAsString(p)))); - - if (!parameter_type.isCanonical()) - parameters.last().setCanonicalType(QString::fromStdString(parameter_type.getCanonicalType().getAsString(p))); - } - - - if (parameters.count() > 0) { - if (parameters.last().type().endsWith(QLatin1String("QPrivateSignal"))) { - parameters.pop_back(); // remove the QPrivateSignal argument - parameters.setPrivateSignal(); - } - } - if (clang_isFunctionTypeVariadic(funcType)) - parameters.append(QStringLiteral("...")); - readParameterNamesAndAttributes(fn, cursor); - - if (declaration->getFriendObjectKind() != clang::Decl::FOK_None) - fn->setRelatedNonmember(true); -} - -bool ClangVisitor::parseProperty(const QString &spelling, const Location &loc) -{ - if (!spelling.startsWith(QLatin1String("Q_PROPERTY")) - && !spelling.startsWith(QLatin1String("QDOC_PROPERTY")) - && !spelling.startsWith(QLatin1String("Q_OVERRIDE"))) - return false; - - qsizetype lpIdx = spelling.indexOf(QChar('(')); - qsizetype rpIdx = spelling.lastIndexOf(QChar(')')); - if (lpIdx <= 0 || rpIdx <= lpIdx) - return false; - - QString signature = spelling.mid(lpIdx + 1, rpIdx - lpIdx - 1); - signature = signature.simplified(); - QStringList parts = signature.split(QChar(' '), Qt::SkipEmptyParts); - - static const QStringList attrs = - QStringList() << "READ" << "MEMBER" << "WRITE" - << "NOTIFY" << "CONSTANT" << "FINAL" - << "REQUIRED" << "BINDABLE" << "DESIGNABLE" - << "RESET" << "REVISION" << "SCRIPTABLE" - << "STORED" << "USER"; - - // Find the location of the first attribute. All preceding parts - // represent the property type + name. - auto it = std::find_if(parts.cbegin(), parts.cend(), - [](const QString &attr) -> bool { - return attrs.contains(attr); - }); - - if (it == parts.cend() || std::distance(parts.cbegin(), it) < 2) - return false; - - QStringList typeParts; - std::copy(parts.cbegin(), it, std::back_inserter(typeParts)); - parts.erase(parts.cbegin(), it); - QString name = typeParts.takeLast(); - - // Move the pointer operator(s) from name to type - while (!name.isEmpty() && name.front() == QChar('*')) { - typeParts.last().push_back(name.front()); - name.removeFirst(); - } - - // Need at least READ or MEMBER + getter/member name - if (parts.size() < 2 || name.isEmpty()) - return false; - - auto *property = new PropertyNode(parent_, name); - property->setAccess(Access::Public); - property->setLocation(loc); - property->setDataType(typeParts.join(QChar(' '))); - - int i = 0; - while (i < parts.size()) { - const QString &key = parts.at(i++); - // Keywords with no associated values - if (key == "CONSTANT") { - property->setConstant(); - } else if (key == "REQUIRED") { - property->setRequired(); - } - if (i < parts.size()) { - QString value = parts.at(i++); - if (key == "READ") { - qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Getter); - } else if (key == "WRITE") { - qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Setter); - property->setWritable(true); - } else if (key == "MEMBER") { - property->setWritable(true); - } else if (key == "STORED") { - property->setStored(value.toLower() == "true"); - } else if (key == "BINDABLE") { - property->setPropertyType(PropertyNode::PropertyType::BindableProperty); - qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Bindable); - } else if (key == "RESET") { - qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Resetter); - } else if (key == "NOTIFY") { - qdb_->addPropertyFunction(property, value, PropertyNode::FunctionRole::Notifier); - } - } - } - return true; -} - -/*! - Given a comment at location \a loc, return a Node for this comment - \a nextCommentLoc is the location of the next comment so the declaration - must be inbetween. - Returns nullptr if no suitable declaration was found between the two comments. - */ -Node *ClangVisitor::nodeForCommentAtLocation(CXSourceLocation loc, CXSourceLocation nextCommentLoc) -{ - ClangVisitor::SimpleLoc docloc; - clang_getPresumedLocation(loc, nullptr, &docloc.line, &docloc.column); - auto decl_it = declMap_.upperBound(docloc); - if (decl_it == declMap_.end()) - return nullptr; - - unsigned int declLine = decl_it.key().line; - unsigned int nextCommentLine; - clang_getPresumedLocation(nextCommentLoc, nullptr, &nextCommentLine, nullptr); - if (nextCommentLine < declLine) - return nullptr; // there is another comment before the declaration, ignore it. - - // make sure the previous decl was finished. - if (decl_it != declMap_.begin()) { - CXSourceLocation prevDeclEnd = clang_getRangeEnd(clang_getCursorExtent(*(std::prev(decl_it)))); - unsigned int prevDeclLine; - clang_getPresumedLocation(prevDeclEnd, nullptr, &prevDeclLine, nullptr); - if (prevDeclLine >= docloc.line) { - // The previous declaration was still going. This is only valid if the previous - // declaration is a parent of the next declaration. - auto parent = clang_getCursorLexicalParent(*decl_it); - if (!clang_equalCursors(parent, *(std::prev(decl_it)))) - return nullptr; - } - } - auto *node = findNodeForCursor(qdb_, *decl_it); - // borrow the parameter name from the definition - if (node && node->isFunction(Node::CPP)) - readParameterNamesAndAttributes(static_cast(node), *decl_it); - return node; -} - -/*! - Get the include paths from the qdoc configuration database - \a config. Call the initializeParser() in the base class. - Get the defines list from the qdocconf database. - - \note on \macos and Linux, we try to also query the system - and framework (\macos) include paths from the compiler. - */ -void ClangCodeParser::initializeParser() -{ - Config &config = Config::instance(); - auto args = config.getCanonicalPathList(CONFIG_INCLUDEPATHS, - Config::IncludePaths); -#ifdef Q_OS_MACOS - args.append(Utilities::getInternalIncludePaths(QStringLiteral("clang++"))); -#elif defined(Q_OS_LINUX) - args.append(Utilities::getInternalIncludePaths(QStringLiteral("g++"))); -#endif - m_includePaths.clear(); - for (const auto &path : std::as_const(args)) { - if (!path.isEmpty()) - m_includePaths.append(path.toUtf8()); - } - m_includePaths.erase(std::unique(m_includePaths.begin(), m_includePaths.end()), - m_includePaths.end()); - m_pchFileDir.reset(nullptr); - m_allHeaders.clear(); - m_pchName.clear(); - m_defines.clear(); - QSet accepted; - { - const QStringList tmpDefines{config.get(CONFIG_CLANGDEFINES).asStringList()}; - for (const QString &def : tmpDefines) { - if (!accepted.contains(def)) { - QByteArray tmp("-D"); - tmp.append(def.toUtf8()); - m_defines.append(tmp.constData()); - accepted.insert(def); - } - } - } - { - const QStringList tmpDefines{config.get(CONFIG_DEFINES).asStringList()}; - for (const QString &def : tmpDefines) { - if (!accepted.contains(def) && !def.contains(QChar('*'))) { - QByteArray tmp("-D"); - tmp.append(def.toUtf8()); - m_defines.append(tmp.constData()); - accepted.insert(def); - } - } - } - qCDebug(lcQdoc).nospace() << __FUNCTION__ << " Clang v" << CINDEX_VERSION_MAJOR << '.' - << CINDEX_VERSION_MINOR; -} - -/*! - */ -QString ClangCodeParser::language() -{ - return "Clang"; -} - -/*! - Returns a list of extensions for source files, i.e. not - header files. - */ -QStringList ClangCodeParser::sourceFileNameFilter() -{ - return QStringList() << "*.c++" - << "*.cc" - << "*.cpp" - << "*.cxx" - << "*.mm"; -} - -/*! - Parse the C++ header file identified by \a filePath and add - the parsed contents to the database. The \a location is used - for reporting errors. - */ -void ClangCodeParser::parseHeaderFile(const Location & /*location*/, const QString &filePath) -{ - QFileInfo fi(filePath); - const QString &fileName = fi.fileName(); - const QString &canonicalPath = fi.canonicalPath(); - - if (m_allHeaders.contains(fileName, canonicalPath)) - return; - - m_allHeaders.insert(fileName, canonicalPath); -} - -static const char *defaultArgs_[] = { -/* - https://bugreports.qt.io/browse/QTBUG-94365 - An unidentified bug in Clang 15.x causes parsing failures due to errors in - the AST. This replicates only with C++20 support enabled - avoid the issue - by using C++17 with Clang 15. - */ -#if LIBCLANG_VERSION_MAJOR == 15 - "-std=c++17", -#else - "-std=c++20", -#endif -#ifndef Q_OS_WIN - "-fPIC", -#else - "-fms-compatibility-version=19", -#endif - "-DQ_QDOC", - "-DQ_CLANG_QDOC", - "-DQT_DISABLE_DEPRECATED_UP_TO=0", - "-DQT_ANNOTATE_CLASS(type,...)=static_assert(sizeof(#__VA_ARGS__),#type);", - "-DQT_ANNOTATE_CLASS2(type,a1,a2)=static_assert(sizeof(#a1,#a2),#type);", - "-DQT_ANNOTATE_FUNCTION(a)=__attribute__((annotate(#a)))", - "-DQT_ANNOTATE_ACCESS_SPECIFIER(a)=__attribute__((annotate(#a)))", - "-Wno-constant-logical-operand", - "-Wno-macro-redefined", - "-Wno-nullability-completeness", - "-fvisibility=default", - "-ferror-limit=0", - ("-I" CLANG_RESOURCE_DIR) -}; - -/*! - Load the default arguments and the defines into \a args. - Clear \a args first. - */ -void ClangCodeParser::getDefaultArgs() -{ - m_args.clear(); - m_args.insert(m_args.begin(), std::begin(defaultArgs_), std::end(defaultArgs_)); - // Add the defines from the qdocconf file. - for (const auto &p : std::as_const(m_defines)) - m_args.push_back(p.constData()); -} - -static QList includePathsFromHeaders(const QMultiHash &allHeaders) -{ - QList result; - for (auto it = allHeaders.cbegin(); it != allHeaders.cend(); ++it) { - const QByteArray path = "-I" + it.value().toLatin1(); - const QByteArray parent = - "-I" + QDir::cleanPath(it.value() + QLatin1String("/../")).toLatin1(); - if (!result.contains(path)) - result.append(path); - if (!result.contains(parent)) - result.append(parent); - } - return result; -} - -/*! - Load the include paths into \a moreArgs. If no include paths - were provided, try to guess reasonable include paths. - */ -void ClangCodeParser::getMoreArgs() -{ - if (m_includePaths.isEmpty()) { - /* - The include paths provided are inadequate. Make a list - of reasonable places to look for include files and use - that list instead. - */ - qCWarning(lcQdoc) << "No include paths passed to qdoc; guessing reasonable include paths"; - - QString basicIncludeDir = QDir::cleanPath(QString(Config::installDir + "/../include")); - m_moreArgs += "-I" + basicIncludeDir.toLatin1(); - m_moreArgs += includePathsFromHeaders(m_allHeaders); - } else { - m_moreArgs = m_includePaths; - } -} - -/*! - Building the PCH must be possible when there are no .cpp - files, so it is moved here to its own member function, and - it is called after the list of header files is complete. - */ -void ClangCodeParser::buildPCH(QString module_header) -{ - if (m_pchFileDir) return; - if (module_header.isEmpty()) return; - - m_pchFileDir.reset(new QTemporaryDir(QDir::tempPath() + QLatin1String("/qdoc_pch"))); - if (m_pchFileDir->isValid()) { - const QByteArray module = module_header.toUtf8(); - QByteArray header; - - qCDebug(lcQdoc) << "Build and visit PCH for" << module_header; - // A predicate for std::find_if() to locate a path to the module's header - // (e.g. QtGui/QtGui) to be used as pre-compiled header - struct FindPredicate - { - enum SearchType { Any, Module }; - QByteArray &candidate_; - const QByteArray &module_; - SearchType type_; - FindPredicate(QByteArray &candidate, const QByteArray &module, - SearchType type = Any) - : candidate_(candidate), module_(module), type_(type) - { - } - - bool operator()(const QByteArray &p) const - { - if (type_ != Any && !p.endsWith(module_)) - return false; - candidate_ = p + "/"; - candidate_.append(module_); - if (p.startsWith("-I")) - candidate_ = candidate_.mid(2); - return QFile::exists(QString::fromUtf8(candidate_)); - } - }; - - // First, search for an include path that contains the module name, then any path - QByteArray candidate; - auto it = std::find_if(m_includePaths.begin(), m_includePaths.end(), - FindPredicate(candidate, module, FindPredicate::Module)); - if (it == m_includePaths.end()) - it = std::find_if(m_includePaths.begin(), m_includePaths.end(), - FindPredicate(candidate, module, FindPredicate::Any)); - if (it != m_includePaths.end()) - header = candidate; - - if (header.isEmpty()) { - qWarning() << "(qdoc) Could not find the module header in include paths for module" - << module << " (include paths: " << m_includePaths << ")"; - qWarning() << " Artificial module header built from header dirs in qdocconf " - "file"; - } - m_args.push_back("-xc++"); - CXTranslationUnit tu; - QString tmpHeader = m_pchFileDir->path() + "/" + module; - if (QFile tmpHeaderFile(tmpHeader); tmpHeaderFile.open(QIODevice::Text | QIODevice::WriteOnly)) { - QTextStream out(&tmpHeaderFile); - if (header.isEmpty()) { - for (auto it = m_allHeaders.constKeyValueBegin(); - it != m_allHeaders.constKeyValueEnd(); ++it) { - if (!(*it).first.endsWith(QLatin1String("_p.h")) - && !(*it).first.startsWith(QLatin1String("moc_"))) { - QString line = QLatin1String("#include \"") + (*it).second - + QLatin1String("/") + (*it).first + QLatin1String("\""); - out << line << "\n"; - } - } - } else { - QFileInfo headerFile(header); - if (!headerFile.exists()) { - qWarning() << "Could not find module header file" << header; - return; - } - out << QLatin1String("#include \"") + header + QLatin1String("\""); - } - } - - CXErrorCode err = - clang_parseTranslationUnit2(index_, tmpHeader.toLatin1().data(), m_args.data(), - static_cast(m_args.size()), nullptr, 0, - flags_ | CXTranslationUnit_ForSerialization, &tu); - qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << tmpHeader << m_args - << ") returns" << err; - - printDiagnostics(tu); - - if (!err && tu) { - m_pchName = m_pchFileDir->path().toUtf8() + "/" + module + ".pch"; - auto error = clang_saveTranslationUnit(tu, m_pchName.constData(), - clang_defaultSaveOptions(tu)); - if (error) { - qCCritical(lcQdoc) << "Could not save PCH file for" << module_header; - m_pchName.clear(); - } else { - // Visit the header now, as token from pre-compiled header won't be visited - // later - CXCursor cur = clang_getTranslationUnitCursor(tu); - ClangVisitor visitor(m_qdb, m_allHeaders); - visitor.visitChildren(cur); - qCDebug(lcQdoc) << "PCH built and visited for" << module_header; - } - } else { - m_pchFileDir->remove(); - qCCritical(lcQdoc) << "Could not create PCH file for " << module_header; - } - clang_disposeTranslationUnit(tu); - m_args.pop_back(); // remove the "-xc++"; - } -} - -/*! - Precompile the header files for the current module. - */ -void ClangCodeParser::precompileHeaders(QString module_header) -{ - getDefaultArgs(); - getMoreArgs(); - for (const auto &p : std::as_const(m_moreArgs)) - m_args.push_back(p.constData()); - - flags_ = static_cast(CXTranslationUnit_Incomplete - | CXTranslationUnit_SkipFunctionBodies - | CXTranslationUnit_KeepGoing); - - index_ = clang_createIndex(1, kClangDontDisplayDiagnostics); - - buildPCH(module_header); - clang_disposeIndex(index_); -} - -static float getUnpatchedVersion(QString t) -{ - if (t.count(QChar('.')) > 1) - t.truncate(t.lastIndexOf(QChar('.'))); - return t.toFloat(); -} - -/*! - Get ready to parse the C++ cpp file identified by \a filePath - and add its parsed contents to the database. \a location is - used for reporting errors. - - Call matchDocsAndStuff() to do all the parsing and tree building. - */ -void ClangCodeParser::parseSourceFile(const Location & /*location*/, const QString &filePath, CppCodeParser& cpp_code_parser) -{ - /* - The set of open namespaces is cleared before parsing - each source file. The word "source" here means cpp file. - */ - m_qdb->clearOpenNamespaces(); - flags_ = static_cast(CXTranslationUnit_Incomplete - | CXTranslationUnit_SkipFunctionBodies - | CXTranslationUnit_KeepGoing); - - index_ = clang_createIndex(1, kClangDontDisplayDiagnostics); - - getDefaultArgs(); - if (!m_pchName.isEmpty() && !filePath.endsWith(".mm")) { - m_args.push_back("-w"); - m_args.push_back("-include-pch"); - m_args.push_back(m_pchName.constData()); - } - getMoreArgs(); - for (const auto &p : std::as_const(m_moreArgs)) - m_args.push_back(p.constData()); - - CXTranslationUnit tu; - CXErrorCode err = - clang_parseTranslationUnit2(index_, filePath.toLocal8Bit(), m_args.data(), - static_cast(m_args.size()), nullptr, 0, flags_, &tu); - qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << filePath << m_args - << ") returns" << err; - printDiagnostics(tu); - - if (err || !tu) { - qWarning() << "(qdoc) Could not parse source file" << filePath << " error code:" << err; - clang_disposeTranslationUnit(tu); - clang_disposeIndex(index_); - return; - } - - CXCursor tuCur = clang_getTranslationUnitCursor(tu); - ClangVisitor visitor(m_qdb, m_allHeaders); - visitor.visitChildren(tuCur); - - CXToken *tokens; - unsigned int numTokens = 0; - const QSet &commands = CppCodeParser::topic_commands + CppCodeParser::meta_commands; - clang_tokenize(tu, clang_getCursorExtent(tuCur), &tokens, &numTokens); - - for (unsigned int i = 0; i < numTokens; ++i) { - if (clang_getTokenKind(tokens[i]) != CXToken_Comment) - continue; - QString comment = fromCXString(clang_getTokenSpelling(tu, tokens[i])); - if (!comment.startsWith("/*!")) - continue; - - auto commentLoc = clang_getTokenLocation(tu, tokens[i]); - auto loc = fromCXSourceLocation(commentLoc); - auto end_loc = fromCXSourceLocation(clang_getRangeEnd(clang_getTokenExtent(tu, tokens[i]))); - Doc::trimCStyleComment(loc, comment); - - // Doc constructor parses the comment. - Doc doc(loc, end_loc, comment, commands, CppCodeParser::topic_commands); - if (cpp_code_parser.hasTooManyTopics(doc)) - continue; - - DocList docs; - QString topic; - NodeList nodes; - const TopicList &topics = doc.topicsUsed(); - if (!topics.isEmpty()) - topic = topics[0].m_topic; - - if (topic.isEmpty()) { - Node *n = nullptr; - if (i + 1 < numTokens) { - // Try to find the next declaration. - CXSourceLocation nextCommentLoc = commentLoc; - while (i + 2 < numTokens && clang_getTokenKind(tokens[i + 1]) != CXToken_Comment) - ++i; // already skip all the tokens that are not comments - nextCommentLoc = clang_getTokenLocation(tu, tokens[i + 1]); - n = visitor.nodeForCommentAtLocation(commentLoc, nextCommentLoc); - } - - if (n) { - nodes.append(n); - docs.append(doc); - } else if (CodeParser::isWorthWarningAbout(doc)) { - bool future = false; - if (doc.metaCommandsUsed().contains(COMMAND_SINCE)) { - QString sinceVersion = doc.metaCommandArgs(COMMAND_SINCE).at(0).first; - if (getUnpatchedVersion(sinceVersion) > - getUnpatchedVersion(Config::instance().get(CONFIG_VERSION).asString())) - future = true; - } - if (!future) { - doc.location().warning( - QStringLiteral("Cannot tie this documentation to anything"), - QStringLiteral("qdoc found a /*! ... */ comment, but there was no " - "topic command (e.g., '\\%1', '\\%2') in the " - "comment and no function definition following " - "the comment.") - .arg(COMMAND_FN, COMMAND_PAGE)); - } - } - } else { - // Store the namespace scope from lexical parents of the comment - m_namespaceScope.clear(); - CXCursor cur = clang_getCursor(tu, commentLoc); - while (true) { - CXCursorKind kind = clang_getCursorKind(cur); - if (clang_isTranslationUnit(kind) || clang_isInvalid(kind)) - break; - if (kind == CXCursor_Namespace) - m_namespaceScope << fromCXString(clang_getCursorSpelling(cur)); - cur = clang_getCursorLexicalParent(cur); - } - cpp_code_parser.processTopicArgs(doc, topic, nodes, docs); - } - cpp_code_parser.processMetaCommands(nodes, docs); - } - - clang_disposeTokens(tu, tokens, numTokens); - clang_disposeTranslationUnit(tu); - clang_disposeIndex(index_); - m_namespaceScope.clear(); - s_fn.clear(); -} - -/*! - Use clang to parse the function signature from a function - command. \a location is used for reporting errors. \a fnSignature - is the string to parse. It is always a function decl. - */ -Node *ClangCodeParser::parseFnArg(const Location &location, const QString &fnSignature, const QString &idTag) -{ - Node *fnNode = nullptr; - /* - If the \fn command begins with a tag, then don't try to - parse the \fn command with clang. Use the tag to search - for the correct function node. It is an error if it can - not be found. Return 0 in that case. - */ - if (!idTag.isEmpty()) { - fnNode = m_qdb->findFunctionNodeForTag(idTag); - if (!fnNode) { - location.error( - QStringLiteral("tag \\fn [%1] not used in any include file in current module").arg(idTag)); - } else { - /* - The function node was found. Use the formal - parameter names from the \fn command, because - they will be the names used in the documentation. - */ - auto *fn = static_cast(fnNode); - QStringList leftParenSplit = fnSignature.mid(fnSignature.indexOf(fn->name())).split('('); - if (leftParenSplit.size() > 1) { - QStringList rightParenSplit = leftParenSplit[1].split(')'); - if (!rightParenSplit.empty()) { - QString params = rightParenSplit[0]; - if (!params.isEmpty()) { - QStringList commaSplit = params.split(','); - Parameters ¶meters = fn->parameters(); - if (parameters.count() == commaSplit.size()) { - for (int i = 0; i < parameters.count(); ++i) { - QStringList blankSplit = commaSplit[i].split(' ', Qt::SkipEmptyParts); - if (blankSplit.size() > 1) { - QString pName = blankSplit.last(); - // Remove any non-letters from the start of parameter name - auto it = std::find_if(std::begin(pName), std::end(pName), - [](const QChar &c) { return c.isLetter(); }); - parameters[i].setName( - pName.remove(0, std::distance(std::begin(pName), it))); - } - } - } - } - } - } - } - return fnNode; - } - auto flags = static_cast(CXTranslationUnit_Incomplete - | CXTranslationUnit_SkipFunctionBodies - | CXTranslationUnit_KeepGoing); - - CXIndex index = clang_createIndex(1, kClangDontDisplayDiagnostics); - - std::vector args(std::begin(defaultArgs_), std::end(defaultArgs_)); - // Add the defines from the qdocconf file. - for (const auto &p : std::as_const(m_defines)) - args.push_back(p.constData()); - if (!m_pchName.isEmpty()) { - args.push_back("-w"); - args.push_back("-include-pch"); - args.push_back(m_pchName.constData()); - } - CXTranslationUnit tu; - s_fn.clear(); - for (const auto &ns : std::as_const(m_namespaceScope)) - s_fn.prepend("namespace " + ns.toUtf8() + " {"); - s_fn += fnSignature.toUtf8(); - if (!s_fn.endsWith(";")) - s_fn += "{ }"; - s_fn.append(m_namespaceScope.size(), '}'); - - const char *dummyFileName = fnDummyFileName; - CXUnsavedFile unsavedFile { dummyFileName, s_fn.constData(), - static_cast(s_fn.size()) }; - CXErrorCode err = clang_parseTranslationUnit2(index, dummyFileName, args.data(), - int(args.size()), &unsavedFile, 1, flags, &tu); - qCDebug(lcQdoc) << __FUNCTION__ << "clang_parseTranslationUnit2(" << dummyFileName << args - << ") returns" << err; - printDiagnostics(tu); - if (err || !tu) { - location.error(QStringLiteral("clang could not parse \\fn %1").arg(fnSignature)); - clang_disposeTranslationUnit(tu); - clang_disposeIndex(index); - return fnNode; - } else { - /* - Always visit the tu if one is constructed, because - it might be possible to find the correct node, even - if clang detected diagnostics. Only bother to report - the diagnostics if they stop us finding the node. - */ - CXCursor cur = clang_getTranslationUnitCursor(tu); - ClangVisitor visitor(m_qdb, m_allHeaders); - bool ignoreSignature = false; - visitor.visitFnArg(cur, &fnNode, ignoreSignature); - /* - If the visitor couldn't find a FunctionNode for the - signature, then print the clang diagnostics if there - were any. - */ - if (fnNode == nullptr) { - unsigned diagnosticCount = clang_getNumDiagnostics(tu); - const auto &config = Config::instance(); - if (diagnosticCount > 0 && (!config.preparing() || config.singleExec())) { - bool report = true; - QStringList signature = fnSignature.split(QChar('(')); - if (signature.size() > 1) { - QStringList qualifiedName = signature.at(0).split(QChar(' ')); - qualifiedName = qualifiedName.last().split(QLatin1String("::")); - if (qualifiedName.size() > 1) { - QString qualifier = qualifiedName.at(0); - int i = 0; - while (qualifier.size() > i && !qualifier.at(i).isLetter()) - qualifier[i++] = QChar(' '); - if (i > 0) - qualifier = qualifier.simplified(); - ClassNode *cn = m_qdb->findClassNode(QStringList(qualifier)); - if (cn && cn->isInternal()) - report = false; - } - } - if (report) { - location.warning( - QStringLiteral("clang couldn't find function when parsing \\fn %1").arg(fnSignature)); - } - } - } - } - clang_disposeTranslationUnit(tu); - clang_disposeIndex(index); - return fnNode; -} - -void ClangCodeParser::printDiagnostics(const CXTranslationUnit &translationUnit) const -{ - if (!lcQdocClang().isDebugEnabled()) - return; - - static const auto displayOptions = CXDiagnosticDisplayOptions::CXDiagnostic_DisplaySourceLocation - | CXDiagnosticDisplayOptions::CXDiagnostic_DisplayColumn - | CXDiagnosticDisplayOptions::CXDiagnostic_DisplayOption; - - for (unsigned i = 0, numDiagnostics = clang_getNumDiagnostics(translationUnit); i < numDiagnostics; ++i) { - auto diagnostic = clang_getDiagnostic(translationUnit, i); - auto formattedDiagnostic = clang_formatDiagnostic(diagnostic, displayOptions); - qCDebug(lcQdocClang) << clang_getCString(formattedDiagnostic); - clang_disposeString(formattedDiagnostic); - clang_disposeDiagnostic(diagnostic); - } -} - -QT_END_NAMESPACE diff --git a/src/qdoc/clangcodeparser.h b/src/qdoc/clangcodeparser.h deleted file mode 100644 index 58a340bca..000000000 --- a/src/qdoc/clangcodeparser.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#ifndef CLANGCODEPARSER_H -#define CLANGCODEPARSER_H - -#include "cppcodeparser.h" - -#include -#include - -typedef struct CXTranslationUnitImpl *CXTranslationUnit; - -QT_BEGIN_NAMESPACE - -class ClangCodeParser : public CodeParser -{ -public: - static const QStringList accepted_header_file_extensions; - -public: - ~ClangCodeParser() override = default; - - void initializeParser() override; - void terminateParser() override {} - QString language() override; - QStringList sourceFileNameFilter() override; - void parseHeaderFile(const Location &location, const QString &filePath); - void parseSourceFile(const Location &location, const QString &filePath, CppCodeParser&) override; - void precompileHeaders(QString module_header); - Node *parseFnArg(const Location &location, const QString &fnSignature, const QString &idTag) override; - static const QByteArray &fn() { return s_fn; } - -private: - void getDefaultArgs(); - void getMoreArgs(); - - void buildPCH(QString module_header); - - void printDiagnostics(const CXTranslationUnit &translationUnit) const; - - QMultiHash m_allHeaders {}; // file name->path - QList m_includePaths {}; - QScopedPointer m_pchFileDir {}; - QByteArray m_pchName {}; - QList m_defines {}; - std::vector m_args {}; - QList m_moreArgs {}; - QStringList m_namespaceScope {}; - static QByteArray s_fn; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/classnode.cpp b/src/qdoc/classnode.cpp deleted file mode 100644 index f6de10f78..000000000 --- a/src/qdoc/classnode.cpp +++ /dev/null @@ -1,291 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "classnode.h" - -#include "functionnode.h" -#include "propertynode.h" -#include "qdocdatabase.h" -#include "qmltypenode.h" - -QT_BEGIN_NAMESPACE - -/*! - \class ClassNode - \brief The ClassNode represents a C++ class. - - It is also used to represent a C++ struct or union. There are some - actual uses for structs, but I don't think any unions have been - documented yet. - */ - -/*! - Adds the base class \a node to this class's list of base - classes. The base class has the specified \a access. This - is a resolved base class. - */ -void ClassNode::addResolvedBaseClass(Access access, ClassNode *node) -{ - m_bases.append(RelatedClass(access, node)); - node->m_derived.append(RelatedClass(access, this)); -} - -/*! - Adds the derived class \a node to this class's list of derived - classes. The derived class inherits this class with \a access. - */ -void ClassNode::addDerivedClass(Access access, ClassNode *node) -{ - m_derived.append(RelatedClass(access, node)); -} - -/*! - Add an unresolved base class to this class node's list of - base classes. The unresolved base class will be resolved - before the generate phase of qdoc. In an unresolved base - class, the pointer to the base class node is 0. - */ -void ClassNode::addUnresolvedBaseClass(Access access, const QStringList &path) -{ - m_bases.append(RelatedClass(access, path)); -} - -/*! - Search the child list to find the property node with the - specified \a name. - */ -PropertyNode *ClassNode::findPropertyNode(const QString &name) -{ - Node *n = findNonfunctionChild(name, &Node::isProperty); - - if (n) - return static_cast(n); - - PropertyNode *pn = nullptr; - - const QList &bases = baseClasses(); - if (!bases.isEmpty()) { - for (const RelatedClass &base : bases) { - ClassNode *cn = base.m_node; - if (cn) { - pn = cn->findPropertyNode(name); - if (pn) - break; - } - } - } - const QList &ignoredBases = ignoredBaseClasses(); - if (!ignoredBases.isEmpty()) { - for (const RelatedClass &base : ignoredBases) { - ClassNode *cn = base.m_node; - if (cn) { - pn = cn->findPropertyNode(name); - if (pn) - break; - } - } - } - - return pn; -} - -/*! - This function does a recursive search of this class node's - base classes looking for one that has a QML element. If it - finds one, it returns the pointer to that QML element. If - it doesn't find one, it returns null. - */ -QmlTypeNode *ClassNode::findQmlBaseNode() -{ - QmlTypeNode *result = nullptr; - const QList &bases = baseClasses(); - - if (!bases.isEmpty()) { - for (const RelatedClass &base : bases) { - ClassNode *cn = base.m_node; - if (cn && cn->qmlElement()) { - return cn->qmlElement(); - } - } - for (const RelatedClass &base : bases) { - ClassNode *cn = base.m_node; - if (cn) { - result = cn->findQmlBaseNode(); - if (result != nullptr) { - return result; - } - } - } - } - return result; -} - -/*! - \a fn is an overriding function in this class or in a class - derived from this class. Find the node for the function that - \a fn overrides in this class's children or in one of this - class's base classes. Return a pointer to the overridden - function or return 0. - - This should be revised because clang provides the path to the - overridden function. mws 15/12/2018 - */ -FunctionNode *ClassNode::findOverriddenFunction(const FunctionNode *fn) -{ - for (auto &bc : m_bases) { - ClassNode *cn = bc.m_node; - if (cn == nullptr) { - cn = QDocDatabase::qdocDB()->findClassNode(bc.m_path); - bc.m_node = cn; - } - if (cn != nullptr) { - FunctionNode *result = cn->findFunctionChild(fn); - if (result != nullptr && !result->isInternal() && !result->isNonvirtual() - && result->hasDoc()) - return result; - result = cn->findOverriddenFunction(fn); - if (result != nullptr && !result->isNonvirtual()) - return result; - } - } - return nullptr; -} - -/*! - \a fn is an overriding function in this class or in a class - derived from this class. Find the node for the property that - \a fn overrides in this class's children or in one of this - class's base classes. Return a pointer to the overridden - property or return 0. - */ -PropertyNode *ClassNode::findOverriddenProperty(const FunctionNode *fn) -{ - for (auto &baseClass : m_bases) { - ClassNode *cn = baseClass.m_node; - if (cn == nullptr) { - cn = QDocDatabase::qdocDB()->findClassNode(baseClass.m_path); - baseClass.m_node = cn; - } - if (cn != nullptr) { - const NodeList &children = cn->childNodes(); - for (const auto &child : children) { - if (child->isProperty()) { - auto *pn = static_cast(child); - if (pn->name() == fn->name() || pn->hasAccessFunction(fn->name())) { - if (pn->hasDoc()) - return pn; - } - } - } - PropertyNode *result = cn->findOverriddenProperty(fn); - if (result != nullptr) - return result; - } - } - return nullptr; -} - -/*! - Returns true if the class or struct represented by this class - node must be documented. If this function returns true, then - qdoc must find a qdoc comment for this class. If it returns - false, then the class need not be documented. - */ -bool ClassNode::docMustBeGenerated() const -{ - if (!hasDoc() || isPrivate() || isInternal() || isDontDocument()) - return false; - if (declLocation().fileName().endsWith(QLatin1String("_p.h")) && !hasDoc()) - return false; - - return true; -} - -/*! - A base class of this class node was private or internal. - That node's list of \a bases is traversed in this function. - Each of its public base classes is promoted to be a base - class of this node for documentation purposes. For each - private or internal class node in \a bases, this function - is called recursively with the list of base classes from - that private or internal class node. - */ -void ClassNode::promotePublicBases(const QList &bases) -{ - if (!bases.isEmpty()) { - for (qsizetype i = bases.size() - 1; i >= 0; --i) { - ClassNode *bc = bases.at(i).m_node; - if (bc == nullptr) - bc = QDocDatabase::qdocDB()->findClassNode(bases.at(i).m_path); - if (bc != nullptr) { - if (bc->isPrivate() || bc->isInternal()) - promotePublicBases(bc->baseClasses()); - else - m_bases.append(bases.at(i)); - } - } - } -} - -/*! - Remove private and internal bases classes from this class's list - of base classes. When a base class is removed from the list, add - its base classes to this class's list of base classes. - */ -void ClassNode::removePrivateAndInternalBases() -{ - int i; - i = 0; - QSet found; - - // Remove private and duplicate base classes. - while (i < m_bases.size()) { - ClassNode *bc = m_bases.at(i).m_node; - if (bc == nullptr) - bc = QDocDatabase::qdocDB()->findClassNode(m_bases.at(i).m_path); - if (bc != nullptr - && (bc->isPrivate() || bc->isInternal() || bc->isDontDocument() - || found.contains(bc))) { - RelatedClass rc = m_bases.at(i); - m_bases.removeAt(i); - m_ignoredBases.append(rc); - promotePublicBases(bc->baseClasses()); - } else { - ++i; - } - found.insert(bc); - } - - i = 0; - while (i < m_derived.size()) { - ClassNode *dc = m_derived.at(i).m_node; - if (dc != nullptr && (dc->isPrivate() || dc->isInternal() || dc->isDontDocument())) { - m_derived.removeAt(i); - const QList &dd = dc->derivedClasses(); - for (qsizetype j = dd.size() - 1; j >= 0; --j) - m_derived.insert(i, dd.at(j)); - } else { - ++i; - } - } -} - -/*! - */ -void ClassNode::resolvePropertyOverriddenFromPtrs(PropertyNode *pn) -{ - for (const auto &baseClass : std::as_const(baseClasses())) { - ClassNode *cn = baseClass.m_node; - if (cn) { - Node *n = cn->findNonfunctionChild(pn->name(), &Node::isProperty); - if (n) { - auto *baseProperty = static_cast(n); - cn->resolvePropertyOverriddenFromPtrs(baseProperty); - pn->setOverriddenFrom(baseProperty); - } else - cn->resolvePropertyOverriddenFromPtrs(pn); - } - } -} - -QT_END_NAMESPACE diff --git a/src/qdoc/classnode.h b/src/qdoc/classnode.h deleted file mode 100644 index d58968d2f..000000000 --- a/src/qdoc/classnode.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CLASSNODE_H -#define CLASSNODE_H - -#include "aggregate.h" -#include "relatedclass.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class FunctionNode; -class PropertyNode; -class QmlTypeNode; - -class ClassNode : public Aggregate -{ -public: - ClassNode(NodeType type, Aggregate *parent, const QString &name) : Aggregate(type, parent, name) - { - } - [[nodiscard]] bool isFirstClassAggregate() const override { return true; } - [[nodiscard]] bool isClassNode() const override { return true; } - [[nodiscard]] bool isRelatableType() const override { return true; } - [[nodiscard]] bool isWrapper() const override { return m_wrapper; } - [[nodiscard]] QString obsoleteLink() const override { return m_obsoleteLink; } - void setObsoleteLink(const QString &t) override { m_obsoleteLink = t; } - void setWrapper() override { m_wrapper = true; } - - void addResolvedBaseClass(Access access, ClassNode *node); - void addDerivedClass(Access access, ClassNode *node); - void addUnresolvedBaseClass(Access access, const QStringList &path); - void removePrivateAndInternalBases(); - void resolvePropertyOverriddenFromPtrs(PropertyNode *pn); - - QList &baseClasses() { return m_bases; } - QList &derivedClasses() { return m_derived; } - QList &ignoredBaseClasses() { return m_ignoredBases; } - - [[nodiscard]] const QList &baseClasses() const { return m_bases; } - - QmlTypeNode *qmlElement() { return m_qmlElement; } - void setQmlElement(QmlTypeNode *qcn) { m_qmlElement = qcn; } - [[nodiscard]] bool isAbstract() const override { return m_abstract; } - void setAbstract(bool b) override { m_abstract = b; } - PropertyNode *findPropertyNode(const QString &name); - QmlTypeNode *findQmlBaseNode(); - FunctionNode *findOverriddenFunction(const FunctionNode *fn); - PropertyNode *findOverriddenProperty(const FunctionNode *fn); - [[nodiscard]] bool docMustBeGenerated() const override; - -private: - void promotePublicBases(const QList &bases); - -private: - QList m_bases {}; - QList m_derived {}; - QList m_ignoredBases {}; - bool m_abstract { false }; - bool m_wrapper { false }; - QString m_obsoleteLink {}; - QmlTypeNode *m_qmlElement { nullptr }; -}; - -QT_END_NAMESPACE - -#endif // CLASSNODE_H diff --git a/src/qdoc/codechunk.cpp b/src/qdoc/codechunk.cpp deleted file mode 100644 index 889e091af..000000000 --- a/src/qdoc/codechunk.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "codechunk.h" - -QT_BEGIN_NAMESPACE - -enum { Other, Alnum, Gizmo, Comma, LBrace, RBrace, RAngle, Colon, Paren }; - -// entries 128 and above are Other -static const int charCategory[256] = { Other, Other, Other, Other, Other, Other, Other, Other, - Other, Other, Other, Other, Other, Other, Other, Other, - Other, Other, Other, Other, Other, Other, Other, Other, - Other, Other, Other, Other, Other, Other, Other, Other, - // ! " # $ % & ' - Other, Other, Other, Other, Other, Gizmo, Gizmo, Other, - // ( ) * + , - . / - Paren, Paren, Gizmo, Gizmo, Comma, Other, Other, Gizmo, - // 0 1 2 3 4 5 6 7 - Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // 8 9 : ; < = > ? - Alnum, Alnum, Colon, Other, Other, Gizmo, RAngle, Gizmo, - // @ A B C D E F G - Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // H I J K L M N O - Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // P Q R S T U V W - Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // X Y Z [ \ ] ^ _ - Alnum, Alnum, Alnum, Other, Other, Other, Gizmo, Alnum, - // ` a b c d e f g - Other, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // h i j k l m n o - Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // p q r s t u v w - Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, Alnum, - // x y z { | } ~ - Alnum, Alnum, Alnum, LBrace, Gizmo, RBrace, Other, Other }; - -static const bool needSpace[9][9] = { - /* [ a + , { } > : ) */ - /* [ */ { false, false, false, false, false, true, false, false, false }, - /* a */ { false, true, true, false, false, true, false, false, false }, - /* + */ { false, true, false, false, false, true, false, true, false }, - /* , */ { true, true, true, true, true, true, true, true, false }, - /* { */ { false, false, false, false, false, false, false, false, false }, - /* } */ { false, false, false, false, false, false, false, false, false }, - /* > */ { true, true, true, false, true, true, true, false, false }, - /* : */ { false, false, true, true, true, true, true, false, false }, - /* ( */ { false, false, false, false, false, false, false, false, false }, -}; - -static int category(QChar ch) -{ - return charCategory[static_cast(ch.toLatin1())]; -} - -/*! - \class CodeChunk - - \brief The CodeChunk class represents a tiny piece of C++ code. - - \note I think this class should be eliminated (mws 11/12/2018 - - The class provides conversion between a list of lexemes and a string. It adds - spaces at the right place for consistent style. The tiny pieces of code it - represents are data types, enum values, and default parameter values. - - Apart from the piece of code itself, there are two bits of metainformation - stored in CodeChunk: the base and the hotspot. The base is the part of the - piece that may be a hypertext link. The base of - - QMap - - is QMap. - - The hotspot is the place the variable name should be inserted in the case of a - variable (or parameter) declaration. The hotspot of - - char * [] - - is between '*' and '[]'. -*/ - -/*! - Appends \a lexeme to the current string contents, inserting - a space if appropriate. - */ -void CodeChunk::append(const QString &lexeme) -{ - if (!m_str.isEmpty() && !lexeme.isEmpty()) { - /* - Should there be a space or not between the code chunk so far and the - new lexeme? - */ - int cat1 = category(m_str.at(m_str.size() - 1)); - int cat2 = category(lexeme[0]); - if (needSpace[cat1][cat2]) - m_str += QLatin1Char(' '); - } - m_str += lexeme; -} - -QT_END_NAMESPACE diff --git a/src/qdoc/codechunk.h b/src/qdoc/codechunk.h deleted file mode 100644 index 00ad26c6d..000000000 --- a/src/qdoc/codechunk.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CODECHUNK_H -#define CODECHUNK_H - -#include - -QT_BEGIN_NAMESPACE - -// ### get rid of that class - -class CodeChunk -{ -public: - CodeChunk() : m_hotspot(-1) { } - - void append(const QString &lexeme); - void appendHotspot() - { - if (m_hotspot == -1) - m_hotspot = m_str.size(); - } - - [[nodiscard]] bool isEmpty() const { return m_str.isEmpty(); } - void clear() { m_str.clear(); } - [[nodiscard]] QString toString() const { return m_str; } - [[nodiscard]] QString left() const - { - return m_str.left(m_hotspot == -1 ? m_str.size() : m_hotspot); - } - [[nodiscard]] QString right() const - { - return m_str.mid(m_hotspot == -1 ? m_str.size() : m_hotspot); - } - -private: - QString m_str {}; - qsizetype m_hotspot {}; -}; - -inline bool operator==(const CodeChunk &c, const CodeChunk &d) -{ - return c.toString() == d.toString(); -} - -inline bool operator!=(const CodeChunk &c, const CodeChunk &d) -{ - return !(c == d); -} - -inline bool operator<(const CodeChunk &c, const CodeChunk &d) -{ - return c.toString() < d.toString(); -} - -inline bool operator>(const CodeChunk &c, const CodeChunk &d) -{ - return d < c; -} - -inline bool operator<=(const CodeChunk &c, const CodeChunk &d) -{ - return !(c > d); -} - -inline bool operator>=(const CodeChunk &c, const CodeChunk &d) -{ - return !(c < d); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/codemarker.cpp b/src/qdoc/codemarker.cpp deleted file mode 100644 index f897f07a7..000000000 --- a/src/qdoc/codemarker.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "codemarker.h" - -#include "classnode.h" -#include "config.h" -#include "functionnode.h" -#include "node.h" -#include "propertynode.h" - -#include - -QT_BEGIN_NAMESPACE - -QString CodeMarker::s_defaultLang; -QList CodeMarker::s_markers; - -/*! - When a code marker constructs itself, it puts itself into - the static list of code markers. All the code markers in - the static list get initialized in initialize(), which is - not called until after the qdoc configuration file has - been read. - */ -CodeMarker::CodeMarker() -{ - s_markers.prepend(this); -} - -/*! - When a code marker destroys itself, it removes itself from - the static list of code markers. - */ -CodeMarker::~CodeMarker() -{ - s_markers.removeAll(this); -} - -/*! - A code market performs no initialization by default. Marker-specific - initialization is performed in subclasses. - */ -void CodeMarker::initializeMarker() {} - -/*! - Terminating a code marker is trivial. - */ -void CodeMarker::terminateMarker() -{ - // nothing. -} - -/*! - All the code markers in the static list are initialized - here, after the qdoc configuration file has been loaded. - */ -void CodeMarker::initialize() -{ - s_defaultLang = Config::instance().get(CONFIG_LANGUAGE).asString(); - for (const auto &marker : std::as_const(s_markers)) - marker->initializeMarker(); -} - -/*! - All the code markers in the static list are terminated here. - */ -void CodeMarker::terminate() -{ - for (const auto &marker : std::as_const(s_markers)) - marker->terminateMarker(); -} - -CodeMarker *CodeMarker::markerForCode(const QString &code) -{ - CodeMarker *defaultMarker = markerForLanguage(s_defaultLang); - if (defaultMarker != nullptr && defaultMarker->recognizeCode(code)) - return defaultMarker; - - for (const auto &marker : std::as_const(s_markers)) { - if (marker->recognizeCode(code)) - return marker; - } - - return defaultMarker; -} - -CodeMarker *CodeMarker::markerForFileName(const QString &fileName) -{ - CodeMarker *defaultMarker = markerForLanguage(s_defaultLang); - qsizetype dot = -1; - while ((dot = fileName.lastIndexOf(QLatin1Char('.'), dot)) != -1) { - QString ext = fileName.mid(dot + 1); - if (defaultMarker != nullptr && defaultMarker->recognizeExtension(ext)) - return defaultMarker; - for (const auto &marker : std::as_const(s_markers)) { - if (marker->recognizeExtension(ext)) - return marker; - } - --dot; - } - return defaultMarker; -} - -CodeMarker *CodeMarker::markerForLanguage(const QString &lang) -{ - for (const auto &marker : std::as_const(s_markers)) { - if (marker->recognizeLanguage(lang)) - return marker; - } - return nullptr; -} - -const Node *CodeMarker::nodeForString(const QString &string) -{ -#if QT_POINTER_SIZE == 4 - const quintptr n = string.toUInt(); -#else - const quintptr n = string.toULongLong(); -#endif - return reinterpret_cast(n); -} - -QString CodeMarker::stringForNode(const Node *node) -{ - return QString::number(reinterpret_cast(node)); -} - -/*! - Returns the 'extra' synopsis string for \a node with status information, - using a specified section \a style. -*/ -QString CodeMarker::extraSynopsis(const Node *node, Section::Style style) -{ - QStringList extra; - if (style == Section::Details) { - switch (node->nodeType()) { - case Node::Function: { - const auto *func = static_cast(node); - if (func->isStatic()) { - extra << "static"; - } else if (!func->isNonvirtual()) { - if (func->isFinal()) - extra << "final"; - if (func->isOverride()) - extra << "override"; - if (func->isPureVirtual()) - extra << "pure"; - extra << "virtual"; - } - - if (func->isExplicit()) extra << "explicit"; - if (func->isConstexpr()) extra << "constexpr"; - if (auto noexcept_info = func->getNoexcept()) { - extra << (QString("noexcept") + (!(*noexcept_info).isEmpty() ? "(...)" : "")); - } - - if (func->access() == Access::Protected) - extra << "protected"; - else if (func->access() == Access::Private) - extra << "private"; - - if (func->isSignal()) { - if (func->parameters().isPrivateSignal()) - extra << "private"; - extra << "signal"; - } else if (func->isSlot()) - extra << "slot"; - else if (func->isDefault()) - extra << "default"; - else if (func->isInvokable()) - extra << "invokable"; - } - break; - case Node::TypeAlias: - extra << "alias"; - break; - case Node::Property: { - auto propertyNode = static_cast(node); - if (propertyNode->propertyType() == PropertyNode::PropertyType::BindableProperty) - extra << "bindable"; - if (!propertyNode->isWritable()) - extra << "read-only"; - } - break; - default: - break; - } - } else if (style == Section::Summary) { - if (node->isPreliminary()) - extra << "preliminary"; - else if (node->isDeprecated()) { - extra << "deprecated"; - if (const QString &since = node->deprecatedSince(); !since.isEmpty()) - extra << QStringLiteral("(%1)").arg(since); - } - } - - if (style == Section::Details && !node->since().isEmpty()) { - if (!extra.isEmpty()) - extra.last() += QLatin1Char(','); - extra << "since" << node->since(); - } - - QString extraStr = extra.join(QLatin1Char(' ')); - if (!extraStr.isEmpty()) { - extraStr.prepend(style == Section::Details ? '[' : '('); - extraStr.append(style == Section::Details ? ']' : ')'); - extraStr.append(' '); - } - - return extraStr; -} - -static const QString samp = QLatin1String("&"); -static const QString slt = QLatin1String("<"); -static const QString sgt = QLatin1String(">"); -static const QString squot = QLatin1String("""); - -QString CodeMarker::protect(const QString &str) -{ - qsizetype n = str.size(); - QString marked; - marked.reserve(n * 2 + 30); - const QChar *data = str.constData(); - for (int i = 0; i != n; ++i) { - switch (data[i].unicode()) { - case '&': - marked += samp; - break; - case '<': - marked += slt; - break; - case '>': - marked += sgt; - break; - case '"': - marked += squot; - break; - default: - marked += data[i]; - } - } - return marked; -} - -void CodeMarker::appendProtectedString(QString *output, QStringView str) -{ - qsizetype n = str.size(); - output->reserve(output->size() + n * 2 + 30); - const QChar *data = str.constData(); - for (int i = 0; i != n; ++i) { - switch (data[i].unicode()) { - case '&': - *output += samp; - break; - case '<': - *output += slt; - break; - case '>': - *output += sgt; - break; - case '"': - *output += squot; - break; - default: - *output += data[i]; - } - } -} - -QString CodeMarker::typified(const QString &string, bool trailingSpace) -{ - QString result; - QString pendingWord; - - for (int i = 0; i <= string.size(); ++i) { - QChar ch; - if (i != string.size()) - ch = string.at(i); - - QChar lower = ch.toLower(); - if ((lower >= QLatin1Char('a') && lower <= QLatin1Char('z')) || ch.digitValue() >= 0 - || ch == QLatin1Char('_') || ch == QLatin1Char(':')) { - pendingWord += ch; - } else { - if (!pendingWord.isEmpty()) { - bool isProbablyType = (pendingWord != QLatin1String("const")); - if (isProbablyType) - result += QLatin1String("<@type>"); - result += pendingWord; - if (isProbablyType) - result += QLatin1String(""); - } - pendingWord.clear(); - - switch (ch.unicode()) { - case '\0': - break; - case '&': - result += QLatin1String("&"); - break; - case '<': - result += QLatin1String("<"); - break; - case '>': - result += QLatin1String(">"); - break; - default: - result += ch; - } - } - } - if (trailingSpace && string.size()) { - if (!string.endsWith(QLatin1Char('*')) && !string.endsWith(QLatin1Char('&'))) - result += QLatin1Char(' '); - } - return result; -} - -QString CodeMarker::taggedNode(const Node *node) -{ - QString tag; - const QString &name = node->name(); - - switch (node->nodeType()) { - case Node::Namespace: - tag = QLatin1String("@namespace"); - break; - case Node::Class: - case Node::Struct: - case Node::Union: - tag = QLatin1String("@class"); - break; - case Node::Enum: - tag = QLatin1String("@enum"); - break; - case Node::Typedef: - tag = QLatin1String("@typedef"); - break; - case Node::Function: - tag = QLatin1String("@function"); - break; - case Node::Property: - tag = QLatin1String("@property"); - break; - case Node::QmlType: - tag = QLatin1String("@property"); - break; - case Node::Page: - tag = QLatin1String("@property"); - break; - default: - tag = QLatin1String("@unknown"); - break; - } - return (QLatin1Char('<') + tag + QLatin1Char('>') + protect(name) + QLatin1String("')); -} - -QString CodeMarker::taggedQmlNode(const Node *node) -{ - QString tag; - if (node->isFunction()) { - const auto *fn = static_cast(node); - switch (fn->metaness()) { - case FunctionNode::QmlSignal: - tag = QLatin1String("@signal"); - break; - case FunctionNode::QmlSignalHandler: - tag = QLatin1String("@signalhandler"); - break; - case FunctionNode::QmlMethod: - tag = QLatin1String("@method"); - break; - default: - tag = QLatin1String("@unknown"); - break; - } - } else if (node->isQmlProperty()) { - tag = QLatin1String("@property"); - } else { - tag = QLatin1String("@unknown"); - } - return QLatin1Char('<') + tag + QLatin1Char('>') + protect(node->name()) + QLatin1String("'); -} - -QString CodeMarker::linkTag(const Node *node, const QString &body) -{ - return QLatin1String("<@link node=\"") + stringForNode(node) + QLatin1String("\">") + body - + QLatin1String(""); -} - -QT_END_NAMESPACE diff --git a/src/qdoc/codemarker.h b/src/qdoc/codemarker.h deleted file mode 100644 index af668b650..000000000 --- a/src/qdoc/codemarker.h +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CODEMARKER_H -#define CODEMARKER_H - -#include "atom.h" -#include "sections.h" - -QT_BEGIN_NAMESPACE - -class CodeMarker -{ -public: - CodeMarker(); - virtual ~CodeMarker(); - - virtual void initializeMarker(); - virtual void terminateMarker(); - virtual bool recognizeCode(const QString & /*code*/) { return true; } - virtual bool recognizeExtension(const QString & /*extension*/) { return true; } - virtual bool recognizeLanguage(const QString & /*language*/) { return false; } - [[nodiscard]] virtual Atom::AtomType atomType() const { return Atom::Code; } - virtual QString markedUpCode(const QString &code, const Node * /*relative*/, - const Location & /*location*/) - { - return protect(code); - } - virtual QString markedUpSynopsis(const Node * /*node*/, const Node * /*relative*/, - Section::Style /*style*/) - { - return QString(); - } - virtual QString markedUpQmlItem(const Node *, bool) { return QString(); } - virtual QString markedUpName(const Node * /*node*/) { return QString(); } - virtual QString markedUpEnumValue(const QString & /*enumValue*/, const Node * /*relative*/) - { - return QString(); - } - virtual QString markedUpInclude(const QString & /*include*/) { return QString(); } - - static void initialize(); - static void terminate(); - static CodeMarker *markerForCode(const QString &code); - static CodeMarker *markerForFileName(const QString &fileName); - static CodeMarker *markerForLanguage(const QString &lang); - static const Node *nodeForString(const QString &string); - static QString stringForNode(const Node *node); - static QString extraSynopsis(const Node *node, Section::Style style); - - QString typified(const QString &string, bool trailingSpace = false); - -protected: - static QString protect(const QString &string); - static void appendProtectedString(QString *output, QStringView str); - QString taggedNode(const Node *node); - QString taggedQmlNode(const Node *node); - QString linkTag(const Node *node, const QString &body); - -private: - static QString s_defaultLang; - static QList s_markers; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/codeparser.cpp b/src/qdoc/codeparser.cpp deleted file mode 100644 index ad35e6d65..000000000 --- a/src/qdoc/codeparser.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "codeparser.h" - -#include "config.h" -#include "generator.h" -#include "node.h" -#include "qdocdatabase.h" - -#include - -QT_BEGIN_NAMESPACE - -QList CodeParser::s_parsers; - -/*! - The constructor adds this code parser to the static - list of code parsers. - */ -CodeParser::CodeParser() -{ - m_qdb = QDocDatabase::qdocDB(); - s_parsers.prepend(this); -} - -/*! - The destructor removes this code parser from the static - list of code parsers. - */ -CodeParser::~CodeParser() -{ - s_parsers.removeAll(this); -} - -/*! - Terminating a code parser is trivial. - */ -void CodeParser::terminateParser() -{ - // nothing. -} - -/*! - All the code parsers in the static list are initialized here, - after the qdoc configuration variables have been set. - */ -void CodeParser::initialize() -{ - for (const auto &parser : std::as_const(s_parsers)) - parser->initializeParser(); -} - -/*! - All the code parsers in the static list are terminated here. - */ -void CodeParser::terminate() -{ - for (const auto parser : s_parsers) - parser->terminateParser(); -} - -CodeParser *CodeParser::parserForLanguage(const QString &language) -{ - for (const auto parser : std::as_const(s_parsers)) { - if (parser->language() == language) - return parser; - } - return nullptr; -} - -CodeParser *CodeParser::parserForSourceFile(const QString &filePath) -{ - QString fileName = QFileInfo(filePath).fileName(); - - for (const auto &parser : s_parsers) { - const QStringList sourcePatterns = parser->sourceFileNameFilter(); - for (const QString &pattern : sourcePatterns) { - auto re = QRegularExpression::fromWildcard(pattern, Qt::CaseInsensitive); - if (re.match(fileName).hasMatch()) - return parser; - } - } - return nullptr; -} - -/*! - \internal - */ -void CodeParser::extractPageLinkAndDesc(QStringView arg, QString *link, QString *desc) -{ - static const QRegularExpression bracedRegExp( - QRegularExpression::anchoredPattern(QLatin1String(R"(\{([^{}]*)\}(?:\{([^{}]*)\})?)"))); - auto match = bracedRegExp.matchView(arg); - if (match.hasMatch()) { - *link = match.captured(1); - *desc = match.captured(2); - if (desc->isEmpty()) - *desc = *link; - } else { - qsizetype spaceAt = arg.indexOf(QLatin1Char(' ')); - if (arg.contains(QLatin1String(".html")) && spaceAt != -1) { - *link = arg.left(spaceAt).trimmed().toString(); - *desc = arg.mid(spaceAt).trimmed().toString(); - } else { - *link = arg.toString(); - *desc = *link; - } - } -} - -/*! - \internal - */ -void CodeParser::setLink(Node *node, Node::LinkType linkType, const QString &arg) -{ - QString link; - QString desc; - extractPageLinkAndDesc(arg, &link, &desc); - node->setLink(linkType, link, desc); -} - -/*! - \brief Test for whether a doc comment warrants warnings. - - Returns true if qdoc should report that it has found something - wrong with the qdoc comment in \a doc. Sometimes, qdoc should - not report the warning, for example, when the comment contains - the \c internal command, which normally means qdoc will not use - the comment in the documentation anyway, so there is no point - in reporting warnings about it. - */ -bool CodeParser::isWorthWarningAbout(const Doc &doc) -{ - return (Config::instance().showInternal() - || !doc.metaCommandsUsed().contains(QStringLiteral("internal"))); -} - -QT_END_NAMESPACE diff --git a/src/qdoc/codeparser.h b/src/qdoc/codeparser.h deleted file mode 100644 index 7282988f4..000000000 --- a/src/qdoc/codeparser.h +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CODEPARSER_H -#define CODEPARSER_H - -#include "node.h" - -#include - -QT_BEGIN_NAMESPACE - -#define COMMAND_ABSTRACT QLatin1String("abstract") -#define COMMAND_CLASS QLatin1String("class") -#define COMMAND_DEFAULT QLatin1String("default") -#define COMMAND_DEPRECATED QLatin1String("deprecated") // ### don't document -#define COMMAND_DONTDOCUMENT QLatin1String("dontdocument") -#define COMMAND_ENUM QLatin1String("enum") -#define COMMAND_EXAMPLE QLatin1String("example") -#define COMMAND_EXTERNALPAGE QLatin1String("externalpage") -#define COMMAND_FN QLatin1String("fn") -#define COMMAND_GROUP QLatin1String("group") -#define COMMAND_HEADERFILE QLatin1String("headerfile") -#define COMMAND_INGROUP QLatin1String("ingroup") -#define COMMAND_INHEADERFILE QLatin1String("inheaderfile") -#define COMMAND_INMODULE QLatin1String("inmodule") // ### don't document -#define COMMAND_INPUBLICGROUP QLatin1String("inpublicgroup") -#define COMMAND_INQMLMODULE QLatin1String("inqmlmodule") -#define COMMAND_INTERNAL QLatin1String("internal") -#define COMMAND_MACRO QLatin1String("macro") -#define COMMAND_MODULE QLatin1String("module") -#define COMMAND_MODULESTATE QLatin1String("modulestate") -#define COMMAND_NAMESPACE QLatin1String("namespace") -#define COMMAND_NEXTPAGE QLatin1String("nextpage") -#define COMMAND_NOAUTOLIST QLatin1String("noautolist") -#define COMMAND_NONREENTRANT QLatin1String("nonreentrant") -#define COMMAND_OBSOLETE QLatin1String("obsolete") -#define COMMAND_OVERLOAD QLatin1String("overload") -#define COMMAND_PAGE QLatin1String("page") -#define COMMAND_PRELIMINARY QLatin1String("preliminary") -#define COMMAND_PREVIOUSPAGE QLatin1String("previouspage") -#define COMMAND_PROPERTY QLatin1String("property") -#define COMMAND_QMLABSTRACT QLatin1String("qmlabstract") -#define COMMAND_QMLATTACHEDMETHOD QLatin1String("qmlattachedmethod") -#define COMMAND_QMLATTACHEDPROPERTY QLatin1String("qmlattachedproperty") -#define COMMAND_QMLATTACHEDSIGNAL QLatin1String("qmlattachedsignal") -#define COMMAND_QMLVALUETYPE QLatin1String("qmlvaluetype") -#define COMMAND_QMLCLASS QLatin1String("qmlclass") -#define COMMAND_QMLDEFAULT QLatin1String("qmldefault") -#define COMMAND_QMLINHERITS QLatin1String("inherits") -#define COMMAND_QMLINSTANTIATES QLatin1String("instantiates") -#define COMMAND_QMLMETHOD QLatin1String("qmlmethod") -#define COMMAND_QMLMODULE QLatin1String("qmlmodule") -#define COMMAND_QMLPROPERTY QLatin1String("qmlproperty") -#define COMMAND_QMLPROPERTYGROUP QLatin1String("qmlpropertygroup") -#define COMMAND_QMLREADONLY QLatin1String("readonly") -#define COMMAND_QMLREQUIRED QLatin1String("required") -#define COMMAND_QMLSIGNAL QLatin1String("qmlsignal") -#define COMMAND_QMLTYPE QLatin1String("qmltype") -#define COMMAND_QTCMAKEPACKAGE QLatin1String("qtcmakepackage") -#define COMMAND_QTVARIABLE QLatin1String("qtvariable") -#define COMMAND_REENTRANT QLatin1String("reentrant") -#define COMMAND_REIMP QLatin1String("reimp") -#define COMMAND_RELATES QLatin1String("relates") -#define COMMAND_SINCE QLatin1String("since") -#define COMMAND_STRUCT QLatin1String("struct") -#define COMMAND_SUBTITLE QLatin1String("subtitle") -#define COMMAND_STARTPAGE QLatin1String("startpage") -#define COMMAND_THREADSAFE QLatin1String("threadsafe") -#define COMMAND_TITLE QLatin1String("title") -#define COMMAND_TYPEALIAS QLatin1String("typealias") -#define COMMAND_TYPEDEF QLatin1String("typedef") -#define COMMAND_VARIABLE QLatin1String("variable") -#define COMMAND_VERSION QLatin1String("version") -#define COMMAND_UNION QLatin1String("union") -#define COMMAND_WRAPPER QLatin1String("wrapper") -#define COMMAND_ATTRIBUTION QLatin1String("attribution") - -// deprecated alias of qmlvaluetype -#define COMMAND_QMLBASICTYPE QLatin1String("qmlbasictype") - -class Location; -class QString; -class QDocDatabase; -class CppCodeParser; - -class CodeParser -{ -public: - static inline const QSet common_meta_commands{ - COMMAND_ABSTRACT, COMMAND_DEFAULT, COMMAND_DEPRECATED, COMMAND_INGROUP, - COMMAND_INMODULE, COMMAND_INPUBLICGROUP, COMMAND_INQMLMODULE, COMMAND_INTERNAL, - COMMAND_MODULESTATE, COMMAND_NOAUTOLIST, COMMAND_NONREENTRANT, COMMAND_OBSOLETE, - COMMAND_PRELIMINARY, COMMAND_QMLABSTRACT, COMMAND_QMLDEFAULT, COMMAND_QMLINHERITS, - COMMAND_QMLREADONLY, COMMAND_QMLREQUIRED, COMMAND_QTCMAKEPACKAGE, COMMAND_QTVARIABLE, - COMMAND_REENTRANT, COMMAND_SINCE, COMMAND_STARTPAGE, COMMAND_SUBTITLE, COMMAND_THREADSAFE, - COMMAND_TITLE, COMMAND_WRAPPER, COMMAND_ATTRIBUTION, - }; - -public: - CodeParser(); - virtual ~CodeParser(); - - virtual void initializeParser() = 0; - virtual void terminateParser(); - virtual QString language() = 0; - virtual QStringList sourceFileNameFilter() = 0; - virtual void parseSourceFile(const Location &location, const QString &filePath, CppCodeParser& cpp_code_parser) = 0; - virtual Node *parseFnArg(const Location &, const QString &, const QString & = QString()) - { - return nullptr; - } - - static void initialize(); - static void terminate(); - static CodeParser *parserForLanguage(const QString &language); - static CodeParser *parserForSourceFile(const QString &filePath); - static void setLink(Node *node, Node::LinkType linkType, const QString &arg); - static bool isWorthWarningAbout(const Doc &doc); - -protected: - static void extractPageLinkAndDesc(QStringView arg, QString *link, QString *desc); - QDocDatabase *m_qdb {}; - -private: - static QList s_parsers; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/collectionnode.cpp b/src/qdoc/collectionnode.cpp deleted file mode 100644 index 12b9214ab..000000000 --- a/src/qdoc/collectionnode.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "collectionnode.h" - -#include - -QT_BEGIN_NAMESPACE - -/*! - \class CollectionNode - \brief A class for holding the members of a collection of doc pages. - */ - -/*! - Appends \a node to the collection node's member list, if - and only if it isn't already in the member list. - */ -void CollectionNode::addMember(Node *node) -{ - if (!m_members.contains(node)) - m_members.append(node); -} - -/*! - Returns \c true if this collection node contains at least - one namespace node. - */ -bool CollectionNode::hasNamespaces() const -{ - return std::any_of(m_members.cbegin(), m_members.cend(), [](const Node *member) { - return member->isClassNode() && member->isInAPI(); - }); -} - -/*! - Returns \c true if this collection node contains at least - one class node. - */ -bool CollectionNode::hasClasses() const -{ - return std::any_of(m_members.cbegin(), m_members.cend(), [](const Node *member) { - return member->isClassNode() && member->isInAPI(); - }); -} - -/*! - Loads \a out with all this collection node's members that - are namespace nodes. - */ -void CollectionNode::getMemberNamespaces(NodeMap &out) -{ - out.clear(); - for (const auto &member : std::as_const(m_members)) { - if (member->isNamespace() && member->isInAPI()) - out.insert(member->name(), member); - } -} - -/*! - Loads \a out with all this collection node's members that - are class nodes. - */ -void CollectionNode::getMemberClasses(NodeMap &out) const -{ - out.clear(); - for (const auto &member : std::as_const(m_members)) { - if (member->isClassNode() && member->isInAPI()) - out.insert(member->name(), member); - } -} - -/*! - Returns the logical module version. -*/ -QString CollectionNode::logicalModuleVersion() const -{ - QStringList version; - version << m_logicalModuleVersionMajor << m_logicalModuleVersionMinor; - version.removeAll(QString()); - return version.join("."); -} - -/*! - This function accepts the logical module \a info as a string - list. If the logical module info contains the version number, - it splits the version number on the '.' character to get the - major and minor version numbers. Both major and minor version - numbers should be provided, but the minor version number is - not strictly necessary. - */ -void CollectionNode::setLogicalModuleInfo(const QStringList &info) -{ - m_logicalModuleName = info[0]; - if (info.size() > 1) { - QStringList dotSplit = info[1].split(QLatin1Char('.')); - m_logicalModuleVersionMajor = dotSplit[0]; - if (dotSplit.size() > 1) - m_logicalModuleVersionMinor = dotSplit[1]; - else - m_logicalModuleVersionMinor = "0"; - } -} - -/*! - \fn void CollectionNode::setState(const QString &state) - \fn QString CollectionNode::state() - - Sets or gets a description of this module's state. For example, - \e {"Technical Preview"}. This string is used when generating the - module's documentation page and reference pages of the module's - members. -*/ - -QT_END_NAMESPACE diff --git a/src/qdoc/collectionnode.h b/src/qdoc/collectionnode.h deleted file mode 100644 index 88abf43b6..000000000 --- a/src/qdoc/collectionnode.h +++ /dev/null @@ -1,107 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef COLLECTIONNODE_H -#define COLLECTIONNODE_H - -#include "pagenode.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -class CollectionNode : public PageNode -{ -public: - CollectionNode(NodeType type, Aggregate *parent, const QString &name) - : PageNode(type, parent, name) - { - } - - [[nodiscard]] bool isCollectionNode() const override { return true; } - [[nodiscard]] QString qtVariable() const override { return m_qtVariable; } - void setQtVariable(const QString &v) override { m_qtVariable = v; } - [[nodiscard]] QString qtCMakeComponent() const override { return m_qtCMakeComponent; } - void setQtCMakeComponent(const QString &target) override { m_qtCMakeComponent = target; } - void addMember(Node *node) override; - [[nodiscard]] bool hasNamespaces() const override; - [[nodiscard]] bool hasClasses() const override; - void getMemberNamespaces(NodeMap &out); - void getMemberClasses(NodeMap &out) const; - [[nodiscard]] bool wasSeen() const override { return m_seen; } - - [[nodiscard]] QString fullTitle() const override { return title(); } - [[nodiscard]] QString logicalModuleName() const override { return m_logicalModuleName; } - [[nodiscard]] QString logicalModuleVersion() const override; - [[nodiscard]] QString logicalModuleIdentifier() const override - { - return m_logicalModuleName + m_logicalModuleVersionMajor; - } - [[nodiscard]] QString state() const { return m_state; } - - void setLogicalModuleInfo(const QStringList &info) override; - void setState(const QString &state) { m_state = state; } - - // REMARK: Those methods are used by QDocDatabase as a performance - // detail to avoid merging a collection node multiple times. They - // should not be addressed in any other part of the code nor - // should their usage appear more than once in QDocDatabase, - // albeit this is not enforced. - // More information are provided in the comment for the definition - // of m_merged. - void markMerged() { m_merged = true; } - bool isMerged() { return m_merged; } - - [[nodiscard]] const NodeList &members() const { return m_members; } - - void markSeen() { m_seen = true; } - void markNotSeen() { m_seen = false; } - -private: - bool m_seen { false }; - // REMARK: This is set by the database when merging the collection - // node and is later used to avoid merging the same collection - // multiple times. - // Currently, collection nodes may come from multiple projects, - // such that to have a complete overview of the members of a - // collection we need to rejoin all members for all instances of - // the "same" collection. - // This is done in QDocDatabase, generally through an external - // method call that is done ad-hoc when a source-of-truth - // collection node is needed. - // As each part of the code that need such a source-of-truth will - // need to merge the node, to avoid the overhead of a relatively - // expensive operation being performed multiple times, we expose - // this detail so that QDocDatabase can avoid performing the - // operation again. - // To avoid the coupling, QDocDatabase could keep track of the - // merged nodes itself, this is a bit less trivial that this - // implementation and doesn't address the source of the problem - // (the multiple merges themselves and the sequencing of the - // related operations) and as such was discarded in favor of this - // simpler implementation. - // Do note that outside the very specific purpose for which this - // member was made, no part of the code should refer to it and its - // associated methods. - // Should this start to be the case, we can switch to the more - // complex encapsulation into QDocDatabase without having to touch - // the outside user of the merges. - // Further down the line, this is expected to go away completely - // as other part of the code are streamlined. - // KLUDGE: Note that this whole exposure is done as a hackish - // solution to QTBUG-104237 and should not be considered final or - // dependable. - bool m_merged { false }; - NodeList m_members {}; - QString m_logicalModuleName {}; - QString m_logicalModuleVersionMajor {}; - QString m_logicalModuleVersionMinor {}; - QString m_qtVariable {}; - QString m_qtCMakeComponent {}; - QString m_state {}; -}; - -QT_END_NAMESPACE - -#endif // COLLECTIONNODE_H diff --git a/src/qdoc/config.cpp b/src/qdoc/config.cpp deleted file mode 100644 index 5b7f9e98f..000000000 --- a/src/qdoc/config.cpp +++ /dev/null @@ -1,1401 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "config.h" -#include "utilities.h" - -#include -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -QString ConfigStrings::AUTOLINKERRORS = QStringLiteral("autolinkerrors"); -QString ConfigStrings::BUILDVERSION = QStringLiteral("buildversion"); -QString ConfigStrings::CLANGDEFINES = QStringLiteral("clangdefines"); -QString ConfigStrings::CODEINDENT = QStringLiteral("codeindent"); -QString ConfigStrings::CODEPREFIX = QStringLiteral("codeprefix"); -QString ConfigStrings::CODESUFFIX = QStringLiteral("codesuffix"); -QString ConfigStrings::CPPCLASSESPAGE = QStringLiteral("cppclassespage"); -QString ConfigStrings::CPPCLASSESTITLE = QStringLiteral("cppclassestitle"); -QString ConfigStrings::DEFINES = QStringLiteral("defines"); -QString ConfigStrings::DEPENDS = QStringLiteral("depends"); -QString ConfigStrings::DESCRIPTION = QStringLiteral("description"); -QString ConfigStrings::DOCBOOKEXTENSIONS = QStringLiteral("usedocbookextensions"); -QString ConfigStrings::ENDHEADER = QStringLiteral("endheader"); -QString ConfigStrings::EXAMPLEDIRS = QStringLiteral("exampledirs"); -QString ConfigStrings::EXAMPLES = QStringLiteral("examples"); -QString ConfigStrings::EXAMPLESINSTALLPATH = QStringLiteral("examplesinstallpath"); -QString ConfigStrings::EXCLUDEDIRS = QStringLiteral("excludedirs"); -QString ConfigStrings::EXCLUDEFILES = QStringLiteral("excludefiles"); -QString ConfigStrings::EXTRAIMAGES = QStringLiteral("extraimages"); -QString ConfigStrings::FALSEHOODS = QStringLiteral("falsehoods"); -QString ConfigStrings::FORMATTING = QStringLiteral("formatting"); -QString ConfigStrings::HEADERDIRS = QStringLiteral("headerdirs"); -QString ConfigStrings::HEADERS = QStringLiteral("headers"); -QString ConfigStrings::HEADERSCRIPTS = QStringLiteral("headerscripts"); -QString ConfigStrings::HEADERSTYLES = QStringLiteral("headerstyles"); -QString ConfigStrings::HOMEPAGE = QStringLiteral("homepage"); -QString ConfigStrings::HOMETITLE = QStringLiteral("hometitle"); -QString ConfigStrings::IGNOREDIRECTIVES = QStringLiteral("ignoredirectives"); -QString ConfigStrings::IGNORESINCE = QStringLiteral("ignoresince"); -QString ConfigStrings::IGNORETOKENS = QStringLiteral("ignoretokens"); -QString ConfigStrings::IGNOREWORDS = QStringLiteral("ignorewords"); -QString ConfigStrings::IMAGEDIRS = QStringLiteral("imagedirs"); -QString ConfigStrings::IMAGES = QStringLiteral("images"); -QString ConfigStrings::INCLUDEPATHS = QStringLiteral("includepaths"); -QString ConfigStrings::INCLUSIVE = QStringLiteral("inclusive"); -QString ConfigStrings::INDEXES = QStringLiteral("indexes"); -QString ConfigStrings::LANDINGPAGE = QStringLiteral("landingpage"); -QString ConfigStrings::LANDINGTITLE = QStringLiteral("landingtitle"); -QString ConfigStrings::LANGUAGE = QStringLiteral("language"); -QString ConfigStrings::LOCATIONINFO = QStringLiteral("locationinfo"); -QString ConfigStrings::LOGPROGRESS = QStringLiteral("logprogress"); -QString ConfigStrings::MACRO = QStringLiteral("macro"); -QString ConfigStrings::MANIFESTMETA = QStringLiteral("manifestmeta"); -QString ConfigStrings::MODULEHEADER = QStringLiteral("moduleheader"); -QString ConfigStrings::NATURALLANGUAGE = QStringLiteral("naturallanguage"); -QString ConfigStrings::NAVIGATION = QStringLiteral("navigation"); -QString ConfigStrings::NOLINKERRORS = QStringLiteral("nolinkerrors"); -QString ConfigStrings::OUTPUTDIR = QStringLiteral("outputdir"); -QString ConfigStrings::OUTPUTFORMATS = QStringLiteral("outputformats"); -QString ConfigStrings::OUTPUTPREFIXES = QStringLiteral("outputprefixes"); -QString ConfigStrings::OUTPUTSUFFIXES = QStringLiteral("outputsuffixes"); -QString ConfigStrings::PROJECT = QStringLiteral("project"); -QString ConfigStrings::REDIRECTDOCUMENTATIONTODEVNULL = - QStringLiteral("redirectdocumentationtodevnull"); -QString ConfigStrings::QHP = QStringLiteral("qhp"); -QString ConfigStrings::QUOTINGINFORMATION = QStringLiteral("quotinginformation"); -QString ConfigStrings::SCRIPTS = QStringLiteral("scripts"); -QString ConfigStrings::SHOWINTERNAL = QStringLiteral("showinternal"); -QString ConfigStrings::SINGLEEXEC = QStringLiteral("singleexec"); -QString ConfigStrings::SOURCEDIRS = QStringLiteral("sourcedirs"); -QString ConfigStrings::SOURCEENCODING = QStringLiteral("sourceencoding"); -QString ConfigStrings::SOURCES = QStringLiteral("sources"); -QString ConfigStrings::SPURIOUS = QStringLiteral("spurious"); -QString ConfigStrings::STYLESHEETS = QStringLiteral("stylesheets"); -QString ConfigStrings::SYNTAXHIGHLIGHTING = QStringLiteral("syntaxhighlighting"); -QString ConfigStrings::TABSIZE = QStringLiteral("tabsize"); -QString ConfigStrings::TAGFILE = QStringLiteral("tagfile"); -QString ConfigStrings::TIMESTAMPS = QStringLiteral("timestamps"); -QString ConfigStrings::TOCTITLES = QStringLiteral("toctitles"); -QString ConfigStrings::URL = QStringLiteral("url"); -QString ConfigStrings::VERSION = QStringLiteral("version"); -QString ConfigStrings::VERSIONSYM = QStringLiteral("versionsym"); -QString ConfigStrings::FILEEXTENSIONS = QStringLiteral("fileextensions"); -QString ConfigStrings::IMAGEEXTENSIONS = QStringLiteral("imageextensions"); -QString ConfigStrings::QMLTYPESPAGE = QStringLiteral("qmltypespage"); -QString ConfigStrings::QMLTYPESTITLE = QStringLiteral("qmltypestitle"); -QString ConfigStrings::WARNINGLIMIT = QStringLiteral("warninglimit"); - -/*! - An entry in a stack, where each entry is a list - of string values. - */ -class MetaStackEntry -{ -public: - void open(); - void close(); - - QStringList accum; - QStringList next; -}; -Q_DECLARE_TYPEINFO(MetaStackEntry, Q_RELOCATABLE_TYPE); - -/*! - Start accumulating values in a list by appending an empty - string to the list. - */ -void MetaStackEntry::open() -{ - next.append(QString()); -} - -/*! - Stop accumulating values and append the list of accumulated - values to the complete list of accumulated values. - - */ -void MetaStackEntry::close() -{ - accum += next; - next.clear(); -} - -/*! - \class MetaStack - - This class maintains a stack of values of config file variables. -*/ -class MetaStack : private QStack -{ -public: - MetaStack(); - - void process(QChar ch, const Location &location); - QStringList getExpanded(const Location &location); -}; - -/*! - The default constructor pushes a new stack entry and - opens it. - */ -MetaStack::MetaStack() -{ - push(MetaStackEntry()); - top().open(); -} - -/*! - Processes the character \a ch using the \a location. - It really just builds up a name by appending \a ch to - it. - */ -void MetaStack::process(QChar ch, const Location &location) -{ - if (ch == QLatin1Char('{')) { - push(MetaStackEntry()); - top().open(); - } else if (ch == QLatin1Char('}')) { - if (size() == 1) - location.fatal(QStringLiteral("Unexpected '}'")); - - top().close(); - const QStringList suffixes = pop().accum; - const QStringList prefixes = top().next; - - top().next.clear(); - for (const auto &prefix : prefixes) { - for (const auto &suffix : suffixes) - top().next << prefix + suffix; - } - } else if (ch == QLatin1Char(',') && size() > 1) { - top().close(); - top().open(); - } else { - for (QString &topNext : top().next) - topNext += ch; - } -} - -/*! - Returns the accumulated string values. - */ -QStringList MetaStack::getExpanded(const Location &location) -{ - if (size() > 1) - location.fatal(QStringLiteral("Missing '}'")); - - top().close(); - return top().accum; -} - -const QString Config::dot = QLatin1String("."); -bool Config::m_debug = false; -bool Config::m_atomsDump = false; -bool Config::generateExamples = true; -QString Config::overrideOutputDir; -QString Config::installDir; -QSet Config::overrideOutputFormats; -QMap Config::m_extractedDirs; -QStack Config::m_workingDirs; -QMap Config::m_includeFilesMap; - -/*! - \class ConfigVar - \brief contains all the information for a single config variable in a - .qdocconf file. -*/ - -/*! - Returns this configuration variable as a string. - - If the variable is not defined, returns \a defaultString. - - \note By default, \a defaultString is a null string. - This allows determining whether a configuration variable is - undefined (returns a null string) or defined as empty - (returns a non-null, empty string). -*/ -QString ConfigVar::asString(const QString defaultString) const -{ - if (m_name.isEmpty()) - return defaultString; - - QString result(""); // an empty but non-null string - for (const auto &value : std::as_const(m_values)) { - if (!result.isEmpty() && !result.endsWith(QChar('\n'))) - result.append(QChar(' ')); - result.append(value.m_value); - } - return result; -} - -/*! - Returns this config variable as a string list. -*/ -QStringList ConfigVar::asStringList() const -{ - QStringList result; - for (const auto &value : std::as_const(m_values)) - result << value.m_value; - return result; -} - -/*! - Returns this config variable as a string set. -*/ -QSet ConfigVar::asStringSet() const -{ - const auto &stringList = asStringList(); - return QSet(stringList.cbegin(), stringList.cend()); -} - -/*! - Returns this config variable as a boolean. -*/ -bool ConfigVar::asBool() const -{ - return QVariant(asString()).toBool(); -} - -/*! - Returns this configuration variable as an integer; iterates - through the string list, interpreting each - string in the list as an integer and adding it to a total sum. - - Returns 0 if this variable is defined as empty, and - -1 if it's is not defined. - */ -int ConfigVar::asInt() const -{ - const QStringList strs = asStringList(); - if (strs.isEmpty()) - return -1; - - int sum = 0; - for (const auto &str : strs) - sum += str.toInt(); - return sum; -} - -/*! - Appends values to this ConfigVar, and adjusts the ExpandVar - parameters so that they continue to refer to the correct values. -*/ -void ConfigVar::append(const ConfigVar &other) -{ - m_expandVars << other.m_expandVars; - QList::Iterator it = m_expandVars.end(); - it -= other.m_expandVars.size(); - std::for_each(it, m_expandVars.end(), [this](ExpandVar &v) { - v.m_valueIndex += m_values.size(); - }); - m_values << other.m_values; - m_location = other.m_location; -} - -/*! - \class Config - \brief The Config class contains the configuration variables - for controlling how qdoc produces documentation. - - Its load() function reads, parses, and processes a qdocconf file. - */ - -/*! - \enum Config::PathFlags - - Flags used for retrieving canonicalized paths from Config. - - \value Validate - Issue a warning for paths that do not exist and - remove them from the returned list. - - \value IncludePaths - Assume the variable contains include paths with - prefixes such as \c{-I} that are to be removed - before canonicalizing and then re-inserted. - - \omitvalue None - - \sa getCanonicalPathList() -*/ - -/*! - Initializes the Config with \a programName and sets all - internal state variables to either default values or to ones - defined in command line arguments \a args. - */ -void Config::init(const QString &programName, const QStringList &args) -{ - m_prog = programName; - processCommandLineOptions(args); - reset(); -} - -Config::~Config() -{ - clear(); -} - -/*! - Clears the location and internal maps for config variables. - */ -void Config::clear() -{ - m_location = Location(); - m_configVars.clear(); - m_includeFilesMap.clear(); -} - -/*! - Resets the Config instance - used by load() - */ -void Config::reset() -{ - clear(); - - // Default values - setStringList(CONFIG_CODEINDENT, QStringList("0")); - setStringList(CONFIG_FALSEHOODS, QStringList("0")); - setStringList(CONFIG_HEADERS + dot + CONFIG_FILEEXTENSIONS, QStringList("*.ch *.h *.h++ *.hh *.hpp *.hxx")); - setStringList(CONFIG_SOURCES + dot + CONFIG_FILEEXTENSIONS, QStringList("*.c++ *.cc *.cpp *.cxx *.mm *.qml *.qdoc")); - setStringList(CONFIG_LANGUAGE, QStringList("Cpp")); // i.e. C++ - setStringList(CONFIG_OUTPUTFORMATS, QStringList("HTML")); - setStringList(CONFIG_TABSIZE, QStringList("8")); - setStringList(CONFIG_LOCATIONINFO, QStringList("true")); - - // Publish options from the command line as config variables - const auto setListFlag = [this](const QString &key, bool test) { - setStringList(key, QStringList(test ? QStringLiteral("true") : QStringLiteral("false"))); - }; -#define SET(opt, test) setListFlag(opt, m_parser.isSet(m_parser.test)) - SET(CONFIG_SYNTAXHIGHLIGHTING, highlightingOption); - SET(CONFIG_SHOWINTERNAL, showInternalOption); - SET(CONFIG_SINGLEEXEC, singleExecOption); - SET(CONFIG_REDIRECTDOCUMENTATIONTODEVNULL, redirectDocumentationToDevNullOption); - SET(CONFIG_AUTOLINKERRORS, autoLinkErrorsOption); -#undef SET - m_showInternal = m_configVars.value(CONFIG_SHOWINTERNAL).asBool(); - setListFlag(CONFIG_NOLINKERRORS, - m_parser.isSet(m_parser.noLinkErrorsOption) - || qEnvironmentVariableIsSet("QDOC_NOLINKERRORS")); - - // CONFIG_DEFINES and CONFIG_INCLUDEPATHS are set in load() -} - -/*! - Loads and parses the qdoc configuration file \a fileName. - If a previous project was loaded, this function first resets the - Config instance. Then it calls the other load() function, which - does the loading, parsing, and processing of the configuration file. - */ -void Config::load(const QString &fileName) -{ - // Reset if a previous project was loaded - if (m_configVars.contains(CONFIG_PROJECT)) - reset(); - - load(Location(), fileName); - if (m_location.isEmpty()) - m_location = Location(fileName); - else - m_location.setEtc(true); - - expandVariables(); - - // Add defines and includepaths from command line to their - // respective configuration variables. Values set here are - // always added to what's defined in configuration file. - insertStringList(CONFIG_DEFINES, m_defines); - insertStringList(CONFIG_INCLUDEPATHS, m_includePaths); - - // Prefetch values that are used internally - m_exampleFiles = getCanonicalPathList(CONFIG_EXAMPLES); - m_exampleDirs = getCanonicalPathList(CONFIG_EXAMPLEDIRS); -} - -/*! - Expands other config variables referred to in all stored ConfigVars. -*/ -void Config::expandVariables() -{ - for (auto &configVar : m_configVars) { - for (auto it = configVar.m_expandVars.crbegin(); it != configVar.m_expandVars.crend(); ++it) { - Q_ASSERT(it->m_valueIndex < configVar.m_values.size()); - const QString &key = it->m_var; - const auto &refVar = m_configVars.value(key); - if (refVar.m_name.isEmpty()) { - configVar.m_location.fatal( - QStringLiteral("Environment or configuration variable '%1' undefined") - .arg(it->m_var)); - } else if (!refVar.m_expandVars.empty()) { - configVar.m_location.fatal( - QStringLiteral("Nested variable expansion not allowed"), - QStringLiteral("When expanding '%1' at %2:%3") - .arg(refVar.m_name, refVar.m_location.filePath(), - QString::number(refVar.m_location.lineNo()))); - } - QString expanded; - if (it->m_delim.isNull()) - expanded = m_configVars.value(key).asStringList().join(QString()); - else - expanded = m_configVars.value(key).asStringList().join(it->m_delim); - configVar.m_values[it->m_valueIndex].m_value.insert(it->m_index, expanded); - } - configVar.m_expandVars.clear(); - } -} - -/*! - Sets the \a values of a configuration variable \a var from a string list. - */ -void Config::setStringList(const QString &var, const QStringList &values) -{ - m_configVars.insert(var, ConfigVar(var, values, QDir::currentPath())); -} - -/*! - Adds the \a values from a string list to the configuration variable \a var. - Existing value(s) are kept. -*/ -void Config::insertStringList(const QString &var, const QStringList &values) -{ - m_configVars[var].append(ConfigVar(var, values, QDir::currentPath())); -} - -/*! - Process and store variables from the command line. - */ -void Config::processCommandLineOptions(const QStringList &args) -{ - m_parser.process(args); - - m_defines = m_parser.values(m_parser.defineOption); - m_dependModules = m_parser.values(m_parser.dependsOption); - setIndexDirs(); - setIncludePaths(); - - generateExamples = !m_parser.isSet(m_parser.noExamplesOption); - if (m_parser.isSet(m_parser.installDirOption)) - installDir = m_parser.value(m_parser.installDirOption); - if (m_parser.isSet(m_parser.outputDirOption)) - overrideOutputDir = m_parser.value(m_parser.outputDirOption); - - const auto outputFormats = m_parser.values(m_parser.outputFormatOption); - for (const auto &format : outputFormats) - overrideOutputFormats.insert(format); - m_debug = m_parser.isSet(m_parser.debugOption) || qEnvironmentVariableIsSet("QDOC_DEBUG"); - m_atomsDump = m_parser.isSet(m_parser.atomsDumpOption); - m_showInternal = m_parser.isSet(m_parser.showInternalOption) - || qEnvironmentVariableIsSet("QDOC_SHOW_INTERNAL"); - - if (m_parser.isSet(m_parser.prepareOption)) - m_qdocPass = Prepare; - if (m_parser.isSet(m_parser.generateOption)) - m_qdocPass = Generate; - if (m_debug || m_parser.isSet(m_parser.logProgressOption)) - setStringList(CONFIG_LOGPROGRESS, QStringList("true")); - if (m_parser.isSet(m_parser.timestampsOption)) - setStringList(CONFIG_TIMESTAMPS, QStringList("true")); - if (m_parser.isSet(m_parser.useDocBookExtensions)) - setStringList(CONFIG_DOCBOOKEXTENSIONS, QStringList("true")); -} - -void Config::setIncludePaths() -{ - QDir currentDir = QDir::current(); - const auto addIncludePaths = [this, currentDir](const char *flag, const QStringList &paths) { - for (const auto &path : paths) - m_includePaths << currentDir.absoluteFilePath(path).insert(0, flag); - }; - - addIncludePaths("-I", m_parser.values(m_parser.includePathOption)); -#ifdef QDOC_PASS_ISYSTEM - addIncludePaths("-isystem", m_parser.values(m_parser.includePathSystemOption)); -#endif - addIncludePaths("-F", m_parser.values(m_parser.frameworkOption)); -} - -/*! - Stores paths from -indexdir command line option(s). - */ -void Config::setIndexDirs() -{ - m_indexDirs = m_parser.values(m_parser.indexDirOption); - auto it = std::remove_if(m_indexDirs.begin(), m_indexDirs.end(), - [](const QString &s) { return !QFile::exists(s); }); - - std::for_each(it, m_indexDirs.end(), [](const QString &s) { - qCWarning(lcQdoc) << "Cannot find index directory: " << s; - }); - m_indexDirs.erase(it, m_indexDirs.end()); -} - -/*! - Function to return the correct outputdir for the output \a format. - If \a format is not specified, defaults to 'HTML'. - outputdir can be set using the qdocconf or the command-line - variable -outputdir. - */ -QString Config::getOutputDir(const QString &format) const -{ - QString t; - if (overrideOutputDir.isNull()) - t = m_configVars.value(CONFIG_OUTPUTDIR).asString(); - else - t = overrideOutputDir; - if (m_configVars.value(CONFIG_SINGLEEXEC).asBool()) { - QString project = m_configVars.value(CONFIG_PROJECT).asString(); - t += QLatin1Char('/') + project.toLower(); - } - if (m_configVars.value(format + Config::dot + "nosubdirs").asBool()) { - t = t.left(t.lastIndexOf('/')); - QString singleOutputSubdir = m_configVars.value(format + Config::dot + "outputsubdir").asString(); - if (singleOutputSubdir.isEmpty()) - singleOutputSubdir = "html"; - t += QLatin1Char('/') + singleOutputSubdir; - } - return t; -} - -/*! - Function to return the correct outputformats. - outputformats can be set using the qdocconf or the command-line - variable -outputformat. - */ -QSet Config::getOutputFormats() const -{ - if (overrideOutputFormats.isEmpty()) - return m_configVars.value(CONFIG_OUTPUTFORMATS).asStringSet(); - else - return overrideOutputFormats; -} - -// TODO: [late-canonicalization][pod-configuration] -// The canonicalization for paths is done at the time where they are -// required, and done each time they are requested. -// Instead, config should be parsed to an intermediate format that is -// a POD type that already contains canonicalized representations for -// each element. -// Those representations should provide specific guarantees about -// their format and be representable at the API boundaries. -// -// This would ensure that the correct canonicalization is always -// applied, is applied only once and that dependent sub-logics can be -// written in a way that doesn't require branching or futher -// canonicalization. - -/*! - Returns a path list where all paths from the config variable \a var - are canonicalized. If \a flags contains \c Validate, outputs a warning - for invalid paths. The \c IncludePaths flag is used as a hint to strip - away potential prefixes found in include paths before attempting to - canonicalize. - */ -QStringList Config::getCanonicalPathList(const QString &var, PathFlags flags) const -{ - QStringList result; - const auto &configVar = m_configVars.value(var); - - for (const auto &value : configVar.m_values) { - const QString ¤tPath = value.m_path; - QString rawValue = value.m_value.simplified(); - QString prefix; - - if (flags & IncludePaths) { - const QStringList prefixes = QStringList() - << QLatin1String("-I") - << QLatin1String("-F") - << QLatin1String("-isystem"); - const auto end = std::end(prefixes); - const auto it = - std::find_if(std::begin(prefixes), end, - [&rawValue](const QString &p) { - return rawValue.startsWith(p); - }); - if (it != end) { - prefix = *it; - rawValue.remove(0, it->size()); - if (rawValue.isEmpty()) - continue; - } else { - prefix = prefixes[0]; // -I as default - } - } - - QDir dir(rawValue.trimmed()); - const QString path = dir.path(); - - if (dir.isRelative()) - dir.setPath(currentPath + QLatin1Char('/') + path); - if ((flags & Validate) && !QFileInfo::exists(dir.path())) - configVar.m_location.warning(QStringLiteral("Cannot find file or directory: %1").arg(path)); - else { - const QString canonicalPath = dir.canonicalPath(); - if (!canonicalPath.isEmpty()) - result.append(prefix + canonicalPath); - else if (path.contains(QLatin1Char('*')) || path.contains(QLatin1Char('?'))) - result.append(path); - else - qCDebug(lcQdoc) << - qUtf8Printable(QStringLiteral("%1: Ignored nonexistent path \'%2\'") - .arg(configVar.m_location.toString(), rawValue)); - } - } - return result; -} - -/*! - Calls getRegExpList() with the control variable \a var and - iterates through the resulting list of regular expressions, - concatenating them with extra characters to form a single - QRegularExpression, which is then returned. - - \sa getRegExpList() - */ -QRegularExpression Config::getRegExp(const QString &var) const -{ - QString pattern; - const auto subRegExps = getRegExpList(var); - - for (const auto ®Exp : subRegExps) { - if (!regExp.isValid()) - return regExp; - if (!pattern.isEmpty()) - pattern += QLatin1Char('|'); - pattern += QLatin1String("(?:") + regExp.pattern() + QLatin1Char(')'); - } - if (pattern.isEmpty()) - pattern = QLatin1String("$x"); // cannot match - return QRegularExpression(pattern); -} - -/*! - Looks up the configuration variable \a var in the string list - map, converts the string list to a list of regular expressions, - and returns it. - */ -QList Config::getRegExpList(const QString &var) const -{ - const QStringList strs = m_configVars.value(var).asStringList(); - QList regExps; - for (const auto &str : strs) - regExps += QRegularExpression(str); - return regExps; -} - -/*! - This function is slower than it could be. What it does is - find all the keys that begin with \a var + dot and return - the matching keys in a set, stripped of the matching prefix - and dot. - */ -QSet Config::subVars(const QString &var) const -{ - QSet result; - QString varDot = var + QLatin1Char('.'); - for (auto it = m_configVars.constBegin(); it != m_configVars.constEnd(); ++it) { - if (it.key().startsWith(varDot)) { - QString subVar = it.key().mid(varDot.size()); - int dot = subVar.indexOf(QLatin1Char('.')); - if (dot != -1) - subVar.truncate(dot); - result.insert(subVar); - } - } - return result; -} - -/*! - Searches for a path to \a fileName in 'sources', 'sourcedirs', and - 'exampledirs' config variables and returns a full path to the first - match found. If the file is not found, returns an empty string. - */ -QString Config::getIncludeFilePath(const QString &fileName) const -{ - QString ext = QFileInfo(fileName).suffix(); - - if (!m_includeFilesMap.contains(ext)) { - QStringList result = getCanonicalPathList(CONFIG_SOURCES); - result.erase(std::remove_if(result.begin(), result.end(), - [&](const QString &s) { return !s.endsWith(ext); }), - result.end()); - const QStringList dirs = - getCanonicalPathList(CONFIG_SOURCEDIRS) + - getCanonicalPathList(CONFIG_EXAMPLEDIRS); - - for (const auto &dir : dirs) - result += getFilesHere(dir, "*." + ext, location()); - result.removeDuplicates(); - m_includeFilesMap.insert(ext, result); - } - const QStringList &paths = (*m_includeFilesMap.find(ext)); - QString match = fileName; - if (!match.startsWith('/')) - match.prepend('/'); - for (const auto &path : paths) { - if (path.endsWith(match)) - return path; - } - return QString(); -} - -/*! - Builds and returns a list of file pathnames for the file - type specified by \a filesVar (e.g. "headers" or "sources"). - The files are found in the directories specified by - \a dirsVar, and they are filtered by \a defaultNameFilter - if a better filter can't be constructed from \a filesVar. - The directories in \a excludedDirs are avoided. The files - in \a excludedFiles are not included in the return list. - */ -QStringList Config::getAllFiles(const QString &filesVar, const QString &dirsVar, - const QSet &excludedDirs, - const QSet &excludedFiles) -{ - QStringList result = getCanonicalPathList(filesVar, Validate); - const QStringList dirs = getCanonicalPathList(dirsVar, Validate); - - const QString nameFilter = m_configVars.value(filesVar + dot + CONFIG_FILEEXTENSIONS).asString(); - - for (const auto &dir : dirs) - result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles); - return result; -} - -QStringList Config::getExampleQdocFiles(const QSet &excludedDirs, - const QSet &excludedFiles) -{ - QStringList result; - const QStringList dirs = getCanonicalPathList("exampledirs"); - const QString nameFilter = " *.qdoc"; - - for (const auto &dir : dirs) - result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles); - return result; -} - -QStringList Config::getExampleImageFiles(const QSet &excludedDirs, - const QSet &excludedFiles) -{ - QStringList result; - const QStringList dirs = getCanonicalPathList("exampledirs"); - const QString nameFilter = m_configVars.value(CONFIG_EXAMPLES + dot + CONFIG_IMAGEEXTENSIONS).asString(); - - for (const auto &dir : dirs) - result += getFilesHere(dir, nameFilter, location(), excludedDirs, excludedFiles); - return result; -} - -// TODO: [misplaced-logic][examples][pod-configuration] -// The definition of how an example is structured and how to find its -// components should not be part of Config or, for that matter, -// CppCodeParser, which is the actual caller of this method. -// Move this method to a more appropriate place as soon as a suitable -// place is available for it. - -/*! - Returns the path to the project file for \a examplePath, or an empty string - if no project file was found. - */ -QString Config::getExampleProjectFile(const QString &examplePath) -{ - QFileInfo fileInfo(examplePath); - QStringList validNames; - validNames << QLatin1String("CMakeLists.txt") - << fileInfo.fileName() + QLatin1String(".pro") - << fileInfo.fileName() + QLatin1String(".qmlproject") - << fileInfo.fileName() + QLatin1String(".pyproject") - << QLatin1String("qbuild.pro"); // legacy - - QString projectFile; - - for (const auto &name : std::as_const(validNames)) { - projectFile = Config::findFile(Location(), m_exampleFiles, m_exampleDirs, - examplePath + QLatin1Char('/') + name); - if (!projectFile.isEmpty()) - return projectFile; - } - - return projectFile; -} - -// TODO: [pod-configuration] -// Remove findFile completely from the configuration. -// External usages of findFile were already removed but a last caller -// of this method exists internally to Config in -// `getExampleProjectFile`. -// That method has to be removed at some point and this method should -// go with it. -// Do notice that FileResolver is the replacement for findFile but it -// is designed, for now, with a scope that does only care about the -// usages of findFile that are outside the Config class. -// More specifically, it was designed to replace only the uses of -// findFile that deal with user provided queries or queries related to -// that. -// The logic that is used internally in Config is the same, but has a -// different conceptual meaning. -// When findFile is permanently removed, it must be considered whether -// FileResolver itself should be used for the same logic or not. - -/*! - \a fileName is the path of the file to find. - - \a files and \a dirs are the lists where we must find the - components of \a fileName. - - \a location is used for obtaining the file and line numbers - for report qdoc errors. - */ -QString Config::findFile(const Location &location, const QStringList &files, - const QStringList &dirs, const QString &fileName, - QString *userFriendlyFilePath) -{ - if (fileName.isEmpty() || fileName.startsWith(QLatin1Char('/'))) { - if (userFriendlyFilePath) - *userFriendlyFilePath = fileName; - return fileName; - } - - QFileInfo fileInfo; - QStringList components = fileName.split(QLatin1Char('?')); - QString firstComponent = components.first(); - - for (const auto &file : files) { - if (file == firstComponent || file.endsWith(QLatin1Char('/') + firstComponent)) { - fileInfo.setFile(file); - if (!fileInfo.exists()) - location.fatal(QStringLiteral("File '%1' does not exist").arg(file)); - break; - } - } - - if (fileInfo.fileName().isEmpty()) { - for (const auto &dir : dirs) { - fileInfo.setFile(QDir(dir), firstComponent); - if (fileInfo.exists()) - break; - } - } - - if (userFriendlyFilePath) - userFriendlyFilePath->clear(); - if (!fileInfo.exists()) - return QString(); - - // <append(*c); - - if (isArchive) { - QString extracted = m_extractedDirs[fileInfo.filePath()]; - - ++c; - fileInfo.setFile(QDir(extracted), *c); - } else { - break; - } - - userFriendlyFilePath->append(QLatin1Char('?')); - } - } - // REMARK>> - - return fileInfo.filePath(); -} - -// TODO: [pod-configuration] -// An intermediate representation for the configuration should only -// contain data that will later be destructured into subsystem that -// care about specific subsets of the configuration and can carry that -// information with them, uniquely. -// Remove copyFile, moving it into whatever will have the unique -// resposability of knowing how to build an output directory for a -// QDoc execution. -// Should copy file being used for not only copying file to the build -// output directory, split its responsabilities into smaller elements -// instead of forcing the logic together. - -/*! - Copies the \a sourceFilePath to the file name constructed by - concatenating \a targetDirPath and the file name from the - \a userFriendlySourceFilePath. \a location is for identifying - the file and line number where a qdoc error occurred. The - constructed output file name is returned. - */ -QString Config::copyFile(const Location &location, const QString &sourceFilePath, - const QString &userFriendlySourceFilePath, const QString &targetDirPath) -{ - // TODO: A copying operation should only be performed on files - // that we assume to be available. Ensure that this is true at the - // API boundary and bubble up the error checking and reporting to - // call-site users. Possibly this will be as simple as - // ResolvedFile, but could not be done at the time of the introduction of - // that type as we first need to encapsulate the logic for - // copying files into an appropriate subsystem and have a better - // understanding of call-site usages. - - QFile inFile(sourceFilePath); - if (!inFile.open(QFile::ReadOnly)) { - location.warning(QStringLiteral("Cannot open input file for copy: '%1': %2") - .arg(sourceFilePath, inFile.errorString())); - return QString(); - } - - // TODO: [non-canonical-representation] - // Similar to other part of QDoc, we do a series of non-intuitive - // checks to canonicalize some multi-format parameter into - // something we can use. - // Understand which of those formats are actually in use and - // provide a canonicalized version that can be requested at the - // API boundary to ensure that correct formatting is used. - // If possible, gradually bubble up the canonicalization until a - // single entry-point in the program exists where the - // canonicalization can be processed to avoid complicating - // intermediate steps. - // ADDENDUM 1: At least one usage of this seems to depend on the - // processing done for files coming from - // Generator::copyTemplateFile, which are expressed as absolute - // paths. This seems to be the only usage that is currently - // needed, hence a temporary new implementation is provided that - // only takes this case into account. - // Do notice that we assume that in this case we always want a - // flat structure, that is, we are copying the file as a direct - // child of the target directory. - // Nonetheless, it is possible that this case will not be needed, - // such that it can be removed later on, or that it will be nedeed - // in multiple places such that an higher level interface for it - // should be provided. - // Furthermoe, it might be possible that there is an edge case - // that is now not considered, as it is unknown, that was - // considered before. - // As it is now unclear what kind of paths are used here, what - // format they have, why they are used and why they have some - // specific format, further processing is avoided but a more - // torough overview of what should is needed must be done when - // more information are gathered and this function is extracted - // away from config. - - QString outFileName{userFriendlySourceFilePath}; - QFileInfo outFileNameInfo{userFriendlySourceFilePath}; - if (outFileNameInfo.isAbsolute()) - outFileName = outFileNameInfo.fileName(); - - outFileName = targetDirPath + "/" + outFileName; - QDir targetDir(targetDirPath); - if (!targetDir.exists()) - targetDir.mkpath("."); - - QFile outFile(outFileName); - if (!outFile.open(QFile::WriteOnly)) { - // TODO: [uncrentralized-warning] - location.warning(QStringLiteral("Cannot open output file for copy: '%1': %2") - .arg(outFileName, outFile.errorString())); - return QString(); - } - - // TODO: There shouldn't be any particular advantage to copying - // the file by readying its content and writing it compared to - // asking the underlying system to do the copy for us. - // Consider simplifying this part by avoiding doing the manual - // work ourselves. - - char buffer[1024]; - qsizetype len; - while ((len = inFile.read(buffer, sizeof(buffer))) > 0) - outFile.write(buffer, len); - return outFileName; -} - -/*! - Finds the largest unicode digit in \a value in the range - 1..7 and returns it. - */ -int Config::numParams(const QString &value) -{ - int max = 0; - for (int i = 0; i != value.size(); ++i) { - uint c = value[i].unicode(); - if (c > 0 && c < 8) - max = qMax(max, static_cast(c)); - } - return max; -} - -/*! - Returns \c true if \a ch is a letter, number, '_', '.', - '{', '}', or ','. - */ -bool Config::isMetaKeyChar(QChar ch) -{ - return ch.isLetterOrNumber() || ch == QLatin1Char('_') || ch == QLatin1Char('.') - || ch == QLatin1Char('{') || ch == QLatin1Char('}') || ch == QLatin1Char(','); -} - -/*! - \a fileName is a master qdocconf file. It contains a list of - qdocconf files and nothing else. Read the list and return it. - */ -QStringList Config::loadMaster(const QString &fileName) -{ - Location location; - QFile fin(fileName); - if (!fin.open(QFile::ReadOnly | QFile::Text)) { - if (!Config::installDir.isEmpty()) { - qsizetype prefix = location.filePath().size() - location.fileName().size(); - fin.setFileName(Config::installDir + QLatin1Char('/') - + fileName.right(fileName.size() - prefix)); - } - if (!fin.open(QFile::ReadOnly | QFile::Text)) - location.fatal(QStringLiteral("Cannot open master qdocconf file '%1': %2") - .arg(fileName, fin.errorString())); - } - QTextStream stream(&fin); - QStringList qdocFiles; - QDir configDir(QFileInfo(fileName).canonicalPath()); - QString line = stream.readLine(); - while (!line.isNull()) { - if (!line.isEmpty()) - qdocFiles.append(QFileInfo(configDir, line).filePath()); - line = stream.readLine(); - } - fin.close(); - return qdocFiles; -} - -/*! - Load, parse, and process a qdoc configuration file. This - function is only called by the other load() function, but - this one is recursive, i.e., it calls itself when it sees - an \c{include} statement in the qdoc configuration file. - */ -void Config::load(Location location, const QString &fileName) -{ - QFileInfo fileInfo(fileName); - pushWorkingDir(fileInfo.canonicalPath()); - static const QRegularExpression keySyntax(QRegularExpression::anchoredPattern(QLatin1String("\\w+(?:\\.\\w+)*"))); - -#define SKIP_CHAR() \ - do { \ - location.advance(c); \ - ++i; \ - c = text.at(i); \ - cc = c.unicode(); \ - } while (0) - -#define SKIP_SPACES() \ - while (c.isSpace() && cc != '\n') \ - SKIP_CHAR() - -#define PUT_CHAR() \ - word += c; \ - SKIP_CHAR(); - - if (location.depth() > 16) - location.fatal(QStringLiteral("Too many nested includes")); - - QFile fin(fileInfo.fileName()); - if (!fin.open(QFile::ReadOnly | QFile::Text)) { - if (!Config::installDir.isEmpty()) { - qsizetype prefix = location.filePath().size() - location.fileName().size(); - fin.setFileName(Config::installDir + QLatin1Char('/') - + fileName.right(fileName.size() - prefix)); - } - if (!fin.open(QFile::ReadOnly | QFile::Text)) - location.fatal( - QStringLiteral("Cannot open file '%1': %2").arg(fileName, fin.errorString())); - } - - QTextStream stream(&fin); - QString text = stream.readAll(); - text += QLatin1String("\n\n"); - text += QLatin1Char('\0'); - fin.close(); - - location.push(fileName); - location.start(); - - int i = 0; - QChar c = text.at(0); - uint cc = c.unicode(); - while (i < text.size()) { - if (cc == 0) { - ++i; - } else if (c.isSpace()) { - SKIP_CHAR(); - } else if (cc == '#') { - do { - SKIP_CHAR(); - } while (cc != '\n'); - } else if (isMetaKeyChar(c)) { - Location keyLoc = location; - bool plus = false; - QStringList rhsValues; - QList expandVars; - QString word; - bool inQuote = false; - bool needsExpansion = false; - - MetaStack stack; - do { - stack.process(c, location); - SKIP_CHAR(); - } while (isMetaKeyChar(c)); - - const QStringList keys = stack.getExpanded(location); - SKIP_SPACES(); - - if (keys.size() == 1 && keys.first() == QLatin1String("include")) { - QString includeFile; - - if (cc != '(') - location.fatal(QStringLiteral("Bad include syntax")); - SKIP_CHAR(); - SKIP_SPACES(); - - while (!c.isSpace() && cc != '#' && cc != ')') { - - if (cc == '$') { - QString var; - SKIP_CHAR(); - while (c.isLetterOrNumber() || cc == '_') { - var += c; - SKIP_CHAR(); - } - if (!var.isEmpty()) { - const QByteArray val = qgetenv(var.toLatin1().data()); - if (val.isNull()) { - location.fatal(QStringLiteral("Environment variable '%1' undefined") - .arg(var)); - } else { - includeFile += QString::fromLatin1(val); - } - } - } else { - includeFile += c; - SKIP_CHAR(); - } - } - SKIP_SPACES(); - if (cc != ')') - location.fatal(QStringLiteral("Bad include syntax")); - SKIP_CHAR(); - SKIP_SPACES(); - if (cc != '#' && cc != '\n') - location.fatal(QStringLiteral("Trailing garbage")); - - /* - Here is the recursive call. - */ - load(location, QFileInfo(QDir(m_workingDirs.top()), includeFile).filePath()); - } else { - /* - It wasn't an include statement, so it's something else. - We must see either '=' or '+=' next. If not, fatal error. - */ - if (cc == '+') { - plus = true; - SKIP_CHAR(); - } - if (cc != '=') - location.fatal(QStringLiteral("Expected '=' or '+=' after key")); - SKIP_CHAR(); - SKIP_SPACES(); - - for (;;) { - if (cc == '\\') { - qsizetype metaCharPos; - - SKIP_CHAR(); - if (cc == '\n') { - SKIP_CHAR(); - } else if (cc > '0' && cc < '8') { - word += QChar(c.digitValue()); - SKIP_CHAR(); - } else if ((metaCharPos = QString::fromLatin1("abfnrtv").indexOf(c)) - != -1) { - word += QLatin1Char("\a\b\f\n\r\t\v"[metaCharPos]); - SKIP_CHAR(); - } else { - PUT_CHAR(); - } - } else if (c.isSpace() || cc == '#') { - if (inQuote) { - if (cc == '\n') - location.fatal(QStringLiteral("Unterminated string")); - PUT_CHAR(); - } else { - if (!word.isEmpty() || needsExpansion) { - rhsValues << word; - word.clear(); - needsExpansion = false; - } - if (cc == '\n' || cc == '#') - break; - SKIP_SPACES(); - } - } else if (cc == '"') { - if (inQuote) { - if (!word.isEmpty() || needsExpansion) - rhsValues << word; - word.clear(); - needsExpansion = false; - } - inQuote = !inQuote; - SKIP_CHAR(); - } else if (cc == '$') { - QString var; - QChar delim(' '); - bool braces = false; - SKIP_CHAR(); - if (cc == '{') { - SKIP_CHAR(); - braces = true; - } - while (c.isLetterOrNumber() || cc == '_') { - var += c; - SKIP_CHAR(); - } - if (braces) { - if (cc == ',') { - SKIP_CHAR(); - delim = c; - SKIP_CHAR(); - } - if (cc == '}') - SKIP_CHAR(); - else if (delim == '}') - delim = QChar(); // null delimiter - else - location.fatal(QStringLiteral("Missing '}'")); - } - if (!var.isEmpty()) { - const QByteArray val = qgetenv(var.toLatin1().constData()); - if (val.isNull()) { - expandVars << ExpandVar(rhsValues.size(), word.size(), var, delim); - needsExpansion = true; - } else if (braces) { // ${VAR} inserts content from an env. variable for processing - text.insert(i, QString::fromLatin1(val)); - c = text.at(i); - cc = c.unicode(); - } else { // while $VAR simply reads the value and stores it to a config variable. - word += QString::fromLatin1(val); - } - } - } else { - if (!inQuote && cc == '=') - location.fatal(QStringLiteral("Unexpected '='")); - PUT_CHAR(); - } - } - for (const auto &key : keys) { - if (!keySyntax.match(key).hasMatch()) - keyLoc.fatal(QStringLiteral("Invalid key '%1'").arg(key)); - - ConfigVar configVar(key, rhsValues, QDir::currentPath(), keyLoc, expandVars); - if (plus && m_configVars.contains(key)) { - m_configVars[key].append(configVar); - } else { - m_configVars.insert(key, configVar); - } - } - } - } else { - location.fatal(QStringLiteral("Unexpected character '%1' at beginning of line").arg(c)); - } - } - popWorkingDir(); - -#undef SKIP_CHAR -#undef SKIP_SPACES -#undef PUT_CHAR -} - -bool Config::isFileExcluded(const QString &fileName, const QSet &excludedFiles) -{ - for (const QString &entry : excludedFiles) { - if (entry.contains(QLatin1Char('*')) || entry.contains(QLatin1Char('?'))) { - QRegularExpression re(QRegularExpression::wildcardToRegularExpression(entry)); - if (re.match(fileName).hasMatch()) - return true; - } - } - return excludedFiles.contains(fileName); -} - -QStringList Config::getFilesHere(const QString &uncleanDir, const QString &nameFilter, - const Location &location, const QSet &excludedDirs, - const QSet &excludedFiles) -{ - // TODO: Understand why location is used to branch the - // canonicalization and why the two different methods are used. - QString dir = - location.isEmpty() ? QDir::cleanPath(uncleanDir) : QDir(uncleanDir).canonicalPath(); - QStringList result; - if (excludedDirs.contains(dir)) - return result; - - QDir dirInfo(dir); - - dirInfo.setNameFilters(nameFilter.split(QLatin1Char(' '))); - dirInfo.setSorting(QDir::Name); - dirInfo.setFilter(QDir::Files); - QStringList fileNames = dirInfo.entryList(); - for (const auto &file : std::as_const(fileNames)) { - // TODO: Understand if this is needed and, should it be, if it - // is indeed the only case that should be considered. - if (!file.startsWith(QLatin1Char('~'))) { - QString s = dirInfo.filePath(file); - QString c = QDir::cleanPath(s); - if (!isFileExcluded(c, excludedFiles)) - result.append(c); - } - } - - dirInfo.setNameFilters(QStringList(QLatin1String("*"))); - dirInfo.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); - fileNames = dirInfo.entryList(); - for (const auto &file : fileNames) - result += getFilesHere(dirInfo.filePath(file), nameFilter, location, excludedDirs, - excludedFiles); - return result; -} - -/*! - Set \a dir as the working directory and push it onto the - stack of working directories. - */ -void Config::pushWorkingDir(const QString &dir) -{ - m_workingDirs.push(dir); - QDir::setCurrent(dir); -} - -/*! - Pop the top entry from the stack of working directories. - Set the working directory to the next one on the stack, - if one exists. - */ -void Config::popWorkingDir() -{ - Q_ASSERT(!m_workingDirs.isEmpty()); - m_workingDirs.pop(); - if (!m_workingDirs.isEmpty()) - QDir::setCurrent(m_workingDirs.top()); -} - -QT_END_NAMESPACE diff --git a/src/qdoc/config.h b/src/qdoc/config.h deleted file mode 100644 index 1b62f691c..000000000 --- a/src/qdoc/config.h +++ /dev/null @@ -1,392 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CONFIG_H -#define CONFIG_H - -#include "location.h" -#include "qdoccommandlineparser.h" -#include "singleton.h" - -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class Config; - -/* - Contains information about a location - where a ConfigVar string needs to be expanded - from another config variable. -*/ -struct ExpandVar -{ - int m_valueIndex {}; - int m_index {}; - QString m_var {}; - QChar m_delim {}; - - ExpandVar(int valueIndex, int index, QString var, const QChar &delim) - : m_valueIndex(valueIndex), m_index(index), m_var(std::move(var)), m_delim(delim) - { - } -}; - -class ConfigVar -{ -public: - struct ConfigValue { - QString m_value; - QString m_path; - }; - - [[nodiscard]] QString asString(const QString defaultString = QString()) const; - [[nodiscard]] QStringList asStringList() const; - [[nodiscard]] QSet asStringSet() const; - [[nodiscard]] bool asBool() const; - [[nodiscard]] int asInt() const; - [[nodiscard]] const Location &location() const { return m_location; } - - ConfigVar() = default; - ConfigVar(QString name, const QStringList &values, const QString &dir, - const Location &loc = Location(), - const QList &expandVars = QList()) - : m_name(std::move(name)), m_location(loc), m_expandVars(expandVars) - { - for (const auto &v : values) - m_values << ConfigValue {v, dir}; - } - -private: - void append(const ConfigVar &other); - -private: - QString m_name {}; - QList m_values {}; - Location m_location {}; - QList m_expandVars {}; - - friend class Config; -}; - -/* - In this multimap, the key is a config variable name. - */ -typedef QMap ConfigVarMap; - -class Config : public Singleton -{ -public: - ~Config(); - - enum QDocPass { Neither, Prepare, Generate }; - - enum PathFlags : unsigned char { - None = 0x0, - // TODO: [unenforced-unclear-validation] - // The Validate flag is used, for example, during the retrival - // of paths in getCanonicalPathList. - // It is unclear what kind of validation it performs, if any, - // and when this validation is required. - // Instead, remove this kind of flag and ensure that any - // amount of required validation is performed during the - // parsing step, if possilbe, and only once. - // Furthemore, ensure any such validation removes some - // uncertainty on dependent subsystems, moving constraints to - // preconditions and expressing them at the API boundaries. - Validate = 0x1, - IncludePaths = 0x2 - }; - - void init(const QString &programName, const QStringList &args); - [[nodiscard]] bool getDebug() const { return m_debug; } - [[nodiscard]] bool getAtomsDump() const { return m_atomsDump; } - [[nodiscard]] bool showInternal() const { return m_showInternal; } - - void clear(); - void reset(); - void load(const QString &fileName); - void setStringList(const QString &var, const QStringList &values); - void insertStringList(const QString &var, const QStringList &values); - - void showHelp(int exitCode = 0) { m_parser.showHelp(exitCode); } - [[nodiscard]] QStringList qdocFiles() const { return m_parser.positionalArguments(); } - [[nodiscard]] const QString &programName() const { return m_prog; } - [[nodiscard]] const Location &location() const { return m_location; } - [[nodiscard]] const ConfigVar &get(const QString &var) const - { - // Avoid injecting default-constructed values to map if var doesn't exist - static ConfigVar empty; - auto it = m_configVars.constFind(var); - return (it != m_configVars.constEnd()) ? *it : empty; - } - [[nodiscard]] QString getOutputDir(const QString &format = QString("HTML")) const; - [[nodiscard]] QSet getOutputFormats() const; - [[nodiscard]] QStringList getCanonicalPathList(const QString &var, - PathFlags flags = None) const; - [[nodiscard]] QRegularExpression getRegExp(const QString &var) const; - [[nodiscard]] QList getRegExpList(const QString &var) const; - [[nodiscard]] QSet subVars(const QString &var) const; - QStringList getAllFiles(const QString &filesVar, const QString &dirsVar, - const QSet &excludedDirs = QSet(), - const QSet &excludedFiles = QSet()); - [[nodiscard]] QString getIncludeFilePath(const QString &fileName) const; - QStringList getExampleQdocFiles(const QSet &excludedDirs, - const QSet &excludedFiles); - QStringList getExampleImageFiles(const QSet &excludedDirs, - const QSet &excludedFiles); - QString getExampleProjectFile(const QString &examplePath); - - static QStringList loadMaster(const QString &fileName); - static bool isFileExcluded(const QString &fileName, const QSet &excludedFiles); - static QStringList getFilesHere(const QString &dir, const QString &nameFilter, - const Location &location = Location(), - const QSet &excludedDirs = QSet(), - const QSet &excludedFiles = QSet()); - static QString findFile(const Location &location, const QStringList &files, - const QStringList &dirs, const QString &fileName, - QString *userFriendlyFilePath = nullptr); - static QString copyFile(const Location &location, const QString &sourceFilePath, - const QString &userFriendlySourceFilePath, - const QString &targetDirPath); - static int numParams(const QString &value); - static void pushWorkingDir(const QString &dir); - static void popWorkingDir(); - - static const QString dot; - - static bool generateExamples; - static QString installDir; - static QString overrideOutputDir; - static QSet overrideOutputFormats; - - [[nodiscard]] inline bool singleExec() const; - [[nodiscard]] inline bool dualExec() const; - QStringList &defines() { return m_defines; } - QStringList &dependModules() { return m_dependModules; } - QStringList &includePaths() { return m_includePaths; } - QStringList &indexDirs() { return m_indexDirs; } - [[nodiscard]] QString currentDir() const { return m_currentDir; } - void setCurrentDir(const QString &path) { m_currentDir = path; } - [[nodiscard]] QString previousCurrentDir() const { return m_previousCurrentDir; } - void setPreviousCurrentDir(const QString &path) { m_previousCurrentDir = path; } - - void setQDocPass(const QDocPass &pass) { m_qdocPass = pass; }; - [[nodiscard]] bool preparing() const { return (m_qdocPass == Prepare); } - [[nodiscard]] bool generating() const { return (m_qdocPass == Generate); } - -private: - void processCommandLineOptions(const QStringList &args); - void setIncludePaths(); - void setIndexDirs(); - void expandVariables(); - - QStringList m_dependModules {}; - QStringList m_defines {}; - QStringList m_includePaths {}; - QStringList m_indexDirs {}; - QStringList m_exampleFiles {}; - QStringList m_exampleDirs {}; - QString m_currentDir {}; - QString m_previousCurrentDir {}; - - bool m_showInternal { false }; - static bool m_debug; - - // An option that can be set trough a similarly named command-line option. - // When this is set, every time QDoc parses a block-comment, a - // human-readable presentation of the `Atom`s structure for that - // block will shown to the user. - static bool m_atomsDump; - - static bool isMetaKeyChar(QChar ch); - void load(Location location, const QString &fileName); - - QString m_prog {}; - Location m_location {}; - ConfigVarMap m_configVars {}; - - static QMap m_extractedDirs; - static QStack m_workingDirs; - static QMap m_includeFilesMap; - QDocCommandLineParser m_parser {}; - - QDocPass m_qdocPass { Neither }; -}; - -struct ConfigStrings -{ - static QString ALIAS; - static QString AUTOLINKERRORS; - static QString BUILDVERSION; - static QString CLANGDEFINES; - static QString CODEINDENT; - static QString CODEPREFIX; - static QString CODESUFFIX; - static QString CPPCLASSESPAGE; - static QString CPPCLASSESTITLE; - static QString DEFINES; - static QString DEPENDS; - static QString DESCRIPTION; - static QString DOCBOOKEXTENSIONS; - static QString ENDHEADER; - static QString EXAMPLEDIRS; - static QString EXAMPLES; - static QString EXAMPLESINSTALLPATH; - static QString EXCLUDEDIRS; - static QString EXCLUDEFILES; - static QString EXTRAIMAGES; - static QString FALSEHOODS; - static QString FORMATTING; - static QString HEADERDIRS; - static QString HEADERS; - static QString HEADERSCRIPTS; - static QString HEADERSTYLES; - static QString HOMEPAGE; - static QString HOMETITLE; - static QString IGNOREDIRECTIVES; - static QString IGNORETOKENS; - static QString IGNORESINCE; - static QString IGNOREWORDS; - static QString IMAGEDIRS; - static QString IMAGES; - static QString INCLUDEPATHS; - static QString INCLUSIVE; - static QString INDEXES; - static QString LANDINGPAGE; - static QString LANDINGTITLE; - static QString LANGUAGE; - static QString LOCATIONINFO; - static QString LOGPROGRESS; - static QString MACRO; - static QString MANIFESTMETA; - static QString MODULEHEADER; - static QString NATURALLANGUAGE; - static QString NAVIGATION; - static QString NOLINKERRORS; - static QString OUTPUTDIR; - static QString OUTPUTFORMATS; - static QString OUTPUTPREFIXES; - static QString OUTPUTSUFFIXES; - static QString PROJECT; - static QString REDIRECTDOCUMENTATIONTODEVNULL; - static QString QHP; - static QString QUOTINGINFORMATION; - static QString SCRIPTS; - static QString SHOWINTERNAL; - static QString SINGLEEXEC; - static QString SOURCEDIRS; - static QString SOURCEENCODING; - static QString SOURCES; - static QString SPURIOUS; - static QString STYLESHEETS; - static QString SYNTAXHIGHLIGHTING; - static QString TABSIZE; - static QString TAGFILE; - static QString TIMESTAMPS; - static QString TOCTITLES; - static QString URL; - static QString VERSION; - static QString VERSIONSYM; - static QString FILEEXTENSIONS; - static QString IMAGEEXTENSIONS; - static QString QMLTYPESPAGE; - static QString QMLTYPESTITLE; - static QString WARNINGLIMIT; -}; - -#define CONFIG_AUTOLINKERRORS ConfigStrings::AUTOLINKERRORS -#define CONFIG_BUILDVERSION ConfigStrings::BUILDVERSION -#define CONFIG_CLANGDEFINES ConfigStrings::CLANGDEFINES -#define CONFIG_CODEINDENT ConfigStrings::CODEINDENT -#define CONFIG_CODEPREFIX ConfigStrings::CODEPREFIX -#define CONFIG_CODESUFFIX ConfigStrings::CODESUFFIX -#define CONFIG_CPPCLASSESPAGE ConfigStrings::CPPCLASSESPAGE -#define CONFIG_CPPCLASSESTITLE ConfigStrings::CPPCLASSESTITLE -#define CONFIG_DEFINES ConfigStrings::DEFINES -#define CONFIG_DEPENDS ConfigStrings::DEPENDS -#define CONFIG_DESCRIPTION ConfigStrings::DESCRIPTION -#define CONFIG_DOCBOOKEXTENSIONS ConfigStrings::DOCBOOKEXTENSIONS -#define CONFIG_ENDHEADER ConfigStrings::ENDHEADER -#define CONFIG_EXAMPLEDIRS ConfigStrings::EXAMPLEDIRS -#define CONFIG_EXAMPLES ConfigStrings::EXAMPLES -#define CONFIG_EXAMPLESINSTALLPATH ConfigStrings::EXAMPLESINSTALLPATH -#define CONFIG_EXCLUDEDIRS ConfigStrings::EXCLUDEDIRS -#define CONFIG_EXCLUDEFILES ConfigStrings::EXCLUDEFILES -#define CONFIG_EXTRAIMAGES ConfigStrings::EXTRAIMAGES -#define CONFIG_FALSEHOODS ConfigStrings::FALSEHOODS -#define CONFIG_FORMATTING ConfigStrings::FORMATTING -#define CONFIG_HEADERDIRS ConfigStrings::HEADERDIRS -#define CONFIG_HEADERS ConfigStrings::HEADERS -#define CONFIG_HEADERSCRIPTS ConfigStrings::HEADERSCRIPTS -#define CONFIG_HEADERSTYLES ConfigStrings::HEADERSTYLES -#define CONFIG_HOMEPAGE ConfigStrings::HOMEPAGE -#define CONFIG_HOMETITLE ConfigStrings::HOMETITLE -#define CONFIG_IGNOREDIRECTIVES ConfigStrings::IGNOREDIRECTIVES -#define CONFIG_IGNORESINCE ConfigStrings::IGNORESINCE -#define CONFIG_IGNORETOKENS ConfigStrings::IGNORETOKENS -#define CONFIG_IGNOREWORDS ConfigStrings::IGNOREWORDS -#define CONFIG_IMAGEDIRS ConfigStrings::IMAGEDIRS -#define CONFIG_IMAGES ConfigStrings::IMAGES -#define CONFIG_INCLUDEPATHS ConfigStrings::INCLUDEPATHS -#define CONFIG_INCLUSIVE ConfigStrings::INCLUSIVE -#define CONFIG_INDEXES ConfigStrings::INDEXES -#define CONFIG_LANDINGPAGE ConfigStrings::LANDINGPAGE -#define CONFIG_LANDINGTITLE ConfigStrings::LANDINGTITLE -#define CONFIG_LANGUAGE ConfigStrings::LANGUAGE -#define CONFIG_LOCATIONINFO ConfigStrings::LOCATIONINFO -#define CONFIG_LOGPROGRESS ConfigStrings::LOGPROGRESS -#define CONFIG_MACRO ConfigStrings::MACRO -#define CONFIG_MANIFESTMETA ConfigStrings::MANIFESTMETA -#define CONFIG_MODULEHEADER ConfigStrings::MODULEHEADER -#define CONFIG_NATURALLANGUAGE ConfigStrings::NATURALLANGUAGE -#define CONFIG_NAVIGATION ConfigStrings::NAVIGATION -#define CONFIG_NOLINKERRORS ConfigStrings::NOLINKERRORS -#define CONFIG_OUTPUTDIR ConfigStrings::OUTPUTDIR -#define CONFIG_OUTPUTFORMATS ConfigStrings::OUTPUTFORMATS -#define CONFIG_OUTPUTPREFIXES ConfigStrings::OUTPUTPREFIXES -#define CONFIG_OUTPUTSUFFIXES ConfigStrings::OUTPUTSUFFIXES -#define CONFIG_PROJECT ConfigStrings::PROJECT -#define CONFIG_REDIRECTDOCUMENTATIONTODEVNULL ConfigStrings::REDIRECTDOCUMENTATIONTODEVNULL -#define CONFIG_QHP ConfigStrings::QHP -#define CONFIG_QUOTINGINFORMATION ConfigStrings::QUOTINGINFORMATION -#define CONFIG_SCRIPTS ConfigStrings::SCRIPTS -#define CONFIG_SHOWINTERNAL ConfigStrings::SHOWINTERNAL -#define CONFIG_SINGLEEXEC ConfigStrings::SINGLEEXEC -#define CONFIG_SOURCEDIRS ConfigStrings::SOURCEDIRS -#define CONFIG_SOURCEENCODING ConfigStrings::SOURCEENCODING -#define CONFIG_SOURCES ConfigStrings::SOURCES -#define CONFIG_SPURIOUS ConfigStrings::SPURIOUS -#define CONFIG_STYLESHEETS ConfigStrings::STYLESHEETS -#define CONFIG_SYNTAXHIGHLIGHTING ConfigStrings::SYNTAXHIGHLIGHTING -#define CONFIG_TABSIZE ConfigStrings::TABSIZE -#define CONFIG_TAGFILE ConfigStrings::TAGFILE -#define CONFIG_TIMESTAMPS ConfigStrings::TIMESTAMPS -#define CONFIG_TOCTITLES ConfigStrings::TOCTITLES -#define CONFIG_URL ConfigStrings::URL -#define CONFIG_VERSION ConfigStrings::VERSION -#define CONFIG_VERSIONSYM ConfigStrings::VERSIONSYM -#define CONFIG_FILEEXTENSIONS ConfigStrings::FILEEXTENSIONS -#define CONFIG_IMAGEEXTENSIONS ConfigStrings::IMAGEEXTENSIONS -#define CONFIG_QMLTYPESPAGE ConfigStrings::QMLTYPESPAGE -#define CONFIG_QMLTYPESTITLE ConfigStrings::QMLTYPESTITLE -#define CONFIG_WARNINGLIMIT ConfigStrings::WARNINGLIMIT - -inline bool Config::singleExec() const -{ - return m_configVars.value(CONFIG_SINGLEEXEC).asBool(); -} - -inline bool Config::dualExec() const -{ - return !m_configVars.value(CONFIG_SINGLEEXEC).asBool(); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/cppcodemarker.cpp b/src/qdoc/cppcodemarker.cpp deleted file mode 100644 index 32b14d24b..000000000 --- a/src/qdoc/cppcodemarker.cpp +++ /dev/null @@ -1,593 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "cppcodemarker.h" - -#include "access.h" -#include "enumnode.h" -#include "functionnode.h" -#include "namespacenode.h" -#include "propertynode.h" -#include "qmlpropertynode.h" -#include "text.h" -#include "tree.h" -#include "typedefnode.h" -#include "variablenode.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -/*! - Returns \c true. - */ -bool CppCodeMarker::recognizeCode(const QString & /* code */) -{ - return true; -} - -/*! - Returns \c true if \a ext is any of a list of file extensions - for the C++ language. - */ -bool CppCodeMarker::recognizeExtension(const QString &extension) -{ - QByteArray ext = extension.toLatin1(); - return ext == "c" || ext == "c++" || ext == "qdoc" || ext == "qtt" || ext == "qtx" - || ext == "cc" || ext == "cpp" || ext == "cxx" || ext == "ch" || ext == "h" - || ext == "h++" || ext == "hh" || ext == "hpp" || ext == "hxx"; -} - -/*! - Returns \c true if \a lang is either "C" or "Cpp". - */ -bool CppCodeMarker::recognizeLanguage(const QString &lang) -{ - return lang == QLatin1String("C") || lang == QLatin1String("Cpp"); -} - -/*! - Returns the type of atom used to represent C++ code in the documentation. -*/ -Atom::AtomType CppCodeMarker::atomType() const -{ - return Atom::Code; -} - -QString CppCodeMarker::markedUpCode(const QString &code, const Node *relative, - const Location &location) -{ - return addMarkUp(code, relative, location); -} - -QString CppCodeMarker::markedUpSynopsis(const Node *node, const Node * /* relative */, - Section::Style style) -{ - const int MaxEnumValues = 6; - const FunctionNode *func; - const VariableNode *variable; - const EnumNode *enume; - QString synopsis; - QString name; - - name = taggedNode(node); - if (style != Section::Details) - name = linkTag(node, name); - name = "<@name>" + name + ""; - - if (style == Section::Details) { - if (!node->isRelatedNonmember() && !node->isProxyNode() && !node->parent()->name().isEmpty() - && !node->parent()->isHeader() && !node->isProperty() && !node->isQmlNode()) { - name.prepend(taggedNode(node->parent()) + "::"); - } - } - - switch (node->nodeType()) { - case Node::Namespace: - case Node::Class: - case Node::Struct: - case Node::Union: - synopsis = Node::nodeTypeString(node->nodeType()); - synopsis += QLatin1Char(' ') + name; - break; - case Node::Function: - func = (const FunctionNode *)node; - if (style == Section::Details) { - const QString &templateDecl = node->templateDecl(); - if (!templateDecl.isEmpty()) - synopsis = templateDecl + QLatin1Char(' '); - } - if (style != Section::AllMembers && !func->returnType().isEmpty()) - synopsis += typified(func->returnType(), true); - synopsis += name; - if (!func->isMacroWithoutParams()) { - synopsis += QLatin1Char('('); - if (!func->parameters().isEmpty()) { - const Parameters ¶meters = func->parameters(); - for (int i = 0; i < parameters.count(); ++i) { - if (i > 0) - synopsis += ", "; - QString name = parameters.at(i).name(); - QString type = parameters.at(i).type(); - QString value = parameters.at(i).defaultValue(); - bool trailingSpace = style != Section::AllMembers && !name.isEmpty(); - synopsis += typified(type, trailingSpace); - if (style != Section::AllMembers && !name.isEmpty()) - synopsis += "<@param>" + protect(name) + ""; - if (style != Section::AllMembers && !value.isEmpty()) - synopsis += " = " + protect(value); - } - } - synopsis += QLatin1Char(')'); - } - if (func->isConst()) - synopsis += " const"; - - if (style == Section::Summary || style == Section::Accessors) { - if (!func->isNonvirtual()) - synopsis.prepend("virtual "); - if (func->isFinal()) - synopsis.append(" final"); - if (func->isOverride()) - synopsis.append(" override"); - if (func->isPureVirtual()) - synopsis.append(" = 0"); - if (func->isRef()) - synopsis.append(" &"); - else if (func->isRefRef()) - synopsis.append(" &&"); - } else if (style == Section::AllMembers) { - if (!func->returnType().isEmpty() && func->returnType() != "void") - synopsis += " : " + typified(func->returnType()); - } else { - if (func->isRef()) - synopsis.append(" &"); - else if (func->isRefRef()) - synopsis.append(" &&"); - } - break; - case Node::Enum: - enume = static_cast(node); - synopsis = "enum "; - if (enume->isScoped()) - synopsis += "class "; - synopsis += name; - if (style == Section::Summary) { - synopsis += " { "; - - QStringList documentedItems = enume->doc().enumItemNames(); - if (documentedItems.isEmpty()) { - const auto &enumItems = enume->items(); - for (const auto &item : enumItems) - documentedItems << item.name(); - } - const QStringList omitItems = enume->doc().omitEnumItemNames(); - for (const auto &item : omitItems) - documentedItems.removeAll(item); - - if (documentedItems.size() > MaxEnumValues) { - // Take the last element and keep it safe, then elide the surplus. - const QString last = documentedItems.last(); - documentedItems = documentedItems.mid(0, MaxEnumValues - 1); - documentedItems += "…"; - documentedItems += last; - } - synopsis += documentedItems.join(QLatin1String(", ")); - - if (!documentedItems.isEmpty()) - synopsis += QLatin1Char(' '); - synopsis += QLatin1Char('}'); - } - break; - case Node::TypeAlias: - if (style == Section::Details) { - const QString &templateDecl = node->templateDecl(); - if (!templateDecl.isEmpty()) - synopsis += templateDecl + QLatin1Char(' '); - } - synopsis += name; - break; - case Node::Typedef: - if (static_cast(node)->associatedEnum()) - synopsis = "flags "; - synopsis += name; - break; - case Node::Property: { - auto property = static_cast(node); - synopsis = name + " : " + typified(property->qualifiedDataType()); - break; - } - case Node::QmlProperty: { - auto property = static_cast(node); - synopsis = name + " : " + typified(property->dataType()); - break; - } - case Node::Variable: - variable = static_cast(node); - if (style == Section::AllMembers) { - synopsis = name + " : " + typified(variable->dataType()); - } else { - synopsis = typified(variable->leftType(), true) + name + protect(variable->rightType()); - } - break; - default: - synopsis = name; - } - - QString extra = CodeMarker::extraSynopsis(node, style); - if (!extra.isEmpty()) { - extra.prepend("<@extra>"); - extra.append(""); - } - - return extra + synopsis; -} - -/*! - */ -QString CppCodeMarker::markedUpQmlItem(const Node *node, bool summary) -{ - QString name = taggedQmlNode(node); - if (summary) { - name = linkTag(node, name); - } else if (node->isQmlProperty()) { - const auto *pn = static_cast(node); - if (pn->isAttached()) - name.prepend(pn->element() + QLatin1Char('.')); - } - name = "<@name>" + name + ""; - QString synopsis; - if (node->isQmlProperty()) { - const auto *pn = static_cast(node); - synopsis = name + " : " + typified(pn->dataType()); - } else if (node->isFunction(Node::QML)) { - const auto *func = static_cast(node); - if (!func->returnType().isEmpty()) - synopsis = typified(func->returnType(), true) + name; - else - synopsis = name; - synopsis += QLatin1Char('('); - if (!func->parameters().isEmpty()) { - const Parameters ¶meters = func->parameters(); - for (int i = 0; i < parameters.count(); ++i) { - if (i > 0) - synopsis += ", "; - QString name = parameters.at(i).name(); - QString type = parameters.at(i).type(); - QString paramName; - if (!name.isEmpty()) { - synopsis += typified(type, true); - paramName = name; - } else { - paramName = type; - } - synopsis += "<@param>" + protect(paramName) + ""; - } - } - synopsis += QLatin1Char(')'); - } else { - synopsis = name; - } - - QString extra; - if (summary) { - if (node->isPreliminary()) - extra += " (preliminary)"; - else if (node->isDeprecated()) { - if (const QString &version = node->deprecatedSince(); !version.isEmpty()) - extra += " (deprecated since " + version + ")"; - else - extra += " (deprecated)"; - } - } - - if (!extra.isEmpty()) { - extra.prepend("<@extra>"); - extra.append(""); - } - return synopsis + extra; -} - -QString CppCodeMarker::markedUpName(const Node *node) -{ - QString name = linkTag(node, taggedNode(node)); - if (node->isFunction() && !node->isMacro()) - name += "()"; - return name; -} - -QString CppCodeMarker::markedUpEnumValue(const QString &enumValue, const Node *relative) -{ - if (!relative->isEnumType()) - return enumValue; - - const Node *node = relative->parent(); - QStringList parts; - while (!node->isHeader() && node->parent()) { - parts.prepend(markedUpName(node)); - if (node->parent() == relative || node->parent()->name().isEmpty()) - break; - node = node->parent(); - } - if (static_cast(relative)->isScoped()) - parts.append(relative->name()); - - parts.append(enumValue); - return parts.join(QLatin1String("<@op>::")); -} - -QString CppCodeMarker::markedUpInclude(const QString &include) -{ - return "<@preprocessor>#include <<@headerfile>" + include + ">"; -} - -/* - @char - @class - @comment - @function - @keyword - @number - @op - @preprocessor - @string - @type -*/ - -QString CppCodeMarker::addMarkUp(const QString &in, const Node * /* relative */, - const Location & /* location */) -{ - static QSet types{ - QLatin1String("bool"), QLatin1String("char"), QLatin1String("double"), - QLatin1String("float"), QLatin1String("int"), QLatin1String("long"), - QLatin1String("short"), QLatin1String("signed"), QLatin1String("unsigned"), - QLatin1String("uint"), QLatin1String("ulong"), QLatin1String("ushort"), - QLatin1String("uchar"), QLatin1String("void"), QLatin1String("qlonglong"), - QLatin1String("qulonglong"), QLatin1String("qint"), QLatin1String("qint8"), - QLatin1String("qint16"), QLatin1String("qint32"), QLatin1String("qint64"), - QLatin1String("quint"), QLatin1String("quint8"), QLatin1String("quint16"), - QLatin1String("quint32"), QLatin1String("quint64"), QLatin1String("qreal"), - QLatin1String("cond") - }; - - static QSet keywords{ - QLatin1String("and"), QLatin1String("and_eq"), QLatin1String("asm"), QLatin1String("auto"), - QLatin1String("bitand"), QLatin1String("bitor"), QLatin1String("break"), - QLatin1String("case"), QLatin1String("catch"), QLatin1String("class"), - QLatin1String("compl"), QLatin1String("const"), QLatin1String("const_cast"), - QLatin1String("continue"), QLatin1String("default"), QLatin1String("delete"), - QLatin1String("do"), QLatin1String("dynamic_cast"), QLatin1String("else"), - QLatin1String("enum"), QLatin1String("explicit"), QLatin1String("export"), - QLatin1String("extern"), QLatin1String("false"), QLatin1String("for"), - QLatin1String("friend"), QLatin1String("goto"), QLatin1String("if"), - QLatin1String("include"), QLatin1String("inline"), QLatin1String("monitor"), - QLatin1String("mutable"), QLatin1String("namespace"), QLatin1String("new"), - QLatin1String("not"), QLatin1String("not_eq"), QLatin1String("operator"), - QLatin1String("or"), QLatin1String("or_eq"), QLatin1String("private"), - QLatin1String("protected"), QLatin1String("public"), QLatin1String("register"), - QLatin1String("reinterpret_cast"), QLatin1String("return"), QLatin1String("sizeof"), - QLatin1String("static"), QLatin1String("static_cast"), QLatin1String("struct"), - QLatin1String("switch"), QLatin1String("template"), QLatin1String("this"), - QLatin1String("throw"), QLatin1String("true"), QLatin1String("try"), - QLatin1String("typedef"), QLatin1String("typeid"), QLatin1String("typename"), - QLatin1String("union"), QLatin1String("using"), QLatin1String("virtual"), - QLatin1String("volatile"), QLatin1String("wchar_t"), QLatin1String("while"), - QLatin1String("xor"), QLatin1String("xor_eq"), QLatin1String("synchronized"), - // Qt specific - QLatin1String("signals"), QLatin1String("slots"), QLatin1String("emit") - }; - - QString code = in; - QString out; - QStringView text; - int braceDepth = 0; - int parenDepth = 0; - int i = 0; - int start = 0; - int finish = 0; - QChar ch; - static const QRegularExpression classRegExp(QRegularExpression::anchoredPattern("Qt?(?:[A-Z3]+[a-z][A-Za-z]*|t)")); - static const QRegularExpression functionRegExp(QRegularExpression::anchoredPattern("q([A-Z][a-z]+)+")); - static const QRegularExpression findFunctionRegExp(QStringLiteral("^\\s*\\(")); - bool atEOF = false; - - auto readChar = [&]() { - if (i < code.size()) - ch = code[i++]; - else - atEOF = true; - }; - - readChar(); - while (!atEOF) { - QString tag; - bool target = false; - - if (ch.isLetter() || ch == '_') { - QString ident; - do { - ident += ch; - finish = i; - readChar(); - } while (!atEOF && (ch.isLetterOrNumber() || ch == '_')); - - if (classRegExp.match(ident).hasMatch()) { - tag = QStringLiteral("type"); - } else if (functionRegExp.match(ident).hasMatch()) { - tag = QStringLiteral("func"); - target = true; - } else if (types.contains(ident)) { - tag = QStringLiteral("type"); - } else if (keywords.contains(ident)) { - tag = QStringLiteral("keyword"); - } else if (braceDepth == 0 && parenDepth == 0) { - if (code.indexOf(findFunctionRegExp, i - 1) == i - 1) - tag = QStringLiteral("func"); - target = true; - } - } else if (ch.isDigit()) { - do { - finish = i; - readChar(); - } while (!atEOF && (ch.isLetterOrNumber() || ch == '.' || ch == '\'')); - tag = QStringLiteral("number"); - } else { - switch (ch.unicode()) { - case '+': - case '-': - case '!': - case '%': - case '^': - case '&': - case '*': - case ',': - case '.': - case '<': - case '=': - case '>': - case '?': - case '[': - case ']': - case '|': - case '~': - finish = i; - readChar(); - tag = QStringLiteral("op"); - break; - case '"': - finish = i; - readChar(); - - while (!atEOF && ch != '"') { - if (ch == '\\') - readChar(); - readChar(); - } - finish = i; - readChar(); - tag = QStringLiteral("string"); - break; - case '#': - finish = i; - readChar(); - while (!atEOF && ch != '\n') { - if (ch == '\\') - readChar(); - finish = i; - readChar(); - } - tag = QStringLiteral("preprocessor"); - break; - case '\'': - finish = i; - readChar(); - - while (!atEOF && ch != '\'') { - if (ch == '\\') - readChar(); - readChar(); - } - finish = i; - readChar(); - tag = QStringLiteral("char"); - break; - case '(': - finish = i; - readChar(); - ++parenDepth; - break; - case ')': - finish = i; - readChar(); - --parenDepth; - break; - case ':': - finish = i; - readChar(); - if (!atEOF && ch == ':') { - finish = i; - readChar(); - tag = QStringLiteral("op"); - } - break; - case '/': - finish = i; - readChar(); - if (!atEOF && ch == '/') { - do { - finish = i; - readChar(); - } while (!atEOF && ch != '\n'); - tag = QStringLiteral("comment"); - } else if (ch == '*') { - bool metAster = false; - bool metAsterSlash = false; - - finish = i; - readChar(); - - while (!metAsterSlash) { - if (atEOF) - break; - if (ch == '*') - metAster = true; - else if (metAster && ch == '/') - metAsterSlash = true; - else - metAster = false; - finish = i; - readChar(); - } - tag = QStringLiteral("comment"); - } else { - tag = QStringLiteral("op"); - } - break; - case '{': - finish = i; - readChar(); - braceDepth++; - break; - case '}': - finish = i; - readChar(); - braceDepth--; - break; - default: - finish = i; - readChar(); - } - } - - text = QStringView{code}.mid(start, finish - start); - start = finish; - - if (!tag.isEmpty()) { - out += QStringLiteral("<@"); - out += tag; - if (target) { - out += QStringLiteral(" target=\""); - out += text; - out += QStringLiteral("()\""); - } - out += QStringLiteral(">"); - } - - appendProtectedString(&out, text); - - if (!tag.isEmpty()) { - out += QStringLiteral(""); - } - } - - if (start < code.size()) { - appendProtectedString(&out, QStringView{code}.mid(start)); - } - - return out; -} - -QT_END_NAMESPACE diff --git a/src/qdoc/cppcodemarker.h b/src/qdoc/cppcodemarker.h deleted file mode 100644 index b0c5f3615..000000000 --- a/src/qdoc/cppcodemarker.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CPPCODEMARKER_H -#define CPPCODEMARKER_H - -#include "codemarker.h" - -QT_BEGIN_NAMESPACE - -class CppCodeMarker : public CodeMarker -{ -public: - CppCodeMarker() = default; - ~CppCodeMarker() override = default; - - bool recognizeCode(const QString &code) override; - bool recognizeExtension(const QString &ext) override; - bool recognizeLanguage(const QString &lang) override; - [[nodiscard]] Atom::AtomType atomType() const override; - QString markedUpCode(const QString &code, const Node *relative, - const Location &location) override; - QString markedUpSynopsis(const Node *node, const Node *relative, Section::Style style) override; - QString markedUpQmlItem(const Node *node, bool summary) override; - QString markedUpName(const Node *node) override; - QString markedUpEnumValue(const QString &enumValue, const Node *relative) override; - QString markedUpInclude(const QString &include) override; - -private: - QString addMarkUp(const QString &protectedCode, const Node *relative, const Location &location); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp deleted file mode 100644 index 9b425114c..000000000 --- a/src/qdoc/cppcodeparser.cpp +++ /dev/null @@ -1,977 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "cppcodeparser.h" - -#include "access.h" -#include "classnode.h" -#include "collectionnode.h" -#include "config.h" -#include "examplenode.h" -#include "externalpagenode.h" -#include "functionnode.h" -#include "generator.h" -#include "headernode.h" -#include "namespacenode.h" -#include "qdocdatabase.h" -#include "qmltypenode.h" -#include "qmlpropertynode.h" -#include "sharedcommentnode.h" -#include "utilities.h" - -#include -#include - -#include - -using namespace Qt::Literals::StringLiterals; - -QT_BEGIN_NAMESPACE - -/* qmake ignore Q_OBJECT */ - -QSet CppCodeParser::m_excludeDirs; -QSet CppCodeParser::m_excludeFiles; - -/* - All these can appear in a C++ namespace. Don't add - anything that can't be in a C++ namespace. - */ -static const QMap s_nodeTypeMap{ - { COMMAND_NAMESPACE, Node::Namespace }, { COMMAND_NAMESPACE, Node::Namespace }, - { COMMAND_CLASS, Node::Class }, { COMMAND_STRUCT, Node::Struct }, - { COMMAND_UNION, Node::Union }, { COMMAND_ENUM, Node::Enum }, - { COMMAND_TYPEALIAS, Node::TypeAlias }, { COMMAND_TYPEDEF, Node::Typedef }, - { COMMAND_PROPERTY, Node::Property }, { COMMAND_VARIABLE, Node::Variable } -}; - -typedef bool (Node::*NodeTypeTestFunc)() const; -static const QMap s_nodeTypeTestFuncMap{ - { COMMAND_NAMESPACE, &Node::isNamespace }, { COMMAND_CLASS, &Node::isClassNode }, - { COMMAND_STRUCT, &Node::isStruct }, { COMMAND_UNION, &Node::isUnion }, - { COMMAND_ENUM, &Node::isEnumType }, { COMMAND_TYPEALIAS, &Node::isTypeAlias }, - { COMMAND_TYPEDEF, &Node::isTypedef }, { COMMAND_PROPERTY, &Node::isProperty }, - { COMMAND_VARIABLE, &Node::isVariable }, -}; - -CppCodeParser::CppCodeParser() -{ - Config &config = Config::instance(); - QStringList exampleFilePatterns{config.get(CONFIG_EXAMPLES - + Config::dot - + CONFIG_FILEEXTENSIONS).asStringList()}; - - // Used for excluding dirs and files from the list of example files - const auto &excludeDirsList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS); - m_excludeDirs = QSet(excludeDirsList.cbegin(), excludeDirsList.cend()); - const auto &excludeFilesList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS); - m_excludeFiles = QSet(excludeFilesList.cbegin(), excludeFilesList.cend()); - - if (!exampleFilePatterns.isEmpty()) - m_exampleNameFilter = exampleFilePatterns.join(' '); - else - m_exampleNameFilter = "*.cpp *.h *.js *.xq *.svg *.xml *.ui"; - - QStringList exampleImagePatterns{config.get(CONFIG_EXAMPLES - + Config::dot - + CONFIG_IMAGEEXTENSIONS).asStringList()}; - - if (!exampleImagePatterns.isEmpty()) - m_exampleImageFilter = exampleImagePatterns.join(' '); - else - m_exampleImageFilter = "*.png"; - - m_showLinkErrors = !config.get(CONFIG_NOLINKERRORS).asBool(); -} - -/*! - Clear the exclude directories and exclude files sets. - */ -CppCodeParser::~CppCodeParser() -{ - m_excludeDirs.clear(); - m_excludeFiles.clear(); -} - -/*! - Process the topic \a command found in the \a doc with argument \a arg. - */ -Node *CppCodeParser::processTopicCommand(const Doc &doc, const QString &command, - const ArgPair &arg) -{ - QDocDatabase* database = QDocDatabase::qdocDB(); - - if (command == COMMAND_FN) { - Q_UNREACHABLE(); - } else if (s_nodeTypeMap.contains(command)) { - /* - We should only get in here if the command refers to - something that can appear in a C++ namespace, - i.e. a class, another namespace, an enum, a typedef, - a property or a variable. I think these are handled - this way to allow the writer to refer to the entity - without including the namespace qualifier. - */ - Node::NodeType type = s_nodeTypeMap[command]; - QStringList words = arg.first.split(QLatin1Char(' ')); - QStringList path; - qsizetype idx = 0; - Node *node = nullptr; - - if (type == Node::Variable && words.size() > 1) - idx = words.size() - 1; - path = words[idx].split("::"); - - node = database->findNodeInOpenNamespace(path, s_nodeTypeTestFuncMap[command]); - if (node == nullptr) - node = database->findNodeByNameAndType(path, s_nodeTypeTestFuncMap[command]); - // Allow representing a type alias as a class - if (node == nullptr && command == COMMAND_CLASS) { - node = database->findNodeByNameAndType(path, &Node::isTypeAlias); - if (node) { - auto access = node->access(); - auto loc = node->location(); - auto templateDecl = node->templateDecl(); - node = new ClassNode(Node::Class, node->parent(), node->name()); - node->setAccess(access); - node->setLocation(loc); - node->setTemplateDecl(templateDecl); - } - } - if (node == nullptr) { - if (CodeParser::isWorthWarningAbout(doc)) { - doc.location().warning( - QStringLiteral("Cannot find '%1' specified with '\\%2' in any header file") - .arg(arg.first, command)); - } - } else if (node->isAggregate()) { - if (type == Node::Namespace) { - auto *ns = static_cast(node); - ns->markSeen(); - ns->setWhereDocumented(ns->tree()->camelCaseModuleName()); - } - /* - This treats a class as a namespace. - */ - if ((type == Node::Class) || (type == Node::Namespace) || (type == Node::Struct) - || (type == Node::Union)) { - if (path.size() > 1) { - path.pop_back(); - QString ns = path.join(QLatin1String("::")); - database->insertOpenNamespace(ns); - } - } - } - return node; - } else if (command == COMMAND_EXAMPLE) { - if (Config::generateExamples) { - auto *en = new ExampleNode(database->primaryTreeRoot(), arg.first); - en->setLocation(doc.startLocation()); - setExampleFileLists(en); - return en; - } - } else if (command == COMMAND_EXTERNALPAGE) { - auto *epn = new ExternalPageNode(database->primaryTreeRoot(), arg.first); - epn->setLocation(doc.startLocation()); - return epn; - } else if (command == COMMAND_HEADERFILE) { - auto *hn = new HeaderNode(database->primaryTreeRoot(), arg.first); - hn->setLocation(doc.startLocation()); - return hn; - } else if (command == COMMAND_GROUP) { - CollectionNode *cn = database->addGroup(arg.first); - cn->setLocation(doc.startLocation()); - cn->markSeen(); - return cn; - } else if (command == COMMAND_MODULE) { - CollectionNode *cn = database->addModule(arg.first); - cn->setLocation(doc.startLocation()); - cn->markSeen(); - return cn; - } else if (command == COMMAND_QMLMODULE) { - QStringList blankSplit = arg.first.split(QLatin1Char(' ')); - CollectionNode *cn = database->addQmlModule(blankSplit[0]); - cn->setLogicalModuleInfo(blankSplit); - cn->setLocation(doc.startLocation()); - cn->markSeen(); - return cn; - } else if (command == COMMAND_PAGE) { - auto *pn = new PageNode(database->primaryTreeRoot(), arg.first.split(' ').front()); - pn->setLocation(doc.startLocation()); - return pn; - } else if (command == COMMAND_QMLTYPE || - command == COMMAND_QMLVALUETYPE || - command == COMMAND_QMLBASICTYPE) { - QmlTypeNode *qcn = nullptr; - auto nodeType = (command == COMMAND_QMLTYPE) ? Node::QmlType : Node::QmlValueType; - Node *candidate = database->primaryTreeRoot()->findChildNode(arg.first, Node::QML); - qcn = (candidate && candidate->nodeType() == nodeType) ? - static_cast(candidate) : - new QmlTypeNode(database->primaryTreeRoot(), arg.first, nodeType); - qcn->setLocation(doc.startLocation()); - return qcn; - } else if ((command == COMMAND_QMLSIGNAL) || (command == COMMAND_QMLMETHOD) - || (command == COMMAND_QMLATTACHEDSIGNAL) || (command == COMMAND_QMLATTACHEDMETHOD)) { - Q_UNREACHABLE(); - } - return nullptr; -} - -/*! - A QML property argument has the form... - - :: - :::: - - This function splits the argument into one of those - two forms. The three part form is the old form, which - was used before the creation of Qt Quick 2 and Qt - Components. A is the QML equivalent of a - C++ namespace. So this function splits \a arg on "::" - and stores the parts in \a type, \a module, \a qmlTypeName, - and \a name, and returns \c true. If any part other than - \a module is not found, a qdoc warning is emitted and - false is returned. - - \note The two QML types \e{Component} and \e{QtObject} - never have a module qualifier. - */ -bool CppCodeParser::splitQmlPropertyArg(const QString &arg, QString &type, QString &module, - QString &qmlTypeName, QString &name, - const Location &location) -{ - QStringList blankSplit = arg.split(QLatin1Char(' ')); - if (blankSplit.size() > 1) { - type = blankSplit[0]; - QStringList colonSplit(blankSplit[1].split("::")); - if (colonSplit.size() == 3) { - module = colonSplit[0]; - qmlTypeName = colonSplit[1]; - name = colonSplit[2]; - return true; - } - if (colonSplit.size() == 2) { - module.clear(); - qmlTypeName = colonSplit[0]; - name = colonSplit[1]; - return true; - } - location.warning( - QStringLiteral("Unrecognizable QML module/component qualifier for %1").arg(arg)); - } else { - location.warning(QStringLiteral("Missing property type for %1").arg(arg)); - } - return false; -} - -/*! - */ -void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocList &docs) -{ - const TopicList &topics = doc.topicsUsed(); - if (topics.isEmpty()) - return; - - QString arg; - QString type; - QString group; - QString module; - QString property; - QString qmlTypeName; - - Topic topic = topics.at(0); - arg = topic.m_args; - if (splitQmlPropertyArg(arg, type, module, qmlTypeName, property, doc.location())) { - qsizetype i = property.indexOf('.'); - if (i != -1) - group = property.left(i); - } - - QDocDatabase* database = QDocDatabase::qdocDB(); - - NodeList sharedNodes; - QmlTypeNode *qmlType = database->findQmlType(module, qmlTypeName); - // Note: Constructing a QmlType node by default, as opposed to QmlValueType. - // This may lead to unexpected behavior if documenting \qmlvaluetype's properties - // before the type itself. - if (qmlType == nullptr) - qmlType = new QmlTypeNode(database->primaryTreeRoot(), qmlTypeName, Node::QmlType); - - for (const auto &topicCommand : topics) { - QString cmd = topicCommand.m_topic; - arg = topicCommand.m_args; - if ((cmd == COMMAND_QMLPROPERTY) || (cmd == COMMAND_QMLATTACHEDPROPERTY)) { - bool attached = cmd.contains(QLatin1String("attached")); - if (splitQmlPropertyArg(arg, type, module, qmlTypeName, property, doc.location())) { - if (qmlType != database->findQmlType(module, qmlTypeName)) { - doc.startLocation().warning( - QStringLiteral( - "All properties in a group must belong to the same type: '%1'") - .arg(arg)); - continue; - } - QmlPropertyNode *existingProperty = qmlType->hasQmlProperty(property, attached); - if (existingProperty) { - processMetaCommands(doc, existingProperty); - if (!doc.body().isEmpty()) { - doc.startLocation().warning( - QStringLiteral("QML property documented multiple times: '%1'") - .arg(arg), QStringLiteral("also seen here: %1") - .arg(existingProperty->location().toString())); - } - continue; - } - auto *qpn = new QmlPropertyNode(qmlType, property, type, attached); - qpn->setLocation(doc.startLocation()); - qpn->setGenus(Node::QML); - nodes.append(qpn); - docs.append(doc); - sharedNodes << qpn; - } - } else { - doc.startLocation().warning( - QStringLiteral("Command '\\%1'; not allowed with QML property commands") - .arg(cmd)); - } - } - - // Construct a SharedCommentNode (scn) if multiple topics generated - // valid nodes. Note that it's important to do this *after* constructing - // the topic nodes - which need to be written to index before the related - // scn. - if (sharedNodes.size() > 1) { - auto *scn = new SharedCommentNode(qmlType, sharedNodes.size(), group); - scn->setLocation(doc.startLocation()); - nodes.append(scn); - docs.append(doc); - for (const auto n : sharedNodes) - scn->append(n); - scn->sort(); - } -} - -/*! - Process the metacommand \a command in the context of the - \a node associated with the topic command and the \a doc. - \a arg is the argument to the metacommand. - - \a node is guaranteed to be non-null. - */ -void CppCodeParser::processMetaCommand(const Doc &doc, const QString &command, - const ArgPair &argPair, Node *node) -{ - QDocDatabase* database = QDocDatabase::qdocDB(); - - QString arg = argPair.first; - if (command == COMMAND_INHEADERFILE) { - // TODO: [incorrect-constructs][header-arg] - // The emptiness check for arg is required as, - // currently, DocParser fancies passing (without any warning) - // incorrect constructs doen the chain, such as an - // "\inheaderfile" command with no argument. - // - // As it is the case here, we require further sanity checks to - // preserve some of the semantic for the later phases. - // This generally has a ripple effect on the whole codebase, - // making it more complex and increasesing the surface of bugs. - // - // The following emptiness check should be removed as soon as - // DocParser is enhanced with correct semantics. - if (node->isAggregate() && !arg.isEmpty()) - static_cast(node)->setIncludeFile(arg); - else - doc.location().warning(QStringLiteral("Ignored '\\%1'").arg(COMMAND_INHEADERFILE)); - } else if (command == COMMAND_OVERLOAD) { - /* - Note that this might set the overload flag of the - primary function. This is ok because the overload - flags and overload numbers will be resolved later - in Aggregate::normalizeOverloads(). - */ - if (node->isFunction()) - static_cast(node)->setOverloadFlag(); - else if (node->isSharedCommentNode()) - static_cast(node)->setOverloadFlags(); - else - doc.location().warning(QStringLiteral("Ignored '\\%1'").arg(COMMAND_OVERLOAD)); - } else if (command == COMMAND_REIMP) { - if (node->parent() && !node->parent()->isInternal()) { - if (node->isFunction()) { - auto *fn = static_cast(node); - // The clang visitor class will have set the - // qualified name of the overridden function. - // If the name of the overridden function isn't - // set, issue a warning. - if (fn->overridesThis().isEmpty() && CodeParser::isWorthWarningAbout(doc)) { - doc.location().warning( - QStringLiteral("Cannot find base function for '\\%1' in %2()") - .arg(COMMAND_REIMP, node->name()), - QStringLiteral("The function either doesn't exist in any " - "base class with the same signature or it " - "exists but isn't virtual.")); - } - fn->setReimpFlag(); - } else { - doc.location().warning( - QStringLiteral("Ignored '\\%1' in %2").arg(COMMAND_REIMP, node->name())); - } - } - } else if (command == COMMAND_RELATES) { - QStringList path = arg.split("::"); - Aggregate *aggregate = database->findRelatesNode(path); - if (aggregate == nullptr) - aggregate = new ProxyNode(node->root(), arg); - - if (node->parent() == aggregate) { // node is already a child of aggregate - doc.location().warning(QStringLiteral("Invalid '\\%1' (already a member of '%2')") - .arg(COMMAND_RELATES, arg)); - } else { - if (node->isAggregate()) { - doc.location().warning(QStringLiteral("Invalid '\\%1' not allowed in '\\%2'") - .arg(COMMAND_RELATES, node->nodeTypeString())); - } else if (!node->isRelatedNonmember() && - !node->parent()->isNamespace() && !node->parent()->isHeader()) { - if (!doc.isInternal()) { - doc.location().warning(QStringLiteral("Invalid '\\%1' ('%2' must be global)") - .arg(COMMAND_RELATES, node->name())); - } - } else if (!node->isRelatedNonmember() && !node->parent()->isHeader()) { - aggregate->adoptChild(node); - node->setRelatedNonmember(true); - } else { - /* - There are multiple \relates commands. This - one is not the first, so clone the node as - a child of aggregate. - */ - Node *clone = node->clone(aggregate); - if (clone == nullptr) { - doc.location().warning( - QStringLiteral("Invalid '\\%1' (multiple uses not allowed in '%2')") - .arg(COMMAND_RELATES, node->nodeTypeString())); - } else { - clone->setRelatedNonmember(true); - } - } - } - } else if (command == COMMAND_NEXTPAGE) { - CodeParser::setLink(node, Node::NextLink, arg); - } else if (command == COMMAND_PREVIOUSPAGE) { - CodeParser::setLink(node, Node::PreviousLink, arg); - } else if (command == COMMAND_STARTPAGE) { - CodeParser::setLink(node, Node::StartLink, arg); - } else if (command == COMMAND_QMLINHERITS) { - if (node->name() == arg) - doc.location().warning(QStringLiteral("%1 tries to inherit itself").arg(arg)); - else if (node->isQmlType()) { - auto *qmlType = static_cast(node); - qmlType->setQmlBaseName(arg); - } - } else if (command == COMMAND_QMLINSTANTIATES) { - if (node->isQmlType()) { - ClassNode *classNode = database->findClassNode(arg.split("::")); - if (classNode) - node->setClassNode(classNode); - else if (m_showLinkErrors) { - doc.location().warning( - QStringLiteral("C++ class %2 not found: \\%1 %2") - .arg(command, arg)); - } - } else { - doc.location().warning( - QStringLiteral("\\%1 is only allowed in \\%2") - .arg(command, COMMAND_QMLTYPE)); - } - } else if (command == COMMAND_DEFAULT) { - if (!node->isQmlProperty()) { - doc.location().warning(QStringLiteral("Ignored '\\%1', applies only to '\\%2'") - .arg(command, COMMAND_QMLPROPERTY)); - } else if (arg.isEmpty()) { - doc.location().warning(QStringLiteral("Expected an argument for '\\%1' (maybe you meant '\\%2'?)") - .arg(command, COMMAND_QMLDEFAULT)); - } else { - static_cast(node)->setDefaultValue(arg); - } - } else if (command == COMMAND_QMLDEFAULT) { - node->markDefault(); - } else if (command == COMMAND_QMLREADONLY) { - node->markReadOnly(true); - } else if (command == COMMAND_QMLREQUIRED) { - if (!node->isQmlProperty()) - doc.location().warning(QStringLiteral("Ignored '\\%1'").arg(COMMAND_QMLREQUIRED)); - else - static_cast(node)->setRequired(); - } else if ((command == COMMAND_QMLABSTRACT) || (command == COMMAND_ABSTRACT)) { - if (node->isQmlType()) - node->setAbstract(true); - } else if (command == COMMAND_DEPRECATED) { - node->setStatus(Node::Deprecated); - if (!argPair.second.isEmpty()) - node->setDeprecatedSince(argPair.second); - } else if (command == COMMAND_INGROUP || command == COMMAND_INPUBLICGROUP) { - // Note: \ingroup and \inpublicgroup are the same (and now recognized as such). - database->addToGroup(arg, node); - } else if (command == COMMAND_INMODULE) { - database->addToModule(arg, node); - } else if (command == COMMAND_INQMLMODULE) { - database->addToQmlModule(arg, node); - } else if (command == COMMAND_OBSOLETE) { - node->setStatus(Node::Deprecated); - } else if (command == COMMAND_NONREENTRANT) { - node->setThreadSafeness(Node::NonReentrant); - } else if (command == COMMAND_PRELIMINARY) { - // \internal wins. - if (!node->isInternal()) - node->setStatus(Node::Preliminary); - } else if (command == COMMAND_INTERNAL) { - if (!Config::instance().showInternal()) - node->markInternal(); - } else if (command == COMMAND_REENTRANT) { - node->setThreadSafeness(Node::Reentrant); - } else if (command == COMMAND_SINCE) { - node->setSince(arg); - } else if (command == COMMAND_WRAPPER) { - node->setWrapper(); - } else if (command == COMMAND_THREADSAFE) { - node->setThreadSafeness(Node::ThreadSafe); - } else if (command == COMMAND_TITLE) { - if (!node->setTitle(arg)) - doc.location().warning(QStringLiteral("Ignored '\\%1'").arg(COMMAND_TITLE)); - else if (node->isExample()) - database->addExampleNode(static_cast(node)); - } else if (command == COMMAND_SUBTITLE) { - if (!node->setSubtitle(arg)) - doc.location().warning(QStringLiteral("Ignored '\\%1'").arg(COMMAND_SUBTITLE)); - } else if (command == COMMAND_QTVARIABLE) { - node->setQtVariable(arg); - if (!node->isModule() && !node->isQmlModule()) - doc.location().warning( - QStringLiteral( - "Command '\\%1' is only meaningful in '\\module' and '\\qmlmodule'.") - .arg(COMMAND_QTVARIABLE)); - } else if (command == COMMAND_QTCMAKEPACKAGE) { - node->setQtCMakeComponent(arg); - if (!node->isModule()) - doc.location().warning( - QStringLiteral("Command '\\%1' is only meaningful in '\\module'.") - .arg(COMMAND_QTCMAKEPACKAGE)); - } else if (command == COMMAND_MODULESTATE ) { - if (!node->isModule() && !node->isQmlModule()) { - doc.location().warning( - QStringLiteral( - "Command '\\%1' is only meaningful in '\\module' and '\\qmlmodule'.") - .arg(COMMAND_MODULESTATE)); - } else { - static_cast(node)->setState(arg); - } - } else if (command == COMMAND_NOAUTOLIST) { - if (!node->isCollectionNode() && !node->isExample()) { - doc.location().warning( - QStringLiteral( - "Command '\\%1' is only meaningful in '\\module', '\\qmlmodule', `\\group` and `\\example`.") - .arg(COMMAND_NOAUTOLIST)); - } else { - static_cast(node)->setNoAutoList(true); - } - } else if (command == COMMAND_ATTRIBUTION) { - // TODO: This condition is not currently exact enough, as it - // will allow any non-aggregate `PageNode` to use the command, - // For example, an `ExampleNode`. - // - // The command is intended only for internal usage by - // "qattributionscanner" and should only work on `PageNode`s - // that are generated from a "\page" command. - // - // It is already possible to provide a more restricted check, - // albeit in a somewhat dirty way. It is not expected that - // this warning will have any particular use. - // If it so happens that a case where the too-broad scope of - // the warning is a problem or hides a bug, modify the - // condition to be restrictive enough. - // Otherwise, wait until a more torough look at QDoc's - // internal representations an way to enable "Attribution - // Pages" is performed before looking at the issue again. - if (!node->isTextPageNode()) { - doc.location().warning(u"Command '\\%1' is only meaningful in '\\%2'"_s.arg(COMMAND_ATTRIBUTION, COMMAND_PAGE)); - } else { static_cast(node)->markAttribution(); } - } -} - -/*! - The topic command has been processed, and now \a doc and - \a node are passed to this function to get the metacommands - from \a doc and process them one at a time. \a node is the - node where \a doc resides. - */ -void CppCodeParser::processMetaCommands(const Doc &doc, Node *node) -{ - const QStringList metaCommandsUsed = doc.metaCommandsUsed().values(); - for (const auto &command : metaCommandsUsed) { - const ArgList args = doc.metaCommandArgs(command); - for (const auto &arg : args) - processMetaCommand(doc, command, arg, node); - } -} - -/*! - Parse QML signal/method topic commands. - */ -FunctionNode *CppCodeParser::parseOtherFuncArg(const QString &topic, const Location &location, - const QString &funcArg) -{ - QString funcName; - QString returnType; - - qsizetype leftParen = funcArg.indexOf(QChar('(')); - if (leftParen > 0) - funcName = funcArg.left(leftParen); - else - funcName = funcArg; - qsizetype firstBlank = funcName.indexOf(QChar(' ')); - if (firstBlank > 0) { - returnType = funcName.left(firstBlank); - funcName = funcName.right(funcName.size() - firstBlank - 1); - } - - QStringList colonSplit(funcName.split("::")); - if (colonSplit.size() < 2) { - QString msg = "Unrecognizable QML module/component qualifier for " + funcArg; - location.warning(msg.toLatin1().data()); - return nullptr; - } - QString moduleName; - QString elementName; - if (colonSplit.size() > 2) { - moduleName = colonSplit[0]; - elementName = colonSplit[1]; - } else { - elementName = colonSplit[0]; - } - funcName = colonSplit.last(); - - QDocDatabase* database = QDocDatabase::qdocDB(); - - Aggregate *aggregate = database->findQmlType(moduleName, elementName); - if (aggregate == nullptr) - return nullptr; - - QString params; - QStringList leftParenSplit = funcArg.split('('); - if (leftParenSplit.size() > 1) { - QStringList rightParenSplit = leftParenSplit[1].split(')'); - if (!rightParenSplit.empty()) - params = rightParenSplit[0]; - } - - FunctionNode::Metaness metaness = FunctionNode::getMetanessFromTopic(topic); - bool attached = topic.contains(QLatin1String("attached")); - auto *fn = new FunctionNode(metaness, aggregate, funcName, attached); - fn->setAccess(Access::Public); - fn->setLocation(location); - fn->setReturnType(returnType); - fn->setParameters(params); - return fn; -} - -/*! - Parse the macro arguments in \a macroArg ad hoc, without using - any actual parser. If successful, return a pointer to the new - FunctionNode for the macro. Otherwise return null. \a location - is used for reporting errors. - */ -FunctionNode *CppCodeParser::parseMacroArg(const Location &location, const QString ¯oArg) -{ - QDocDatabase* database = QDocDatabase::qdocDB(); - - QStringList leftParenSplit = macroArg.split('('); - if (leftParenSplit.isEmpty()) - return nullptr; - QString macroName; - FunctionNode *oldMacroNode = nullptr; - QStringList blankSplit = leftParenSplit[0].split(' '); - if (!blankSplit.empty()) { - macroName = blankSplit.last(); - oldMacroNode = database->findMacroNode(macroName); - } - QString returnType; - if (blankSplit.size() > 1) { - blankSplit.removeLast(); - returnType = blankSplit.join(' '); - } - QString params; - if (leftParenSplit.size() > 1) { - const QString &afterParen = leftParenSplit.at(1); - qsizetype rightParen = afterParen.indexOf(')'); - if (rightParen >= 0) - params = afterParen.left(rightParen); - } - int i = 0; - while (i < macroName.size() && !macroName.at(i).isLetter()) - i++; - if (i > 0) { - returnType += QChar(' ') + macroName.left(i); - macroName = macroName.mid(i); - } - FunctionNode::Metaness metaness = FunctionNode::MacroWithParams; - if (params.isEmpty()) - metaness = FunctionNode::MacroWithoutParams; - auto *macro = new FunctionNode(metaness, database->primaryTreeRoot(), macroName); - macro->setAccess(Access::Public); - macro->setLocation(location); - macro->setReturnType(returnType); - macro->setParameters(params); - if (macro->compare(oldMacroNode)) { - location.warning(QStringLiteral("\\macro %1 documented more than once") - .arg(macroArg), QStringLiteral("also seen here: %1") - .arg(oldMacroNode->doc().location().toString())); - } - return macro; -} - -void CppCodeParser::setExampleFileLists(ExampleNode *en) -{ - Config &config = Config::instance(); - QString fullPath = config.getExampleProjectFile(en->name()); - if (fullPath.isEmpty()) { - QString details = QLatin1String("Example directories: ") - + config.getCanonicalPathList(CONFIG_EXAMPLEDIRS).join(QLatin1Char(' ')); - en->location().warning( - QStringLiteral("Cannot find project file for example '%1'").arg(en->name()), - details); - return; - } - - QDir exampleDir(QFileInfo(fullPath).dir()); - - QStringList exampleFiles = Config::getFilesHere(exampleDir.path(), m_exampleNameFilter, - Location(), m_excludeDirs, m_excludeFiles); - // Search for all image files under the example project, excluding doc/images directory. - QSet excludeDocDirs(m_excludeDirs); - excludeDocDirs.insert(exampleDir.path() + QLatin1String("/doc/images")); - QStringList imageFiles = Config::getFilesHere(exampleDir.path(), m_exampleImageFilter, - Location(), excludeDocDirs, m_excludeFiles); - if (!exampleFiles.isEmpty()) { - // move main.cpp to the end, if it exists - QString mainCpp; - - const auto isGeneratedOrMainCpp = [&mainCpp](const QString &fileName) { - if (fileName.endsWith("/main.cpp")) { - if (mainCpp.isEmpty()) - mainCpp = fileName; - return true; - } - return fileName.contains("/qrc_") || fileName.contains("/moc_") - || fileName.contains("/ui_"); - }; - - exampleFiles.erase( - std::remove_if(exampleFiles.begin(), exampleFiles.end(), isGeneratedOrMainCpp), - exampleFiles.end()); - - if (!mainCpp.isEmpty()) - exampleFiles.append(mainCpp); - - // Add any resource and project files - exampleFiles += Config::getFilesHere(exampleDir.path(), - QLatin1String("*.qrc *.pro *.qmlproject *.pyproject CMakeLists.txt qmldir")); - } - - const qsizetype pathLen = exampleDir.path().size() - en->name().size(); - for (auto &file : exampleFiles) - file = file.mid(pathLen); - for (auto &file : imageFiles) - file = file.mid(pathLen); - - en->setFiles(exampleFiles, fullPath.mid(pathLen)); - en->setImages(imageFiles); -} - -/*! - returns true if \a t is \e {qmlsignal}, \e {qmlmethod}, - \e {qmlattachedsignal}, or \e {qmlattachedmethod}. - */ -bool CppCodeParser::isQMLMethodTopic(const QString &t) -{ - return (t == COMMAND_QMLSIGNAL || t == COMMAND_QMLMETHOD || t == COMMAND_QMLATTACHEDSIGNAL - || t == COMMAND_QMLATTACHEDMETHOD); -} - -/*! - Returns true if \a t is \e {qmlproperty}, \e {qmlpropertygroup}, - or \e {qmlattachedproperty}. - */ -bool CppCodeParser::isQMLPropertyTopic(const QString &t) -{ - return (t == COMMAND_QMLPROPERTY || t == COMMAND_QMLATTACHEDPROPERTY); -} - -void CppCodeParser::processTopicArgs(const Doc &doc, const QString &topic, NodeList &nodes, - DocList &docs) -{ - - QDocDatabase* database = QDocDatabase::qdocDB(); - - if (isQMLPropertyTopic(topic)) { - processQmlProperties(doc, nodes, docs); - } else { - ArgList args = doc.metaCommandArgs(topic); - Node *node = nullptr; - if (args.size() == 1) { - if (topic == COMMAND_FN) { - if (Config::instance().showInternal() || !doc.isInternal()) - node = CodeParser::parserForLanguage("Clang")->parseFnArg(doc.location(), args[0].first, args[0].second); - } else if (topic == COMMAND_MACRO) { - node = parseMacroArg(doc.location(), args[0].first); - } else if (isQMLMethodTopic(topic)) { - node = parseOtherFuncArg(topic, doc.location(), args[0].first); - } else if (topic == COMMAND_DONTDOCUMENT) { - database->primaryTree()->addToDontDocumentMap(args[0].first); - } else { - node = processTopicCommand(doc, topic, args[0]); - } - if (node != nullptr) { - nodes.append(node); - docs.append(doc); - } - } else if (args.size() > 1) { - QList sharedCommentNodes; - for (const auto &arg : std::as_const(args)) { - node = nullptr; - if (topic == COMMAND_FN) { - if (Config::instance().showInternal() || !doc.isInternal()) - node = CodeParser::parserForLanguage("Clang")->parseFnArg(doc.location(), arg.first, arg.second); - } else if (topic == COMMAND_MACRO) { - node = parseMacroArg(doc.location(), arg.first); - } else if (isQMLMethodTopic(topic)) { - node = parseOtherFuncArg(topic, doc.location(), arg.first); - } else { - node = processTopicCommand(doc, topic, arg); - } - if (node != nullptr) { - bool found = false; - for (SharedCommentNode *scn : sharedCommentNodes) { - if (scn->parent() == node->parent()) { - scn->append(node); - found = true; - break; - } - } - if (!found) { - auto *scn = new SharedCommentNode(node); - sharedCommentNodes.append(scn); - nodes.append(scn); - docs.append(doc); - } - processMetaCommands(doc, node); - } - } - for (auto *scn : sharedCommentNodes) - scn->sort(); - } - } -} - -/*! - For each node that is part of C++ API and produces a documentation - page, this function ensures that the node belongs to a module. - */ -static void checkModuleInclusion(Node *n) -{ - if (n->physicalModuleName().isEmpty()) { - if (n->isInAPI() && !n->name().isEmpty()) { - switch (n->nodeType()) { - case Node::Class: - case Node::Struct: - case Node::Union: - case Node::Namespace: - case Node::HeaderFile: - break; - default: - return; - } - n->setPhysicalModuleName(Generator::defaultModuleName()); - QDocDatabase::qdocDB()->addToModule(Generator::defaultModuleName(), n); - n->doc().location().warning( - QStringLiteral("Documentation for %1 '%2' has no \\inmodule command; " - "using project name by default: %3") - .arg(Node::nodeTypeString(n->nodeType()), n->name(), - n->physicalModuleName())); - } - } -} - -void CppCodeParser::processMetaCommands(NodeList &nodes, DocList &docs) -{ - QList::Iterator d = docs.begin(); - for (const auto &node : nodes) { - if (node != nullptr) { - processMetaCommands(*d, node); - node->setDoc(*d); - checkModuleInclusion(node); - if (node->isAggregate()) { - auto *aggregate = static_cast(node); - - if (!aggregate->includeFile()) { - Aggregate *parent = aggregate; - while (parent->physicalModuleName().isEmpty() && (parent->parent() != nullptr)) - parent = parent->parent(); - - if (parent == aggregate) - // TODO: Understand if the name can be empty. - // In theory it should not be possible as - // there would be no aggregate to refer to - // such that this code is never reached. - // - // If the name can be empty, this would - // endanger users of the include file down the - // line, forcing them to ensure that, further - // to there being an actual include file, that - // include file is not an empty string, such - // that we would require a different way to - // generate the include file here. - aggregate->setIncludeFile(aggregate->name()); - else if (aggregate->includeFile()) - aggregate->setIncludeFile(*parent->includeFile()); - } - } - } - ++d; - } -} - -/*! - * \internal - * \brief Checks if there are too many topic commands in \a doc. - * - * This method compares the commands used in \a doc with the set of topic - * commands. If zero or one topic command is found, or if all found topic - * commands are {\\qml*}-commands, the method returns \c false. - * - * If more than one topic command is found, QDoc issues a warning and the list - * of topic commands used in \a doc, and the method returns \c true. - */ -bool CppCodeParser::hasTooManyTopics(const Doc &doc) const -{ - const QSet topicCommandsUsed = CppCodeParser::topic_commands & doc.metaCommandsUsed(); - - if (topicCommandsUsed.empty() || topicCommandsUsed.size() == 1) - return false; - if (std::all_of(topicCommandsUsed.cbegin(), topicCommandsUsed.cend(), - [](const auto &cmd) { return cmd.startsWith(QLatin1String("qml")); })) - return false; - - const QStringList commands = topicCommandsUsed.values(); - const QString topicCommands{ std::accumulate( - commands.cbegin(), commands.cend(), QString{}, - [index = qsizetype{ 0 }, numberOfCommands = commands.size()]( - const QString &accumulator, const QString &topic) mutable -> QString { - return accumulator + QLatin1String("\\") + topic - + Utilities::separator(index++, numberOfCommands); - }) }; - - doc.location().warning( - QStringLiteral("Multiple topic commands found in comment: %1").arg(topicCommands)); - return true; -} - -QT_END_NAMESPACE diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h deleted file mode 100644 index b312ee6e9..000000000 --- a/src/qdoc/cppcodeparser.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef CPPCODEPARSER_H -#define CPPCODEPARSER_H - -#include "codeparser.h" - -QT_BEGIN_NAMESPACE - -class ClassNode; -class ExampleNode; -class FunctionNode; -class Aggregate; - -class CppCodeParser -{ -public: - static inline const QSet topic_commands{ - COMMAND_CLASS, COMMAND_DONTDOCUMENT, COMMAND_ENUM, COMMAND_EXAMPLE, - COMMAND_EXTERNALPAGE, COMMAND_FN, COMMAND_GROUP, COMMAND_HEADERFILE, - COMMAND_MACRO, COMMAND_MODULE, COMMAND_NAMESPACE, COMMAND_PAGE, - COMMAND_PROPERTY, COMMAND_TYPEALIAS, COMMAND_TYPEDEF, COMMAND_VARIABLE, - COMMAND_QMLTYPE, COMMAND_QMLPROPERTY, COMMAND_QMLPROPERTYGROUP, - COMMAND_QMLATTACHEDPROPERTY, COMMAND_QMLSIGNAL, COMMAND_QMLATTACHEDSIGNAL, - COMMAND_QMLMETHOD, COMMAND_QMLATTACHEDMETHOD, COMMAND_QMLVALUETYPE, COMMAND_QMLBASICTYPE, - COMMAND_QMLMODULE, COMMAND_STRUCT, COMMAND_UNION, - }; - - static inline const QSet meta_commands = QSet(CodeParser::common_meta_commands) - << COMMAND_INHEADERFILE << COMMAND_NEXTPAGE - << COMMAND_OVERLOAD << COMMAND_PREVIOUSPAGE - << COMMAND_QMLINSTANTIATES << COMMAND_REIMP - << COMMAND_RELATES; - -public: - CppCodeParser(); - ~CppCodeParser(); - - FunctionNode *parseMacroArg(const Location &location, const QString ¯oArg); - FunctionNode *parseOtherFuncArg(const QString &topic, const Location &location, - const QString &funcArg); - static bool isQMLMethodTopic(const QString &t); - static bool isQMLPropertyTopic(const QString &t); - - [[nodiscard]] bool hasTooManyTopics(const Doc &doc) const; - - void processTopicArgs(const Doc &doc, const QString &topic, NodeList &nodes, DocList &docs); - - void processMetaCommand(const Doc &doc, const QString &command, const ArgPair &argLocPair, - Node *node); - void processMetaCommands(const Doc &doc, Node *node); - void processMetaCommands(NodeList &nodes, DocList &docs); - -protected: - virtual Node *processTopicCommand(const Doc &doc, const QString &command, - const ArgPair &arg); - void processQmlProperties(const Doc &doc, NodeList &nodes, DocList &docs); - bool splitQmlPropertyArg(const QString &arg, QString &type, QString &module, QString &element, - QString &name, const Location &location); - -private: - void setExampleFileLists(ExampleNode *en); - -private: - static QSet m_excludeDirs; - static QSet m_excludeFiles; - QString m_exampleNameFilter; - QString m_exampleImageFilter; - bool m_showLinkErrors { false }; -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/doc.cpp b/src/qdoc/doc.cpp deleted file mode 100644 index 762af2ebd..000000000 --- a/src/qdoc/doc.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include "doc.h" - -#include "atom.h" -#include "config.h" -#include "codemarker.h" -#include "docparser.h" -#include "docprivate.h" -#include "generator.h" -#include "qmltypenode.h" -#include "quoter.h" -#include "text.h" - -QT_BEGIN_NAMESPACE - -using namespace Qt::StringLiterals; - -DocUtilities &Doc::m_utilities = DocUtilities::instance(); - -/*! - \typedef ArgList - \relates Doc - - A list of metacommand arguments that appear in a Doc. Each entry - in the list is a pair (ArgPair): - - \list - \li \c {ArgPair.first} - arguments passed to the command. - \li \c {ArgPair.second} - optional argument string passed - within brackets immediately following the command. - \endlist -*/ - -/*! - Parse the qdoc comment \a source. Build up a list of all the topic - commands found including their arguments. This constructor is used - when there can be more than one topic command in theqdoc comment. - Normally, there is only one topic command in a qdoc comment, but in - QML documentation, there is the case where the qdoc \e{qmlproperty} - command can appear multiple times in a qdoc comment. - */ -Doc::Doc(const Location &start_loc, const Location &end_loc, const QString &source, - const QSet &metaCommandSet, const QSet &topics) -{ - m_priv = new DocPrivate(start_loc, end_loc, source); - DocParser parser; - parser.parse(source, m_priv, metaCommandSet, topics); - - if (Config::instance().getAtomsDump()) { - start_loc.information(u"==== Atoms Structure for block comment starting at %1 ===="_s.arg( - start_loc.toString())); - body().dump(); - end_loc.information( - u"==== Ending atoms Structure for block comment ending at %1 ===="_s.arg( - end_loc.toString())); - } -} - -Doc::Doc(const Doc &doc) : m_priv(nullptr) -{ - operator=(doc); -} - -Doc::~Doc() -{ - if (m_priv && m_priv->deref()) - delete m_priv; -} - -Doc &Doc::operator=(const Doc &doc) -{ - if (doc.m_priv) - doc.m_priv->ref(); - if (m_priv && m_priv->deref()) - delete m_priv; - m_priv = doc.m_priv; - return *this; -} - -/*! - Returns the starting location of a qdoc comment. - */ -const Location &Doc::location() const -{ - static const Location dummy; - return m_priv == nullptr ? dummy : m_priv->m_start_loc; -} - -/*! - Returns the starting location of a qdoc comment. - */ -const Location &Doc::startLocation() const -{ - return location(); -} - -const QString &Doc::source() const -{ - static QString null; - return m_priv == nullptr ? null : m_priv->m_src; -} - -bool Doc::isEmpty() const -{ - return m_priv == nullptr || m_priv->m_src.isEmpty(); -} - -const Text &Doc::body() const -{ - static const Text dummy; - return m_priv == nullptr ? dummy : m_priv->m_text; -} - -Text Doc::briefText(bool inclusive) const -{ - return body().subText(Atom::BriefLeft, Atom::BriefRight, nullptr, inclusive); -} - -Text Doc::trimmedBriefText(const QString &className) const -{ - QString classNameOnly = className; - if (className.contains("::")) - classNameOnly = className.split("::").last(); - - Text originalText = briefText(); - Text resultText; - const Atom *atom = originalText.firstAtom(); - if (atom) { - QString briefStr; - QString whats; - /* - This code is really ugly. The entire \brief business - should be rethought. - */ - while (atom) { - if (atom->type() == Atom::AutoLink || atom->type() == Atom::String) { - briefStr += atom->string(); - } else if (atom->type() == Atom::C) { - briefStr += Generator::plainCode(atom->string()); - } - atom = atom->next(); - } - - QStringList w = briefStr.split(QLatin1Char(' ')); - if (!w.isEmpty() && w.first() == "Returns") { - } else { - if (!w.isEmpty() && w.first() == "The") - w.removeFirst(); - - if (!w.isEmpty() && (w.first() == className || w.first() == classNameOnly)) - w.removeFirst(); - - if (!w.isEmpty() - && ((w.first() == "class") || (w.first() == "function") || (w.first() == "macro") - || (w.first() == "widget") || (w.first() == "namespace") - || (w.first() == "header"))) - w.removeFirst(); - - if (!w.isEmpty() && (w.first() == "is" || w.first() == "provides")) - w.removeFirst(); - - if (!w.isEmpty() && (w.first() == "a" || w.first() == "an")) - w.removeFirst(); - } - - whats = w.join(' '); - - if (whats.endsWith(QLatin1Char('.'))) - whats.truncate(whats.size() - 1); - - if (!whats.isEmpty()) - whats[0] = whats[0].toUpper(); - - // ### move this once \brief is abolished for properties - resultText << whats; - } - return resultText; -} - -Text Doc::legaleseText() const -{ - if (m_priv == nullptr || !m_priv->m_hasLegalese) - return Text(); - else - return body().subText(Atom::LegaleseLeft, Atom::LegaleseRight); -} - -QSet Doc::parameterNames() const -{ - return m_priv == nullptr ? QSet() : m_priv->m_params; -} - -QStringList Doc::enumItemNames() const -{ - return m_priv == nullptr ? QStringList() : m_priv->m_enumItemList; -} - -QStringList Doc::omitEnumItemNames() const -{ - return m_priv == nullptr ? QStringList() : m_priv->m_omitEnumItemList; -} - -QSet Doc::metaCommandsUsed() const -{ - return m_priv == nullptr ? QSet() : m_priv->m_metacommandsUsed; -} - -/*! - Returns true if the set of metacommands used in the doc - comment contains \e {internal}. - */ -bool Doc::isInternal() const -{ - return metaCommandsUsed().contains(QLatin1String("internal")); -} - -/*! - Returns true if the set of metacommands used in the doc - comment contains \e {reimp}. - */ -bool Doc::isMarkedReimp() const -{ - return metaCommandsUsed().contains(QLatin1String("reimp")); -} - -/*! - Returns a reference to the list of topic commands used in the - current qdoc comment. Normally there is only one, but there - can be multiple \e{qmlproperty} commands, for example. - */ -TopicList Doc::topicsUsed() const -{ - return m_priv == nullptr ? TopicList() : m_priv->m_topics; -} - -ArgList Doc::metaCommandArgs(const QString &metacommand) const -{ - return m_priv == nullptr ? ArgList() : m_priv->m_metaCommandMap.value(metacommand); -} - -QList Doc::alsoList() const -{ - return m_priv == nullptr ? QList() : m_priv->m_alsoList; -} - -bool Doc::hasTableOfContents() const -{ - return m_priv && m_priv->extra && !m_priv->extra->m_tableOfContents.isEmpty(); -} - -bool Doc::hasKeywords() const -{ - return m_priv && m_priv->extra && !m_priv->extra->m_keywords.isEmpty(); -} - -bool Doc::hasTargets() const -{ - return m_priv && m_priv->extra && !m_priv->extra->m_targets.isEmpty(); -} - -const QList &Doc::tableOfContents() const -{ - m_priv->constructExtra(); - return m_priv->extra->m_tableOfContents; -} - -const QList &Doc::tableOfContentsLevels() const -{ - m_priv->constructExtra(); - return m_priv->extra->m_tableOfContentsLevels; -} - -const QList &Doc::keywords() const -{ - m_priv->constructExtra(); - return m_priv->extra->m_keywords; -} - -const QList &Doc::targets() const -{ - m_priv->constructExtra(); - return m_priv->extra->m_targets; -} - -QStringMultiMap *Doc::metaTagMap() const -{ - return m_priv && m_priv->extra ? &m_priv->extra->m_metaMap : nullptr; -} - -void Doc::initialize(FileResolver& file_resolver) -{ - Config &config = Config::instance(); - DocParser::initialize(config, file_resolver); - - const auto &configMacros = config.subVars(CONFIG_MACRO); - for (const auto ¯oName : configMacros) { - QString macroDotName = CONFIG_MACRO + Config::dot + macroName; - Macro macro; - macro.numParams = -1; - const auto ¯oConfigVar = config.get(macroDotName); - macro.m_defaultDef = macroConfigVar.asString(); - if (!macro.m_defaultDef.isEmpty()) { - macro.m_defaultDefLocation = macroConfigVar.location(); - macro.numParams = Config::numParams(macro.m_defaultDef); - } - bool silent = false; - - const auto ¯oDotNames = config.subVars(macroDotName); - for (const auto &f : macroDotNames) { - const auto ¯oSubVar = config.get(macroDotName + Config::dot + f); - QString def{macroSubVar.asString()}; - if (!def.isEmpty()) { - macro.m_otherDefs.insert(f, def); - int m = Config::numParams(def); - if (macro.numParams == -1) - macro.numParams = m; - // .match definition is a regular expression that contains no params - else if (macro.numParams != m && f != QLatin1String("match")) { - if (!silent) { - QString other = QStringLiteral("default"); - if (macro.m_defaultDef.isEmpty()) - other = macro.m_otherDefs.constBegin().key(); - macroSubVar.location().warning( - QStringLiteral("Macro '\\%1' takes inconsistent number of " - "arguments (%2 %3, %4 %5)") - .arg(macroName, f, QString::number(m), other, - QString::number(macro.numParams))); - silent = true; - } - if (macro.numParams < m) - macro.numParams = m; - } - } - } - if (macro.numParams != -1) - m_utilities.macroHash.insert(macroName, macro); - } -} - -/*! - All the heap allocated variables are deleted. - */ -void Doc::terminate() -{ - m_utilities.cmdHash.clear(); - m_utilities.macroHash.clear(); -} - -/*! - Trims the deadwood out of \a str. i.e., this function - cleans up \a str. - */ -void Doc::trimCStyleComment(Location &location, QString &str) -{ - QString cleaned; - Location m = location; - bool metAsterColumn = true; - int asterColumn = location.columnNo() + 1; - int i; - - for (i = 0; i < str.size(); ++i) { - if (m.columnNo() == asterColumn) { - if (str[i] != '*') - break; - cleaned += ' '; - metAsterColumn = true; - } else { - if (str[i] == '\n') { - if (!metAsterColumn) - break; - metAsterColumn = false; - } - cleaned += str[i]; - } - m.advance(str[i]); - } - if (cleaned.size() == str.size()) - str = cleaned; - - for (int i = 0; i < 3; ++i) - location.advance(str[i]); - str = str.mid(3, str.size() - 5); -} - -CodeMarker *Doc::quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file) -{ - // TODO: quoteFromFile should not care about modifying a stateful - // quoter from the outside, instead, it should produce a quoter - // that allows the caller to retrieve the required information - // about the quoted file. - // - // When changing the way in which quoting works, this kind of - // spread resposability should be removed, together with quoteFromFile. - quoter.reset(); - - QString code; - { - QFile input_file{resolved_file.get_path()}; - input_file.open(QFile::ReadOnly); - code = DocParser::untabifyEtc(QTextStream{&input_file}.readAll()); - } - - CodeMarker *marker = CodeMarker::markerForFileName(resolved_file.get_path()); - quoter.quoteFromFile(resolved_file.get_path(), code, marker->markedUpCode(code, nullptr, location)); - return marker; -} - -QString Doc::canonicalTitle(const QString &title) -{ - // The code below is equivalent to the following chunk, but _much_ - // faster (accounts for ~10% of total running time) - // - // QRegularExpression attributeExpr("[^A-Za-z0-9]+"); - // QString result = title.toLower(); - // result.replace(attributeExpr, " "); - // result = result.simplified(); - // result.replace(QLatin1Char(' '), QLatin1Char('-')); - - QString result; - result.reserve(title.size()); - - bool dashAppended = false; - bool begun = false; - qsizetype lastAlnum = 0; - for (int i = 0; i != title.size(); ++i) { - uint c = title.at(i).unicode(); - if (c >= 'A' && c <= 'Z') - c += 'a' - 'A'; - bool alnum = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); - if (alnum) { - result += QLatin1Char(c); - begun = true; - dashAppended = false; - lastAlnum = result.size(); - } else if (!dashAppended) { - if (begun) - result += QLatin1Char('-'); - dashAppended = true; - } - } - result.truncate(lastAlnum); - return result; -} - -void Doc::detach() -{ - if (m_priv == nullptr) { - m_priv = new DocPrivate; - return; - } - if (m_priv->count == 1) - return; - - --m_priv->count; - - auto *newPriv = new DocPrivate(*m_priv); - newPriv->count = 1; - if (m_priv->extra) - newPriv->extra = new DocPrivateExtra(*m_priv->extra); - - m_priv = newPriv; -} - -QT_END_NAMESPACE diff --git a/src/qdoc/doc.h b/src/qdoc/doc.h deleted file mode 100644 index a4917e3e0..000000000 --- a/src/qdoc/doc.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#ifndef DOC_H -#define DOC_H - -#include "location.h" -#include "docutilities.h" -#include "topic.h" - -#include "filesystem/fileresolver.h" -#include "boundaries/filesystem/resolvedfile.h" - -#include -#include -#include - -QT_BEGIN_NAMESPACE - -class Atom; -class CodeMarker; -class DocPrivate; -class Quoter; -class Text; - -typedef std::pair ArgPair; -typedef QList ArgList; -typedef QMultiMap QStringMultiMap; - -class Doc -{ -public: - // the order is important - enum Sections { - NoSection = -1, - Section1 = 1, - Section2 = 2, - Section3 = 3, - Section4 = 4 - }; - - Doc() = default; - Doc(const Location &start_loc, const Location &end_loc, const QString &source, - const QSet &metaCommandSet, const QSet &topics); - Doc(const Doc &doc); - ~Doc(); - - Doc &operator=(const Doc &doc); - - [[nodiscard]] const Location &location() const; - [[nodiscard]] const Location &startLocation() const; - [[nodiscard]] bool isEmpty() const; - [[nodiscard]] const QString &source() const; - [[nodiscard]] const Text &body() const; - [[nodiscard]] Text briefText(bool inclusive = false) const; - [[nodiscard]] Text trimmedBriefText(const QString &className) const; - [[nodiscard]] Text legaleseText() const; - [[nodiscard]] QSet parameterNames() const; - [[nodiscard]] QStringList enumItemNames() const; - [[nodiscard]] QStringList omitEnumItemNames() const; - [[nodiscard]] QSet metaCommandsUsed() const; - [[nodiscard]] TopicList topicsUsed() const; - [[nodiscard]] ArgList metaCommandArgs(const QString &metaCommand) const; - [[nodiscard]] QList alsoList() const; - [[nodiscard]] bool hasTableOfContents() const; - [[nodiscard]] bool hasKeywords() const; - [[nodiscard]] bool hasTargets() const; - [[nodiscard]] bool isInternal() const; - [[nodiscard]] bool isMarkedReimp() const; - [[nodiscard]] const QList &tableOfContents() const; - [[nodiscard]] const QList &tableOfContentsLevels() const; - [[nodiscard]] const QList &keywords() const; - [[nodiscard]] const QList &targets() const; - [[nodiscard]] QStringMultiMap *metaTagMap() const; - - static void initialize(FileResolver& file_resolver); - static void terminate(); - static void trimCStyleComment(Location &location, QString &str); - static CodeMarker *quoteFromFile(const Location &location, Quoter "er, ResolvedFile resolved_file); - static QString canonicalTitle(const QString &title); - -private: - void detach(); - DocPrivate *m_priv { nullptr }; - static DocUtilities &m_utilities; -}; -Q_DECLARE_TYPEINFO(Doc, Q_RELOCATABLE_TYPE); -typedef QList DocList; - -QT_END_NAMESPACE - -#endif diff --git a/src/qdoc/doc/config/qdoc.qdocconf b/src/qdoc/doc/config/qdoc.qdocconf deleted file mode 100644 index 982615da9..000000000 --- a/src/qdoc/doc/config/qdoc.qdocconf +++ /dev/null @@ -1,59 +0,0 @@ -include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) -include($QT_INSTALL_DOCS/config/exampleurl-qttools.qdocconf) - -project = QDoc -description = QDoc Manual -version = $QT_VERSION -moduleheader = - -sourcedirs = .. - -exampledirs = .. \ - ../examples - -imagedirs = ../images - -tagfile = ../html/qdoc.tags - -examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml *.css *.qdoc *.qdocinc *.sample" - -qhp.projects = QDoc - -qhp.QDoc.file = qdoc.qhp -qhp.QDoc.namespace = org.qt-project.qdoc.$QT_VERSION_TAG -qhp.QDoc.virtualFolder = qdoc -qhp.QDoc.indexTitle = QDoc Manual -qhp.QDoc.indexRoot = - -qhp.QDoc.subprojects = overviews -qhp.QDoc.subprojects.overviews.title = Overviews -qhp.QDoc.subprojects.overviews.indexTitle = QDoc Manual -qhp.QDoc.subprojects.overviews.selectors = doc:page - -depends += \ - qtconcurrent \ - qtcore \ - qtdbus \ - qtdesigner \ - qtdoc \ - qthelp \ - qtgui \ - qtlinguist \ - qtnetwork \ - qtopengl \ - qtprintsupport \ - qtqml \ - qtquick \ - qtquickcontrols \ - qtsql \ - qtsvg \ - qttestlib \ - qtuitools \ - qtwidgets \ - qtxml - -ignorewords += QDoc - -navigation.landingpage = "QDoc Manual" - -warninglimit = 0 diff --git a/src/qdoc/doc/corefeatures.qdoc b/src/qdoc/doc/corefeatures.qdoc deleted file mode 100644 index e1edc3a92..000000000 --- a/src/qdoc/doc/corefeatures.qdoc +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (C) 2023 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page corefeatures.html - \title Core Features - - \include examples/signalandslots.qdocinc - \include examples/objectmodel.qdocinc - \include examples/layoutmanagement.qdocinc -*/ diff --git a/src/qdoc/doc/examples/cpp.qdoc.sample b/src/qdoc/doc/examples/cpp.qdoc.sample deleted file mode 100644 index 39c77f63c..000000000 --- a/src/qdoc/doc/examples/cpp.qdoc.sample +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -//![class] -/*! - \class QCache - \brief The QCache class is a template class that provides a cache. - - \ingroup tools - \ingroup shared - - \reentrant - - QCache\ defines a cache that stores objects of type T - associated with keys of type Key. For example, here's the - definition of a cache that stores objects of type Employee - associated with an integer key: - - \snippet code/doc_src_qcache.cpp 0 - - Here's how to insert an object in the cache: - - \snippet code/doc_src_qcache.cpp 1 - - ... detailed description omitted - - \sa QPixmapCache, QHash, QMap -*/ -//![class] - -//![function] -/*! - \fn QString &QString::remove(int position, int n) - - Removes \a n characters from the string, starting at the given \a - position index, and returns a reference to the string. - - If the specified \a position index is within the string, but \a - position + \a n is beyond the end of the string, the string is - truncated at the specified \a position. - - \snippet qstring/main.cpp 37 - - \sa insert(), replace() -*/ -QString &QString::remove(int pos, int len) -//! [function] - -//! [return] -/*! - Returns \c true if a QScroller object was already created for \a target; \c false otherwise. - - \sa scroller() -*/ -bool QScroller::hasScroller(QObject *target) -//! [return] - -//! [property] -/*! - \property QVariantAnimation::duration - \brief the duration of the animation - - This property describes the duration in milliseconds of the - animation. The default duration is 250 milliseconds. - - \sa QAbstractAnimation::duration() - */ -int QVariantAnimation::duration() const -//! [property] - -//! [signals] -/*! - \fn QAbstractTransition::triggered() - - This signal is emitted when the transition has been triggered (after - onTransition() has been called). -*/ -//! [signals] - -//! [enums] -/*! - \enum QSql::TableType - - This enum type describes types of SQL tables. - - \value Tables All the tables visible to the user. - \value SystemTables Internal tables used by the database. - \value Views All the views visible to the user. - \value AllTables All of the above. -*/ -//! [enums] - -//! [overloaded notifier] -/*! -\property QSpinBox::value -\brief the value of the spin box - -setValue() will emit valueChanged() if the new value is different -from the old one. The \l{QSpinBox::}{value} property has a second notifier -signal which includes the spin box's prefix and suffix. -*/ -//! [overloaded notifier] diff --git a/src/qdoc/doc/examples/layoutmanagement.qdocinc b/src/qdoc/doc/examples/layoutmanagement.qdocinc deleted file mode 100644 index 780b03c8f..000000000 --- a/src/qdoc/doc/examples/layoutmanagement.qdocinc +++ /dev/null @@ -1,13 +0,0 @@ -\section1 Layout Classes - -The Qt layout system provides a simple and powerful way of specifying -the layout of child widgets. - -By specifying the logical layout once, you get the following benefits: - -\list - \li Positioning of child widgets. - \li Sensible default sizes for windows. - \li Sensible minimum sizes for windows. - \li ... -\endlist diff --git a/src/qdoc/doc/examples/main.cpp b/src/qdoc/doc/examples/main.cpp deleted file mode 100644 index b93308ee9..000000000 --- a/src/qdoc/doc/examples/main.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include -#include - -int main(int argc, char *argv[]) -{ - QApplication app(argc, argv); - - QPushButton hello("Hello world!"); - hello.resize(100, 30); - - hello.show(); - return app.exec(); -} diff --git a/src/qdoc/doc/examples/mainwindow.cpp b/src/qdoc/doc/examples/mainwindow.cpp deleted file mode 100644 index 053d429ce..000000000 --- a/src/qdoc/doc/examples/mainwindow.cpp +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - -#include - -#include "mainwindow.h" -#include "scribblearea.h" - -//! [0] -MainWindow::MainWindow() -{ - scribbleArea = new ScribbleArea; - setCentralWidget(scribbleArea); - - createActions(); - createMenus(); - - setWindowTitle(tr("Scribble")); - resize(500, 500); -} -//! [0] - -//! [1] -void MainWindow::closeEvent(QCloseEvent *event) -//! [1] //! [2] -{ - if (maybeSave()) { - event->accept(); - } else { - event->ignore(); - } -} -//! [2] - -//! [3] -void MainWindow::open() -//! [3] //! [4] -{ - if (maybeSave()) { - QString fileName = QFileDialog::getOpenFileName(this, - tr("Open File"), QDir::currentPath()); - if (!fileName.isEmpty()) - scribbleArea->openImage(fileName); - } -} -//! [4] - -//! [5] -void MainWindow::save() -//! [5] //! [6] -{ - QAction *action = qobject_cast(sender()); - QByteArray fileFormat = action->data().toByteArray(); - saveFile(fileFormat); -} -//! [6] - -//! [7] -void MainWindow::penColor() -//! [7] //! [8] -{ - QColor newColor = QColorDialog::getColor(scribbleArea->penColor()); - if (newColor.isValid()) - scribbleArea->setPenColor(newColor); -} -//! [8] - -//! [9] -void MainWindow::penWidth() -//! [9] //! [10] -{ - bool ok; - int newWidth = QInputDialog::getInteger(this, tr("Scribble"), - tr("Select pen width:"), - scribbleArea->penWidth(), - 1, 50, 1, &ok); - if (ok) - scribbleArea->setPenWidth(newWidth); -} -//! [10] - -//! [11] -void MainWindow::about() -//! [11] //! [12] -{ - QMessageBox::about(this, tr("About Scribble"), - tr("

The Scribble example shows how to use QMainWindow as the " - "base widget for an application, and how to reimplement some of " - "QWidget's event handlers to receive the events generated for " - "the application's widgets:

We reimplement the mouse event " - "handlers to facilitate drawing, the paint event handler to " - "update the application and the resize event handler to optimize " - "the application's appearance. In addition we reimplement the " - "close event handler to intercept the close events before " - "terminating the application.

The example also demonstrates " - "how to use QPainter to draw an image in real time, as well as " - "to repaint widgets.

")); -} -//! [12] - -//! [13] -void MainWindow::createActions() -//! [13] //! [14] -{ - openAct = new QAction(tr("&Open..."), this); - openAct->setShortcuts(QKeySequence::Open); - connect(openAct, SIGNAL(triggered()), this, SLOT(open())); - - foreach (const QByteArray &format, QImageWriter::supportedImageFormats()) { - QString text = tr("%1...").arg(QString(format).toUpper()); - - QAction *action = new QAction(text, this); - action->setData(format); - connect(action, SIGNAL(triggered()), this, SLOT(save())); - saveAsActs.append(action); - } - - printAct = new QAction(tr("&Print..."), this); - connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print())); - - exitAct = new QAction(tr("E&xit"), this); - exitAct->setShortcuts(QKeySequence::Quit); - connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); - - penColorAct = new QAction(tr("&Pen Color..."), this); - connect(penColorAct, SIGNAL(triggered()), this, SLOT(penColor())); - - penWidthAct = new QAction(tr("Pen &Width..."), this); - connect(penWidthAct, SIGNAL(triggered()), this, SLOT(penWidth())); - - clearScreenAct = new QAction(tr("&Clear Screen"), this); - clearScreenAct->setShortcut(tr("Ctrl+L")); - connect(clearScreenAct, SIGNAL(triggered()), - scribbleArea, SLOT(clearImage())); - - aboutAct = new QAction(tr("&About"), this); - connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - - aboutQtAct = new QAction(tr("About &Qt"), this); - connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); -} -//! [14] - -//! [15] -void MainWindow::createMenus() -//! [15] //! [16] -{ - saveAsMenu = new QMenu(tr("&Save As"), this); - foreach (QAction *action, saveAsActs) - saveAsMenu->addAction(action); - - fileMenu = new QMenu(tr("&File"), this); - fileMenu->addAction(openAct); - fileMenu->addMenu(saveAsMenu); - fileMenu->addAction(printAct); - fileMenu->addSeparator(); - fileMenu->addAction(exitAct); - - optionMenu = new QMenu(tr("&Options"), this); - optionMenu->addAction(penColorAct); - optionMenu->addAction(penWidthAct); - optionMenu->addSeparator(); - optionMenu->addAction(clearScreenAct); - - helpMenu = new QMenu(tr("&Help"), this); - helpMenu->addAction(aboutAct); - helpMenu->addAction(aboutQtAct); - - menuBar()->addMenu(fileMenu); - menuBar()->addMenu(optionMenu); - menuBar()->addMenu(helpMenu); -} -//! [16] - -//! [17] -bool MainWindow::maybeSave() -//! [17] //! [18] -{ - if (scribbleArea->isModified()) { - QMessageBox::StandardButton ret; - ret = QMessageBox::warning(this, tr("Scribble"), - tr("The image has been modified.\n" - "Do you want to save your changes?"), - QMessageBox::Save | QMessageBox::Discard - | QMessageBox::Cancel); - if (ret == QMessageBox::Save) { - return saveFile("png"); - } else if (ret == QMessageBox::Cancel) { - return false; - } - } - return true; -} -//! [18] - -//! [19] -bool MainWindow::saveFile(const QByteArray &fileFormat) -//! [19] //! [20] -{ - QString initialPath = QDir::currentPath() + "/untitled." + fileFormat; - - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), - initialPath, - tr("%1 Files (*.%2);;All Files (*)") - .arg(QString(fileFormat.toUpper())) - .arg(QString(fileFormat))); - if (fileName.isEmpty()) { - return false; - } else { - return scribbleArea->saveImage(fileName, fileFormat); - } -} -//! [20] diff --git a/src/qdoc/doc/examples/minimum.qdocconf b/src/qdoc/doc/examples/minimum.qdocconf deleted file mode 100644 index 8f53ffc11..000000000 --- a/src/qdoc/doc/examples/minimum.qdocconf +++ /dev/null @@ -1,36 +0,0 @@ -# QDoc is a tool that constantly evolves to suit our needs, -# and there are some compatibility issues between old and new -# practices. For that reason, any QDoc configuration file needs to -# include compat.qdocconf. -#include(compat.qdocconf) - -# QDoc needs lists of file extensions to know which files to process in -# different situations. Uncomment the following include statement to get -# a pre-defined list of file extensions. -#include(fileextensions.qdocconf) - -# You can also specify file extensions manually. -headers.fileextensions = "*.h *.hpp" -sources.fileextensions = "*.cpp *.qml *.qdoc" - -# The outputdir variable specifies the directory -# where QDoc will put the generated documentation. -outputdir = html - -# The headerdirs variable specifies the directories -# containing the header files associated -# with the .cpp source files used in the documentation. -headerdirs = . - -# The sourcedirs variable specifies the -# directories containing the .cpp or .qdoc -# files used in the documentation. -sourcedirs = . - -# The exampledirs variable specifies the directories containing -# the source code of the example files. -exampledirs = . - -# The imagedirs variable specifies the -# directories containing the images used in the documentation. -imagedirs = ./images diff --git a/src/qdoc/doc/examples/objectmodel.qdocinc b/src/qdoc/doc/examples/objectmodel.qdocinc deleted file mode 100644 index 02b5991c4..000000000 --- a/src/qdoc/doc/examples/objectmodel.qdocinc +++ /dev/null @@ -1,11 +0,0 @@ -\section1 Qt Object Model - -The standard C++ object model provides very efficient runtime support -for the object paradigm. But its static nature is inflexibile in -certain problem domains. Graphical user interface programming is a -domain that requires both runtime efficiency and a high level of -flexibility. Qt provides this, by combining the speed of C++ with the -flexibility of the Qt Object Model. - -... - diff --git a/src/qdoc/doc/examples/qml.qdoc.sample b/src/qdoc/doc/examples/qml.qdoc.sample deleted file mode 100644 index e0f9a66b9..000000000 --- a/src/qdoc/doc/examples/qml.qdoc.sample +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -//![qmltype] - \qmltype TextEdit - \instantiates QQuickTextEdit - \inqmlmodule QtQuick - \ingroup qtquick-visual - \ingroup qtquick-input - \inherits Item - \brief Displays multiple lines of editable formatted text - - The TextEdit item displays a block of editable, formatted text. - - It can display both plain and rich text. For example: - - \qml - TextEdit { - width: 240 - text: "Hello World!" - font.family: "Helvetica" - font.pointSize: 20 - color: "blue" - focus: true - } - \endqml - - \image declarative-textedit.gif - - ... omitted detailed description - - \sa Text, TextInput, {examples/quick/text/textselection}{Text Selection example} -//![qmltype] - -//![function] -/* - \qmlmethod QtQuick2::ListModel::remove(int index, int count = 1) - - Deletes the content at \a index from the model. - - \sa clear() -*/ -void QQuickListModel::remove(QQmlV8Function *args) -//! [function] - -//! [return] -/* - Returns \c true if a QScroller object was already created for \a target; \c false otherwise. - - \sa scroller() -*/ -bool QScroller::hasScroller(QObject *target) -//! [return] - -//! [property] -/* - \property QVariantAnimation::duration - \brief the duration of the animation - - This property describes the duration in milliseconds of the - animation. The default duration is 250 milliseconds. - - \sa QAbstractAnimation::duration() - */ -int QVariantAnimation::duration() const -//! [property] - -//! [signals] -/* - This signal is emitted when the user clicks the button. A click is defined - as a press followed by a release. The corresponding handler is - \c onClicked. -*/ -signal clicked() -//! [signals] - -//! [enums] -/*! -\qmlproperty enumeration QtQuick2::Text::font.weight - -Sets the font's weight. - -The weight can be one of: -\value Font.Light -\value Font.Normal The default -\value Font.DemiBold -\value Font.Bold -\value Font.Black - -//! [enums] diff --git a/src/qdoc/doc/examples/samples.qdocinc b/src/qdoc/doc/examples/samples.qdocinc deleted file mode 100644 index ea257852f..000000000 --- a/src/qdoc/doc/examples/samples.qdocinc +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -//! [qvector3d-class] -/*! - \class QVector3D - \brief The QVector3D class represents a vector or vertex in 3D space. - \since 4.6 - \ingroup painting-3D - - Vectors are one of the main building blocks of 3D representation and - drawing. They consist of three coordinates, traditionally called - x, y, and z. - - The QVector3D class can also be used to represent vertices in 3D space. - We therefore do not need to provide a separate vertex class. - - \note By design values in the QVector3D instance are stored as \c float. - This means that on platforms where the \c qreal arguments to QVector3D - functions are represented by \c double values, it is possible to - lose precision. - - \sa QVector2D, QVector4D, QQuaternion -*/ -//! [qvector3d-class] - -//! [qvector3d-function] -/*! - \fn QVector3D::QVector3D(const QPoint& point) - - Constructs a vector with x and y coordinates from a 2D \a point, and a - z coordinate of 0. -*/ -//! [qvector3d-function] - -//! [sample-page] -/*! - \page generic-guide.html - \title Generic QDoc Guide - \nextpage Creating QDoc Configuration Files - There are three essential materials for generating documentation with QDoc: - - \list - \li \c QDoc binary (\c {qdoc}) - \li \c qdocconf configuration files - \li \c Documentation in \c C++, \c QML, and \c .qdoc files - \endlist -*/ -//! [sample-page] - -//! [sample-faq] -/*! - \page altruism-faq.html - \title Altruism Frequently Asked Questions - - \brief All the questions about altruism, answered. - - ... -*/ -//! [sample-faq] - -//! [sample-example] -/*! - \title UI Components: Tab Widget Example - \example declarative/ui-components/tabwidget - - This example shows how to create a tab widget. It also demonstrates how - \l {Property aliases}{property aliases} and - \l {Introduction to the QML Language#Default Properties}{default properties} can be used to collect and - assemble the child items declared within an \l Item. - - \image qml-tabwidget-example.png -*/ -//! [sample-example] - -//! [sample-overview] -/*! - \page overview-qt-technology.html - \title Overview of a Qt Technology - - \brief provides a technology never seen before. - -*/ -//! [sample-overview] - diff --git a/src/qdoc/doc/examples/signalandslots.qdocinc b/src/qdoc/doc/examples/signalandslots.qdocinc deleted file mode 100644 index e14ede144..000000000 --- a/src/qdoc/doc/examples/signalandslots.qdocinc +++ /dev/null @@ -1,9 +0,0 @@ -\section1 Signals and Slots - -Signals and slots are used for communication between objects. The signals and -slots mechanism is a central feature of Qt and probably the part that differs -most from the features provided by other frameworks. - -\section2 Introduction - -In GUI programming, when we ... diff --git a/src/qdoc/doc/files/basicqt.qdoc.sample b/src/qdoc/doc/files/basicqt.qdoc.sample deleted file mode 100644 index 1243387b2..000000000 --- a/src/qdoc/doc/files/basicqt.qdoc.sample +++ /dev/null @@ -1,64 +0,0 @@ - /*! - \page basicqt.html - \nextpage Getting Started - - \indexpage Index - \startpage Basic Qt - - \title Basic Qt - - The Qt toolkit is a C++ class library and a set of tools for - building multiplatform GUI programs using a "write once, - compile anywhere approach". - - Table of contents: - - \list - \li \l {Getting Started} - \li \l {Creating Dialogs} - \li \l {Creating Main Windows} - \endlist - */ - - /*! - \page gettingstarted.html - \previouspage Basic Qt - \nextpage Creating Dialogs - - \indexpage Index - \startpage Basic Qt - - \title Getting Started - - This chapter shows how to combine basic C++ with the - functionality provided by Qt to create a few small graphical - interface (GUI) applications. -*/ - -/ *! - \page creatingdialogs.html - \previouspage Getting Started - - \indexpage Index - \startpage Basic Qt - - \title Creating Dialogs - - This chapter will teach you how to create dialog boxes using Qt. -*/ - -/*! - \page index.html - - \indexpage Index - \startpage Basic Qt - - \title Index - - \list - \li \l {Basic Qt} - \li \l {Creating Dialogs} - \li \l {Getting Started} - \endlist -*/ - diff --git a/src/qdoc/doc/files/compat.qdocconf b/src/qdoc/doc/files/compat.qdocconf deleted file mode 100644 index 94e2ffd7d..000000000 --- a/src/qdoc/doc/files/compat.qdocconf +++ /dev/null @@ -1,10 +0,0 @@ -macro.0 = "\\\\0" -macro.b = "\\\\b" -macro.n = "\\\\n" -macro.r = "\\\\r" -macro.img = "\\image" -macro.endquote = "\\endquotation" -macro.relatesto = "\\relates" - -spurious = "Missing comma in .*" \ - "Missing pattern .*" diff --git a/src/qdoc/doc/files/qtgui.qdocconf b/src/qdoc/doc/files/qtgui.qdocconf deleted file mode 100644 index ae873e83d..000000000 --- a/src/qdoc/doc/files/qtgui.qdocconf +++ /dev/null @@ -1,45 +0,0 @@ -include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) - -project = QtGui -description = Qt GUI Reference Documentation -version = $QT_VERSION - -examplesinstallpath = gui - -qhp.projects = QtGui - -qhp.QtGui.file = qtgui.qhp -qhp.QtGui.namespace = org.qt-project.qtgui.$QT_VERSION_TAG -qhp.QtGui.virtualFolder = qtgui -qhp.QtGui.indexTitle = Qt GUI -qhp.QtGui.indexRoot = - -qhp.QtGui.subprojects = classes -qhp.QtGui.subprojects.classes.title = C++ Classes -qhp.QtGui.subprojects.classes.indexTitle = Qt GUI C++ Classes -qhp.QtGui.subprojects.classes.selectors = class fake:headerfile -qhp.QtGui.subprojects.classes.sortPages = true - -tagfile = ../../../doc/qtgui/qtgui.tags - -depends += \ - qtcore \ - qtnetwork \ - qtopengl \ - qtsvg \ - qtqml \ - qtquick \ - qtwidgets \ - qtdoc - -headerdirs += .. - -sourcedirs += .. \ - ../../../examples/gui/doc/src - -exampledirs += ../../../examples/gui \ - snippets - -imagedirs += images \ - ../../../examples/gui/doc/images \ - ../../../doc/src/images \ diff --git a/src/qdoc/doc/images/happy.gif b/src/qdoc/doc/images/happy.gif deleted file mode 100644 index a4597f6fa..000000000 Binary files a/src/qdoc/doc/images/happy.gif and /dev/null differ diff --git a/src/qdoc/doc/images/happyguy.jpg b/src/qdoc/doc/images/happyguy.jpg deleted file mode 100644 index e8604793c..000000000 Binary files a/src/qdoc/doc/images/happyguy.jpg and /dev/null differ diff --git a/src/qdoc/doc/images/link-to-qquickitem.png b/src/qdoc/doc/images/link-to-qquickitem.png deleted file mode 100644 index 00e03c371..000000000 Binary files a/src/qdoc/doc/images/link-to-qquickitem.png and /dev/null differ diff --git a/src/qdoc/doc/images/links-to-broken-links.png b/src/qdoc/doc/images/links-to-broken-links.png deleted file mode 100644 index 775143bd4..000000000 Binary files a/src/qdoc/doc/images/links-to-broken-links.png and /dev/null differ diff --git a/src/qdoc/doc/images/links-to-links.png b/src/qdoc/doc/images/links-to-links.png deleted file mode 100644 index 9d2cc2fae..000000000 Binary files a/src/qdoc/doc/images/links-to-links.png and /dev/null differ diff --git a/src/qdoc/doc/images/qa-table.png b/src/qdoc/doc/images/qa-table.png deleted file mode 100644 index 5818739fa..000000000 Binary files a/src/qdoc/doc/images/qa-table.png and /dev/null differ diff --git a/src/qdoc/doc/images/qt-logo.png b/src/qdoc/doc/images/qt-logo.png deleted file mode 100644 index 835f5a3fe..000000000 Binary files a/src/qdoc/doc/images/qt-logo.png and /dev/null differ diff --git a/src/qdoc/doc/images/training.jpg b/src/qdoc/doc/images/training.jpg deleted file mode 100644 index c2ce5c3b2..000000000 Binary files a/src/qdoc/doc/images/training.jpg and /dev/null differ diff --git a/src/qdoc/doc/images/windows-pushbutton.png b/src/qdoc/doc/images/windows-pushbutton.png deleted file mode 100644 index 14528d680..000000000 Binary files a/src/qdoc/doc/images/windows-pushbutton.png and /dev/null differ diff --git a/src/qdoc/doc/images/windows-toolbutton.png b/src/qdoc/doc/images/windows-toolbutton.png deleted file mode 100644 index 9ceb846ed..000000000 Binary files a/src/qdoc/doc/images/windows-toolbutton.png and /dev/null differ diff --git a/src/qdoc/doc/qdoc-guide/qdoc-guide.qdoc b/src/qdoc/doc/qdoc-guide/qdoc-guide.qdoc deleted file mode 100644 index 086cf78ca..000000000 --- a/src/qdoc/doc/qdoc-guide/qdoc-guide.qdoc +++ /dev/null @@ -1,670 +0,0 @@ -// Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only -/*! - \page qdoc-guide.html - \title Getting Started with QDoc - \nextpage Installing Clang for QDoc - - Qt uses QDoc to generate its documentation set into HTML and DocBook XML - formats. QDoc uses a set of configuration files to generate documentation - from QDoc comments. The comments have types called - \l{writing-topic-commands}{topics} that determine whether a comment is a - class documentation or a property documentation. A comment may also have - \l{writing-markup}{mark up} to enhance the layout and formatting of the - final output. - - There are three essential materials for generating documentation with QDoc: - \list - \li \c QDoc binary - \li \c qdocconf configuration files - \li \c Documentation in \c C++, \c QML, and \c .qdoc files - \endlist - - \note \l{QDoc Manual}{QDoc} requires \l{http://clang.llvm.org}{Clang} - for parsing C++ header and source files, and for parsing the function - signatures in \l {fn-command} {\\fn} commands. See \l {Installing Clang for QDoc} - for details. - - This section intends to cover the basic necessities for creating a - documentation set. Additionally, the guide presents special considerations - and options to documenting non-C++ API documentation as well as QML - documentation. Finally, the guide will provide a sample project - documentation and an example of a QML type documentation. - - For specific QDoc information, consult the - \l{QDoc Manual}. - \section1 Chapters - - \list 1 - \li \l{Installing Clang for QDoc} - \li \l{Creating QDoc Configuration Files} - \li \l{Writing Documentation} - \li \l{Categories of Documentation} - \list - \li \l{C++ Documentation Style} - \li \l{QML Documentation Style} - \endlist - \li \l{How to Resolve QDoc Warnings} - \endlist - -*/ - -/*! - \page qdoc-guide-conf.html - \title Creating QDoc Configuration Files - \previouspage Installing Clang for QDoc - \nextpage Writing Documentation - To generate documentation, QDoc uses configuration files, with the - \c qdocconf extension, to store configuration settings. - - The \l{The QDoc Configuration File} article covers the various configuration - variables in greater detail. - - \section1 QDoc Configuration Files - QDoc's configuration settings can reside in a single \e qdocconf file, but - can also be in other qdocconf files. The \c {include()} command - allows configuration files to include other configuration files. - - QDoc has two outputs, HTML documentation and documentation in DocBook XML - format. The main distinction between the two outputs is that HTML - documentation needs to have its HTML styling information in the - configuration files. DocBook documentation does not, and a separate process - can style the documentation in DocBook at a later time. DocBook therefore - more flexible in allowing different styles to apply to the same information. - - To run QDoc, the project configuration file is supplied as an argument. - \code - qdoc project.qdocconf - \endcode - - The project configuration contains information that QDoc uses to create the - documentation. - - \section2 Project Information - - QDoc uses the \c project information to generate the documentation. - \code - project = QDoc Project - description = Sample QDoc project - \endcode - - \target qdoc-input-output-dir - \section2 Input and Output Directories - - Specifying the path to the source directories allow QDoc to find sources and - generate documentation. - - \badcode - sourcedirs = - exampledirs = - imagedirs = - - sources.fileextensions = "*.cpp *.qdoc *.mm *.qml" - headers.fileextensions = "*.h *.ch *.h++ *.hh *.hpp *.hxx" - examples.fileextensions = "*.cpp *.h *.js *.xq *.svg *.xml *.ui *.qhp *.qhcp *.qml" - examples.imageextensions = "*.png *.jpeg *.jpg *.gif *.mng" - \endcode - - QDoc will process headers and sources from the ones specified in the - \c fileextensions variable. - - Likewise, QDoc needs the path to the output directory. The \c outputformats - variable determines the type of documentation. These variables should be - in separate configuration files to modularize the documentation build. - \badcode - outputdir = $SAMPLE_PROJECT/doc/html - outputformats = HTML - \endcode - - QDoc can resolve the paths relative to the qdocconf file as well as - environment variables. - - \note During each QDoc run, the output directory is deleted. - \section2 Extra Files - - QDoc will output generated documentation into the directory specified in - the \l{Input and Output Directories}{output} directory. It is also possible - to specify extra files that QDoc should export. - - \badcode - HTML.extraimages = extraImage.png \ - extraImage2.png - \endcode - - The \c extraImage.png and the \c extraImage2.png files will be copied to the - HTML output directory. - - \section2 Qt Help Framework Configuration - - QDoc will also export a \e {Qt Help Project} file, in a \c qhp file. - The qhp file is then used by the \c qhelpgenerator to package the - documentation into a \c qch file. Qt Creator and Qt Assistant reads the qch - file to display the documentation. - - The \l {Creating Help Project Files} article covers the configuration - options. - - \section2 HTML Configuration - - QDoc has an HTML generator that will export a set of documentation into - HTML files using various configuration settings. QDoc will place the - generated documentation into the directory specified by the \c outputdir - variable. - - \badcode - outputformats = HTML - outputdir = - \endcode - - QDoc needs to know where the styles and templates for generating HTML - are located. Typically, the templates directory contains a \c scripts, - \c images, and a \c style directory, containing scripts and CSS files. - - The main configuration variables are: - \badcode - HTML.postheader - HTML.postpostheader - HTML.postheader - HTML.footer - - HTML.headerstyles - HTML.stylesheets = template/style/style.css \ - template/style/style1.css - - HTML.scripts = template/scripts/script.js - \endcode - - The \c{HTML.headerstyles} variable inserts the style information into the - HTML file and the \c{HTML.stylesheets} specifies which files QDoc should - copy into the output directory. As well, QDoc will embed the string - in the \c postheader, \c footer, and related variables into each HTML file. - - The \l {Format-specific Configuration Variables} article outlines the usage - of each variable. - - \section2 QDoc Index Files - - Documentation projects can link to targets in other projects by specifying - a set of dependencies, or a set of direct paths to index file(s) this - project depends on. When QDoc generates documentation for a project, - it will also generate an \c .index file containing URLs to each linkable - entity in the project. Other projects can then define a dependency to the - index file in order to link to the documentation within that project. - - \b {See also}: \l {depends-variable}{depends} and - \l {indexes-variable}{indexes}. - - \section1 Macros and Other Configurations - - Macros for substituting HTML characters exist and are helpful for generating - specific HTML-valid characters. - - \badcode - macro.pi.HTML = "Π" - \endcode - The snippet code will replace any instances of \c{\\pi} with \c Π in the - HTML file, which will appear as the Greek \pi symbol when viewed in - browsers. - - \b {See also:} \l {macro-variable}{macro}. - - \section2 QML Additions - - QDoc is able to parse QML files for QDoc comments. QDoc will parse files - with the QML extension, \c{.qml}, if the extension type is included in the - \l{Input and Output Directories}{fileextensions} variable. - - Also, the generated HTML files can have a prefix and a suffix following the - QML module name, specified in the QDoc configuration file. - \badcode - outputprefixes = QML - outputprefixes.QML = uicomponents- - outputsuffixes = QML - outputsuffixes.QML = -tp - \endcode - - \b {See also}: \l {outputprefixes-variable}{outputprefixes}, - \l {outputsuffixes-variable}{outputsuffixes}. - -*/ - -/*! - \page qdoc-guide-writing.html - \title Writing Documentation - \previouspage Creating QDoc Configuration Files - \nextpage Categories of Documentation - - \section1 QDoc Comments - - Documentation is contained within QDoc \e comments, delimited by - \beginqdoc and \endqdoc comments. Note that these are valid comments - in C++ and QML. - - Within a QDoc comment, \c {//!} is used as a single-line documentation - comment; the comment itself and anything after it, until a newline, - is omitted from the generated output. - - QDoc will parse C++ and QML files to look for QDoc comments. To explicitly - omit a certain file type, omit it from the - \l{Input and Output Directories}{configuration} file. - - \section1 QDoc Commands - - QDoc uses \e commands to retrieve information about the documentation. \c - Topic commands determine the type of documentation element, the \c context - commands provide hints and information about a topic, and \c markup commands - provide information on how QDoc should format a piece of documentation. - - \target writing-topic-commands - \section2 QDoc Topics - Each QDoc comment must have a \e topic type. A topic distinguishes it from - other topics. To specify a topic type, use one of the several - \l{Topic Commands}{topic commands}. - - QDoc will collect similar topics and create a page for each one. For - example, all the enumerations, properties, functions, and class description - of a particular C++ class will reside in one page. A generic page is - specified using the \l{page-command}{\\page} command and the filename is the - argument. - - Example of topic commands: - \list - \li \l{enum-command}{\\enum} - for enumeration documentation - \li \l{class-command}{\\class} - for C++ class documentation - \li \l{qmltype-command}{\\qmltype} - for QML type documentation - \li \l{page-command}{\\page} - for creating a page. - \endlist - - A QDoc comment can contain multiple topic commands in the same category, with - some restrictions. This way, it's possible to write a single comment that - documents all overloads of a function (using multiple \l {fn-command}{\\fn} - commands), or all properties in a QML property group (using - \l {qmlproperty-command}{\\qmlproperty} commands) in one go. - - If a QDoc comment contains multiple topic commands, it's possible to - provide additional \e {context commands} for individual topics in - follow-up comments: - - \badcode * - /\1! - \qmlproperty string Type::element.name - \qmlproperty int Type::element.id - - \brief Holds the element name and id. - \1/ - - /\1! - \qmlproperty int Type::element.id - \readonly - \1/ - \endcode - - Here, the follow-up comment marks the \e element.id property as read-only, - while \e element.name remains writable. - - \note A follow-up comment cannot contain any additional text, only - \l {writing-context}{context commands} that document the context of - the item. - - The \l{page-command}{\\page} command is for creating articles that are not - part of source documentation. The command can also accept two arguments: the - file name of the article and the documentation type. The possible types are: - \list - \li \c howto - \li \c overview - \li \c tutorial - \li \c faq - \li \c attribution - used for documenting license attributions - \li \c article - \e default when there is no type - \endlist - - \snippet examples/samples.qdocinc sample-faq - - The \l{Topic Commands} page has information on all of the available topic - commands. - - \target writing-context - \section2 Topic Contexts - - Context commands give QDoc a hint about the \e context of the topic. For - example, if a C++ function is deprecated, then it should be marked as such - with the \l{deprecated-command}{\\deprecated} command. Likewise, - \l{nextpage-command}{page navigation} and \l{title-command}{page title} - give extra page information to QDoc. - - QDoc will create additional links or pages for these contexts. For example, - a group is created using the \l{group-command}{\\group} command and the - members have the \l{ingroup-command}{\\ingroup} command. The group name is - supplied as an argument. - - The \l{Context Commands} page has a listing of all the available context - commands. - - \target writing-markup - \section2 Documentation Markup - - QDoc can do \e markup of text similar to other markup or - documentation tools. QDoc can mark a section of text in \b{bold}, - when the text is marked up with the \l{b-command}{\\b} command. - - \code - \b{This} text will be in \b{bold}. - \endcode - - The \l{Markup Commands} page has a full listing of the available markup - commands. - - \section1 Anatomy of Documentation - - Essentially, for QDoc to create a page, there must be some essential - ingredients present. - - \list - \li Assign a topic to a QDoc comment - A comment could be a page, a - property documentation, a class documentation, or any of the available - \l{Topic Commands}{topic commands}. - - \li Give the topic a context - QDoc can associate certain topics to other - pages such as associating deprecated functions when the documentation is - marked with \l{deprecated-command}{\\deprecated}. - - \li Mark sections of the document with - \l{Markup Commands}{markup commands} - QDoc can create layouts and - format the documentation for the documentation. - \endlist - - In Qt, the \l{QVector3D} class was documented with the following QDoc - comment: - \snippet examples/samples.qdocinc qvector3d-class - - It has a constructor, \l{QVector3D::QVector3D()}, which was documented with - the following QDoc comment: - \snippet examples/samples.qdocinc qvector3d-function - - The different comments may reside in different files and QDoc will collect - them depending on their topic and their context. The resulting documentation - from the snippets are generated into the \l{QVector3D} class documentation. - - Note that if the documentation immediately precedes the function or class - in the source code, then it does not need to have a topic. QDoc will assume - that the documentation above the code is the documentation for that code. - - An article is created using \l{page-command}{\\page} command. The first - argument is the HTML file that QDoc will create. The topic is supplemented - with context commands, the \l{title-command}{\\title} and - \l{nextpage-command}{\\nextpage} commands. There are several other - QDoc commands such as the \l{list-command}{\\list} command. - \snippet examples/samples.qdocinc sample-page - - The section on \l{QDoc Topics}{topic commands} gives an overview on several - other topic types. - - -*/ - -/*! - \page qdoc-categories.html - \title Categories of Documentation - \previouspage Writing Documentation - \nextpage How to Resolve QDoc Warnings - \brief Describes the different types such as How-To's, Tutorials, Overviews, - Examples, and Class Documentation. - - There are several types of predefined documentation \e categories or - \e types: - \list - \li How-To's - \li Tutorial - \li Overview - \li Article - \li FAQ (Frequently Asked Questions) - \li C++ API Documentation - \li QML Type Documentation - \li Code Example - \endlist - - QDoc has the ability to format a page depending on the type. Further, - stylesheets can provide additional control on the display of each category. - - \section1 API Documentation - QDoc excels in the creation of API documentation given a set of source code - and documentation in QDoc comments. Specifically, QDoc is aware of Qt's - architecture and can validate the existence of Qt C++ class, function, or - property documentation. QDoc gives warnings and errors if it cannot - associate a documentation with a code entity or if a code entity does not - have documentation. - - In general, every Qt code entity such as properties, classes, methods, - signals, and enumerations have a corresponding - \l{qdoc-topics}{topic command}. QDoc will associate the documentation to the - source using C++ naming rules. - - QDoc will parse the header files (typically \c .h files) to build a tree of - the class structures. Then QDoc will parse the source files and - documentation files to attach documentation to the class structure. - Afterwards, QDoc will generate a page for the class. - - \note QDoc uses the header files to inform itself about the class and will - not properly process QDoc comments in header files. - - \section2 Language Styles - - To produce quality API documentation, the Qt API references follow a - particular language guidelines. While the contents of this page demonstrates - how to create API documentation, the style guidelines demonstrate how - the reference materials follow a consistent use of language. - - \list - \li \l{C++ Documentation Style} - \li \l{QML Documentation Style} - \endlist - - \keyword qml-documentation - \section2 Documenting QML Types - - In the world of \l{Qt Quick}{QML}, there are additional entities we need to - document such as QML signals, attached properties, and QML methods. - Internally, they use Qt technologies, however, QML API documentation - requires different layout and naming conventions from the Qt C++ API - documentation. - - A list of QML related QDoc commands: - \list - \li \l{qmlattachedproperty-command}{\\qmlattachedproperty} - \li \l{qmlattachedsignal-command}{\\qmlattachedsignal} - \li \l{qmlvaluetype-command}{\\qmlvaluetype} - \li \l{qmltype-command}{\\qmltype} - creates a QML type documentation - \li \l{qmlmethod-command}{\\qmlmethod} - \li \l{qmlproperty-command}{\\qmlproperty} - \li \l{qmlsignal-command}{\\qmlsignal} - \li \l{inherits-command}{\\inherits} - \li \l{qmlmodule-command}{\\qmlmodule} - \li \l{inqmlmodule-command}{\\inqmlmodule} - \li \l{instantiates-command}{\\instantiates} - - \endlist - - \note Remember to enable QML parsing by including the \c{*.qml} filetype in - the \l{qdoc-input-output-dir}{fileextension} variable. - - To document a QML type, start by creating a QDoc comment that uses the - \l{qmltype-command} {\\qmltype} command as its topic command. - - \section3 QML Parser - - If your QML type is defined in a \e qml file, document it there. - If your QML type is represented by a C++ class, document it in the - \e cpp file for that C++ class and include an - \l{instantiates-command}{\\instantiates} command to specify the - name of the C++ class. Don't document a QML type in a \e{cpp} file - if the QML type is defined in a \e{qml} file. - - When documenting a QML type in a \e{qml} file, place each QDoc - comment directly above the entity to which the comment applies. - For example, place the QDoc comment containing the \e{\\qmltype} - command (the topic comment) directly above the outer QML type in - the \e{qml} file. Place the comment for documenting a QML property - directly above the property declaration, and so on for QML signal - handlers and QML methods. Note that when documenting QML - properties in a \e{qml} file, you don't normally include the - \e{\\qmlproperty} command as a topic command (which you must do - when documenting QML types in \e{cpp} files), because the QML - parser automatically associates each QDoc comment with the next - QML declaration it parses. The same is true for QML signal handler - and QML method comments. But it is sometimes useful to include one - or more \e{\\qmlproperty} commands in the comment, e.g. when the - property type is another QML type and you want the user to only - use certain properties within that other QML type, but not all of - them. But when documenting a property that has an alias, place the - QDoc comment for it directly above the alias declaration. In these - cases, the QDoc comment \e must contain a \e{\\qmlproperty} - command, because that is the only way QDoc can know the type of - the aliased property. - - When documenting a QML type in the \e cpp file of its - corresponding C++ class (if it has one), you normally place each - QDoc comment directly above the entity it documents. However, QDoc - does not use the QML parser to parse these files (the C++ parser - is used), so these QML QDoc comments can appear anywhere in the - \e{cpp} file. Note that QML QDoc comments in \e cpp files \e must - use the QML topic commands. i.e., the \l{qmltype-command} - {\\qmltype} command \e must appear in the QDoc comment for the - QML type, and a \l{qmlproperty-command} {\\qmlproperty} command \e - must appear in each QML property QDoc comment. - - \section3 QML Modules - - A QML type belongs to a \e module. The module - may include all the related types for a platform or contain a certain - version of \l{Qt Quick}. For example, the Qt Quick 2 QML types belong - to the Qt Quick 2 module while there is also a Qt Quick 1 module for the older - types introduced in Qt 4. - - QML modules allow grouping QML types. The \l{qmltype-command} - {\\qmltype} topic command must have an \l{inqmlmodule-command} - {\\inqmlmodule} context command to relate the type to a QML - module. Similarly, a \l{qmlmodule-command}{\\qmlmodule} topic - command must exist in a separate \c{.qdoc} file to create the - overview page for the module. The overview page will list the - QML types of the QML module. - - The links to the QML types must therefore also contain the module name. - For example, if a type called \c TabWidget is in the \c UIComponents - module, it must be linked as \c {UIComponents::TabWidget}. - - \section3 Read-only and Internal QML Properties - - QDoc detects QML properties that are marked as \c readonly. Note that the - property must be initialized with a value. - - \badcode - readonly property int sampleReadOnlyProperty: 0 - \endcode - - Properties and signals that are not meant for the public interface may - be marked with the \l{internal-command}{\\internal} command. QDoc will not - publish the documentation in the generated outputs. - - \section1 Articles & Overviews - - Articles and overviews are a style of writing best used for providing - summary detail on a topic or concept. It may introduce a technology or - discuss how a concept may be applied, but without discussing exact steps - in too much detail. However, this type of content could provide the entry - point for readers to find instructional and reference materials that do, - such as tutorials, examples and class documentation. An example of an - overview might be a product page, such as a top level discussion of - Qt Quick, individual modules, design principles, or tools. - - To signify that a document is an article, you append the article keyword - to the \\page command: - - \snippet examples/samples.qdocinc sample-overview - - The \l{writing-topic-commands}{writing topic commands} section has a listing - of the available \\page command arguments. - - \section1 Tutorials, How-To's, FAQ's - - Tutorials, How-To's, and FAQ's are all instructional material, in that they - instruct or prescribe to the reader. Tutorials are content designed to guide - the reader along a progressive learning path for a concept or technology. - How-To's and FAQ's (\e{Frequently Asked Questions}) provide guidance by - presenting material in the form of answers to commonly asked topics. - How-To's and FAQ's are designed for easy reference and are not necessarily - presented in a linear progression. - - To create these types, mark the pages by providing a \c type argument to the - \l{page-command}{\\page} command. The \c type argument is the second - argument, with the file name being the first. - \snippet examples/samples.qdocinc sample-faq - - The \l{writing-topic-commands}{writing topic commands} section has a listing - of the available \\page command arguments. - - \section1 Code Examples - Examples are an effective way to demonstrate practical usage of a given - technology or concept. When it comes to middleware this is usually in the - form of an application using simple code and clear explanations of what the - code is doing. Any module, API, project, pattern etc. should have at least - one good example. - - An example may have an accompanying tutorial. The tutorial instructs and - describes the code, while the code example is the code content that users - may study. Code examples may have accompanying text that are not in the - tutorial. - - QDoc will create a page containing the example code with a description - using the \l{example-command}{\\example} command. - - \snippet examples/samples.qdocinc sample-example - - QDoc will use the directory specified in the input - \l{Input and Output Directories}{exampledirs} variable to find the Qt - Project (\c .pro) file to generate the example files. The generated HTML - will have the filename, \c {declarative-ui-components-tabwidget.html}. QDoc - will also list all of the example code. - - \note The example's project file must be the same as the - directory name. -*/ - - -/*! - \page qdoc-guide-clang.html - \title Installing Clang for QDoc - \previouspage Getting Started with QDoc - \nextpage Creating QDoc Configuration Files - - QDoc uses Clang when parsing C++ files as well as function signatures in - \l {fn-command} {\\fn} commands. Clang is part of - \l {https://llvm.org/}{the LLVM Compiler Infrastructure Project}. - If you're going to build QDoc from source, you must install - \l{http://clang.llvm.org}{Clang 8.0} or later. - - You can get Clang through various channels: - - \list - \li Qt provides the - \l{http://download.qt.io/development_releases/prebuilt/libclang/qt} - {prebuilt Clang packages} that are used for the Qt binaries in the - online installer. These let you link LLVM/Clang libraries statically, - but only support Release builds on Windows. - \li Linux distributions often provide a package called \e libclang-dev or - \e libclang-devel. Qt's build system instructs CMake to look for - \e {ClangConfig.cmake}, so make sure you install the package that - provides this file if you want to build QDoc. Running QDoc requires - only \e libclang. - \li On macOS, you can also use Homebrew's - \l{https://formulae.brew.sh/formula/llvm}{llvm formula}. - \endlist - - \note the prebuilt binaries from \l{http://releases.llvm.org/download.html} - cannot be used, as they miss certain components required by QDoc. - - If you install Clang in a custom location you need to tell CMake where - to find it. This can be done by specifying your LLVM installation path - using the \c LLVM_INSTALL_DIR environment variable when configuring Qt. - Alternatively, you can add the installation path to the \c CMAKE_PREFIX_PATH - CMake cache variable. -*/ diff --git a/src/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc b/src/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc deleted file mode 100644 index 43387ca7e..000000000 --- a/src/qdoc/doc/qdoc-guide/qtwritingstyle-cpp.qdoc +++ /dev/null @@ -1,163 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! -\page qtwritingstyle-cpp.html -\title C++ Documentation Style -\brief Style guidelines for C++ documentation - -To generate the documentation, QDoc goes through the source code and generates -documentation for C++ types such as classes. QDoc then associates member -functions, properties, and other types to the appropriate class. - -Note that the documentation must be in the implementation files such as \c .cpp. - -\section1 Class Documentation - -Class documentation is generated using the \l{class-command}{\\class} command and -the name of the class as the first argument. - -\snippet examples/cpp.qdoc.sample class - -\l{Context commands} add information about the class, such as its module or -which version the class was added. - -Some common context commands are: -\list -\li \l{brief-command}{\\brief} - the class' brief description \b (mandatory) -\li \l{since-command}{\\since} - the version to which the class was added \b (mandatory) -\li \l{internal-command}{\\internal} - marks the class as internal. Internal -classes do not appear in the public API documentation. -\endlist - - -\section2 The Brief and Detailed Description - -The \e{brief description} is marked with the \l{brief-command}{\\brief} command -and it is for summarizing the purpose or functionality of the class. For C++ -classes, QDoc will take the class and create annotated information for the -class. The annotated information appears in lists and tables which display the -class. - -The C++ brief should start with: -\code -"The class" -\endcode - -The \e{detailed description} section starts after the brief description. It -provides more information about the class. The detailed description may contain -images, snippet code, or links to other relevant documents. There -must be an empty line which separates the brief and detailed description. - -\section1 Member Functions - -Typically, function documentation immediately precedes the implementation of the -function in the \c .cpp file. For function documentation that is not immediately -above the implementation, the \l{fn-command}{\\fn} is needed. - -\snippet examples/cpp.qdoc.sample function - -The function documentation starts with a verb, indicating the operation the -function performs. This also applies to constructors and destructors. - -Some common verbs for function documentation: -\list -\li "Constructs..." - for constructors -\li "Destroys..." - for destructors -\li "Returns..." - for accessor functions -\endlist - -The function documentation must document: -\list -\li the return type -\li the parameters -\li the actions of the functions -\endlist - -The \l{a-command}{\\a} command marks the parameter in the documentation. -The return type documentation should link to the type documentation or be -marked with the \l{c-command}{\\c} command in the case of boolean values. - -\snippet examples/cpp.qdoc.sample return - -\section1 Properties - -The property documentation resides immediately above the read function's -implementation. The \l{writing-topic-commands}{topic command} for properties is -\l{property-command}{\\property}. - -\snippet examples/cpp.qdoc.sample property - -Property documentation usually starts with "This property...", but these are -alternate expressions: -\list -\li "This property holds..." -\li "This property describes..." -\li "This property represents..." -\li "Returns \c true when... and \c false when..." - for properties that -are read. -\li "Sets the..." - for properties that configure a type. -\endlist - -Property documentation must include: -\list -\li description and behavior of the property -\li accepted values for the property -\li the default value of the property -\endlist -Similar to \l{Member Functions}{functions}, the default type may be linked -or marked with the \c{\c} command. - -An example of a value range style is: -\quotation -The values range from 0.0 (no blur) to maximumRadius (maximum blur). By default, the property is set to 0.0 (no blur). -\endquotation - -\section1 Signals, Notifiers, and Slots -The \l{writing-topic-commands}{topic command} for signals, notifiers, and slots -is \l{fn-command}{\\fn}. Signal documentation state when they are triggered -or emitted. - -\snippet examples/cpp.qdoc.sample signals - -Signal documentation typically begin with "This signal is triggered when...". -Here are alternate styles: -\list -\li "This signal is triggered when..." -\li "Triggered when..." -\li "Emitted when..." -\endlist - -For slots or notifiers, the condition when they are executed or triggered by -a signal should be documented. -\list -\li "Executed when..." -\li "This slot is executed when..." -\endlist - -For properties that have overloaded signals, QDoc groups the overloaded -notifiers together. To refer to a specific version of a notifier or signal, -simply refer to the property and mention that there are different versions of -the notifier. - -\snippet examples/cpp.qdoc.sample overloaded notifier - -\section1 Enums, Namespaces, and Other Types - -Enums, namespaces, and macros have a \l{writing-topic-commands}{topic command} for their documentation: -\list -\li \l{enum-command}{\\enum} -\li \l{typedef-command}{\\typedef} -\li \l{macro-command}{\\macro} -\endlist - -The language style for these types mention that they are an enum or a macro and -continues with the type description. - -For enumerations, the \l{value-command}{\\value} command is for listing the -values. QDoc creates a table of values for the enum. - -\snippet examples/cpp.qdoc.sample enums - -*/ - diff --git a/src/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc b/src/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc deleted file mode 100644 index cbf76b175..000000000 --- a/src/qdoc/doc/qdoc-guide/qtwritingstyle-qml.qdoc +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! -\page qtwritingstyle-qml.html -\title QML Documentation Style -\brief Style guidelines for QML documentation - -QDoc can process QML types defined as C++ classes and QML types defined in -\c .qml files. For C++ classes documented as QML types, the QDoc comments are -in the \c .cpp file while QML types defined in QML are in the \c .qml -file. The C++ classes must also be documented -documented with the QML \l{topic-commands}{topic commands}: - -\list -\li \l{qmlattachedproperty-command}{\\qmlattachedproperty} -\li \l{qmlattachedsignal-command}{\\qmlattachedsignal} -\li \l{qmlvaluetype-command}{\\qmlvaluetype} -\li \l{qmltype-command}{\\qmltype} -\li \l{qmlmethod-command}{\\qmlmethod} -\li \l{qmlproperty-command}{\\qmlproperty} -\li \l{qmlsignal-command}{\\qmlsignal} -\li \l{qmlmodule-command}{\\qmlmodule} -\li \l{inqmlmodule-command}{\\inqmlmodule} -\li \l{instantiates-command}{\\instantiates} -\endlist - -For QML types defined in \c .qml files, QDoc will parse the QML and determine -the properties, signals, and the type within the QML definition. The QDoc -block then needs to be immediately above the declaration. For QML types -implemented in C++, QDoc will output warnings if the C++ class documentation -does not exist. The class documentation may be marked as -\l{internal-command}{internal} if it is not a public API. - -\section1 QML Types - -The \l{qmltype-command}{\\qmltype} command is for QML type documentation. - -\snippet examples/qml.qdoc.sample qmltype - -The \l{instantiates-command}{\\instantiates} accepts the C++ class which -implements the QML type as the argument. For types implemented in QML, this -is not needed. - -The \e{brief description} provides a summary for the QML type. The brief does -not need to be a complete sentence and may start with a verb. QDoc will append -the brief description onto the QML type in tables and generated lists. - -\code -\qmltype ColorAnimation -\brief Animates changes in color values -\endcode - -Here are some alternate verbs for the brief statement: -\list -\li "Provides..." -\li "Specifies..." -\li "Describes..." -\endlist - -The \e{detailed description} follows the brief and may contain images, snippet, -and link to other documentation. - -\section1 Properties - -The property description focuses on what the property \e does and may use the -following style: - -Property documentation usually starts with "This property..." but for certain -properties, these are the common expressions: -\list -\li "This property holds..." -\li "This property describes..." -\li "This property represents..." -\li "Returns \c true when... and \c false when..." - for properties that -are marked \c{read-only}. -\li "Sets the..." - for properties that configure a type. -\endlist - -\section1 Signals and Handlers Documentation - -QML signals are documented either in the QML file or in the C++ implementation -with the \l{qmlsignal-command}{\\qmlsignal} command. Signal documentation -must include the condition for emitting the signal, mention the corresponding -signal handler, and document whether the signal accepts a parameter. - -\snippet examples/qml.qdoc.sample signals - -These are the possible documentation styles for signals: -\list -\li "This signal is triggered when..." -\li "Triggered when..." -\li "Emitted when..." -\endlist - -\section1 Methods and QML Functions - -Typically, function documentation immediately precedes the implementation of the -function in the \c .cpp file. The \l{topic-commands}{topic command} for -functions is \l{fn-command}{\\fn}. For functions in QML, the -documentation must reside immediately above the function declaration. - -The function documentation starts with a verb, indicating the operation the -function performs. - -\snippet examples/qml.qdoc.sample function - -Some common verbs for function documentation: -\list -\li "Copies..." - for constructors -\li "Destroys..." - for destructors -\li "Returns..." - for accessor functions -\endlist - -The function documentation must document: -\list -\li the return type -\li the parameters -\li the actions of the functions -\endlist - -The \l{a-command}{\\a} command marks the parameter in the documentation. -The return type documentation should link to the type documentation or be -marked with the \l{c-command}{\\c} command in the case of boolean values. - -\section1 Enumerations - -QML enumerations are documented as QML properties with the -\l{qmlproperty-command}{\\qmlproperty} command. The type of the property -is \c enumeration. Use the \l{value-command}{\\value} command to document -the enum values. Add the type name as a prefix to each value, separated by -a period (.), as QDoc does not do this automatically. - -\snippet examples/qml.qdoc.sample enums - -The QDoc comment lists the values of the enumeration. If the enumeration is -implemented in C++, the documentation may link to the corresponding C++ -enumeration. However, the QDoc comment should advise that the enumeration -is a C++ enumeration. - -*/ - diff --git a/src/qdoc/doc/qdoc-manual-cmdindex.qdoc b/src/qdoc/doc/qdoc-manual-cmdindex.qdoc deleted file mode 100644 index a915a9f7c..000000000 --- a/src/qdoc/doc/qdoc-manual-cmdindex.qdoc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page 27-qdoc-commands-alphabetical.html - \previouspage Introduction to QDoc - \nextpage Topic Commands - - \title Command Index - - This is a complete, alphabetized list of the QDoc commands. - - \list - - \li \l {a-command} {\\a} - \li \l {abstract-command} {\\abstract} - \li \l {annotatedlist-command} {\\annotatedlist} - \li \l {b-command} {\\b} - \li \l {badcode-command} {\\badcode} - \li \l {b-command} {\\bold} (deprecated, use \\b) - \li \l {brief-command} {\\brief} - \li \l {c-command} {\\c} - \li \l {caption-command} {\\caption} - \li \l {class-command} {\\class} - \li \l {code-command} {\\code} - \li \l {codeline-command} {\\codeline} - \li \l {deprecated-command} {\\deprecated} - \li \l {default-command} {\\default} - \li \l {div-command} {\\div} - \li \l {dots-command} {\\dots} - \li \l {e-command} {\\e} - \li \l {else-command} {\\else} - \li \l {endif-command} {\\endif} - \li \l {enum-command} {\\enum} - \li \l {example-command} {\\example} - \li \l {externalpage-command} {\\externalpage} - \li \l {fn-command} {\\fn} - \li \l {footnote-command} {\\footnote} - \li \l {generatelist-command} {\\generatelist} - \li \l {group-command} {\\group} - \li \l {header-command} {\\header} - \li \l {headerfile-command} {\\headerfile} - \li \l {e-command} {\\i} (deprecated, use \\e) - \li \l {if-command} {\\if} - \li \l {image-command} {\\image} - \li \l {include-command} {\\include} - \li \l {ingroup-command} {\\ingroup} - \li \l {inheaderfile-command}{\\inheaderfile} - \li \l {inherits-command}{\\inherits} - \li \l {inlineimage-command} {\\inlineimage} - \li \l {inmodule-command} {\\inmodule} - \li \l {inqmlmodule-command} {\\inqmlmodule} - \li \l {instantiates-command} {\\instantiates} - \li \l {internal-command} {\\internal} - \li \l {keyword-command} {\\keyword} - \li \l {l-command} {\\l} - \li \l {legalese-command} {\\legalese} - \li \l {li-command} {\\li} - \li \l {list-command} {\\list} - \li \l {macro-command} {\\macro} - \li \l {meta-command} {\\meta} - \li \l {module-command} {\\module} - \li \l {namespace-command} {\\namespace} - \li \l {nextpage-command} {\\nextpage} - \li \l {noautolist-command} {\\noautolist} - \li \l {nonreentrant-command} {\\nonreentrant} - \li \l {note-command} {\\note} - \li \l {li-command} {\\o} (deprecated, use \\li) - \li \l {omit-command} {\\omit} - \li \l {omitvalue-command} {\\omitvalue} - \li \l {overload-command} {\\overload} - \li \l {page-command} {\\page} - \li \l {preliminary-command} {\\preliminary} - \li \l {previouspage-command} {\\previouspage} - \li \l {printline-command} {\\printline} - \li \l {printto-command} {\\printto} - \li \l {printuntil-command} {\\printuntil} - \li \l {property-command} {\\property} - \li \l {qml-command} {\\qml} - \li \l {qmlabstract-command} {\\qmlabstract} - \li \l {qmlattachedproperty-command} {\\qmlattachedproperty} - \li \l {qmlattachedsignal-command} {\\qmlattachedsignal} - \li \l {qmlvaluetype-command} {\\qmlvaluetype} - \li \l {qmlclass-command} {\\qmlclass} (deprecated, use \\qmltype) - \li \l {qmldefault-command} {\\qmldefault} - \li \l {qmltype-command} {\\qmltype} - \li \l {qmlmethod-command} {\\qmlmethod} - \li \l {qmlproperty-command} {\\qmlproperty} - \li \l {qmlsignal-command} {\\qmlsignal} - \li \l {qmlmodule-command} {\\qmlmodule} - \li \l {qtcmakepackage-command} {\\qtcmakepackage} - \li \l {quotation-command} {\\quotation} - \li \l {quotefile-command} {\\quotefile} - \li \l {quotefromfile-command} {\\quotefromfile} - \li \l {raw-command} {\\raw} - \li \l {readonly-command} {\\readonly} - \li \l {reentrant-command} {\\reentrant} - \li \l {reimp-command} {\\reimp} - \li \l {relates-command} {\\relates} - \li \l {required-command} {\\required} - \li \l {row-command} {\\row} - \li \l {sa-command} {\\sa} - \li \l {sectionOne-command} {\\section1} - \li \l {sectionTwo-command} {\\section2} - \li \l {sectionThree-command} {\\section3} - \li \l {sectionFour-command} {\\section4} - \li \l {since-command} {\\since} - \li \l {sincelist-command} {\\sincelist} - \li \l {skipline-command} {\\skipline} - \li \l {skipto-command} {\\skipto} - \li \l {skipuntil-command} {\\skipuntil} - \li \l {snippet-command} {\\snippet} - \li \l {span-command} {\\span} - \li \l {startpage-command} {\\startpage} - \li \l {sub-command} {\\sub} - \li \l {subtitle-command} {\\subtitle} - \li \l {sup-command} {\\sup} - \li \l {table-command} {\\table} - \li \l {tableofcontents-command} {\\tableofcontents} - \li \l {target-command} {\\target} - \li \l {threadsafe-command} {\\threadsafe} - \li \l {title-command} {\\title} - \li \l {tt-command} {\\tt} - \li \l {typealias-command} {\\typealias} - \li \l {typedef-command} {\\typedef} - \li \l {uicontrol-command} {\\uicontrol} - \li \l {underline-command} {\\underline} - \li \l {variable-command} {\\variable} - \li \l {value-command} {\\value} - \li \l {warning-command} {\\warning} - \li \l {wrapper-command} {\\wrapper} - \endlist -*/ diff --git a/src/qdoc/doc/qdoc-manual-contextcmds.qdoc b/src/qdoc/doc/qdoc-manual-contextcmds.qdoc deleted file mode 100644 index 821c6b0fa..000000000 --- a/src/qdoc/doc/qdoc-manual-contextcmds.qdoc +++ /dev/null @@ -1,1075 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page 14-qdoc-commands-contextcommands.html - \previouspage Topic Commands - \nextpage Document Navigation - - \title Context Commands - - The context commands provide information about the element being - documented that QDoc can't deduce on its own. For example: - \list - \li Is this class thread-safe? - \li Is this function reentrant? - \li Of which module is this class a member? - \li Which include statement is needed to use this class? - \endlist - - Context commands can appear anywhere in a QDoc comment, - but they are normally placed near the top of the comment, just - below the \l {Topic Commands} {topic} command. - - \list - \li \l {abstract-command} {\\abstract} - \li \l {default-command} {\\default} - \li \l {deprecated-command}{\\deprecated} - \li \l {ingroup-command}{\\ingroup} - \li \l {inheaderfile-command}{\\inheaderfile} - \li \l {inherits-command}{\\inherits} - \li \l {inmodule-command}{\\inmodule} - \li \l {internal-command}{\\internal} - \li \l {modulestate-command} {\\modulestate} (Since QDoc 6.5) - \li \l {nextpage-command}{\\nextpage} - \li \l {nonreentrant-command}{\\nonreentrant} - \li \l {overload-command}{\\overload} - \li \l {preliminary-command}{\\preliminary} - \li \l {previouspage-command}{\\previouspage} - \li \l {qmlabstract-command} {\\qmlabstract} - \li \l {qmldefault-command} {\\qmldefault} - \li \l {qtcmakepackage-command} {\\qtcmakepackage} - \li \l {readonly-command} {\\readonly} - \li \l {reentrant-command}{\\reentrant} - \li \l {reimp-command}{\\reimp} - \li \l {relates-command}{\\relates} - \li \l {required-command} {\\required} - \li \l {since-command}{\\since} - \li \l {startpage-command}{\\startpage} - \li \l {subtitle-command}{\\subtitle} - \li \l {threadsafe-command}{\\threadsafe} - \li \l {title-command}{\\title} - \li \l {wrapper-command}{\\wrapper} - \endlist - -*/ - -/*! - \page 15-qdoc-commands-navigation.html - \previouspage Context Commands - \nextpage Status - - \title Document Navigation - - The navigation commands are for linking the pages of a document in - a meaningful sequence. Below is a sequence of QDoc comments that - shows a typical use of the navigation commands. - - \section1 Example - \quotefile files/basicqt.qdoc.sample - - QDoc renders the "Getting Started" page in \c{creatingdialogs.html}: - - \quotation - \raw HTML - - - -

- [Previous: - Basic Qt] - [Contents] - [Next: - Creating Dialogs] -

- -

Getting Started

- -

- This chapter shows how to combine basic C++ with the - functionality provided by Qt to create a few small graphical - interface (GUI) applications. -

- -

- [Previous: - Basic Qt] - [Contents] - [Next: - Creating Dialogs] -

- -
- \endraw - \endquotation - - The \l {startpage-command} {\\startpage} command creates a link to - the page the author wants as the first page of a multipage document. - - The link is included in the generated HTML source code but has no - visual effect on the documentation: - - \code - - ... - - ... - - \endcode - - \section1 Commands - - \target previouspage-command - \section2 \\previouspage - - The \\previouspage command links the current page to the previous - page in a sequence. The command has two arguments, each enclosed - by curly braces: the first is the link target (the title of - the previous page), the second is the link text. If the page's - title is equivalent to the link text, the second argument can be - omitted. - - The command must stand alone on its own line. - - \target nextpage-command - \section2 \\nextpage - - The \\nextpage command links the current page to the next page in - a sequence. The command follows the same syntax and argument - convention as the \l {previouspage-command} {\\previouspage} - command. - - \target startpage-command - \section2 \\startpage - - The \\startpage command specifies the first page of a sequence of - pages. The command must stand alone on its own line, and its - unique argument is the title of the first document. - - QDoc will generate a link to the start page and include it in the - generated HTML file, but this has no visual effect on the - documentation. The generated link type tells browsers and search - engines which document is considered by the author to be the - starting point of the collection. -*/ - -/*! - \page 16-qdoc-commands-status.html - \previouspage Document Navigation - \nextpage Thread Support - - \title Status - - These commands are for indicating that a documented element has - some special status. The element could be marked \e deprecated, - that is, it's about to be made obsolete and no longer included - in the public interface. The \l {since-command}{\\since} command - is for specifying the version number in which a function or class - first appeared. The \l {qmlabstract-command} {\\qmlabstract} command - is for marking a QML type as an abstract base class. - - \target abstract-command - \target qmlabstract-command - \section1 \\abstract and \\qmlabstract - - \\abstract is a synonym for the \\qmlabstract command. Add this - command to the \l {qmltype-command} {\\qmltype} comment for a QML - type when that type is meant to be used \e {only} as an abstract - base type. When a QML type is abstract, it means that the QML type - that can't be instantiated. Instead, the properties in its public - API are included in the public properties list on the reference - page for each QML type that inherits the abstract QML type. The - properties are documented as if they are properties of the - inheriting QML type. - - Normally, when a QML type is marked with \e{\\qmlabstract}, it is - also marked with \e{\\internal} so that its reference page is not - generated. It the abstract QML type is not marked internal, it - will have a reference page in the documentation. - - \target default-command - \section1 \\default - - The \\default command is used for documenting a default value for - a QML property. The command takes a single argument, which is - displayed in the documentation as the default value. - - \badcode * - /\1! - \qmlproperty real Item::x - \default 0.0 - \1/ - \endcode - - If the default value is a non-empty string, use quotes: - - \badcode * - /\1! - \qmlproperty string Item::state - \default "invalid" - \1/ - \endcode - - \target qmldefault-command - \section1 \\qmldefault - - The \\qmldefault command is for marking a QML property as the - \l {default-properties} - {default property}. The word \c default is displayed in - the documentation of the property. - - \badcode * - /\1! - \qmlproperty list State::changes - This property holds the changes to apply for this state. - \qmldefault - - By default, these changes are applied against the default state. If the state - extends another state, then the changes are applied against the state being - extended. - \1/ - \endcode - - See how QDoc renders this property on the reference page for the - \l {QtQuick::State::changes}{State} type. - - \target dontdocument-command - \section1 \\dontdocument - - The \\dontdocument command is only used in a dontdocument.qdoc file - for a particular module. This file specifies publically declared - classes or structs that are not meant to be documented. QDoc will - not print warnings about missing \\class comments for these classes - and structs. - - Below you will find the \\dontdocument command in the - dontdocument.qdoc for widgets: - - \badcode * - /\1! - \dontdocument (QTypeInfo QMetaTypeId) - \1/ - \endcode - - \target inheaderfile-command - \section1 \\inheaderfile - - The \\inheaderfile meta-command is used for overriding the include statement - generated for a C++ class, namespace, or header file reference documentation. - - By default, QDoc documents a \c {\class SomeClass} to be available with - a following include statement: - - \code - #include - \endcode - - If the actual include statement differs from the default, this can be - documented as - - \badcode - \class SomeClass - \inheaderfile Tools/SomeClass - ... - \endcode - - See also \l {class-command}{\\class} and - \l {headerfile-command}{\\headerfile}. - - - \target obsolete-command - \section1 \\obsolete - The \\obsolete command is superceded by the \\deprecated command. - - This command is kept for backwards compatibility reasons only. - It may be removed in a future version of QDoc. Use the \\deprecated - command instead. - - See also \l {deprecated-command}{\\deprecated}. - - \target deprecated-command - \section1 \\deprecated - - The \\deprecated command is for indicating that a function is being - deprecated, and that it should no longer be used in new code. There - is no guarantee for how long it will remain in the library. - - The \\deprecated command takes two optional arguments: - \list - \li A version in square brackets (e.g. [6.2]). - \li A string with more information, for example a suggested - replacement. - \endlist - - When generating the reference documentation for a class, QDoc will - create and link to a separate page documenting its deprecated - functions. It is good practice to suggest an equivalent function - as an alternative. - - \badcode * - /\1! - \fn MyClass::MyDeprecatedFunction - \deprecated [6.2] Use MyNewFunction() instead. - \1/ - \endcode - - QDoc renders this in \c{myclass-obsolete.html} as: - - \quotation - \raw HTML -

Deprecated Members for MyClass

- \endraw - - \b {The following class members are deprecated.} We strongly - advise against using them in new code. - - ... - - \list - \li void MyDeprecatedFunction() \c (deprecated) - \li ... - \endlist - - \raw HTML -
-

Member Function Documentation

-

void MyDeprecatedFunction ()

-

This function is deprecated since 6.2. It is provided to - keep old source code working. We strongly advise against using - it in new code. Use MyNewFunction() instead.

- \endraw - ... - \endquotation - - \target internal-command - \section1 \\internal - - The \\internal command indicates that the referenced - function is not part of the public interface. - - The command must stand on its own line. - - QDoc ignores the documentation as well as the documented item, - when generating the associated class reference documentation. - - \badcode * - /\1! - \internal - - Tries to find the decimal separator. If it can't find - it and the thousand delimiter is != '.' it will try to - find a '.'; - \1/ - int QDoubleSpinBoxPrivate::findDelimiter - (const QString &str, int index) const - { - int dotindex = str.indexOf(delimiter, index); - if (dotindex == -1 && thousand != dot && delimiter != dot) - dotindex = str.indexOf(dot, index); - return dotindex; - } - \endcode - - This function will not be included in the documentation, unless QDoc - is called with the \c{-showinternal} command line option or the - \c{QDOC_SHOW_INTERNAL} environment variable is set. - - \target modulestate-command - \section1 \\modulestate - - The \\modulestate command can be used within a \\module or \\qmlmodule - topic to provide a module state description other than \e preliminary or - \e deprecated. - - Rest of the line is taken as an argument that describes the module's - state. For example: - - \badcode * - /*! - \module QtFoo - \modulestate Technical Preview - \1/ - \endcode - - QDoc will then add this information on the module page: - - \quotation - This module is in \e {Technical Preview} state. - \endquotation - - In HTML output, this state information appears also in the navigation - bar (breadcrumbs) of reference pages for the module's members. - - \target preliminary-command - \section1 \\preliminary - - The \\preliminary command is for indicating that a referenced - function is still under development. - - The command must stand on its own line. - - The \\preliminary command expands to a notification in the - function documentation, and marks the function as preliminary when - it appears in lists. - - \badcode * - /\1! - \preliminary - - Returns information about the joining type attributes of the - character (needed for certain languages such as Arabic or - Syriac). - - \1/ - QChar::JoiningType QChar::joiningType() const - { - return QChar::joiningType(ucs); - } - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

- JoiningType - QChar::joiningType() const

- \endraw - - \b {This function is under development and - subject to change.} - - Returns information about the joining type attributes of the - character (needed for certain languages such as Arabic or - Syriac). - \endquotation - - And the function's entry in QChar's list of public functions will be - rendered as: - - \quotation - \list - \li ... - \li JoiningType \l {QChar::joiningType()} {joiningType}() const \c (preliminary) - \li ... - \endlist - \endquotation - - \target readonly-command - \section1 \\readonly - - The \\readonly command is used in conjunction with a \l {qmlproperty-command} - {\\qmlproperty} command to mark the QML property as read-only. - - \target required-command - \section1 \\required - - The \\required command is used in conjunction with a \l {qmlproperty-command} - {\\qmlproperty} command to mark the QML property as required. - - \b {See also} \l {The Property System}. - - \target since-command - \section1 \\since - - The \\since command tells in which minor release - the associated functionality was added. - - \badcode * - /\1! - \since 4.1 - - Returns an icon for \a standardIcon. - - ... - - \sa standardPixmap() - \1/ - QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const - { - } - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

QIcon QStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const

- \endraw - - This function was introduced in Qt version 4.1. - - Returns an icon for \a standardIcon. - - ... - - \b {See also} \l {QStyle::standardPixmap()} {standardPixmap()}. - \endquotation - - If the argument passed to \\since contains no spaces, it is assumed to be - a version number string for the Qt project, and QDoc will prefix it with - 'Qt' in the generated output. The argument can also contain the project - name explicitly: - - \badcode - \since MyFramework 2.0 - \endcode - - In this case, the arguments (project and version) are used as is. - - \section2 Inheritance of Since Information - - Since QDoc version 6.5, C++ classes and QML types inherit the \\since statement - from their respective \l {module-command}{module} or \l {qmlmodule-command} - {QML module}, unless \\since is explicitly used in the type documentation. - - \section2 Since Clause - - The \\value command allows an optional \e {since} clause, enclosed in square - brackets, to immediately follow the command string. This is used for - marking specific C++ enum values with since information. - - See also \l {value-command}{\\value} and \l {ignoresince}. - - \target wrapper-command - \section1 \\wrapper - - The \\wrapper command, when used in a C++ class documentation, marks the - class as a \e wrapper that provides access to a non-Qt API. This command - is used for suppressing warnings that might otherwise be generated for - members of such a class. -*/ - - -/*! - \page 17-qdoc-commands-thread.html - \previouspage Status - \nextpage Relating Things - - \title Thread Support - - The thread support commands are for specifying the level of - support for multithreaded programming in a class or function. - There are three levels of support: \c threadsafe, \c reentrant and - \c nonreentrant. - - The default is \c nonreentrant which means that the associated - class or function cannot be called by multiple threads. \c - Reentrant and \c threadsafe are levels primarily used for classes. - - \c Reentrant means that all the functions in the referenced class - can be called simultaneously by multiple threads, provided that - each invocation of the functions reference unique data. While \c - threadsafe means that all the functions in the referenced class - can be called simultaneously by multiple threads even when each - invocation references shared data. - - When a class is marked \l {reentrant-command} {\\reentrant} or \l - {threadsafe-command} {\\threadsafe}, functions in that class can - be marked \c nonreentrant using the \l {nonreentrant-command} - {\\nonreentrant} command. - - \section1 Example - - \target reentrant-example - \badcode * - /\1! - \class QLocale - \brief The QLocale class converts between numbers and their - string representations in various languages. - - \reentrant - \ingroup i18n - \ingroup text - - QLocale is initialized with a language/country pair in its - constructor and offers number-to-string and string-to-number - conversion functions similar to those in QString. - - ... - - \nonreentrant - - Sets the global default locale to \a locale. These values are - used when a QLocale object is constructed with no - arguments. If this function is not called, the system's locale - is used. - - \warning In a multithreaded application, the default locale - should be set at application startup, before any non-GUI - threads are created. - - \sa system(), c() - \1/ - void QLocale::setDefault(const QLocale &locale) - { - default_d = locale.d; - } - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

QLocale Class Reference

- \endraw - - The QLocale class converts between numbers and their string - representations in various languages. More... - - \code - #include - \endcode - - \b {Note:} All the functions in this class are \l - {17-qdoc-commands-thread.html#reentrant} {reentrant}, except \l - {QLocale::setDefault()} {setDefault()}. - - ... - - \raw HTML -
-

Member Type Documentation

- \endraw - - ... - - \raw HTML -

void QLocale::setDefault ( const QLocale & locale )

- \endraw - - Sets the global default locale to locale. These values are - used when a QLocale object is constructed with no - arguments. If this function is not called, the system's locale - is used. - - \warning In a multithreaded application, the default locale - should be set at application startup, before any non-GUI - threads are created. - - \warning This function is not reentrant. - - See also \l {QLocale::system()} {system()} and \l - {QLocale::c()} {c()}. - - ... - \endquotation - - As shown above, QDoc generates a notification when a class is - declared reentrant, and lists the exceptions (the declared - nonreentrant functions). A link to the general documentation on \l - {17-qdoc-commands-thread.html#reentrant} {reentrancy and thread-safety} is - included. In addition a warning, "\b Warning: This function is - not reentrant.", is generated in the nonreentrant functions' - documentation. - - QDoc will generate the same notification and warnings when a class - is declared threadsafe. - - For more information see the general documentation on \l - {17-qdoc-commands-thread.html#reentrant} {reentrancy and thread-safety}. - - \section1 Commands - - \target threadsafe-command - \section2 \\threadsafe - - The \\threadsafe command includes a line in the documentation to - indicate that the associated class or function is \e threadsafe - and can be called simultaneously by multiple threads, even when - separate invocations reference shared data. - - The command must stand on its own line. - - The documentation generated from this command will be similar to - the what is generated for the \l {reentrant-command} {\\reentrant} - command. See the example above in the \l {reentrant-example} - {introduction}. - - See also \l{reentrant-command} {\\reentrant} and - \l{nonreentrant-command} {\\nonreentrant}. - - \target reentrant-command - \section2 \\reentrant - - The \\reentrant command indicates that the associated class or - function can be called simultaneously by multiple threads, - provided that each invocation references its own data. See the \l - {reentrant-example} {example} above. - - The command must stand on its own line. - - See also \l{nonreentrant-command} {\\nonreentrant} and - \l{threadsafe-command} {\\threadsafe}. - - \target nonreentrant-command - \section2 \\nonreentrant - - The \\nonreentrant command indicates that the associated class or - function cannot be called by multiple threads. Nonreentrant is the - default case. - - The command must stand on its own line. - - When a class is marked \l {reentrant-command} {\\reentrant} or \l - {threadsafe-command} {\\threadsafe}, functions in that class can - be marked \c nonreentrant using this command in the \l{fn-command} - {\\fn} comment of the functions to be excluded. - - See also \l{reentrant-command} {\\reentrant} and - \l{threadsafe-command} {\\threadsafe}. -*/ - -/*! - \page 18-qdoc-commands-relating.html - \previouspage Thread Support - \nextpage Grouping Things - - \title Relating Things - - The relating commands are for specifying how one documented - element relates to another documented element. Some examples: - \list - \li This function is an overload of another function. - \li This function is a reimplementation of another function. - \li This typedef is \e related to some class or header file. - \endlist - - There is also a command for documenting that a QML type inherits - some other QML type. - - \section1 Commands - - \target inherits-command - \section2 \\inherits - - The \\inherits command is for documenting that one QML type - inherits some other QML type. It must be included in the - inheriting element's \l{qmltype-command}{\\qmltype} comment. - The argument is the name of the inherited QML type. - - \badcode * - /\1! - \qmltype PauseAnimation - \instantiates QDeclarativePauseAnimation - \ingroup qml-animation-transition - \since 4.7 - \inherits Animation - \brief The PauseAnimation element provides a pause for an animation. - - When used in a SequentialAnimation, PauseAnimation is a step - when nothing happens, for a specified duration. - - A 500ms animation sequence, with a 100ms pause between two animations: - - SequentialAnimation { - NumberAnimation { ... duration: 200 } - PauseAnimation { duration: 100 } - NumberAnimation { ... duration: 200 } - } - - \sa {QML Animation and Transitions}, {declarative/animation/basics}{Animation basics example} - \1/ - \endcode - - QDoc includes this line on the reference page for the - \l [QML] PauseAnimation - element: - - \quotation - Inherits \l [QML] Animation - \endquotation - - \target overload-command - \section2 \\overload - - The \\overload command is for indicating that a function is a - secondary overload of its name. - - The command must stand on its own line. - - For a function name that is overloaded (except constructors), QDoc - expects one primary version of the function, and all the others - marked with the \b {\\overload command}. The primary version - should be fully documented. Each overload can have whatever extra - documentation you want to add for just that overloaded version. - - You can include the function name plus '()' as a parameter to - the \b{\\overload} command, which will include a standard - \e{This function overloads...} line of text with a link - to the documentation for the primary version of the function. - - \badcode * - /\1! - \overload addAction() - - This convenience function creates a new action with an - \a icon and some \a text. The function adds the newly - created action to the menu's list of actions, and - returns it. - - \sa QWidget::addAction() - \1/ - QAction *QMenu::addAction(const QIcon &icon, const QString &text) - { - QAction *ret = new QAction(icon, text, this); - addAction(ret); - return ret; - } - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

QAction - * QMenu::addAction ( const QIcon & icon, - const QString & text ) -

- \endraw - - This function overloads \l {QMenu::addAction()} {addAction()} - - This convenience function creates a new action with an - \e icon and some \e text. The function adds the newly - created action to the menu's list of actions, and - returns it. - - See also - \l {QWidget::addAction()} {QWidget::addAction}(). - \endquotation - - If you don't include the function name with the \b{\\overload} - command, then instead of the "This function overloads..." line - with the link to the documentation for the primary version, you - get the old standard line: - - \quotation - This is an overloaded member function, provided for - convenience. - \endquotation. - - \target reimp-command - \section2 \\reimp - - The \\reimp command is for indicating that a function is a - reimplementation of a virtual function. - - The command must stand on its own line. - - QDoc will omit the reimplemented function from the class - reference. - - \badcode * - /\1! - \reimp - \1/ - void QToolButton::nextCheckState() - { - Q_D(QToolButton); - if (!d->defaultAction) - QAbstractButton::nextCheckState(); - else - d->defaultAction->trigger(); - } - \endcode - - This function will not be included in the documentation. Instead, - a link to the base function QAbstractButton::nextCheckState() will - appear in the documentation. - - \target relates-command - \section2 \\relates - - The \\relates command is for including the documentation of a - global element to some class or header file. The argument is a - class name or header file. For template types, use the type name only. - - \badcode * - /\1! - \relates QChar - - Reads a char from the stream \a in into char \a chr. - - \sa {Format of the QDataStream operators} - \1/ - QDataStream &operator>>(QDataStream &in, QChar &chr) - { - quint16 u; - in >> u; - chr.unicode() = ushort(u); - return in; - } - \endcode - - The documentation for this function will be included on the reference page - for class QChar. -*/ - -/*! - \page 19-qdoc-commands-grouping.html - \previouspage Relating Things - \nextpage Naming Things - - \title Grouping Things - - The grouping commands relate classes to defined groups and - modules. The groups are used when generating lists of related - classes in the documentation, while the modules are elements of - Qt's structure. - - \section1 Commands - - \target ingroup-command - \section2 \\ingroup - - The \\ingroup command indicates that the given - overview or documented class belongs to a certain group of - related documentation. - - A class or overview may belong to many groups. - - The \\ingroup command's argument is a group name, but note - that the command considers the rest of the line as part of - its argument. Make sure that the group name is followed by - a linebreak. - - \badcode * - /\1! - \class QDir - \brief The QDir class provides access to directory - structures and their contents. - - \ingroup io - ... - \1/ - \endcode - - This will include the QDir class in the \c io group, which means, - for example, that QDir will appear on the list created by calling - the \l {group-command} {\\group} command with the \c io argument. - - To list overviews that are related to a certain group, you must - generate the list explicitly using the \l {generatelist-command} - {\\generatelist} command with the \c related argument. - - See also \l {group-command} {\\group}. - - \target inmodule-command - \section2 \\inmodule - - The \\inmodule command relates a class to the module specified by - the command's argument. - - For the basic classes in Qt, a class's module is determined by its - location, namely its directory. However, for extensions like - ActiveQt and Qt Designer, a class must be related to a module - explicitly. - - The command's argument is a module name, but note that the command - considers the rest of the line as part of its argument. Make sure - that the module name is followed by a linebreak. - - \code - /*! - \class QDesignerTaskMenuExtension - \inmodule QtDesigner - * / - \endcode - - This ensures that the QDesignerTaskMenuExtension class is included - in the Qt Designer module, which means, for example, that the - class will appear on the list created by calling the \l - {generatelist-command} {\\generatelist} command with the \c - {{classesbymodule QtDesigner}} argument. - - See also \l {module-command} {\\module} and \l - {generatelist-command} {\\generatelist}. -*/ - -/*! - \page 20-qdoc-commands-namingthings.html - \previouspage Grouping Things - \nextpage Markup Commands - - \title Naming Things - - In general, a title command considers everything that follows it - until the first line break as its argument. If the title is so - long it must span multiple lines, end each line (except the last - one) with a backslash. - - \section1 Commands - - \target title-command - \section2 \\title - - The \\title command sets the title for a documentation page, or - allows you to override it. - - \badcode * - /\1! - \page signalandslots.html - - \title Signals & Slots - - Signals and slots are used for communication between - objects. The signals and slots mechanism is a central - feature of Qt, and probably the part that differs most - from the features provided by other frameworks. - - ... - \1/ - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

Signal and Slots

- \endraw - - Signals and slots are used for communication between - objects. The signals and slots mechanism is a central - feature of Qt and probably the part that differs most - from the features provided by other frameworks. - ... - \endquotation - See also \l {subtitle-command} {\\subtitle}. - - \target subtitle-command - \section2 \\subtitle - - The \\subtitle command sets a subtitle for a documentation page. - - \badcode * - /\1! - \page qtopiacore-overview.html - - \title Qtopia Core - \subtitle Qt for Embedded Linux - - Qt/Embedded, the embedded Linux port of Qt, is a - complete and self-contained C++ GUI and platform - development tool for Linux-based embedded development. - ... - \1/ - \endcode - - QDoc renders this as: - - \quotation - \raw HTML -

Qtopia Core

-

Qt for Embedded Linux

- \endraw - - Qt/Embedded, the embedded Linux port of Qt, is a - complete and self-contained C++ GUI and platform - development tool for Linux-based embedded development. - ... - \endquotation - - See also \l {title-command} {\\title}. - -*/ diff --git a/src/qdoc/doc/qdoc-manual-intro.qdoc b/src/qdoc/doc/qdoc-manual-intro.qdoc deleted file mode 100644 index 0aeb715c9..000000000 --- a/src/qdoc/doc/qdoc-manual-intro.qdoc +++ /dev/null @@ -1,299 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page 01-qdoc-manual.html - \previouspage QDoc Manual - \nextpage Command Index - - \title Introduction to QDoc - - QDoc is a tool used by Qt Developers to generate documentation for - software projects. It works by extracting \e {QDoc comments} from - project source files and then formatting these comments as HTML - pages or DocBook XML documents. QDoc finds QDoc comments in \c - {.cpp} files and in \c {.qdoc} files. QDoc does not look for QDoc - comments in \c {.h} files. A QDoc comment always begins with an - exclamation mark (\b{!})). For example: - - \badcode * - /\1! - \class QObject - \brief The QObject class is the base class of all Qt objects. - - \ingroup objectmodel - - \reentrant - - QObject is the heart of the Qt \l{Object Model}. The - central feature in this model is a very powerful mechanism - for seamless object communication called \l{signals and - slots}. You can connect a signal to a slot with connect() - and destroy the connection with disconnect(). To avoid - never ending notification loops you can temporarily block - signals with blockSignals(). The protected functions - connectNotify() and disconnectNotify() make it possible to - track connections. - - QObjects organize themselves in \l {Object Trees & - Ownership} {object trees}. When you create a QObject with - another object as parent, the object will automatically - add itself to the parent's \c children() list. The parent - takes ownership of the object. It will automatically - delete its children in its destructor. You can look for an - object by name and optionally type using findChild() or - findChildren(). - - Every object has an objectName() and its class name can be - found via the corresponding metaObject() (see - QMetaObject::className()). You can determine whether the - object's class inherits another class in the QObject - inheritance hierarchy by using the \c inherits() function. - - .... - \1/ - \endcode - - From the QDoc comment above, QDoc generates the HTML \l {QObject} - {QObject class reference} page. - - This manual explains how to use the QDoc commands in QDoc comments - to embed good documentation in your source files. It also explains - how to make a \l {The QDoc Configuration File} {QDoc configuration - file}, which you will pass to QDoc on the command line. - - \section1 Running QDoc - - The name of the QDoc program is \c {qdoc}. To run QDoc from the - command line, give it the name of a configuration file: - - \quotation - \c {$ ../../bin/qdoc ./config.qdocconf} - \endquotation - - QDoc recognizes the \c {.qdocconf} suffix as a \l{The QDoc - Configuration File} {QDoc configuration file}. The configuration - file is where you tell QDoc where to find the project source - files, header files, and \c {.qdoc} files. It is also where you - tell QDoc what kind of output to generate (HTML, DocBook XML...), - and where to put the generated documentation. The configuration - file also contains other information for QDoc. - - See \l{The QDoc Configuration File} for instructions on how to - set up a QDoc configuration file. - - \section2 Running QDoc in Single Execution Mode - - Beginning with Qt 5.5, a new way to run QDoc is available that - reduces the time it takes to generate the Qt5 documentation by as - much as 90%. The new way to run QDoc is \e{single execution} mode. - Single execution mode is not currently available in the Qt5 build - system, which still uses the \e {standard} mode. Single execution - mode is only available when you run QDoc yourself, which you will - want to do often as you document your module and integrate your - documentation with the other Qt modules. - - To run QDoc in single execution mode, add \c {-single-exec} to the - command line and pass QDoc a master \c qdocconf file that is - simply a list of file paths for qdocconf files of all the Qt5 - modules. For example: - - \code - /Users/me/qt5/qtbase/bin/qdoc -outputdir /Users/me/qt5/qtbase/doc -installdir /Users/me/qt5/qtbase/doc /Users/me/qt5/master.qdocconf -single-exec - \endcode - - The qdocconf file, \c {master.qdocconf}, just lists the qdocconf files for all the Qt5 modules to be processed: - - \badcode - /Users/me/qt5/qtbase/src/corelib/doc/qtcore.qdocconf - /Users/me/qt5/qtbase/src/network/doc/qtnetwork.qdocconf - /Users/me/qt5/qtbase/src/sql/doc/qtsql.qdocconf - /Users/me/qt5/qtbase/src/xml/doc/qtxml.qdocconf - /Users/me/qt5/qtbase/src/testlib/doc/qttestlib.qdocconf - /Users/me/qt5/qtbase/src/concurrent/doc/qtconcurrent.qdocconf - /Users/me/qt5/qtbase/src/gui/doc/qtgui.qdocconf - /Users/me/qt5/qtbase/src/platformheaders/doc/qtplatformheaders.qdocconf - /Users/me/qt5/qtbase/src/widgets/doc/qtwidgets.qdocconf - /Users/me/qt5/qtbase/src/opengl/doc/qtopengl.qdocconf - /Users/me/qt5/qtbase/src/printsupport/doc/qtprintsupport.qdocconf - /Users/me/qt5/qtbase/src/tools/qdoc/doc/config/qdoc.qdocconf - /Users/me/qt5/qtbase/qmake/doc/qmake.qdocconf - /Users/me/qt5/qtsvg/src/svg/doc/qtsvg.qdocconf - /Users/me/qt5/qtxmlpatterns/src/xmlpatterns/doc/qtxmlpatterns.qdocconf - /Users/me/qt5/qtdeclarative/src/qml/doc/qtqml.qdocconf - /Users/me/qt5/qtdeclarative/src/quick/doc/qtquick.qdocconf - /Users/me/qt5/qtquickcontrols/src/controls/doc/qtquickcontrols.qdocconf - /Users/me/qt5/qtquickcontrols/src/layouts/doc/qtquicklayouts.qdocconf - /Users/me/qt5/qtquickcontrols/src/dialogs/doc/qtquickdialogs.qdocconf - /Users/me/qt5/qtmultimedia/src/multimedia/doc/qtmultimedia.qdocconf - /Users/me/qt5/qtmultimedia/src/multimediawidgets/doc/qtmultimediawidgets.qdocconf - /Users/me/qt5/qtactiveqt/src/activeqt/doc/activeqt.qdocconf - /Users/me/qt5/qtsensors/src/sensors/doc/qtsensors.qdocconf - /Users/me/qt5/qtwebkit/Source/qtwebkit.qdocconf - /Users/me/qt5/qttools/src/assistant/help/doc/qthelp.qdocconf - /Users/me/qt5/qttools/src/assistant/assistant/doc/qtassistant.qdocconf - /Users/me/qt5/qttools/src/designer/src/uitools/doc/qtuitools.qdocconf - /Users/me/qt5/qttools/src/designer/src/designer/doc/qtdesigner.qdocconf - /Users/me/qt5/qttools/src/linguist/linguist/doc/qtlinguist.qdocconf - /Users/me/qt5/qtwebkit-examples/doc/qtwebkitexamples.qdocconf - /Users/me/qt5/qtgraphicaleffects/src/effects/doc/qtgraphicaleffects.qdocconf - /Users/me/qt5/qtscript/src/script/doc/qtscript.qdocconf - /Users/me/qt5/qtscript/src/scripttools/doc/qtscripttools.qdocconf - /Users/me/qt5/qtserialport/src/serialport/doc/qtserialport.qdocconf - /Users/me/qt5/qtdoc/doc/config/qtdoc.qdocconf - \endcode - - \section3 Why Standard Mode Is Slow - - Currently, the Qt5 build system does not use QDoc's \e {single - execution} mode for generating the Qt5 documentation. It runs QDoc - in the \e {standard} mode. The standard mode was came about - because it was the easiest way to get convert the Qt4 QDoc to - handle the modularization of Qt in Qt5. In Qt4, QDoc ran once over - all the Qt4 sources to generate the HTML documentation for Qt. - While generating the Qt documentation, Qt4 QDoc also generated an - \e {index file} for Qt. That index file was meant to be used as - input to subsequent QDoc runs for generating HTML documentation - for other software libraries/products that were based on Qt. The - Qt index file allowed QDoc to link documentation written for those - other libraries/products to the Qt4 documentation. - - When Qt5 came along, Qt was divided into modules. Since then, - many new modules have been added to Qt. As of version 5.5, there - are over 40 separate modules in Qt5, each with its own - documentation that links to (depends on) the documentation of - other Qt modules. - - In \e {standard mode}, QDoc runs twice for each module. The first - QDoc run for a particular Qt module, parses all the module's - source files and then uses the information to generate the - module's index file. It is called the \e{prepare phase} because - it \e prepares the module's index file. The second QDoc run for - the module also parses all the module's source files and then - generates the module's documentation pages. This is called the \e - {generate phase} because it generates the module's documentation. - - The module's documentation will likely contain HTML links to the - documentation of one or more of the other Qt modules. For example, - most Qt5 modules contain links to documentation in QtCore. When a - Qt module contains links into the documentation of other Qt - module's, that module is said to depend on those other Qt modules. - Hence when QDoc runs the \e {generate phase} for that module, it - must also load the index files for those modules so it can create - those links. - - Hence, when the Qt build system generates the Qt documentation, it - first runs QDoc once for each module to perform the \e {prepare - phase} to generate all the index files. Then it runs QDoc once for - each module to perform the \e {generate phase}, where it uses the - dependent index files to generate the module's documentation, - including any cross-module links it finds. Each execution of - QDoc, both \e {prepare phase} and \e {generate phase}, parses - all the source files that are included in the module, and in the - \e {generate phase} also parses the index files for the dependent - modules. Nothing is retained or retainable between QDoc runs. - - \section3 Why Single Execution Mode Is Much Faster - - As the name implies, single execution mode uses a single QDoc - process to generate all the Qt5 documentation. The single QDoc - process still performs a \e{prepare phase} for each module and - then a \e{generate phase} for each module, but there are a few - differences. It begins by reading the master qdocconf file. Then - it reads each qdocconf file in the master list and performs the - \e{prepare phase} for each module. During the \e{prepare phase}, - all the source files for the module are parsed to build a syntax - tree for the module. The module's index file is then generated, - although QDoc will not re-read the index files in the \e{generate - phase}. The important difference here is that the module's syntax - tree is retained after the index file is generated, so that after - the \e{prepare phase} has been run for all the modules, QDoc still - has all the syntax trees it built. - - QDoc then processes each module again for the \e{generate phase}. - But now QDoc doesn't need to re-parse each module's source files, - because the module's syntax tree is still in memory. Nor does QDoc - need to re-read the index files for the dependent modules, again - because it still has the syntax trees for those modules in memory. - It remains only to traverse each module's syntax tree to generate - the documentation pages. - - Hence, QDoc parses each source file once and only once and doesn't - need to read index files. This is what makes single execution mode - much faster than the standard mode. It is anticipated that the Qt - build system will eventually run QDoc in single execution mode. - However, changes to the master qdocconf file might be required, so - the method described above for running QDoc in single execution - mode might have to change, watch this space for updates. - - \section1 How QDoc Works - - QDoc begins by reading the configuration file you specified on the - command line. It stores all the variables from the configuration - file for later use. One of the first variables it uses is \c - {outputformats}. This variable tells QDoc which output generators - it will run. The default value is \e {HTML}, so if you don't set - \c {outputformats} in your configuration file, QDoc will generate - HTML output. That's usually what you will want anyway, but you can - also specify \e {DocBook} to get DocBook output instead. - - Next, QDoc uses the values of the - \l {headerdirs-variable} - {headerdirs} variable and/or the \l - {22-qdoc-configuration-generalvariables.html#headers-variable} - {headers} variable to find and parse all the header files for your - project. QDoc does \e not scan header files for QDoc comments. It - parses the header files to build a master tree of all the items - that should be documented, in other words, the items that QDoc should find - QDoc comments for. - - After parsing all the header files and building the master tree of - items to be documented, QDoc uses the value of the \l - {22-qdoc-configuration-generalvariables.html#sourcedirs-variable} - {sourcedirs} variable and/or the value of the \l - {22-qdoc-configuration-generalvariables.html#sources-variable} - {sources} variable to find and parse all the \c {.cpp} and \c - {.qdoc} files for your project. These are the files QDoc scans for - \e {QDoc comments}. Remember that a QDoc comment begins with - an exclamation mark: \b {/*!} . - - For each QDoc comment it finds, it searches the master tree for - the item where the documentation belongs. Then it interprets the - QDoc commands in the comment and stores the interpreted commands - and the comment text in the tree node for the item. - - Finally, QDoc traverses the master tree. For each node, if the - node has stored documentation, QDoc calls the output generator - specified by the \c {outputformats} variable to format and write - the documentation in the directory specified in the configuration - file in the \l - {22-qdoc-configuration-generalvariables.html#outputdir-variable} - {outputdir} variable. - - \section1 Command Types - - QDoc interprets three types of commands: - - \list - \li \l {Topic Commands} - \li \l {Context Commands} - \li \l {Markup Commands} - \endlist - - Topic commands identify the element you are documenting, for example - a C++ class, function, type, or an extra page of text - that doesn't map to an underlying C++ element. - - Context commands tell QDoc how the element being documented - relates to other documented elements, for example, next and previous page - links, inclusion in page groups, or library modules. Context - commands can also provide information about the documented element - that QDoc can't get from the source files, for example, whether the - element is thread-safe, whether it is an overloaded or reimplemented function, - or whether it has been deprecated. - - Markup commands tell QDoc how text and image elements in the - document should be rendered, or about the document's outline - structure. -*/ - diff --git a/src/qdoc/doc/qdoc-manual-markupcmds.qdoc b/src/qdoc/doc/qdoc-manual-markupcmds.qdoc deleted file mode 100644 index 04d9f7cc3..000000000 --- a/src/qdoc/doc/qdoc-manual-markupcmds.qdoc +++ /dev/null @@ -1,4034 +0,0 @@ -// Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only - -/*! - \page 03-qdoc-commands-markup.html - \previouspage Naming Things - \nextpage Text Markup - - \title Markup Commands - - The markup commands indicate the generated documentation's visual - appearance and logical structure. - - \list - \li \l {a-command} {\\a} - \li \l {annotatedlist-command} {\\annotatedlist} - \li \l {b-command} {\\b} - \li \l {badcode-command} {\\badcode} - \li \l {b-command} {\\bold} (deprecated, use \\b) - \li \l {brief-command} {\\brief} - \li \l {c-command} {\\c} - \li \l {caption-command} {\\caption} - \li \l {code-command} {\\code} - \li \l {codeline-command} {\\codeline} - \li \l {div-command} {\\div} - \li \l {dots-command} {\\dots} - \li \l {e-command} {\\e} - \li \l {else-command} {\\else} - \li \l {endif-command} {\\endif} - \li \l {footnote-command} {\\footnote} - \li \l {generatelist-command} {\\generatelist} - \li \l {header-command} {\\header} - \li \l {e-command} {\\i} (deprecated, use \\e) - \li \l {if-command} {\\if} - \li \l {image-command} {\\image} - \li \l {include-command} {\\include} - \li \l {inlineimage-command} {\\inlineimage} - \li \l {keyword-command} {\\keyword} - \li \l {l-command} {\\l} - \li \l {legalese-command} {\\legalese} - \li \l {li-command} {\\li} - \li \l {list-command} {\\list} - \li \l {meta-command} {\\meta} - \li \l {noautolist-command} {\\noautolist} - \li \l {li-command} {\\o} (deprecated, use \\li) - \li \l {note-command} {\\note} - \li \l {omit-command} {\\omit} - \li \l {printline-command} {\\printline} - \li \l {printto-command} {\\printto} - \li \l {printuntil-command} {\\printuntil} - \li \l {qml-command}{\\qml} - \li \l {quotation-command} {\\quotation} - \li \l {quotefile-command} {\\quotefile} - \li \l {quotefromfile-command} {\\quotefromfile} - \li \l {raw-command} {\\raw} - \li \l {row-command} {\\row} - \li \l {sa-command} {\\sa} - \li \l {sectionOne-command} {\\section1} - \li \l {sectionTwo-command} {\\section2} - \li \l {sectionThree-command} {\\section3} - \li \l {sectionFour-command} {\\section4} - \li \l {sincelist-command} {\\sincelist} - \li \l {skipline-command} {\\skipline} - \li \l {skipto-command} {\\skipto} - \li \l {skipuntil-command} {\\skipuntil} - \li \l {snippet-command} {\\snippet} - \li \l {span-command} {\\span} - \li \l {sub-command} {\\sub} - \li \l {sup-command} {\\sup} - \li \l {table-command} {\\table} - \li \l {tableofcontents-command} {\\tableofcontents} - \li \l {target-command} {\\target} - \li \l {tt-command} {\\tt} - \li \l {uicontrol-command} {\\uicontrol} - \li \l {underline-command} {\\underline} - \li \l {raw-command} {\\unicode} - \li \l {warning-command} {\\warning} - \li \l {backslash-sequence} {\\\\} - \li \l {endash-sequence} {\--} - \li \l {emdash-sequence} {-\--} - \endlist -*/ - - -/*! - \page 04-qdoc-commands-textmarkup.html - \previouspage Markup Commands - \nextpage Document Structure - - \title Text Markup - - The text formatting commands indicate how text is to be rendered. - - \target a-command - \section1 \\a (parameter marker) - - The \\a command tells QDoc the next word is a formal parameter name. - - A warning is emitted when a formal parameter is not documented or - is misspelled, so when you document a function you should mention - each formal parameter by name in the function description, - preceded by the \\a command. The parameter name is then rendered - in italics. - - \badcode * - /\1! - Constructs a line edit containing the text - \a contents. The \a parent parameter is sent - to the QWidget constructor. - \1/ - QLineEdit::QLineEdit(const QString &contents, QWidget *parent) :QWidget(parent) - { - ... - } - \endcode - - QDoc renders this as: - - \quotation - \b {QLineEdit::QLineEdit ( const QString & - contents, QWidget *parent )} - - Constructs a line edit containing the text \a contents. - The \a parent parameter is sent to the QWidget constructor. - \endquotation - - The formal parameter name may be enclosed between curly brackets, - but that isn't required. - - \target c-command - \section1 \\c (code font) - - The \\c command is used for rendering variable names, user-defined - class names, and C++ keywords (for example, \c int and \c for) in the code - font. - - The command renders its argument using a monospace font. For - example: - - \badcode * - /\1! - The \c AnalogClock class provides a clock widget with hour - and minute hands that is automatically updated every - few seconds. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \c AnalogClock class provides a clock widget with hour - and minute hands, which are automatically updated every - few seconds. - \endquotation - - If the text to be rendered in the code font contains spaces, enclose the - entire text in curly brackets. - - \code - \c {QLineEdit::QLineEdit(const QString &contents, QWidget *parent) : QWidget(parent)} - \endcode - - QDoc renders this as: - - \quotation - \c {QLineEdit::QLineEdit(const QString &contents, QWidget *parent) : QWidget(parent)} - \endquotation - - The \\c command accepts the special character \c \ within its - argument, which renders it as a normal character. So if you want - to use nested commands, you must use the \l {tt-command} {teletype - (\\tt)} command instead. - - See also \l {tt-command} {\\tt} and \l {code-command} {\\code}. - - \target div-command - \section1 \\div - - The \\div and \\enddiv commands delimit a large or small block of - text (which may include other QDoc commands) to which special - formatting attributes should be applied. - - An argument must be provided in curly braces, as in the QDoc - comment shown below. The argument is not interpreted but is used - as attribute(s) of the tag that is output by QDoc. - - For example, we might want to render an inline image so that it - floats to the right of the current block of text: - - \badcode * - /\1! - \div {class="float-right"} - \inlineimage qml-column.png - \enddiv - \1/ - \endcode - - If QDoc is generating HTML, it will translate these commands to: - - \code -

- \endcode - - For HTML, the attribute value \e {float-right} then will refer to - a clause in the style.css file, which in this case could be: - - \code - div.float-right - { - float: right; margin-left: 2em - } - \endcode - - \note Note that the \b {\\div} command can be nested. - - Below you can find an example taken from the index.qdoc file used to - generate index.html for Qt 4.7: - - \code - \div {class="indexbox guide"} - \div {class="heading"} - Qt Developer Guide - \enddiv - \div {class="indexboxcont indexboxbar"} - \div {class="section indexIcon"} \emptyspan - \enddiv - \div {class="section"} - Qt is a cross-platform application and UI - framework. Using Qt, you can write web-enabled - applications once and deploy them across desktop, - mobile and embedded operating systems without - rewriting the source code. - \enddiv - \div {class="section sectionlist"} - \list - \li \l{Getting Started} - \li \l{Installation} {Installation} - \li \l{how-to-learn-qt.html} {How to learn Qt} - \li \l{tutorials.html} {Tutorials} - \li \l{Qt Examples} {Examples} - \li \l{qt4-7-intro.html} {What's new in Qt 4.7} - \endlist - \enddiv - \enddiv - \enddiv - \endcode - - When all the class attribute values are defined as they are in the - style.css file that is used for rendering the Qt documentation, - the above example is rendered as: - - \div {class="indexbox guide"} - \div {class="heading"} - Qt Developer Guide - \enddiv - \div {class="indexboxcont indexboxbar"} - \div {class="section indexIcon"} \emptyspan - \enddiv - \div {class="section"} - Qt is a cross-platform application and UI - framework. Using Qt, you can write web-enabled - applications once and deploy them across desktop, - mobile and embedded operating systems without - rewriting the source code. - \enddiv - \div {class="section sectionlist"} - \list - \li Getting Started - \li Installation - \li How to learn Qt - \li Tutorials - \li Examples - \li What's new in Qt 4.7 - \endlist - \enddiv - \enddiv - \enddiv - - See also \l {span-command} {\\span}. - - \target span-command - \section1 \\span - - The \\span command applies special formatting to a small block of text. - - Two arguments must be provided, each argument in curly braces, as - shown in the QDoc comment below. The first argument is not - interpreted, but specifies the formatting attribute(s) of the tag - output by QDoc. The second argument is the text to be rendered with - the special formatting attributes. - - For example, we might want to render the first word of each - element in a numeric list in blue. - - \badcode * - /\1! - Global variables with complex types: - \list 1 - \li \span {class="variableName"} {mutableComplex1} in globals.cpp at line 14 - \li \span {class="variableName"} {mutableComplex2} in globals.cpp at line 15 - \li \span {class="variableName"} {constComplex1} in globals.cpp at line 16 - \li \span {class="variableName"} {constComplex2} in globals.cpp at line 17 - \endlist - \1/ - \endcode - - Class \e {variableName} refers to a clause in your style.css. - - \code - .variableName - { - font-family: courier; - color: blue - } - \endcode - - Using the \e {variableName} clause shown above, the example is rendered as: - - Global variables with complex types: - \list 1 - \li \span {class="variableName"} {mutableComplex1} in globals.cpp at line 14 - \li \span {class="variableName"} {mutableComplex2} in globals.cpp at line 15 - \li \span {class="variableName"} {constComplex1} in globals.cpp at line 16 - \li \span {class="variableName"} {constComplex2} in globals.cpp at line 17 - \endlist - - \note The \b span command does not cause a new paragraph to be - started. - - See also \l {div-command} {\\div}. - - \target tt-command - \section1 \\tt (teletype font) - - The \\tt command renders its argument in a monospace font. This - command behaves just like the \l {c-command} {\\c} command, except - that \\tt allows you to nest QDoc commands within the argument - (e.g. \l {e-command} {\\e}, \l {b-command} {\\b} and \l - {underline-command} {\\underline}). - - \badcode * - /\1! - After having populated the main container with - child widgets, \c setupUi() scans the main container's list of - slots for names with the form - \tt{on_\e{objectName}_\e{signalName}().} - \1/ - \endcode - - QDoc renders this as: - - \quotation - After having populated the main container with - child widgets, \c setupUi() scans the main container's list of - slots for names with the form - \tt{on_\e{objectName}_\e{signalName}().} - \endquotation - - If the text to be rendered in the code font contains spaces, enclose the - entire text in curly brackets. - - \code - \tt {QLineEdit::QLineEdit(const QString &contents, QWidget *parent) :QWidget(parent)} - \endcode - - QDoc renders this as: - - \quotation - \tt {QLineEdit::QLineEdit(const QString &contents, QWidget *parent) :QWidget(parent)} - \endquotation - - See also \l {c-command} {\\c}. - - \target b-command - \section1 \\b - - The \\b command renders its argument in bold font. This command used - to be called \\bold. - - \badcode * - /\1! - This is regular text; \b {this text is - rendered using the \\b command}. - \1/ - \endcode - - QDoc renders this as: - - \quotation - This is regular text; \b {this text is rendered using - the \\b command}. - \endquotation - - \target e-command - \section1 \\e (emphasis, italics) - - The \\e command renders its argument in a special font, normally italics. This - command used to be called \\i, which is now deprecated. - - If the argument contains spaces or other punctuation, enclose the - argument in curly brackets. - - \badcode * - /\1! - Here, we render \e {a few words} in italics. - \1/ - \endcode - - QDoc renders this as: - - \quotation - Here, we render \e {a few words} in italics. - \endquotation - - If you want to use other QDoc commands within an argument that - contains spaces, you always need to enclose the argument in - braces. But QDoc is smart enough to count parentheses [3], so you - don't need braces in cases like this: - - \badcode * - /\1! - An argument can sometimes contain whitespaces, - for example: \e QPushButton(tr("A Brand New Button")) - \1/ - \endcode - - QDoc renders this as: - - \quotation - An argument can sometimes contain whitespaces, - for example: \e QPushButton(tr("A Brand New Button")) - \endquotation - - Finally, trailing punctuation is not included in an argument [4], - nor is "'s" [5] - - \raw HTML - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
QDoc SyntaxGenerated Documentation
1A variation of a command button is a \e menu - button.A variation of a command button is a menu - button.
2The QPushButton widget provides a - \e {command button}.The QPushButton widget provides a - command button.
3Another class of buttons are option buttons - \e (see QRadioButton).Another class of buttons are option buttons - (see QRadioButton).
4A push button emits the signal \e clicked().A push button emits the signal clicked().
5The \e QPushButton's checked property is - false by default.The QPushButton's checked property is - false by default.
- \endraw - - \target sub-command - \section1 \\sub - - The \\sub command renders its argument lower than the baseline of - the regular text, using a smaller font. - - \badcode * - /\1! - Definition (Range): Consider the sequence - {x\sub n}\sub {n > 1} . The set - - {x\sub 2, x\sub 3, x\sub 4, ...} = {x\sub n ; n = 2, 3, 4, ...} - - is called the range of the sequence. - \1/ - \endcode - - QDoc renders this as: - - \quotation - Definition (Range): Consider the sequence - {x\sub n}\sub {n > 1} . The set - - {x\sub 2, x\sub 3, x\sub 4, ...} = {x\sub n ; n = 2, 3, 4, ...} - - is called the range of the sequence. - \endquotation - - If the argument contains spaces or other punctuation, enclose the - argument in curly brackets. - - \target sup-command - \section1 \\sup - - The \\sup command renders its argument higher than - the baseline of the regular text, using a smaller font. - - \badcode * - /\1! - The series - - 1 + a + a\sup 2 + a\sup 3 + a\sup 4 + ... - - is called the \i {geometric series}. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The series - - 1 + a + a\sup 2 + a\sup 3 + a\sup 4 + ... - - is called the \e {geometric series}. - \endquotation - - If the argument contains spaces or other punctuation, enclose the - argument in curly brackets. - - \target uicontrol-command - \section1 \\uicontrol - - The \\uicontrol command is used to mark content as being used for UI - control elements. When using HTML, the output is rendered in bold. - - See also \l {b-command}{\\b}. - - \target underline-command - \section1 \\underline - - The \\underline command renders its argument underlined. - - \badcode * - /\1! - The \underline {F}ile menu gives the users the possibility - to edit an existing file, or save a new or modified - file, and exit the application. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \underline {F}ile menu gives the users the possibility - to edit an existing file, or save a new or modified - file, and exit the application. - \endquotation - - If the argument contains spaces or other punctuation, enclose the - argument in curly brackets. - - \target backslash-sequence - \section1 \\\\ (double backslash) - - The sequence \\\\ expands to a single backslash. - - QDoc commands always start with a single backslash. To display a - single backslash in the text, you must type two backslashes. If - you want to display two backslashes, you must type four. - - \badcode * - /\1! - The \\\\ command is useful if you want a - backslash to appear verbatim, for example, - writing C:\\windows\\home\\. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \\\\ command is useful if you want a - backslash to appear verbatim, for example, - writing C:\\windows\\home\\. - \endquotation - - However, if you want your text to appear in a monospace font as - well, you can use the \l {c-command} {\\c} command instead, which - accepts and renders the backslash as any other character. For - example: - - \badcode * - /\1! - The \\c command is useful if you want a - backslash to appear verbatim, and the word - that contains it written in a monospace font, - like this: \c {C:\windows\home\}. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \\c command is useful if you want a - backslash to appear verbatim, and the word - that contains it written in a monospace font, - like this: \c {C:\windows\home\}. - \endquotation - - \target endash-sequence - \section1 \-- (en dash) - QDoc renders double hyphens as an en dash. QDoc markup commands - designed to make their input appear verbatim---such as the \\c - command---won't replace the double hyphens with an en dash character. - For example: - - \badcode * - /\1! - The \\c command -- useful if you want text in a monospace font -- - is well documented. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \\c command -- useful if you want text in a monospace font -- - is well documented. - \endquotation - - However, other commands may require that the hyphens are escaped to ensure - QDoc renders the output as expected. For example; - - \badcode * - /\1! - This \l {endash-sequence}{link to the -- (endash) sequence} - isn't escaped and QDoc therefore renders an endash in the link - text. However, the escaped - \l {endash-sequence}{link to the \-- (endash) sequence} - renders both hyphens as intended. - \1/ - \endcode - - QDoc renders this as: - - \quotation - This \l {endash-sequence}{link to the -- (endash) sequence} - isn't escaped and QDoc therefore renders an endash in the link - text. However, the escaped - \l {endash-sequence}{link to the \-- (endash) sequence} - renders both hyphens as intended. - \endquotation - - See also \l {emdash-sequence}{\-\-- (em dash)}. - - \target emdash-sequence - \section1 -\-- (em dash) - - QDoc renders triple hyphens as an en dash. QDoc markup commands - designed to make their input appear verbatim---such as the \\c - command---won't replace the triple hyphens with an en dash character. - For example: - - \badcode * - /\1! - The \\c command---useful when you want text to be rendered - verbatim---is well documented. - \1/ - \endcode - - QDoc renders this as: - - \quotation - The \\c command---useful when you want text to be rendered - verbatim---is well documented. - \endquotation - - However, other commands may require that the hyphens are escaped to ensure - QDoc renders the output as expected. For example; - - \badcode * - /\1! - This \l {emdash-sequence}{link to the --- (emdash) sequence} - isn't escaped and QDoc therefore renders an emdash in the link - text. However, the escaped - \l {emdash-sequence}{link to the -\-- (emdash) sequence} - renders both hyphens as intended. - \1/ - \endcode - - QDoc renders this as: - - \quotation - This \l {emdash-sequence}{link to the --- (emdash) sequence} - isn't escaped and QDoc therefore renders an emdash in the link - text. However, the escaped - \l {emdash-sequence}{link to the -\-- (emdash) sequence} - renders both hyphens as intended. - \endquotation - - \note The escaped control sequence in this example is for the en dash. - This avoids a hyphen followed by an en dash in the output. - - See also \l {endash-sequence}{\-- (en dash)}. -*/ - - -/*! - \page 05-qdoc-commands-documentstructure.html - \previouspage Text Markup - \nextpage Including Code Inline - - \title Document Structure - - The document structuring commands are for dividing your document - into sections. QDoc supports four levels of section: \c \section1, - \c \section2, \c \section3, and \c \section4. The section commands - correspond to the traditional section, subsection, etc used in - outlining. - - \target section-commands - \section1 Section commands - - In general a document structuring command considers everything - that follows it until the first line break as its argument. The - argument is rendered as the unit's title. If the title needs to be - spanned over several lines, make sure that each line (except the - last one) is ended with a backslash. - - In total, there are four levels for sections in QDoc: \c \section1, - \c \section2, \c \section3 and \c \section4. These correspond to the - traditional section, subsection, subsubsection and subsubsubsection. - - There is a strict ordering of the section units: - - \code - section1 - | - section2 - | - section3 - | - section4 - \endcode - - When sections are used, the first section command should be \c section1. - - \badcode * - /\1! - \section1 Basic Qt - - This is the first section. - - - \section2 Getting Started - - This is the first subsection. - - - \section3 Hello Qt - - This is the first subsubsection. - - - \section3 Making Connections - - This is the second subsubsection. - - - \section3 Using the Reference Documentation - - This is the third subsubsection. - - - \section2 Creating Dialogs - - This is the second subsection. - - - \section3 Subclassing QDialog - - This is the first subsubsection. - - ... - - - \section1 Intermediate Qt - - This is the second section. - - - \section2 Layout Management - - This is the second section's first subsection. - - - \section3 Basic Layouts - - This is the first subsubsection. - - ... - \1/ - \endcode - - QDoc renders this as: - - \quotation - \raw HTML - -

Basic Qt

-
-

This is the first section.

- - -

Getting Started

-
- This is the first subsection.

- - -

Hello Qt

-
-

This is the first subsubsection.

- - -

Making Connections

-
-

This is the second subsubsection.

- - -

Using the Reference Documentation

-
-

This is the third subsubsection.

- - -

Creating Dialogs

-
-

This is the second subsection.

- - -

Subclassing QDialog

-
-

This is the first subsubsection.

- - ... - - -

Intermediate Qt

-
-

This is the second section.

- - -

Layout Management

-
-

This is the second section's first subsection.

- - -

Basic Layouts

-
-

This is the first subsubsection.

- - ... - - \endraw - \endquotation - - Each section is a logical unit in the document. The section - heading appears in the automatically generated table of contents - that normally appears in the upper right-hand corner of the page. - - \target sectionOne-command - \section1 \\section1 - - The \\section1 command starts a new section. - - See \l{section-commands} {Section commands} for an explanation of the various - section units, command argument, and rendering. - - \target sectionTwo-command - \section1 \\section2 - - The \\section2 command starts a new section. - - See \l{section-commands} {Section commands} for an explanation of the various - section units, command argument, and rendering. - - \target sectionThree-command - \section1 \\section3 - - The \\section3 command starts a new section. - - See \l{section-commands} {Section commands} for an explanation of the various - section units, command argument, and rendering. - - \target sectionFour-command - \section1 \\section4 - - The \\section4 command starts a new section. - - See \l{section-commands} {Section commands} for an explanation of the various - section units, command argument, and rendering. - -*/ - - -/*! - \page 06-qdoc-commands-includecodeinline.html - \previouspage Document Structure - \nextpage Including External Code - - \title Including Code Inline - - The following commands are used to render source code without - formatting. The source code begins on a new line, rendered in the - code. - - \note Although most of these commands are for rendering C++ - code, the - \l{07-0-qdoc-commands-includingexternalcode.html#snippet-command} - {\\snippet} and - \l{07-0-qdoc-commands-includingexternalcode.html#codeline-command} - {\\codeline} commands are preferred over the others. These - commands allow equivalent code snippets for other Qt language - bindings to be substituted for the C++ snippets in the - documentation. - - \target code-command - \section1 \\code - - The \\code and \\endcode commands enclose a snippet of source code. - - \note The \l {c-command} {\\c} command can be used for short code - fragments within a sentence. The \\code command is for longer code - snippets. It renders the code verbatim in a separate paragraph in - a html
 element, and parses the enclosed snippet, creating links
-    to any known types in the code.
-
-    For documenting command-line instructions, shell scripts, or any
-    content that is not in a Qt language recognized by QDoc, use
-    \l {badcode-command}{\\badcode} instead.
-
-    When processing the \\code command, QDoc removes all indentation
-    that is common for the verbatim code blocks within a \c{/}\c{*!}
-    ... \c{*}\c{/} comment before it adds the standard indentation.
-
-    \note This doesn't apply to externally quoted code using the \l
-    {quotefromfile-command} {\\quotefromfile} or \l
-    {quotefile-command} {\\quotefile} command.
-
-       \code \\endcode *
-       /*!
-           \code
-               #include 
-               #include 
-
-               int main(int argc, char *argv[])
-               {
-                   ...
-               }
-           \1
-       \2/
-       \endcode
-
-       QDoc renders this as:
-
-       \code
-           #include 
-           #include 
-
-           int main(int argc, char *argv[])
-           {
-               ...
-           }
-       \endcode
-
-    Other QDoc commands are disabled within \\code... \\endcode, and
-    the special character '\\' is accepted and rendered like the rest
-    of the code, unless it is followed by a digit and parameters were
-    passed to \\code.
-
-    \section2 Highlighting and autolinking
-
-    The \\code commands attempts to parse its contents as code of a
-    specific language, as defined in the \l {language-variable}{language}
-    configuration variable. This provides highlighting and automatic
-    linking to types detected in the code.
-
-    As an exception since QDoc version 6.4, when the \\code command
-    is used within a QML-specific \l {Topic Commands}{topic}, QDoc
-    first attempts to recognize the code as QML; for other topics,
-    the language configuration variable takes precedence. To
-    explicitly mark the code snippet as QML, use the \l {qml-command}
-    {\\qml} command instead.
-
-    \section2 Code snippet parameters
-
-    Since QDoc version 5.12, \\code command accepts also optional
-    parameters. Parameters are useful for injecting simple
-    strings into the code snippet. To inject a string to a specific
-    location in the snippet, add a backslash followed by a digit (1..8).
-    The digits correspond with the order of the argument list, where
-    arguments are separated by spaces.
-
-    For example:
-
-    \badcode 1 2 * endcode
-    /\3!
-        \code * hello
-        /\\1 \\2 \\1/
-        \\4
-    \3/
-    \endcode
-
-    For the above snippet, QDoc renders the word \e hello enclosed in
-    a C-style comment.
-
-    \section2 Including code from external files
-
-    To include code snippets from an external file, use the
-    \l{snippet-command}{\\snippet} and \l{codeline-command}
-    {\\codeline} commands.
-
-    See also \l {c-command}{\\c}, \l {qml-command}{\\qml},
-    \l {badcode-command}{\\badcode}, \l {quotefromfile-command}
-    {\\quotefromfile}, and \l {language-variable}{language}.
-
-    \target badcode-command
-    \section1 \\badcode
-
-    Similar to \l {code-command}{\\code}, \\badcode and \\endcode commands
-    enclose content that is rendered verbatim in a separate paragraph, but no
-    parsing or automatic link creation is performed. Instead, the content is
-    treated as plain text.
-
-    Substitute \\code with this command when documenting command-line
-    instructions, shell scripts or any other content that is not in a Qt
-    language, but should still be styled similarly to a \\code paragraph.
-
-    Like \\code, \\badcode accepts also optional parameters.
-
-    \target qml-command
-    \section1 \\qml
-
-    The \\qml and \\endqml commands enclose a snippet of QML source
-    code. Use these for proper syntax highlighting of QML code snippets.
-    The enclosed snippet must be complete as if it was a valid .qml file.
-    If the snippet is incomplete, QDoc will issue a warning and ignore the
-    snippet.
-
-    \badcode *
-    /\1!
-        \qml
-            import QtQuick 2.0
-
-            Row {
-                Rectangle {
-                    width: 100; height: 100
-                    color: "blue"
-                    transform: Translate { y: 20 }
-                }
-                Rectangle {
-                    width: 100; height: 100
-                    color: "red"
-                    transform: Translate { y: -20 }
-                }
-            }
-        \endqml
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \qml
-        import QtQuick 2.0
-
-        Row {
-            Rectangle {
-                width: 100; height: 100
-                color: "blue"
-                transform: Translate { y: 20 }
-            }
-            Rectangle {
-                width: 100; height: 100
-                color: "red"
-                transform: Translate { y: -20 }
-            }
-        }
-    \endqml
-
-    Like the \l{code-command}{\\code} command, \\qml accepts optional
-    parameters.
-*/
-
-
-/*!
-    \page 07-0-qdoc-commands-includingexternalcode.html
-    \previouspage Including Code Inline
-    \nextpage Creating Links
-
-    \title Including External Code
-
-    The following commands enable you to include code snippets from
-    external files. You can make QDoc include the complete contents of
-    a file, or you can quote specific parts of the file and skip
-    others. The typical use of the latter is to quote a file chunk by
-    chunk.
-
-    \note Although all these commands can be used for rendering C++
-    code, the
-    \l{07-0-qdoc-commands-includingexternalcode.html#snippet-command}
-    {\\snippet} and
-    \l{07-0-qdoc-commands-includingexternalcode.html#codeline-command}
-    {\\codeline} commands are preferred over the others. These
-    commands allow equivalent code snippets for other Qt language
-    bindings to be substituted for the C++ snippets in the
-    documentation.
-
-    \target quotefile-command
-    \section1 \\quotefile
-
-    The \\quotefile command expands to the complete contents of the
-    file given as argument.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the file name with a line break.
-
-    The file's contents is rendered in a separate paragraph, using a
-    monospace font and the standard indentation. The code is shown
-    verbatim.
-
-    \badcode *
-    /\1!
-       This is a simple "Hello world" example:
-
-       \quotefile examples/main.cpp
-
-       It contains only the bare minimum you need
-       to get a Qt application up and running.
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       This is a simple "Hello world" example:
-
-       \quotefile examples/main.cpp
-
-       It contains only the bare minimum you need to get a Qt
-       application up and running.
-    \endquotation
-
-    See also \l {quotefromfile-command} {\\quotefromfile} and
-    \l {code-command} {\\code}.
-
-
-    \target quotefromfile-command
-    \section1 \\quotefromfile
-
-    The \\quotefromfile command opens the file given as argument for
-    quoting.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the file name with a line break.
-
-    The command is intended for use when quoting parts from file with
-    the walkthrough commands: \l {printline-command} {\\printline}, \l
-    {printto-command} {\\printto}, \l {printuntil-command}
-    {\\printuntil}, \l {skipline-command} {\\skipline}, \l
-    {skipto-command} {\\skipto}, \l {skipuntil-command}
-    {\\skipuntil}. This enables you to quote specific portions of a
-    file.
-
-    \badcode *
-    /\1!
-       The whole application is contained within
-       the \c main() function:
-
-       \quotefromfile examples/main.cpp
-
-       \skipto main
-       \printuntil app(argc, argv)
-
-       First we create a QApplication object using
-       the \c argc and \c argv parameters.
-
-       \skipto QPushButton
-       \printuntil resize
-
-       Then we create a QPushButton, and give it a reasonable
-       size using the QWidget::resize() function.
-
-       ...
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       The whole application is contained within
-       the \c main() function:
-
-       \quotefromfile examples/main.cpp
-
-       \skipto main
-       \printuntil app(argc, argv)
-
-       First we create a QApplication object using the \c argc
-       and \c argv parameters.
-
-       \skipto QPushButton
-       \printuntil resize
-
-       Then we create a QPushButton, and give it a reasonable
-       size using the QWidget::resize() function.
-
-       ...
-    \endquotation
-
-    QDoc remembers which file it is quoting from, and the current
-    position in that file (see \l {file} {\\printline} for more
-    information). There is no need to "close" the file.
-
-    See also \l {quotefile-command} {\\quotefile}, \l {code-command}
-    {\\code} and \l {dots} {\\dots}.
-
-    \target printline-command
-    \section1 \\printline
-
-    The \\printline command expands to the line from the current
-    position to the next non-blank line of the current source file.
-
-    To ensure that the documentation remains synchronized with the
-    source file, a substring of the line must be specified as an
-    argument to the command. Note that the command considers the rest
-    of the line as part of its argument, make sure to follow the
-    substring with a line break.
-
-    The line from the source file is rendered as a separate paragraph,
-    using a monospace font and the standard indentation. The code is
-    shown verbatim.
-
-    \badcode *
-    /\1!
-       There has to be exactly one QApplication object
-       in every GUI application that uses Qt.
-
-       \quotefromfile examples/main.cpp
-
-       \printline QApplication
-
-       This line includes the QApplication class
-       definition. QApplication manages various
-       application-wide resources, such as the
-       default font and cursor.
-
-       \printline QPushButton
-
-       This line includes the QPushButton class
-       definition. The QPushButton widget provides a command
-       button.
-
-       \printline main
-
-       The main function...
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       There has to be exactly one QApplication object
-       in every GUI application that uses Qt.
-
-       \quotefromfile examples/main.cpp
-
-       \skipto QApplication
-       \printline QApplication
-
-       This line includes the QApplication class
-       definition. QApplication manages various
-       application-wide resources, such as the
-       default font and cursor.
-
-       \printline QPushButton
-
-       This line includes the QPushButton class
-       definition. The QPushButton widget provides a command
-       button.
-
-       \printline main
-
-       The main function...
-    \endquotation
-
-    \target file
-
-    QDoc reads the file sequentially. To move the current position
-    forward you can use either of the \l {skipline-command}
-    {\\skip...} commands. To move the current position backward, you
-    can use the \l {quotefromfile-command} {\\quotefromfile} command
-    again.
-
-    \target substring
-
-    If the substring argument is surrounded by slashes it is
-    interpreted as a \l {QRegularExpression}{regular expression}.
-
-    \badcode *
-    /\1!
-       \quotefromfile examples/mainwindow.cpp
-
-       \skipto closeEvent
-       \printuntil /^\}/
-
-       Close events are sent to widgets that the users want to
-       close, usually by clicking \c File|Exit or by clicking
-       the \c X title bar button. By reimplementing the event
-       handler, we can intercept attempts to close the
-       application.
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       \quotefromfile examples/mainwindow.cpp
-
-       \skipto closeEvent
-       \printuntil /^\}/
-
-       Close events are sent to widgets that the users want to
-       close, usually by clicking \c File|Exit or by clicking
-       the \c X title bar button. By reimplementing the event
-       handler, we can intercept attempts to close the
-       application.
-    \endquotation
-
-    (\l {widgets/scribble} {The complete example file...})
-
-    The regular expression \c /^\}/ makes QDoc print until the first
-    '}' character occurring at the beginning of the line without
-    indentation. /.../ encloses the regular expression, and '^' means
-    the beginning of the line. The '}' character must be escaped since
-    it is a special character in regular expressions.
-
-    QDoc will emit a warning if the specified substring or regular
-    expression cannot be located, i.e. if the source code has changed.
-
-    See also \l {printto-command} {\\printto} and \l
-    {printuntil-command} {\\printuntil}.
-
-    \target printto-command
-    \section1 \\printto
-
-    The \\printto command expands to all the lines from the current
-    position up to and \e excluding the next line containing a given
-    substring.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the substring with a line break. The
-    command also follows the same conventions for \l {file}
-    {positioning} and \l {substring} {argument} as the \l
-    {printline-command} {\\printline} command.
-
-    The lines from the source file are rendered in a separate
-    paragraph, using a monospace font and the standard
-    indentation. The code is shown verbatim.
-
-    \badcode *
-    /\1!
-       The whole application is contained within the
-       \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \printto hello
-
-       First we create a QApplication object using the \c argc and
-       \c argv parameters...
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       The whole application is contained within the
-       \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printto hello
-
-       First we create a QApplication object using the \c argc
-       and \c argv parameters...
-    \endquotation
-
-    See also \l {printline-command} {\\printline} and \l
-    {printuntil-command} {\\printuntil}.
-
-    \target printuntil-command
-    \section1 \\printuntil
-
-    The \\printuntil command expands to all the lines from the current
-    position up to and \e including the next line containing a given
-    substring.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the substring with a line break. The
-    command also follows the same conventions for \l {file}
-    {positioning} and \l {substring} {argument} as the \l
-    {printline-command} {\\printline} command.
-
-    If \\printuntil is used without an argument, it expands to all the
-    lines from the current position to the end of the quoted file.
-
-    The lines from the source file are rendered in a separate
-    paragraph, using a monospace font and the standard
-    indentation. The code is shown verbatim.
-
-    \badcode *
-    /\1!
-       The whole application is contained within the
-       \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printuntil hello
-
-       First we create a QApplication object using the
-       \c argc and \c argv parameters, then we create
-       a QPushButton.
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       The whole application is contained within the
-       \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printuntil hello
-
-       First we create a \l
-       {http://doc.qt.io/qt-6/qapplication.html} {QApplication}
-       object using the \c argc and \c argv parameters, then we
-       create a \l
-       {http://doc.qt.io/qt-6/qpushbutton.html} {QPushButton}.
-    \endquotation
-
-    See also \l {printline-command} {\\printline} and \l
-    {printto-command} {\\printto}.
-
-    \target skipline-command
-    \section1 \\skipline
-
-    The \\skipline command ignores the next non-blank line in the
-    current source file.
-
-    Doc reads the file sequentially, and the \\skipline command is
-    used to move the current position (omitting a line of the source
-    file). See the remark about \l {file} {file positioning} above.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the substring with a line break. The
-    command also follows the same conventions for \l {substring}
-    {argument} as the \l {printline-command} {\\printline} command,
-    and it is used in conjunction with the \l {quotefromfile-command}
-    {\\quotefromfile} command.
-
-    \badcode *
-    /\1!
-       QPushButton is a GUI push button that the user
-       can press and release.
-
-       \quotefromfile examples/main.cpp
-       \skipline QApplication
-       \printline QPushButton
-
-       This line includes the QPushButton class
-       definition. For each class that is part of the
-       public Qt API, there exists a header file of
-       the same name that contains its definition.
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       \l
-       QPushButton is a GUI push button that the user
-       can press and release.
-
-       \quotefromfile examples/main.cpp
-       \skipto QApplication
-       \skipline QApplication
-       \printline QPushButton
-
-       This line includes the QPushButton class
-       definition. For each class that is part of the public
-       Qt API, there exists a header file of the same name
-       that contains its definition.
-    \endquotation
-
-    See also \l {skipto-command} {\\skipto}, \l {skipuntil-command}
-    {\\skipuntil} and \l {dots} {\\dots}.
-
-    \target skipto-command
-    \section1 \\skipto
-
-    The \\skipto command ignores all the lines from the current
-    position up to and \e excluding the next line containing a given
-    substring.
-
-    QDoc reads the file sequentially, and the \\skipto command is used
-    to move the current position (omitting one or several lines of the
-    source file). See the remark about \l {file} {file positioning}
-    above.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the substring with a line break.
-
-    The command also follows the same conventions for \l {substring}
-    {argument} as the \l {printline-command} {\\printline} command,
-    and it is used in conjunction with the \l {quotefromfile-command}
-    {\\quotefromfile} command.
-
-    \badcode *
-    /\1!
-       The whole application is contained within
-       the \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printuntil }
-
-       First we create a QApplication object. There
-       has to be exactly one such object in
-       every GUI application that uses Qt. Then
-       we create a QPushButton, resize it to a reasonable
-       size ...
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       The whole application is contained within
-       the \c main() function:
-
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printuntil }
-
-       First we create a QApplication object. There has to be
-       exactly one such object in every GUI application that
-       uses Qt. Then we create a QPushButton, resize it to a
-       reasonable size ...
-    \endquotation
-
-    See also \l {skipline-command} {\\skipline}, \l
-    {skipuntil-command} {\\skipuntil} and \l {dots} {\\dots}.
-
-    \target skipuntil-command
-    \section1 \\skipuntil
-
-    The \\skipuntil command ignores all the lines from the current
-    position up to and \e including the next line containing a given
-    substring.
-
-    QDoc reads the file sequentially, and the \\skipuntil command is
-    used to move the current position (omitting one or several lines
-    of the source file). See the remark about \l {file} {file
-    positioning} above.
-
-    The command considers the rest of the line as part of its
-    argument, make sure to follow the substring with a line break.
-
-    The command also follows the same conventions for \l {substring}
-    {argument} as the \l {printline-command} {\\printline} command,
-    and it is used in conjunction with the \l {quotefromfile-command}
-    {\\quotefromfile} command.
-
-    \badcode *
-    /\1!
-       The first thing we did in the \c main() function
-       was to create a QApplication object \c app.
-
-       \quotefromfile examples/main.cpp
-       \skipuntil show
-       \dots
-       \printuntil }
-
-       In the end we must remember to make \c main() pass the
-       control to Qt. QCoreApplication::exec() will return when
-       the application exits...
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotation
-       The first thing we did in the \c main() function was to
-       create a QApplication object \c app.
-
-       \quotefromfile examples/main.cpp
-       \skipuntil show
-       \dots
-       \printuntil }
-
-       In the end we must remember to make \c main() pass the
-       control to Qt. QCoreApplication::exec()
-       will return when the application exits...
-    \endquotation
-
-    See also \l {skipline-command} {\\skipline}, \l {skipto-command}
-    {\\skipto} and \l {dots} {\\dots}.
-
-    \target dots-command
-    \section1 \\dots
-
-    The \\dots command indicates that parts of the source file have
-    been omitted when quoting a file.
-
-    The command is used in conjunction with the \l
-    {quotefromfile-command} {\\quotefromfile} command, and should be
-    stated on its own line. The dots are rendered on a new line, using
-    a monospace font.
-
-    \badcode *
-    /\1!
-       \quotefromfile examples/main.cpp
-       \skipto main
-       \printuntil {
-       \dots
-       \skipuntil exec
-       \printline }
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \quotefromfile examples/main.cpp
-    \skipto main
-    \printuntil {
-    \dots
-    \skipuntil exec
-    \printline }
-
-    The default indentation is 4 spaces, but this can be adjusted
-    using the command's optional argument.
-
-    \badcode *
-    /\1!
-        \dots 0
-        \dots
-        \dots 8
-        \dots 12
-        \dots 16
-    \1/
-    \endcode
-
-    QDoc renders this as:
-
-    \dots 0
-    \dots
-    \dots 8
-    \dots 12
-    \dots 16
-
-    See also \l {skipline-command} {\\skipline}, \l {skipto-command}
-    {\\skipto} and \l {skipuntil-command} {\\skipuntil}.
-
-    \target snippet-command
-    \section1 \\snippet
-
-    The \\snippet command causes a code snippet to be included
-    verbatim as preformatted text, which may be syntax highlighted.
-
-    Each code snippet is referenced by the file that holds it and by
-    a unique identifier for that file. Snippet files are typically
-    stored in a \c{snippets} directory inside the documentation
-    directory (for example, \c{$QTDIR/doc/src/snippets}).
-
-    For example, the following documentation references a snippet in a
-    file residing in a subdirectory of the documentation directory:
-
-           \code
-           \snippet snippets/textdocument-resources/main.cpp Adding a resource
-           \endcode
-
-    The text following the file name is the unique identifier for the
-    snippet. This is used to delimit the quoted code in the relevant
-    snippet file, as shown in the following example that corresponds to
-    the above \c{\snippet} command:
-
-    \code
-    ...
-    QImage image(64, 64, QImage::Format_RGB32);
-    image.fill(qRgb(255, 160, 128));
-
-//! [Adding a resource]
-    document->addResource(QTextDocument::ImageResource,
-        QUrl("mydata://image.png"), QVariant(image));
-//! [Adding a resource]
-    ...
-    \endcode
-
-    By default, QDoc looks for \c{//!} as a code snippet marker.
-    For \c{.pro}, \c{.py}, \c{.cmake}, and \c{CMakeLists.txt}
-    files, \c {#!} is detected. Finally, \c{
Import Statement: - // import - // QtQuick.Controls.Imagine 2.12 - //
- // Since: - // Qt 5.10 - //
- // The structure being fixed, a rigid but simple solution is implemented: don't parse the - // table, simply output the expected set of tags. An alternative would be to parse the HTML - // table and to replicate the tags. The output is identical to - // DocBookGenerator::generateQmlRequisites. - else if ( - str.startsWith( - R"(
Import Statement:)") - && matchAhead(atom, Atom::String) && matchAhead(atom->next(), Atom::RawString) - && matchAhead(atom->next()->next(), Atom::String) - && matchAhead(atom->next()->next()->next(), Atom::RawString)) { - m_rewritingCustomQmlModuleSummary = true; - hasRewrittenString = true; - - m_writer->writeStartElement(dbNamespace, "variablelist"); - newLine(); - - generateStartRequisite("Import Statement"); - m_writer->writeCharacters("import "); - } else if (m_rewritingCustomQmlModuleSummary) { - if (str.startsWith( - R"(
Since:)")) { - generateEndRequisite(); - generateStartRequisite("Since"); - - hasRewrittenString = true; - } else if (str.startsWith(R"(
)")) { - m_rewritingCustomQmlModuleSummary = false; - hasRewrittenString = true; - - generateEndRequisite(); - m_writer->writeEndElement(); // variablelist - newLine(); - } - } - // Another idiosyncrasy for this module: - //

- // Universal.accent - // : - // color - //

- // Several variants of this template exist, with more than three String between the - // RawString. They are defined in - // qtdeclarative\src\quickcontrols2\doc\qtquickcontrols.qdocconf. - else if ( - str.startsWith( - R"(
next(), Atom::RawString) - && matchAhead(atom->next()->next(), Atom::String) - && matchAhead(atom->next()->next()->next(), Atom::RawString)) { - hasRewrittenString = true; - m_hasSection = true; - - // Determine which case occurs (property or method). - const bool isStyleProperty = atom->next()->next()->string().startsWith( - R"(">

)"); - const bool isStyleMethod = - !isStyleProperty; // atom->next()->next()->string().startsWith(R"(">

)") - - // Parse the sequence of atoms. - const Atom *nextStringAtom = - atom->next(); // Invariant: ->type() == Atom::String (except after parsing). - const QString id = nextStringAtom->string(); - skipAhead += 2; - QString name; - QString type; - QString arg1; - QString type1; - QString arg2; - QString type2; - - if (isStyleProperty) { - nextStringAtom = nextStringAtom->next()->next(); - name = nextStringAtom->string(); - skipAhead += 2; - - nextStringAtom = nextStringAtom->next()->next(); - type = nextStringAtom->string(); - skipAhead += 2; - } else if (isStyleMethod) { - nextStringAtom = nextStringAtom->next()->next(); - type = nextStringAtom->string(); - skipAhead += 2; - - nextStringAtom = nextStringAtom->next()->next(); - type = nextStringAtom->string(); - skipAhead += 2; - - nextStringAtom = nextStringAtom->next()->next(); - arg1 = nextStringAtom->string(); - skipAhead += 2; - - nextStringAtom = nextStringAtom->next()->next(); - type1 = nextStringAtom->string(); - skipAhead += 2; - - if (matchAhead(nextStringAtom, Atom::RawString) - && matchAhead(nextStringAtom->next(), Atom::String) - && matchAhead(nextStringAtom->next()->next(), Atom::RawString) - && matchAhead(nextStringAtom->next()->next()->next(), Atom::String) - && matchAhead(nextStringAtom->next()->next()->next()->next(), - Atom::RawString)) { - nextStringAtom = nextStringAtom->next()->next(); - arg2 = nextStringAtom->string(); - skipAhead += 2; - - nextStringAtom = nextStringAtom->next()->next(); - type2 = nextStringAtom->string(); - skipAhead += 2; - } - - // For now (Qt 6.4.0), the macro is only defined up to two arguments: \stylemethod - // and \stylemethod2. - } - - // Write the corresponding DocBook. - // This should be wrapped in a section, but there is no mechanism to check for - // \endstyleproperty or \endstylemethod within qdoc (it must be done at the macro - // level), hence the bridgehead. - QString title; - if (isStyleProperty) { - title = name + " : " + type; - } else if (isStyleMethod) { - title = type + " " + name; - } - - m_writer->writeStartElement(dbNamespace, "bridgehead"); - m_writer->writeAttribute("renderas", "sect2"); - writeXmlId(id); - m_writer->writeCharacters(title); - m_writer->writeEndElement(); // bridgehead - newLine(); - - if (m_config->get(CONFIG_DOCBOOKEXTENSIONS).asBool()) { - if (isStyleProperty) { - m_writer->writeStartElement(dbNamespace, "fieldsynopsis"); - - m_writer->writeTextElement(dbNamespace, "type", type); - newLine(); - m_writer->writeTextElement(dbNamespace, "varname", name); - newLine(); - - m_writer->writeEndElement(); // fieldsynopsis - } else if (isStyleMethod) { - m_writer->writeStartElement(dbNamespace, "methodsynopsis"); - - m_writer->writeTextElement(dbNamespace, "type", type); - newLine(); - m_writer->writeTextElement(dbNamespace, "methodname", name); - newLine(); - - if (!arg1.isEmpty() && !type1.isEmpty()) { - m_writer->writeStartElement(dbNamespace, "methodparam"); - newLine(); - m_writer->writeTextElement(dbNamespace, "type", type1); - newLine(); - m_writer->writeTextElement(dbNamespace, "parameter", arg1); - newLine(); - m_writer->writeEndElement(); // methodparam - newLine(); - } - if (!arg2.isEmpty() && !type2.isEmpty()) { - m_writer->writeStartElement(dbNamespace, "methodparam"); - newLine(); - m_writer->writeTextElement(dbNamespace, "type", type2); - newLine(); - m_writer->writeTextElement(dbNamespace, "parameter", arg2); - newLine(); - m_writer->writeEndElement(); // methodparam - newLine(); - } - - m_writer->writeEndElement(); // methodsynopsis - } - } - } - // This time, a specificity of Qt Virtual Keyboard to embed SVG images. Typically, there are - // several images at once with the same encoding. - else if ( - str.startsWith( - R"(

", Qt::SkipEmptyParts, Qt::CaseInsensitive); - - for (const QString& image : images) { - // Find the caption. - const QStringList parts = image.split(""); - const QString svgImage = ""; - const QString caption = parts[1].split("
")[1].split("
")[0]; - - // Output the DocBook equivalent. - m_writer->writeStartElement(dbNamespace, "figure"); - newLine(); - m_writer->writeStartElement(dbNamespace, "title"); - m_writer->writeCharacters(caption); - m_writer->writeEndElement(); // title - newLine(); - m_writer->writeStartElement(dbNamespace, "mediaobject"); - newLine(); - m_writer->writeStartElement(dbNamespace, "imageobject"); - newLine(); - m_writer->writeStartElement(dbNamespace, "imagedata"); - newLine(); - m_writer->device()->write(svgImage.toUtf8()); // SVG image as raw XML. - m_writer->writeEndElement(); // imagedata - newLine(); - m_writer->writeEndElement(); // imageobject - newLine(); - m_writer->writeEndElement(); // mediaobject - newLine(); - m_writer->writeEndElement(); // figure - newLine(); - } - - hasRewrittenString = true; - } - // This time, a specificity of Qt Virtual Keyboard to embed SVG images. Typically, there are - // several images at once with the same encoding. - else if ( - str.startsWith( - R"(
", Qt::SkipEmptyParts, Qt::CaseInsensitive); - - for (const QString &image : images) { - // Find the caption. - const QStringList parts = image.split(""); - const QString svgImage = ""; - const QString caption = parts[1].split("
")[1].split("
")[0]; - - // Output the DocBook equivalent. - m_writer->writeStartElement(dbNamespace, "figure"); - newLine(); - m_writer->writeStartElement(dbNamespace, "title"); - m_writer->writeCharacters(caption); - m_writer->writeEndElement(); // title - newLine(); - m_writer->writeStartElement(dbNamespace, "mediaobject"); - newLine(); - m_writer->writeStartElement(dbNamespace, "imageobject"); - newLine(); - m_writer->writeStartElement(dbNamespace, "imagedata"); - newLine(); - m_writer->device()->write(svgImage.toUtf8()); // SVG image as raw XML. - m_writer->writeEndElement(); // imagedata - newLine(); - m_writer->writeEndElement(); // imageobject - newLine(); - m_writer->writeEndElement(); // mediaobject - newLine(); - m_writer->writeEndElement(); // figure - newLine(); - } - - hasRewrittenString = true; - } - // For ActiveQt, there is some raw HTML that has no meaningful - // translation into DocBook. - else if (str.trimmed().toLower().startsWith(R"(