| 1 | // Copyright (C) 2021 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 |
| 3 | |
| 4 | #ifndef CPPCODEPARSER_H |
| 5 | #define CPPCODEPARSER_H |
| 6 | |
| 7 | #include "clangcodeparser.h" |
| 8 | #include "codeparser.h" |
| 9 | #include "parsererror.h" |
| 10 | #include "utilities.h" |
| 11 | |
| 12 | QT_BEGIN_NAMESPACE |
| 13 | |
| 14 | class ClassNode; |
| 15 | class EnumNode; |
| 16 | class ExampleNode; |
| 17 | class FunctionNode; |
| 18 | class Aggregate; |
| 19 | |
| 20 | class CppCodeParser |
| 21 | { |
| 22 | public: |
| 23 | static inline const QSet<QString> topic_commands{ |
| 24 | COMMAND_CLASS, COMMAND_DONTDOCUMENT, COMMAND_ENUM, COMMAND_EXAMPLE, |
| 25 | COMMAND_EXTERNALPAGE, COMMAND_FN, COMMAND_GROUP, COMMAND_HEADERFILE, |
| 26 | COMMAND_MACRO, COMMAND_MODULE, COMMAND_NAMESPACE, COMMAND_PAGE, |
| 27 | COMMAND_PROPERTY, COMMAND_TYPEALIAS, COMMAND_TYPEDEF, COMMAND_VARIABLE, |
| 28 | COMMAND_QMLTYPE, COMMAND_QMLPROPERTY, COMMAND_QMLPROPERTYGROUP, |
| 29 | COMMAND_QMLATTACHEDPROPERTY, COMMAND_QMLENUM, COMMAND_QMLSIGNAL, COMMAND_QMLATTACHEDSIGNAL, |
| 30 | COMMAND_QMLMETHOD, COMMAND_QMLATTACHEDMETHOD, COMMAND_QMLVALUETYPE, COMMAND_QMLBASICTYPE, |
| 31 | COMMAND_QMLMODULE, COMMAND_STRUCT, COMMAND_UNION, |
| 32 | }; |
| 33 | |
| 34 | static inline const QSet<QString> meta_commands = QSet<QString>(CodeParser::common_meta_commands) |
| 35 | << COMMAND_COMPARES << COMMAND_COMPARESWITH << COMMAND_INHEADERFILE |
| 36 | << COMMAND_NEXTPAGE << COMMAND_OVERLOAD << COMMAND_PREVIOUSPAGE |
| 37 | << COMMAND_QMLINSTANTIATES << COMMAND_QMLNATIVETYPE << COMMAND_REIMP << COMMAND_RELATES; |
| 38 | |
| 39 | public: |
| 40 | explicit CppCodeParser(FnCommandParser&& parser); |
| 41 | |
| 42 | FunctionNode *parseMacroArg(const Location &location, const QString ¯oArg); |
| 43 | FunctionNode *parseOtherFuncArg(const QString &topic, const Location &location, |
| 44 | const QString &funcArg); |
| 45 | static bool isQMLMethodTopic(const QString &t); |
| 46 | static bool isQMLPropertyTopic(const QString &t); |
| 47 | |
| 48 | std::pair<std::vector<TiedDocumentation>, std::vector<FnMatchError>> |
| 49 | processTopicArgs(const UntiedDocumentation &untied); |
| 50 | |
| 51 | void processMetaCommand(const Doc &doc, const QString &command, const ArgPair &argLocPair, |
| 52 | Node *node); |
| 53 | void processMetaCommands(const Doc &doc, Node *node); |
| 54 | void processMetaCommands(const std::vector<TiedDocumentation> &tied); |
| 55 | |
| 56 | protected: |
| 57 | virtual Node *processTopicCommand(const Doc &doc, const QString &command, |
| 58 | const ArgPair &arg); |
| 59 | std::vector<TiedDocumentation> processQmlProperties(const UntiedDocumentation& untied); |
| 60 | |
| 61 | private: |
| 62 | void setExampleFileLists(ExampleNode *en); |
| 63 | static void processComparesCommand(Node *node, const QString &arg, const Location &loc); |
| 64 | void processQmlNativeTypeCommand(Node *node, const QString &cmd, |
| 65 | const QString &arg, const Location &loc); |
| 66 | EnumNode *processQmlEnumTopic(const QStringList &enumItemNames, const Location &location, |
| 67 | const QString &arg); |
| 68 | |
| 69 | private: |
| 70 | FnCommandParser fn_parser; |
| 71 | QString m_exampleNameFilter; |
| 72 | QString m_exampleImageFilter; |
| 73 | bool m_showLinkErrors { false }; |
| 74 | }; |
| 75 | |
| 76 | /*! |
| 77 | * \internal |
| 78 | * \brief Checks if there are too many topic commands in \a doc. |
| 79 | * |
| 80 | * This method compares the commands used in \a doc with the set of topic |
| 81 | * commands. If zero or one topic command is found, or if all found topic |
| 82 | * commands are {\\qml*}-commands, the method returns \c false. |
| 83 | * |
| 84 | * If more than one topic command is found, QDoc issues a warning and the list |
| 85 | * of topic commands used in \a doc, and the method returns \c true. |
| 86 | */ |
| 87 | [[nodiscard]] inline bool hasTooManyTopics(const Doc &doc) |
| 88 | { |
| 89 | const QSet<QString> topicCommandsUsed = CppCodeParser::topic_commands & doc.metaCommandsUsed(); |
| 90 | |
| 91 | if (topicCommandsUsed.empty() || topicCommandsUsed.size() == 1) |
| 92 | return false; |
| 93 | if (std::all_of(first: topicCommandsUsed.cbegin(), last: topicCommandsUsed.cend(), |
| 94 | pred: [](const auto &cmd) { return cmd.startsWith(QLatin1String("qml" )); })) |
| 95 | return false; |
| 96 | |
| 97 | const QStringList commands = topicCommandsUsed.values(); |
| 98 | const QString topicCommands{ std::accumulate( |
| 99 | first: commands.cbegin(), last: commands.cend(), init: QString{}, |
| 100 | binary_op: [index = qsizetype{ 0 }, numberOfCommands = commands.size()]( |
| 101 | const QString &accumulator, const QString &topic) mutable -> QString { |
| 102 | return accumulator + QLatin1String("\\" ) + topic |
| 103 | + Utilities::separator(wordPosition: index++, numberOfWords: numberOfCommands); |
| 104 | }) }; |
| 105 | |
| 106 | doc.location().warning( |
| 107 | QStringLiteral("Multiple topic commands found in comment: %1" ).arg(a: topicCommands)); |
| 108 | return true; |
| 109 | } |
| 110 | |
| 111 | QT_END_NAMESPACE |
| 112 | |
| 113 | #endif |
| 114 | |