diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2021-06-12 18:11:51 (GMT) |
---|---|---|
committer | Dimitri van Heesch <doxygen@gmail.com> | 2021-06-12 18:11:51 (GMT) |
commit | 5be74469a6c35b086393b339ebb27328ceb73a4c (patch) | |
tree | 71bbd56524ce265ed5ae4746502a3f1f1d7dd9e5 | |
parent | 146dc3afae082d1177068a0e48ca2dc8a92c404a (diff) | |
download | Doxygen-5be74469a6c35b086393b339ebb27328ceb73a4c.zip Doxygen-5be74469a6c35b086393b339ebb27328ceb73a4c.tar.gz Doxygen-5be74469a6c35b086393b339ebb27328ceb73a4c.tar.bz2 |
Regression: No warnings were given for multiple @param commands with the same name
-rw-r--r-- | src/containers.h | 1 | ||||
-rw-r--r-- | src/docparser.cpp | 74 |
2 files changed, 29 insertions, 46 deletions
diff --git a/src/containers.h b/src/containers.h index f8027fd..4a739cd 100644 --- a/src/containers.h +++ b/src/containers.h @@ -28,6 +28,7 @@ using StringUnorderedMap = std::unordered_map<std::string,std::string>; using StringUnorderedSet = std::unordered_set<std::string>; using StringMap = std::map<std::string,std::string>; using StringSet = std::set<std::string>; +using StringMultiSet = std::multiset<std::string>; using StringVector = std::vector<std::string>; using BoolStack = std::stack<bool>; using BoolVector = std::vector<bool>; diff --git a/src/docparser.cpp b/src/docparser.cpp index 4e316a8..a53a29b 100644 --- a/src/docparser.cpp +++ b/src/docparser.cpp @@ -109,8 +109,8 @@ static QCString g_relPath; static bool g_hasParamCommand; static bool g_hasReturnCommand; -static StringSet g_retvalsFound; -static StringSet g_paramsFound; +static StringMultiSet g_retvalsFound; +static StringMultiSet g_paramsFound; static const MemberDef * g_memberDef; static bool g_isExample; static QCString g_exampleName; @@ -145,8 +145,8 @@ struct DocParserContext bool hasParamCommand; bool hasReturnCommand; const MemberDef * memberDef; - StringSet retvalsFound; - StringSet paramsFound; + StringMultiSet retvalsFound; + StringMultiSet paramsFound; bool isExample; QCString exampleName; QCString searchUrl; @@ -483,7 +483,7 @@ static void checkRetvalName(const QCString &name) { if (!Config_getBool(WARN_IF_DOC_ERROR)) return; if (g_memberDef==0 || name.isEmpty()) return; // not a member or no valid name - if (g_retvalsFound.find(name.str())!=g_retvalsFound.end()) + if (g_retvalsFound.count(name.str())==1) // only report the first double entry { warn_doc_error(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), @@ -511,10 +511,9 @@ static void checkUnOrMultipleDocumentedParams() SrcLangExt lang = g_memberDef->getLanguage(); if (!al.empty()) { - int notArgCnt=0; + ArgumentList undocParams; for (const Argument &a: al) { - int count = 0; QCString argName = g_memberDef->isDefine() ? a.type : a.name; if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); @@ -524,59 +523,42 @@ static void checkUnOrMultipleDocumentedParams() { // allow undocumented self / cls parameter for Python } - else if (!argName.isEmpty() && g_paramsFound.find(argName.str())==g_paramsFound.end() && a.docs.isEmpty()) + else if (!argName.isEmpty()) { - notArgCnt++; - } - else - { - for (const auto &par : g_paramsFound) + size_t count = g_paramsFound.count(argName.str()); + if (count==0 && a.docs.isEmpty()) { - if (argName == QCString(par)) count++; + undocParams.push_back(a); + } + else if (count>1 && Config_getBool(WARN_IF_DOC_ERROR)) + { + warn_doc_error(g_memberDef->getDefFileName(), + g_memberDef->getDefLine(), + "%s", + qPrint("argument '" + aName + + "' from the argument list of " + + QCString(g_memberDef->qualifiedName()) + + " has multiple @param documentation sections")); } - } - if ((count > 1) && Config_getBool(WARN_IF_DOC_ERROR)) - { - warn_doc_error(g_memberDef->getDefFileName(), - g_memberDef->getDefLine(), - "%s", - qPrint("argument '" + aName + - "' from the argument list of " + - QCString(g_memberDef->qualifiedName()) + - " has multiple @param documentation sections")); } } - if ((notArgCnt>0) && Config_getBool(WARN_IF_INCOMPLETE_DOC)) + if (!undocParams.empty() && Config_getBool(WARN_IF_INCOMPLETE_DOC)) { bool first=TRUE; - QCString errMsg= - "The following parameter"; - errMsg+= (notArgCnt>1 ? "s" : ""); + QCString errMsg = "The following parameter"; + if (undocParams.size()>1) errMsg+="s"; errMsg+=" of "+ QCString(g_memberDef->qualifiedName()) + QCString(argListToString(al)) + - (notArgCnt>1 ? " are" : " is") + " not documented:\n"; - for (const Argument &a : al) + (undocParams.size()>1 ? " are" : " is") + " not documented:\n"; + for (const Argument &a : undocParams) { QCString argName = g_memberDef->isDefine() ? a.type : a.name; if (lang==SrcLangExt_Fortran) argName = argName.lower(); argName=argName.stripWhiteSpace(); - if (lang==SrcLangExt_Python && (argName=="self" || argName=="cls")) - { - // allow undocumented self / cls parameter for Python - } - else if (!argName.isEmpty() && g_paramsFound.find(argName.str())==g_paramsFound.end()) - { - if (!first) - { - errMsg+="\n"; - } - else - { - first=FALSE; - } - errMsg+=" parameter '"+argName+"'"; - } + if (!first) errMsg+="\n"; + first=FALSE; + errMsg+=" parameter '"+argName+"'"; } warn_incomplete_doc(g_memberDef->getDefFileName(), g_memberDef->getDefLine(), |