diff options
21 files changed, 169 insertions, 83 deletions
diff --git a/src/qdoc/config.cpp b/src/qdoc/config.cpp index 695d59444..1387fb411 100644 --- a/src/qdoc/config.cpp +++ b/src/qdoc/config.cpp @@ -344,6 +344,10 @@ void Config::load(const QString &fileName) // 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); } /*! @@ -795,6 +799,32 @@ QStringList Config::getExampleImageFiles(const QSet<QString> &excludedDirs, } /*! + 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 << fileInfo.fileName() + QLatin1String(".pro") + << fileInfo.fileName() + QLatin1String(".qmlproject") + << fileInfo.fileName() + QLatin1String(".pyproject") + << QLatin1String("CMakeLists.txt") + << QLatin1String("qbuild.pro"); // legacy + + QString projectFile; + + for (const auto &name : qAsConst(validNames)) { + projectFile = Config::findFile(Location(), m_exampleFiles, m_exampleDirs, + examplePath + QLatin1Char('/') + name); + if (!projectFile.isEmpty()) + return projectFile; + } + + return projectFile; +} + +/*! \a fileName is the path of the file to find. \a files and \a dirs are the lists where we must find the diff --git a/src/qdoc/config.h b/src/qdoc/config.h index 29ad59afb..f8823d521 100644 --- a/src/qdoc/config.h +++ b/src/qdoc/config.h @@ -135,6 +135,7 @@ public: const QSet<QString> &excludedFiles); QStringList getExampleImageFiles(const QSet<QString> &excludedDirs, const QSet<QString> &excludedFiles); + QString getExampleProjectFile(const QString &examplePath); static QStringList loadMaster(const QString &fileName); static bool isFileExcluded(const QString &fileName, const QSet<QString> &excludedFiles); @@ -189,6 +190,8 @@ private: QStringList m_defines {}; QStringList m_includePaths {}; QStringList m_indexDirs {}; + QStringList m_exampleFiles {}; + QStringList m_exampleDirs {}; QString m_currentDir {}; QString m_previousCurrentDir {}; diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index 647631c27..ed12f64c2 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE /* qmake ignore Q_OBJECT */ -QStringList CppCodeParser::exampleFiles; -QStringList CppCodeParser::exampleDirs; QSet<QString> CppCodeParser::excludeDirs; QSet<QString> CppCodeParser::excludeFiles; @@ -120,8 +118,6 @@ void CppCodeParser::initializeParser() nodeTypeTestFuncMap_.insert(COMMAND_VARIABLE, &Node::isVariable); Config &config = Config::instance(); - exampleFiles = config.getCanonicalPathList(CONFIG_EXAMPLES); - exampleDirs = config.getCanonicalPathList(CONFIG_EXAMPLEDIRS); QStringList exampleFilePatterns = config.getStringList(CONFIG_EXAMPLES + Config::dot + CONFIG_FILEEXTENSIONS); @@ -771,58 +767,29 @@ FunctionNode *CppCodeParser::parseMacroArg(const Location &location, const QStri return macro; } -void CppCodeParser::setExampleFileLists(PageNode *pn) +void CppCodeParser::setExampleFileLists(ExampleNode *en) { - QString examplePath = pn->name(); - QString proFileName = - examplePath + QLatin1Char('/') + examplePath.split(QLatin1Char('/')).last() + ".pro"; - QString fullPath = - Config::findFile(pn->doc().location(), exampleFiles, exampleDirs, proFileName); - + Config &config = Config::instance(); + QString fullPath = config.getExampleProjectFile(en->name()); if (fullPath.isEmpty()) { - QString tmp = proFileName; - proFileName = examplePath + QLatin1Char('/') + "qbuild.pro"; - fullPath = Config::findFile(pn->doc().location(), exampleFiles, exampleDirs, proFileName); - if (fullPath.isEmpty()) { - proFileName = examplePath + QLatin1Char('/') - + examplePath.split(QLatin1Char('/')).last() + ".qmlproject"; - fullPath = - Config::findFile(pn->doc().location(), exampleFiles, exampleDirs, proFileName); - if (fullPath.isEmpty()) { - proFileName = examplePath + QLatin1Char('/') - + examplePath.split(QLatin1Char('/')).last() + ".pyproject"; - fullPath = Config::findFile(pn->doc().location(), exampleFiles, exampleDirs, - proFileName); - if (fullPath.isEmpty()) { - QString details = QLatin1String("Example directories: ") - + exampleDirs.join(QLatin1Char(' ')); - if (!exampleFiles.isEmpty()) - details += QLatin1String(", example files: ") - + exampleFiles.join(QLatin1Char(' ')); - pn->location().warning( - tr("Cannot find file '%1' or '%2'").arg(tmp).arg(proFileName), details); - pn->location().warning(tr(" EXAMPLE PATH DOES NOT EXIST: %1").arg(examplePath), - details); - return; - } - } - } + QString details = QLatin1String("Example directories: ") + + config.getCanonicalPathList(CONFIG_EXAMPLEDIRS).join(QLatin1Char(' ')); + en->location().warning( + tr("Cannot find project file for example '%1'").arg(en->name()), details); + return; } - int sizeOfBoringPartOfName = fullPath.size() - proFileName.size(); - if (fullPath.startsWith("./")) - sizeOfBoringPartOfName = sizeOfBoringPartOfName - 2; - fullPath.truncate(fullPath.lastIndexOf('/')); + QDir exampleDir(QFileInfo(fullPath).dir()); - QStringList exampleFiles = Config::getFilesHere(fullPath, exampleNameFilter, Location(), + QStringList exampleFiles = Config::getFilesHere(exampleDir.path(), exampleNameFilter, Location(), excludeDirs, excludeFiles); // Search for all image files under the example project, excluding doc/images directory. QSet<QString> excludeDocDirs(excludeDirs); - excludeDocDirs.insert(QDir(fullPath).canonicalPath() + "/doc/images"); - QStringList imageFiles = Config::getFilesHere(fullPath, exampleImageFilter, Location(), + excludeDocDirs.insert(exampleDir.path() + QLatin1String("/doc/images")); + QStringList imageFiles = Config::getFilesHere(exampleDir.path(), exampleImageFilter, Location(), excludeDocDirs, excludeFiles); if (!exampleFiles.isEmpty()) { - // move main.cpp and to the end, if it exists + // move main.cpp to the end, if it exists QString mainCpp; const auto isGeneratedOrMainCpp = [&mainCpp](const QString &fileName) { @@ -842,16 +809,19 @@ void CppCodeParser::setExampleFileLists(PageNode *pn) if (!mainCpp.isEmpty()) exampleFiles.append(mainCpp); - // add any qmake Qt resource files and qmake project files - exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro *.qmlproject qmldir"); + // Add any resource and project files + exampleFiles += Config::getFilesHere(exampleDir.path(), + QLatin1String("*.qrc *.pro *.qmlproject *.pyproject CMakeLists.txt qmldir")); } + exampleDir.cdUp(); + int pathLen = exampleDir.path().size() + 1; for (auto &file : exampleFiles) - file = file.mid(sizeOfBoringPartOfName); + file = file.mid(pathLen); for (auto &file : imageFiles) - file = file.mid(sizeOfBoringPartOfName); - ExampleNode *en = static_cast<ExampleNode *>(pn); - en->setFiles(exampleFiles); + file = file.mid(pathLen); + + en->setFiles(exampleFiles, fullPath.mid(pathLen)); en->setImages(imageFiles); } diff --git a/src/qdoc/cppcodeparser.h b/src/qdoc/cppcodeparser.h index 41607434f..df92b71c4 100644 --- a/src/qdoc/cppcodeparser.h +++ b/src/qdoc/cppcodeparser.h @@ -86,7 +86,7 @@ protected: bool hasTooManyTopics(const Doc &doc) const; private: - void setExampleFileLists(PageNode *pn); + void setExampleFileLists(ExampleNode *en); protected: typedef bool (Node::*NodeTypeTestFunc)() const; @@ -94,8 +94,6 @@ protected: QMap<QString, Node::NodeType> nodeTypeMap_; private: - static QStringList exampleFiles; - static QStringList exampleDirs; static QSet<QString> excludeDirs; static QSet<QString> excludeFiles; QString exampleNameFilter; diff --git a/src/qdoc/htmlgenerator.cpp b/src/qdoc/htmlgenerator.cpp index c32e26b4b..104d97bc2 100644 --- a/src/qdoc/htmlgenerator.cpp +++ b/src/qdoc/htmlgenerator.cpp @@ -3919,33 +3919,9 @@ void HtmlGenerator::generateManifestFile(const QString &manifest, const QString writer.writeAttribute("name", en->title()); QString docUrl = manifestDir + fileBase(en) + ".html"; writer.writeAttribute("docUrl", docUrl); - QStringList proFiles; const auto exampleFiles = en->files(); - for (const QString &file : exampleFiles) { - if (file.endsWith(".pro") || file.endsWith(".qmlproject") - || file.endsWith(".pyproject")) - proFiles << file; - } - if (!proFiles.isEmpty()) { - if (proFiles.size() == 1) { - writer.writeAttribute("projectPath", installPath + proFiles[0]); - } else { - QString exampleName = en->name().split('/').last(); - bool proWithExampleNameFound = false; - for (int j = 0; j < proFiles.size(); j++) { - if (proFiles[j].endsWith(QStringLiteral("%1/%1.pro").arg(exampleName)) - || proFiles[j].endsWith(QStringLiteral("%1/%1.qmlproject").arg(exampleName)) - || proFiles[j].endsWith( - QStringLiteral("%1/%1.pyproject").arg(exampleName))) { - writer.writeAttribute("projectPath", installPath + proFiles[j]); - proWithExampleNameFound = true; - break; - } - } - if (!proWithExampleNameFound) - writer.writeAttribute("projectPath", installPath + proFiles[0]); - } - } + if (!en->projectFile().isEmpty()) + writer.writeAttribute("projectPath", installPath + en->projectFile()); if (!en->imageFileName().isEmpty()) { writer.writeAttribute("imageUrl", manifestDir + en->imageFileName()); usedAttributes << "imageUrl"; diff --git a/src/qdoc/node.h b/src/qdoc/node.h index 9f78cc824..b7293f408 100644 --- a/src/qdoc/node.h +++ b/src/qdoc/node.h @@ -705,13 +705,19 @@ public: void setImageFileName(const QString &ifn) override { imageFileName_ = ifn; } const QStringList &files() const { return files_; } const QStringList &images() const { return images_; } - void setFiles(const QStringList files) { files_ = files; } + const QString &projectFile() const { return projectFile_; } + void setFiles(const QStringList files, const QString &projectFile) + { + files_ = files; + projectFile_ = projectFile; + } void setImages(const QStringList images) { images_ = images; } void appendFile(QString &file) { files_.append(file); } void appendImage(QString &image) { images_.append(image); } private: QString imageFileName_; + QString projectFile_; QStringList files_; QStringList images_; }; diff --git a/tests/auto/qdoc/config/testdata/configs/exampletest.qdocconf b/tests/auto/qdoc/config/testdata/configs/exampletest.qdocconf new file mode 100644 index 000000000..a1459f977 --- /dev/null +++ b/tests/auto/qdoc/config/testdata/configs/exampletest.qdocconf @@ -0,0 +1,2 @@ +project = ExampleTest +exampledirs = ../exampletest/examples diff --git a/tests/auto/qdoc/config/testdata/exampletest/examples/test/empty/test.pro b/tests/auto/qdoc/config/testdata/exampletest/examples/test/empty/test.pro new file mode 100644 index 000000000..556df42ea --- /dev/null +++ b/tests/auto/qdoc/config/testdata/exampletest/examples/test/empty/test.pro @@ -0,0 +1 @@ +# nothing diff --git a/tests/auto/qdoc/config/testdata/exampletest/examples/test/example1/example1.pro b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example1/example1.pro new file mode 100644 index 000000000..556df42ea --- /dev/null +++ b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example1/example1.pro @@ -0,0 +1 @@ +# nothing diff --git a/tests/auto/qdoc/config/testdata/exampletest/examples/test/example2/example2.qmlproject b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example2/example2.qmlproject new file mode 100644 index 000000000..556df42ea --- /dev/null +++ b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example2/example2.qmlproject @@ -0,0 +1 @@ +# nothing diff --git a/tests/auto/qdoc/config/testdata/exampletest/examples/test/example3/example3.pyproject b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example3/example3.pyproject new file mode 100644 index 000000000..556df42ea --- /dev/null +++ b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example3/example3.pyproject @@ -0,0 +1 @@ +# nothing diff --git a/tests/auto/qdoc/config/testdata/exampletest/examples/test/example4/CMakeLists.txt b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example4/CMakeLists.txt new file mode 100644 index 000000000..556df42ea --- /dev/null +++ b/tests/auto/qdoc/config/testdata/exampletest/examples/test/example4/CMakeLists.txt @@ -0,0 +1 @@ +# nothing diff --git a/tests/auto/qdoc/config/tst_config.cpp b/tests/auto/qdoc/config/tst_config.cpp index 1e9383fb9..44a1ba953 100644 --- a/tests/auto/qdoc/config/tst_config.cpp +++ b/tests/auto/qdoc/config/tst_config.cpp @@ -28,6 +28,8 @@ #include "config.h" +#include <QtCore/qdir.h> +#include <QtCore/qfileinfo.h> #include <QtCore/qhash.h> #include <QtCore/qstringlist.h> #include <QtTest/QtTest> @@ -43,6 +45,7 @@ class tst_Config : public QObject private slots: void classMembersInitializeToFalseOrEmpty(); void includePathsFromCommandLine(); + void getExampleProjectFile(); }; void tst_Config::classMembersInitializeToFalseOrEmpty() @@ -80,6 +83,32 @@ void tst_Config::includePathsFromCommandLine() QCOMPARE(actual, expected); } +void::tst_Config::getExampleProjectFile() +{ + QStringList commandLineArgs = { QStringLiteral("./qdoc") }; + Config::instance().init("QDoc Test", commandLineArgs); + auto &config = Config::instance(); + + const auto docConfig = QFINDTESTDATA("/testdata/configs/exampletest.qdocconf"); + config.load(docConfig); + + auto rootDir = QFileInfo(docConfig).dir(); + QVERIFY(rootDir.cd("../exampletest/examples/test")); + + QVERIFY(config.getExampleProjectFile("invalid").isEmpty()); + QVERIFY(config.getExampleProjectFile("test/empty").isEmpty()); + + QCOMPARE(config.getExampleProjectFile("test/example1"), + rootDir.absoluteFilePath("example1/example1.pro")); + QCOMPARE(config.getExampleProjectFile("test/example2"), + rootDir.absoluteFilePath("example2/example2.qmlproject")); + QCOMPARE(config.getExampleProjectFile("test/example3"), + rootDir.absoluteFilePath("example3/example3.pyproject")); + QCOMPARE(config.getExampleProjectFile("test/example4"), + rootDir.absoluteFilePath("example4/CMakeLists.txt")); +} + + QTEST_APPLESS_MAIN(tst_Config) #include "tst_config.moc" diff --git a/tests/auto/qdoc/generatedoutput/expected_output/examples-manifest.xml b/tests/auto/qdoc/generatedoutput/expected_output/examples-manifest.xml index 7f206d0e8..8aa9ce303 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/examples-manifest.xml +++ b/tests/auto/qdoc/generatedoutput/expected_output/examples-manifest.xml @@ -1,6 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <instructionals module="Test"> <examples> + <example name="CMake Example Project" docUrl="qthelp://org.qt-project.test.001/test/test-cmaketest-example.html" projectPath="test/cmaketest/CMakeLists.txt" isTest="true"> + <description><![CDATA[No description available]]></description> + <tags>cmake,project,test</tags> + <fileToOpen mainFile="true">test/cmaketest/main.cpp</fileToOpen> + </example> <example name="QML Documentation Example" docUrl="qthelp://org.qt-project.test.001/test/test-componentset-example.html" projectPath="tutorials/componentset/componentset.pro" isTest="true"> <description><![CDATA[Example for documenting QML types.]]></description> <tags>documentation,qml,sample,test</tags> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/test-cmaketest-example.html b/tests/auto/qdoc/generatedoutput/expected_output/test-cmaketest-example.html new file mode 100644 index 000000000..dc123674d --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/expected_output/test-cmaketest-example.html @@ -0,0 +1,22 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> +<!-- cmaketest.qdoc --> + <title>CMake Example Project | Test</title> +</head> +<body> +<div class="sidebar"><div class="sidebar-content" id="sidebar-content"></div></div> +<h1 class="title">CMake Example Project</h1> +<span class="subtitle"></span> +<!-- $$$cmaketest-description --> +<div class="descr"> <a name="details"></a> +<p>Files:</p> +<ul> +<li><a href="test-cmaketest-cmakelists-txt.html">cmaketest/CMakeLists.txt</a></li> +<li><a href="test-cmaketest-main-cpp.html">cmaketest/main.cpp</a></li> +</ul> +</div> +<!-- @@@cmaketest --> +</body> +</html> diff --git a/tests/auto/qdoc/generatedoutput/expected_output/test.qhp b/tests/auto/qdoc/generatedoutput/expected_output/test.qhp index 4816ef1d5..459892df1 100644 --- a/tests/auto/qdoc/generatedoutput/expected_output/test.qhp +++ b/tests/auto/qdoc/generatedoutput/expected_output/test.qhp @@ -8,6 +8,7 @@ <section ref="uicomponents-qmlmodule.html" title="UI Components"> <section ref="uicomponents-qmlmodule.html" title="Test"> <section ref="qdoc-test-qmlmodule.html" title=""/> + <section ref="test-cmaketest-example.html" title="CMake Example Project"/> <section ref="testcpp-module.html" title="QDoc Test C++ Classes"/> <section ref="test-componentset-example.html" title="QML Documentation Example"/> <section ref="uicomponents-qmlmodule.html" title="UI Components"/> @@ -119,6 +120,9 @@ <file>qml-uicomponents-switch.html</file> <file>qml-uicomponents-tabwidget-members.html</file> <file>qml-uicomponents-tabwidget.html</file> + <file>test-cmaketest-cmakelists-txt.html</file> + <file>test-cmaketest-example.html</file> + <file>test-cmaketest-main-cpp.html</file> <file>test-componentset-componentset-pro.html</file> <file>test-componentset-example.html</file> <file>test-componentset-progressbar-qml.html</file> diff --git a/tests/auto/qdoc/generatedoutput/testdata/configs/testqml.qdocconf b/tests/auto/qdoc/generatedoutput/testdata/configs/testqml.qdocconf index 2eb2c5036..8eec4ea4d 100644 --- a/tests/auto/qdoc/generatedoutput/testdata/configs/testqml.qdocconf +++ b/tests/auto/qdoc/generatedoutput/testdata/configs/testqml.qdocconf @@ -16,7 +16,7 @@ excludedirs = ../bug80259 sources.fileextensions = "*.qml *.cpp *.qdoc" headers.fileextensions = "*.h" -examples.fileextensions = "*.qml" +examples.fileextensions = "*.qml *.cpp" macro.begincomment = "\\c{/*}" macro.QDocTestVer = "1.1" diff --git a/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/CMakeLists.txt b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/CMakeLists.txt new file mode 100644 index 000000000..c6a5c654b --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/CMakeLists.txt @@ -0,0 +1,2 @@ +cmake_minimum_required (VERSION 2.8.11) +project (QDOCTEST) diff --git a/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/doc/src/cmaketest.qdoc b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/doc/src/cmaketest.qdoc new file mode 100644 index 000000000..13767e147 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/doc/src/cmaketest.qdoc @@ -0,0 +1,32 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the tools applications of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example cmaketest + \title CMake Example Project +*/ diff --git a/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/main.cpp b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/main.cpp new file mode 100644 index 000000000..68d71eb71 --- /dev/null +++ b/tests/auto/qdoc/generatedoutput/testdata/qml/cmaketest/main.cpp @@ -0,0 +1 @@ +void main(){} diff --git a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp index ead94584a..b3c69af71 100644 --- a/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp +++ b/tests/auto/qdoc/generatedoutput/tst_generatedoutput.cpp @@ -204,6 +204,7 @@ void tst_generatedOutput::htmlFromQml() { testAndCompare("testdata/configs/testqml.qdocconf", "test-componentset-example.html " + "test-cmaketest-example.html " "uicomponents-qmlmodule.html " "qdoc-test-qmlmodule.html " "qml-qdoc-test-abstractparent.html " |