diff options
Diffstat (limited to 'src/qdoc/cppcodeparser.cpp')
-rw-r--r-- | src/qdoc/cppcodeparser.cpp | 168 |
1 files changed, 86 insertions, 82 deletions
diff --git a/src/qdoc/cppcodeparser.cpp b/src/qdoc/cppcodeparser.cpp index f6f2eb5f2..b05e2ab3c 100644 --- a/src/qdoc/cppcodeparser.cpp +++ b/src/qdoc/cppcodeparser.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. @@ -30,15 +30,19 @@ cppcodeparser.cpp */ -#include <qfile.h> -#include <stdio.h> -#include <errno.h> -#include "config.h" #include "cppcodeparser.h" + +#include "config.h" #include "qdocdatabase.h" -#include <qdebug.h> #include "generator.h" +#include <QtCore/qdebug.h> +#include <QtCore/qfile.h> + +#include <algorithm> +#include <errno.h> +#include <stdio.h> + QT_BEGIN_NAMESPACE /* qmake ignore Q_OBJECT */ @@ -151,8 +155,10 @@ void CppCodeParser::initializeParser(const Config &config) CONFIG_EXAMPLES + Config::dot + CONFIG_FILEEXTENSIONS); // Used for excluding dirs and files from the list of example files - excludeDirs = QSet<QString>::fromList(config.getCanonicalPathList(CONFIG_EXCLUDEDIRS)); - excludeFiles = QSet<QString>::fromList(config.getCanonicalPathList(CONFIG_EXCLUDEFILES)); + const auto &excludeDirsList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS); + excludeDirs = QSet<QString>(excludeDirsList.cbegin(), excludeDirsList.cend()); + const auto &excludeFilesList = config.getCanonicalPathList(CONFIG_EXCLUDEDIRS); + excludeFiles = QSet<QString>(excludeFilesList.cbegin(), excludeFilesList.cend()); if (!exampleFilePatterns.isEmpty()) exampleNameFilter = exampleFilePatterns.join(' '); @@ -201,7 +207,7 @@ QStringList CppCodeParser::sourceFileNameFilter() /*! Returns the set of strings reopresenting the topic commands. */ -const QSet<QString>& CppCodeParser::topicCommands() +const QSet<QString> &CppCodeParser::topicCommands() { return topicCommands_; } @@ -209,9 +215,9 @@ const QSet<QString>& CppCodeParser::topicCommands() /*! Process the topic \a command found in the \a doc with argument \a arg. */ -Node* CppCodeParser::processTopicCommand(const Doc& doc, - const QString& command, - const ArgLocPair& arg) +Node *CppCodeParser::processTopicCommand(const Doc &doc, + const QString &command, + const ArgLocPair &arg) { ExtraFuncData extra; if (command == COMMAND_FN) { @@ -247,7 +253,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else if (node->isAggregate()) { if (type == Node::Namespace) { - NamespaceNode* ns = static_cast<NamespaceNode*>(node); + NamespaceNode *ns = static_cast<NamespaceNode *>(node); ns->markSeen(); ns->setWhereDocumented(ns->tree()->camelCaseModuleName()); } @@ -269,37 +275,37 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else if (command == COMMAND_EXAMPLE) { if (Config::generateExamples) { - ExampleNode* en = new ExampleNode(qdb_->primaryTreeRoot(), arg.first); + ExampleNode *en = new ExampleNode(qdb_->primaryTreeRoot(), arg.first); en->setLocation(doc.startLocation()); setExampleFileLists(en); return en; } } else if (command == COMMAND_EXTERNALPAGE) { - ExternalPageNode* epn = new ExternalPageNode(qdb_->primaryTreeRoot(), arg.first); + ExternalPageNode *epn = new ExternalPageNode(qdb_->primaryTreeRoot(), arg.first); epn->setLocation(doc.startLocation()); return epn; } else if (command == COMMAND_HEADERFILE) { - HeaderNode* hn = new HeaderNode(qdb_->primaryTreeRoot(), arg.first); + HeaderNode *hn = new HeaderNode(qdb_->primaryTreeRoot(), arg.first); hn->setLocation(doc.startLocation()); return hn; } else if (command == COMMAND_GROUP) { - CollectionNode* cn = qdb_->addGroup(arg.first); + CollectionNode *cn = qdb_->addGroup(arg.first); cn->setLocation(doc.startLocation()); cn->markSeen(); return cn; } else if (command == COMMAND_MODULE) { - CollectionNode* cn = qdb_->addModule(arg.first); + CollectionNode *cn = qdb_->addModule(arg.first); cn->setLocation(doc.startLocation()); cn->markSeen(); return cn; } else if (command == COMMAND_QMLMODULE) { QStringList blankSplit = arg.first.split(QLatin1Char(' ')); - CollectionNode* cn = qdb_->addQmlModule(blankSplit[0]); + CollectionNode *cn = qdb_->addQmlModule(blankSplit[0]); cn->setLogicalModuleInfo(blankSplit); cn->setLocation(doc.startLocation()); cn->markSeen(); @@ -307,7 +313,7 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else if (command == COMMAND_JSMODULE) { QStringList blankSplit = arg.first.split(QLatin1Char(' ')); - CollectionNode* cn = qdb_->addJsModule(blankSplit[0]); + CollectionNode *cn = qdb_->addJsModule(blankSplit[0]); cn->setLogicalModuleInfo(blankSplit); cn->setLocation(doc.startLocation()); cn->markSeen(); @@ -333,14 +339,14 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, else if (t == "attribution") ptype = Node::AttributionPage; } - PageNode* pn = new PageNode(qdb_->primaryTreeRoot(), args[0], ptype); + PageNode *pn = new PageNode(qdb_->primaryTreeRoot(), args[0], ptype); pn->setLocation(doc.startLocation()); return pn; } else if (command == COMMAND_QMLTYPE) { QmlTypeNode *qcn = nullptr; Node *candidate = qdb_->primaryTreeRoot()->findChildNode(arg.first, Node::QML); if (candidate != nullptr && candidate->isQmlType()) - qcn = static_cast<QmlTypeNode*>(candidate); + qcn = static_cast<QmlTypeNode *>(candidate); else qcn = new QmlTypeNode(qdb_->primaryTreeRoot(), arg.first); qcn->setLocation(doc.startLocation()); @@ -349,17 +355,17 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, QmlTypeNode *qcn = nullptr; Node *candidate = qdb_->primaryTreeRoot()->findChildNode(arg.first, Node::JS); if (candidate != nullptr && candidate->isJsType()) - qcn = static_cast<QmlTypeNode*>(candidate); + qcn = static_cast<QmlTypeNode *>(candidate); else qcn = new QmlTypeNode(qdb_->primaryTreeRoot(), arg.first, Node::JsType); qcn->setLocation(doc.startLocation()); return qcn; } else if (command == COMMAND_QMLBASICTYPE) { - QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first); + QmlBasicTypeNode *n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first); n->setLocation(doc.startLocation()); return n; } else if (command == COMMAND_JSBASICTYPE) { - QmlBasicTypeNode* n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first, Node::JsBasicType); + QmlBasicTypeNode *n = new QmlBasicTypeNode(qdb_->primaryTreeRoot(), arg.first, Node::JsBasicType); n->setLocation(doc.startLocation()); return n; } @@ -395,11 +401,11 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, \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, +bool CppCodeParser::splitQmlPropertyArg(const QString &arg, + QString &type, + QString &module, + QString &qmlTypeName, + QString &name, const Location &location) { QStringList blankSplit = arg.split(QLatin1Char(' ')); @@ -432,7 +438,7 @@ bool CppCodeParser::splitQmlPropertyArg(const QString& arg, */ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocList &docs) { - const TopicList& topics = doc.topicsUsed(); + const TopicList &topics = doc.topicsUsed(); if (topics.isEmpty()) return; @@ -452,22 +458,11 @@ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocLis group = property.left(i); } - QmlTypeNode* qmlType = qdb_->findQmlType(module, qmlTypeName); + NodeList sharedNodes; + QmlTypeNode *qmlType = qdb_->findQmlType(module, qmlTypeName); if (qmlType == nullptr) qmlType = new QmlTypeNode(qdb_->primaryTreeRoot(), qmlTypeName); - SharedCommentNode* scn = nullptr; - if (topics.size() > 1) { - scn = new SharedCommentNode(qmlType, topics.size(), group); - scn->setLocation(doc.startLocation()); - if (jsProps) - scn->setGenus(Node::JS); - else - scn->setGenus(Node::QML); - nodes.append(scn); - docs.append(doc); - } - for (int i=0; i<topics.size(); ++i) { QString cmd = topics.at(i).topic; arg = topics.at(i).args; @@ -485,28 +480,37 @@ void CppCodeParser::processQmlProperties(const Doc &doc, NodeList &nodes, DocLis doc.startLocation().warning(msg); continue; } - QmlPropertyNode* qpn = new QmlPropertyNode(qmlType, property, type, attached); - if (scn != nullptr) - qpn->setSharedCommentNode(scn); + QmlPropertyNode *qpn = new QmlPropertyNode(qmlType, property, type, attached); qpn->setLocation(doc.startLocation()); - if (jsProps) - qpn->setGenus(Node::JS); - else - qpn->setGenus(Node::QML); + qpn->setGenus(jsProps ? Node::JS : Node::QML); nodes.append(qpn); docs.append(doc); + sharedNodes << qpn; } } else { doc.startLocation().warning(tr("Command '\\%1'; not allowed with QML/JS 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.count() > 1) { + SharedCommentNode *scn = new SharedCommentNode(qmlType, sharedNodes.count(), group); + scn->setLocation(doc.startLocation()); + nodes.append(scn); + docs.append(doc); + for (const auto n : sharedNodes) + scn->append(n); + } } /*! Returns the set of strings representing the common metacommands plus some other metacommands. */ -const QSet<QString>& CppCodeParser::metaCommands() +const QSet<QString> &CppCodeParser::metaCommands() { return metaCommands_; } @@ -526,7 +530,7 @@ void CppCodeParser::processMetaCommand(const Doc &doc, QString arg = argLocPair.first; if (command == COMMAND_INHEADERFILE) { if (node->isAggregate()) - static_cast<Aggregate*>(node)->addIncludeFile(arg); + static_cast<Aggregate *>(node)->addIncludeFile(arg); else doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_INHEADERFILE)); } @@ -538,16 +542,16 @@ void CppCodeParser::processMetaCommand(const Doc &doc, in Aggregate::normalizeOverloads(). */ if (node->isFunction()) - static_cast<FunctionNode*>(node)->setOverloadFlag(); + static_cast<FunctionNode *>(node)->setOverloadFlag(); else if (node->isSharedCommentNode()) - static_cast<SharedCommentNode*>(node)->setOverloadFlags(); + static_cast<SharedCommentNode *>(node)->setOverloadFlags(); else doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_OVERLOAD)); } else if (command == COMMAND_REIMP) { if (node->parent() && !node->parent()->isInternal()) { if (node->isFunction()) { - FunctionNode *fn = static_cast<FunctionNode*>(node); + FunctionNode *fn = static_cast<FunctionNode *>(node); // The clang visitor class will have set the // qualified name of the ovverridden function. // If the name of the overridden function isn't @@ -622,13 +626,13 @@ void CppCodeParser::processMetaCommand(const Doc &doc, if (node->name() == arg) doc.location().warning(tr("%1 tries to inherit itself").arg(arg)); else if (node->isQmlType() || node->isJsType()) { - QmlTypeNode* qmlType = static_cast<QmlTypeNode*>(node); + QmlTypeNode *qmlType = static_cast<QmlTypeNode *>(node); qmlType->setQmlBaseName(arg); } } else if (command == COMMAND_QMLINSTANTIATES) { if (node->isQmlType() || node->isJsType()) { - ClassNode* classNode = qdb_->findClassNode(arg.split("::")); + ClassNode *classNode = qdb_->findClassNode(arg.split("::")); if (classNode) node->setClassNode(classNode); else @@ -684,14 +688,14 @@ void CppCodeParser::processMetaCommand(const Doc &doc, if (!node->setTitle(arg)) doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_TITLE)); else if (node->isExample()) - qdb_->addExampleNode(static_cast<ExampleNode*>(node)); + qdb_->addExampleNode(static_cast<ExampleNode *>(node)); } else if (command == COMMAND_SUBTITLE) { if (!node->setSubtitle(arg)) doc.location().warning(tr("Ignored '\\%1'").arg(COMMAND_SUBTITLE)); } else if (command == COMMAND_QTVARIABLE) { node->setQtVariable(arg); if (!node->isModule() && !node->isQmlModule()) - doc.location().warning(tr("Command '\\%1' is only meanigfule in '\\module' and '\\qmlmodule'.") + doc.location().warning(tr("Command '\\%1' is only meaningful in '\\module' and '\\qmlmodule'.") .arg(COMMAND_QTVARIABLE)); } else if (command == COMMAND_NOAUTOLIST) { node->setNoAutoList(true); @@ -706,7 +710,7 @@ void CppCodeParser::processMetaCommand(const Doc &doc, */ void CppCodeParser::processMetaCommands(const Doc &doc, Node *node) { - QStringList metaCommandsUsed = doc.metaCommandsUsed().toList(); + QStringList metaCommandsUsed = doc.metaCommandsUsed().values(); metaCommandsUsed.sort(); // TODO: why are these sorted? mws 24/12/2018 QStringList::ConstIterator cmd = metaCommandsUsed.constBegin(); while (cmd != metaCommandsUsed.constEnd()) { @@ -791,7 +795,7 @@ FunctionNode *CppCodeParser::parseMacroArg(const Location &location, const QStri if (leftParenSplit.isEmpty()) return nullptr; QString macroName; - FunctionNode* oldMacroNode = nullptr; + FunctionNode *oldMacroNode = nullptr; QStringList blankSplit = leftParenSplit[0].split(' '); if (blankSplit.size() > 0) { macroName = blankSplit.last(); @@ -819,7 +823,7 @@ FunctionNode *CppCodeParser::parseMacroArg(const Location &location, const QStri FunctionNode::Metaness metaness = FunctionNode::MacroWithParams; if (params.isEmpty()) metaness = FunctionNode::MacroWithoutParams; - FunctionNode* macro = new FunctionNode(metaness, qdb_->primaryTreeRoot(), macroName); + FunctionNode *macro = new FunctionNode(metaness, qdb_->primaryTreeRoot(), macroName); macro->setAccess(Node::Public); macro->setLocation(location); macro->setReturnType(returnType); @@ -884,18 +888,20 @@ void CppCodeParser::setExampleFileLists(PageNode *pn) if (!exampleFiles.isEmpty()) { // move main.cpp and to the end, if it exists QString mainCpp; - QMutableStringListIterator i(exampleFiles); - i.toBack(); - while (i.hasPrevious()) { - QString fileName = i.previous(); + + const auto isGeneratedOrMainCpp = [&mainCpp](const QString &fileName) { if (fileName.endsWith("/main.cpp")) { - mainCpp = fileName; - i.remove(); + if (mainCpp.isEmpty()) + mainCpp = fileName; + return true; } - else if (fileName.contains("/qrc_") || fileName.contains("/moc_") - || fileName.contains("/ui_")) - i.remove(); - } + 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); @@ -903,13 +909,11 @@ void CppCodeParser::setExampleFileLists(PageNode *pn) exampleFiles += Config::getFilesHere(fullPath, "*.qrc *.pro *.qmlproject qmldir"); } - int i = 0; - foreach (const QString &exampleFile, exampleFiles) - exampleFiles[i++] = exampleFile.mid(sizeOfBoringPartOfName); - i = 0; - foreach (const QString &imageFile, imageFiles) - imageFiles[i++] = imageFile.mid(sizeOfBoringPartOfName); - ExampleNode* en = static_cast<ExampleNode*>(pn); + for (auto &file : exampleFiles) + file = file.mid(sizeOfBoringPartOfName); + for (auto &file : imageFiles) + file = file.mid(sizeOfBoringPartOfName); + ExampleNode *en = static_cast<ExampleNode *>(pn); en->setFiles(exampleFiles); en->setImages(imageFiles); } @@ -981,7 +985,7 @@ void CppCodeParser::processTopicArgs(const Doc &doc, const QString &topic, NodeL docs.append(doc); } } else if (args.size() > 1) { - QVector<SharedCommentNode*> sharedCommentNodes; + QVector<SharedCommentNode *> sharedCommentNodes; ArgList::ConstIterator arg = args.constBegin(); while (arg != args.constEnd()) { node = nullptr; @@ -999,7 +1003,7 @@ void CppCodeParser::processTopicArgs(const Doc &doc, const QString &topic, NodeL bool found = false; for (SharedCommentNode *scn : sharedCommentNodes) { if (scn->parent() == node->parent()) { - node->setSharedCommentNode(scn); + scn->append(node); found = true; break; } |