From 69f51747c37bb24b7e296ff01bb7e45a624f6225 Mon Sep 17 00:00:00 2001 From: Joenio Costa Date: Sun, 4 Aug 2019 22:22:12 -0300 Subject: doxyparse addon new features and bugfixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit this commit is a squashed merge from lots of doxyparse evolution and concentrates contributions from many authors, all listed at the end of this message as Signed-off-by follow a list of all improvements and bugfixes on doxyparse: * workarounding strings replaced by doxygen core * print missing module name for some C code (analizo/analizo#155) * do not count/print 'void' as a function argument * rough instructions for doxyparse release * limit identifiers to 1024 chars (analizo/analizo#135) * removing "\\" from function signatures (analizo/analizo#138) * fix override args references (analizo/analizo#79) * check if new_data in removeDoubleQuotes function is empty (analizo/analizo#120) * removing double quotes from function signature (analizo/analizo#117) * check if ArgumentList is null (analizo/analizo#116) * don't report same module/class more than once (analizo/analizo#112) * add missing key "defines:" to all modules (analizo/analizo#111) * check if string is larger than 1 before removing surrounding quotes (analizo/analizo#110) * doxyparse properly detects package methods * output inheritance as list instead of hash * start yaml document: --- * adding double quoted in module name (analizo/analizo#106) * added --version flag to doxyparse * removing double quotes from function arguments list * fix doxyparse segfault for python source files * using quotes to surround members definition on yaml * add the number of conditionals path * generate configvalues.h * adding .cs (csharp) as non-C file extension * adding .pyw (python) as non-C file extension * adding .py (python) as non-C file extension Signed-off-by: Antonio Terceiro Signed-off-by: Henrique Dutra Signed-off-by: Igor Ribeiro Barbosa Duarte Signed-off-by: João M. Miranda Signed-off-by: Jonathan Moraes Signed-off-by: Kleber Signed-off-by: leonardork Signed-off-by: Marcelo Ferreira Signed-off-by: Mateus Andrade Signed-off-by: Matheus Miranda Signed-off-by: Paulo Meirelles Signed-off-by: Sabryna de Sousa Signed-off-by: Vinicius Daros Signed-off-by: VinyPinheiro --- addon/doxyparse/README | 14 +++- addon/doxyparse/doxyparse.cpp | 147 ++++++++++++++++++++++++++++++++---------- src/code.l | 16 +++++ src/memberdef.cpp | 11 ++++ src/memberdef.h | 5 ++ 5 files changed, 158 insertions(+), 35 deletions(-) diff --git a/addon/doxyparse/README b/addon/doxyparse/README index 288b31e..95cce8c 100644 --- a/addon/doxyparse/README +++ b/addon/doxyparse/README @@ -18,8 +18,20 @@ More info and source code repository: https://github.com/analizo/doxygen sudo make install +## release + +* ensure analizo testsuite passing on newer doxyparse version +* update debian/changelog, commit, push +* create git tag, push to github analizo/doxyparse +* build on amd64 and i386 archs, upload tar.gz to github + * tar -zcf doxyparse__amd64.tar.gz -C bin/ doxyparse + * tar -zcf doxyparse__i386.tar.gz -C bin/ doxyparse +* build debian packages for amd64 and i386, update analizo.org repository + * (see analizo.github.io/README.md file for updating repository instructions) + * upload the deb files to github release tag also +* check if a alien-doxyparse release is necessary and do it on cpan + AUTHORS -======= Antonio Terceiro João M. Miranda diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index 26ecea9..babf3d7 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -24,6 +24,7 @@ #else #include #endif +#include "version.h" #include "doxygen.h" #include "outputgen.h" #include "parserintf.h" @@ -40,6 +41,9 @@ #include #include #include +#include +#include +#include "namespacedef.h" class Doxyparse : public CodeOutputInterface { @@ -81,8 +85,6 @@ class Doxyparse : public CodeOutputInterface }; static bool is_c_code = true; -static std::map modules; -static std::string current_module; static void findXRefSymbols(FileDef *fd) { @@ -107,7 +109,7 @@ static void findXRefSymbols(FileDef *fd) static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) { if (md->isStatic()) { - if(md->getFileDef()) { + if(md->getFileDef() && context->getFileDef()) { if(md->getFileDef()->getOutputFileBase() == context->getFileDef()->getOutputFileBase()) // TODO ignore prefix of file return false; @@ -123,27 +125,48 @@ static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) { } } +// that undo some replacing by src/util.cpp escapeCharsInString(...) +// * https://github.com/doxygen/doxygen/pull/577 +std::string unescapeCharsInString(std::string name) { + QCString module = QCString(name.c_str()); + bool replaced = false; + if (module.find('.') == -1) { + module.replace(QRegExp("_8"), "."); + replaced = true; + } + if (module.find('/') == -1) { + module.replace(QRegExp("_2"), "/"); + replaced = true; + } + if (replaced) { + module.replace(QRegExp("__"), "_"); + } + return module.data(); +} + +static void startYamlDocument() { + printf("---\n"); +} static void printFile(std::string file) { printf("%s:\n", file.c_str()); } static void printModule(std::string module) { - current_module = module; - printf(" %s:\n", module.c_str()); + printf(" \"%s\":\n", unescapeCharsInString(module).c_str()); } static void printClassInformation(std::string information) { printf(" information: %s\n", information.c_str()); } +static void printInherits() { + printf(" inherits:\n"); +} static void printInheritance(std::string base_class) { - printf(" inherits: %s\n", base_class.c_str()); + printf(" - %s\n", base_class.c_str()); } static void printDefines() { - if (! modules[current_module]) { - printf(" defines:\n"); - } - modules[current_module] = true; + printf(" defines:\n"); } static void printDefinition(std::string type, std::string signature, int line) { - printf(" - \"%s\":\n", signature.c_str()); + printf(" - \"%s\":\n", signature.substr(0, 1022).c_str()); printf(" type: %s\n", type.c_str()); printf(" line: %d\n", line); } @@ -160,44 +183,47 @@ static void printUses() { printf(" uses:\n"); } static void printReferenceTo(std::string type, std::string signature, std::string defined_in) { - printf(" - \"%s\":\n", signature.c_str()); + printf(" - \"%s\":\n", signature.substr(0, 1022).c_str()); printf(" type: %s\n", type.c_str()); - printf(" defined_in: %s\n", defined_in.c_str()); + printf(" defined_in: \"%s\"\n", unescapeCharsInString(defined_in).c_str()); +} +static void printNumberOfConditionalPaths(MemberDef* md) { + printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords()); } static int isPartOfCStruct(MemberDef * md) { return is_c_code && md->getClassDef() != NULL; } -std::string removeDoubleQuotes(std::string data) { - // remove surrounding double quotes - if (data.front() == '"' && data.back() == '"') { - data.erase(0, 1); // first double quote - data.erase(data.size() - 1); // last double quote - } - return data; +std::string sanitizeString(std::string data) { + QCString new_data = QCString(data.c_str()); + new_data.replace(QRegExp("\""), ""); + new_data.replace(QRegExp("\\"), ""); // https://github.com/analizo/analizo/issues/138 + return !new_data.isEmpty() ? new_data.data() : ""; } std::string argumentData(Argument *argument) { std::string data = ""; - if (argument->type != NULL) - data = removeDoubleQuotes(argument->type.data()); + if (argument->type != NULL && argument->type.size() > 1) + data = sanitizeString(argument->type.data()); else if (argument->name != NULL) - data = removeDoubleQuotes(argument->name.data()); + data = sanitizeString(argument->name.data()); return data; } std::string functionSignature(MemberDef* md) { - std::string signature = md->name().data(); + std::string signature = sanitizeString(md->name().data()); if(md->isFunction()){ ArgumentList *argList = md->argumentList(); - ArgumentListIterator iterator(*argList); signature += "("; - Argument * argument = iterator.toFirst(); - if(argument != NULL) { - signature += argumentData(argument); - for(++iterator; (argument = iterator.current()); ++iterator){ - signature += std::string(",") + argumentData(argument); + if (argList) { + ArgumentListIterator iterator(*argList); + Argument * argument = iterator.toFirst(); + if(argument != NULL) { + signature += argumentData(argument); + for(++iterator; (argument = iterator.current()); ++iterator) { + signature += std::string(",") + argumentData(argument); + } } } signature += ")"; @@ -221,6 +247,9 @@ static void referenceTo(MemberDef* md) { else if (md->getFileDef()) { defined_in = md->getFileDef()->getOutputFileBase().data(); } + else if (md->getNamespaceDef()) { + defined_in = md->getNamespaceDef()->name().data(); + } } printReferenceTo(type, signature, defined_in); } @@ -228,6 +257,12 @@ static void referenceTo(MemberDef* md) { void cModule(ClassDef* cd) { MemberList* ml = cd->getMemberList(MemberListType_variableMembers); if (ml) { + FileDef *fd = cd->getFileDef(); + MemberList *fd_ml = fd->getMemberList(MemberListType_allMembersList); + if (!fd_ml || fd_ml->count() == 0) { + printModule(fd->getOutputFileBase().data()); + printDefines(); + } MemberListIterator mli(*ml); MemberDef* md; for (mli.toFirst(); (md=mli.current()); ++mli) { @@ -239,18 +274,50 @@ void cModule(ClassDef* cd) { } } +static bool checkOverrideArg(ArgumentList *argList, MemberDef *md) { + ArgumentListIterator iterator(*argList); + Argument * argument = iterator.toFirst(); + + if(!md->isFunction() || argList->count() == 0){ + return false; + } + + if(argument != NULL) { + for(; (argument = iterator.current()); ++iterator){ + if(md->name() == argument->name) { + return true; + } + } + } + + return false; +} + void functionInformation(MemberDef* md) { + std::string temp = ""; int size = md->getEndBodyLine() - md->getStartBodyLine() + 1; printNumberOfLines(size); ArgumentList *argList = md->argumentList(); - printNumberOfArguments(argList->count()); + if (argList) { + ArgumentListIterator iterator(*argList); + Argument * argument = iterator.toFirst(); + if(argument != NULL) { + temp = argumentData(argument); +// TODO: This is a workaround; better not include "void" in argList, in the first place. + if(temp != "void") { + printNumberOfArguments(argList->count()); + } + } + } + + printNumberOfConditionalPaths(md); MemberSDict *defDict = md->getReferencesMembers(); if (defDict) { MemberSDict::Iterator msdi(*defDict); MemberDef *rmd; printUses(); for (msdi.toFirst(); (rmd=msdi.current()); ++msdi) { - if (rmd->definitionType() == Definition::TypeMember && !ignoreStaticExternalCall(md, rmd)) { + if (rmd->definitionType() == Definition::TypeMember && !ignoreStaticExternalCall(md, rmd) && !checkOverrideArg(argList, rmd)) { referenceTo(rmd); } } @@ -276,7 +343,6 @@ void listMembers(MemberList *ml) { if (ml) { MemberListIterator mli(*ml); MemberDef *md; - printDefines(); for (mli.toFirst(); (md=mli.current()); ++mli) { lookupSymbol((Definition*) md); } @@ -299,6 +365,7 @@ static void classInformation(ClassDef* cd) { printModule(cd->name().data()); BaseClassList* baseClasses = cd->baseClasses(); if (baseClasses) { + printInherits(); BaseClassListIterator bci(*baseClasses); BaseClassDef* bcd; for (bci.toFirst(); (bcd = bci.current()); ++bci) { @@ -308,6 +375,7 @@ static void classInformation(ClassDef* cd) { if(cd->isAbstract()) { printClassInformation("abstract class"); } + printDefines(); listAllMembers(cd); } } @@ -356,6 +424,7 @@ static void listSymbols() { MemberList *ml = fd->getMemberList(MemberListType_allMembersList); if (ml && ml->count() > 0) { printModule(fd->getOutputFileBase().data()); + printDefines(); listMembers(ml); } @@ -364,7 +433,10 @@ static void listSymbols() { ClassSDict::Iterator cli(*classes); ClassDef *cd; for (cli.toFirst(); (cd = cli.current()); ++cli) { - classInformation(cd); + if (!cd->isVisited()) { + classInformation(cd); + cd->setVisited(TRUE); + } } } } @@ -377,6 +449,11 @@ int main(int argc,char **argv) { printf("Usage: %s [source_file | source_dir]\n",argv[0]); exit(1); } + if (qstrcmp(&argv[1][2], "version") == 0) { + QCString versionString = getVersion(); + printf("%s\n", versionString); + exit(0); + } // initialize data structures initDoxygen(); @@ -411,6 +488,7 @@ int main(int argc,char **argv) { Config_getBool(EXTRACT_STATIC)=TRUE; Config_getBool(EXTRACT_PRIVATE)=TRUE; Config_getBool(EXTRACT_LOCAL_METHODS)=TRUE; + Config_getBool(EXTRACT_PACKAGE)=TRUE; // Extract source browse information, needed // to make doxygen gather the cross reference info Config_getBool(SOURCE_BROWSER)=TRUE; @@ -464,6 +542,7 @@ int main(int argc,char **argv) { // clean up after us thisDir.rmdir(Config_getString(OUTPUT_DIRECTORY)); + startYamlDocument(); listSymbols(); std::string cleanup_command = "rm -rf "; diff --git a/src/code.l b/src/code.l index 8df0085..45429c3 100644 --- a/src/code.l +++ b/src/code.l @@ -2472,6 +2472,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" BEGIN(FuncCall); } {FLOWCONDITION}/{BN}*"(" { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->addFlowKeyWord(); + } startFontClass("keywordflow"); codifyLines(yytext); endFontClass(); @@ -2489,6 +2493,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" } } {FLOWCONDITION}/([^a-z_A-Z0-9]) { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->addFlowKeyWord(); + } startFontClass("keywordflow"); codifyLines(yytext); endFontClass(); @@ -2503,6 +2511,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" endFontClass(); } {FLOWCONDITION}/{B}* { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->addFlowKeyWord(); + } startFontClass("keywordflow"); codifyLines(yytext); endFontClass(); @@ -3038,6 +3050,10 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" endFontClass(); } {FLOWCONDITION}/([^a-z_A-Z0-9]) { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->addFlowKeyWord(); + } addParmType(); g_parmName=yytext; startFontClass("keywordflow"); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index 4693bdb..d0b70bb 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -1581,6 +1581,7 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, //printf("MemberDefImpl::MemberDef(%s)\n",na); m_impl = new MemberDefImpl::IMPL; m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al,meta); + number_of_flowkw = 1; m_isLinkableCached = 0; m_isConstructorCached = 0; m_isDestructorCached = 0; @@ -5970,6 +5971,16 @@ void MemberDefImpl::invalidateCachedArgumentTypes() invalidateCachedTypesInArgumentList(m_impl->declArgList); } +void MemberDef::addFlowKeyWord() +{ + number_of_flowkw++; +} + +int MemberDef::numberOfFlowKeyWords() +{ + return number_of_flowkw; +} + //---------------- QCString MemberDefImpl::displayName(bool) const diff --git a/src/memberdef.h b/src/memberdef.h index af4fb0a..a94005f 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -183,6 +183,7 @@ class MemberDef : virtual public Definition virtual bool isSliceLocal() const = 0; virtual bool isConstExpr() const = 0; + int numberOfFlowKeyWords(); // derived getters virtual bool isFriendToHide() const = 0; virtual bool isNotFriend() const = 0; @@ -280,6 +281,8 @@ class MemberDef : virtual public Definition // ---- setters ----- //----------------------------------------------------------------------------------- + void addFlowKeyWord(); + // set functions virtual void setMemberType(MemberType t) = 0; virtual void setDefinition(const char *d) = 0; @@ -405,6 +408,8 @@ class MemberDef : virtual public Definition const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool onlyText=FALSE) const = 0; + int number_of_flowkw; + // write helpers virtual void warnIfUndocumented() const = 0; virtual void warnIfUndocumentedParams() const = 0; -- cgit v0.12 From c60743a4b63f71f2cced85b729cc0d32b66e0500 Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Tue, 6 Aug 2019 20:30:19 +0200 Subject: Some fixes and restructuring - moved unescapeCharsInString to util.cpp - restructured flow keyword counting - make flow keyword counting work for python and fortran code as well --- addon/doxyparse/doxyparse.cpp | 25 ++-------------- src/code.l | 8 ++--- src/fortrancode.l | 4 +++ src/memberdef.cpp | 18 +++++++---- src/memberdef.h | 8 ++--- src/pycode.l | 8 +++++ src/util.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++ src/util.h | 1 + 8 files changed, 105 insertions(+), 37 deletions(-) diff --git a/addon/doxyparse/doxyparse.cpp b/addon/doxyparse/doxyparse.cpp index babf3d7..2f6e32d 100644 --- a/addon/doxyparse/doxyparse.cpp +++ b/addon/doxyparse/doxyparse.cpp @@ -125,25 +125,6 @@ static bool ignoreStaticExternalCall(MemberDef *context, MemberDef *md) { } } -// that undo some replacing by src/util.cpp escapeCharsInString(...) -// * https://github.com/doxygen/doxygen/pull/577 -std::string unescapeCharsInString(std::string name) { - QCString module = QCString(name.c_str()); - bool replaced = false; - if (module.find('.') == -1) { - module.replace(QRegExp("_8"), "."); - replaced = true; - } - if (module.find('/') == -1) { - module.replace(QRegExp("_2"), "/"); - replaced = true; - } - if (replaced) { - module.replace(QRegExp("__"), "_"); - } - return module.data(); -} - static void startYamlDocument() { printf("---\n"); } @@ -151,7 +132,7 @@ static void printFile(std::string file) { printf("%s:\n", file.c_str()); } static void printModule(std::string module) { - printf(" \"%s\":\n", unescapeCharsInString(module).c_str()); + printf(" \"%s\":\n", unescapeCharsInString(module.c_str()).data()); } static void printClassInformation(std::string information) { printf(" information: %s\n", information.c_str()); @@ -185,7 +166,7 @@ static void printUses() { static void printReferenceTo(std::string type, std::string signature, std::string defined_in) { printf(" - \"%s\":\n", signature.substr(0, 1022).c_str()); printf(" type: %s\n", type.c_str()); - printf(" defined_in: \"%s\"\n", unescapeCharsInString(defined_in).c_str()); + printf(" defined_in: \"%s\"\n", unescapeCharsInString(defined_in.c_str()).data()); } static void printNumberOfConditionalPaths(MemberDef* md) { printf(" conditional_paths: %d\n", md->numberOfFlowKeyWords()); @@ -451,7 +432,7 @@ int main(int argc,char **argv) { } if (qstrcmp(&argv[1][2], "version") == 0) { QCString versionString = getVersion(); - printf("%s\n", versionString); + printf("%s\n", versionString.data()); exit(0); } diff --git a/src/code.l b/src/code.l index 45429c3..b932a43 100644 --- a/src/code.l +++ b/src/code.l @@ -2474,7 +2474,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" {FLOWCONDITION}/{BN}*"(" { if (g_currentMemberDef && g_currentMemberDef->isFunction()) { - g_currentMemberDef->addFlowKeyWord(); + g_currentMemberDef->incrementFlowKeyWordCount(); } startFontClass("keywordflow"); codifyLines(yytext); @@ -2495,7 +2495,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" {FLOWCONDITION}/([^a-z_A-Z0-9]) { if (g_currentMemberDef && g_currentMemberDef->isFunction()) { - g_currentMemberDef->addFlowKeyWord(); + g_currentMemberDef->incrementFlowKeyWordCount(); } startFontClass("keywordflow"); codifyLines(yytext); @@ -2513,7 +2513,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" {FLOWCONDITION}/{B}* { if (g_currentMemberDef && g_currentMemberDef->isFunction()) { - g_currentMemberDef->addFlowKeyWord(); + g_currentMemberDef->incrementFlowKeyWordCount(); } startFontClass("keywordflow"); codifyLines(yytext); @@ -3052,7 +3052,7 @@ RAWEND ")"[^ \t\(\)\\]{0,16}\" {FLOWCONDITION}/([^a-z_A-Z0-9]) { if (g_currentMemberDef && g_currentMemberDef->isFunction()) { - g_currentMemberDef->addFlowKeyWord(); + g_currentMemberDef->incrementFlowKeyWordCount(); } addParmType(); g_parmName=yytext; diff --git a/src/fortrancode.l b/src/fortrancode.l index 0712afd..3e443b5 100644 --- a/src/fortrancode.l +++ b/src/fortrancode.l @@ -750,6 +750,10 @@ LANGUAGE_BIND_SPEC BIND{BS}"("{BS}C{BS}(,{BS}NAME{BS}"="{BS}"\""(.*)"\""{BS})?") { if ((yy_my_start == 1) && ((yytext[0] == 'c') || (yytext[0] == 'C'))) YY_FTN_REJECT; } + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->incrementFlowKeyWordCount(); + } /* font class is defined e.g. in doxygen.css */ startFontClass("keywordflow"); codifyLines(yytext); diff --git a/src/memberdef.cpp b/src/memberdef.cpp index d0b70bb..9d6ac51 100644 --- a/src/memberdef.cpp +++ b/src/memberdef.cpp @@ -174,6 +174,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual bool livesInsideEnum() const; virtual bool isSliceLocal() const; virtual bool isConstExpr() const; + virtual int numberOfFlowKeyWords() const; virtual bool isFriendToHide() const; virtual bool isNotFriend() const; virtual bool isFunctionOrSignalSlot() const; @@ -308,6 +309,7 @@ class MemberDefImpl : public DefinitionImpl, public MemberDef virtual void setBriefDescription(const char *b,const char *briefFile,int briefLine); virtual void setInbodyDocumentation(const char *d,const char *inbodyFile,int inbodyLine); virtual void setHidden(bool b); + virtual void incrementFlowKeyWordCount(); virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool inGroup, const ClassDef *inheritFrom=0,const char *inheritId=0) const; @@ -605,6 +607,8 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef { return getMdAlias()->isSliceLocal(); } virtual bool isConstExpr() const { return getMdAlias()->isConstExpr(); } + virtual int numberOfFlowKeyWords() const + { return getMdAlias()->numberOfFlowKeyWords(); } virtual bool isFriendToHide() const { return getMdAlias()->isFriendToHide(); } virtual bool isNotFriend() const @@ -820,6 +824,7 @@ class MemberDefAliasImpl : public DefinitionAliasImpl, public MemberDef virtual MemberDef *createTemplateInstanceMember(ArgumentList *formalArgs, ArgumentList *actualArgs) const { return getMdAlias()->createTemplateInstanceMember(formalArgs,actualArgs); } + virtual void incrementFlowKeyWordCount() {} virtual void writeDeclaration(OutputList &ol, const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, @@ -1408,6 +1413,7 @@ class MemberDefImpl::IMPL QCString declFileName; int declLine; int declColumn; + int numberOfFlowKW; }; MemberDefImpl::IMPL::IMPL() : @@ -1423,7 +1429,8 @@ MemberDefImpl::IMPL::IMPL() : category(0), categoryRelation(0), declLine(-1), - declColumn(-1) + declColumn(-1), + numberOfFlowKW(0) { } @@ -1581,7 +1588,6 @@ MemberDefImpl::MemberDefImpl(const char *df,int dl,int dc, //printf("MemberDefImpl::MemberDef(%s)\n",na); m_impl = new MemberDefImpl::IMPL; m_impl->init(this,t,a,e,p,v,s,r,mt,tal,al,meta); - number_of_flowkw = 1; m_isLinkableCached = 0; m_isConstructorCached = 0; m_isDestructorCached = 0; @@ -5971,14 +5977,14 @@ void MemberDefImpl::invalidateCachedArgumentTypes() invalidateCachedTypesInArgumentList(m_impl->declArgList); } -void MemberDef::addFlowKeyWord() +void MemberDefImpl::incrementFlowKeyWordCount() { - number_of_flowkw++; + m_impl->numberOfFlowKW++; } -int MemberDef::numberOfFlowKeyWords() +int MemberDefImpl::numberOfFlowKeyWords() const { - return number_of_flowkw; + return m_impl->numberOfFlowKW; } //---------------- diff --git a/src/memberdef.h b/src/memberdef.h index a94005f..c81af80 100644 --- a/src/memberdef.h +++ b/src/memberdef.h @@ -182,8 +182,8 @@ class MemberDef : virtual public Definition virtual bool livesInsideEnum() const = 0; virtual bool isSliceLocal() const = 0; virtual bool isConstExpr() const = 0; + virtual int numberOfFlowKeyWords() const = 0; - int numberOfFlowKeyWords(); // derived getters virtual bool isFriendToHide() const = 0; virtual bool isNotFriend() const = 0; @@ -281,7 +281,6 @@ class MemberDef : virtual public Definition // ---- setters ----- //----------------------------------------------------------------------------------- - void addFlowKeyWord(); // set functions virtual void setMemberType(MemberType t) = 0; @@ -302,12 +301,13 @@ class MemberDef : virtual public Definition virtual void setReadAccessor(const char *r) = 0; virtual void setWriteAccessor(const char *w) = 0; virtual void setTemplateSpecialization(bool b) = 0; - + virtual void makeRelated() = 0; virtual void makeForeign() = 0; virtual void setInheritsDocsFrom(MemberDef *md) = 0; virtual void setTagInfo(TagInfo *i) = 0; virtual void setArgsString(const char *as) = 0; + virtual void incrementFlowKeyWordCount() = 0; // relation to other members virtual void setReimplements(MemberDef *md) = 0; @@ -408,8 +408,6 @@ class MemberDef : virtual public Definition const ClassDef *cd,const NamespaceDef *nd,const FileDef *fd,const GroupDef *gd, bool onlyText=FALSE) const = 0; - int number_of_flowkw; - // write helpers virtual void warnIfUndocumented() const = 0; virtual void warnIfUndocumentedParams() const = 0; diff --git a/src/pycode.l b/src/pycode.l index 3d57727..0f04baa 100644 --- a/src/pycode.l +++ b/src/pycode.l @@ -1173,6 +1173,10 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT } {FLOWKW} { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->incrementFlowKeyWordCount(); + } startFontClass("keywordflow"); codify(yytext); endFontClass(); @@ -1210,6 +1214,10 @@ TARGET ({IDENTIFIER}|"("{TARGET_LIST}")"|"["{TARGET_LIST}"]"|{ATTRIBUT } {FLOWKW} { + if (g_currentMemberDef && g_currentMemberDef->isFunction()) + { + g_currentMemberDef->incrementFlowKeyWordCount(); + } startFontClass("keywordflow"); codifyLines(yytext); endFontClass(); diff --git a/src/util.cpp b/src/util.cpp index e028660..69f91d5 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -5564,6 +5564,76 @@ QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscor return growBuf.get(); } +QCString unescapeCharsInString(const char *s) +{ + static bool caseSenseNames = Config_getBool(CASE_SENSE_NAMES); + QCString result; + const char *p = s; + if (p) + { + char c; + while ((c=*p++)) + { + if (c=='_') // 2 or 3 character escape + { + switch (*p) + { + case '_': result+=c; p++; break; // __ -> '_' + case '1': result+=':'; p++; break; // _1 -> ':' + case '2': result+='/'; p++; break; // _2 -> '/' + case '3': result+='<'; p++; break; // _3 -> '<' + case '4': result+='>'; p++; break; // _4 -> '>' + case '5': result+='*'; p++; break; // _5 -> '*' + case '6': result+='&'; p++; break; // _6 -> '&' + case '7': result+='|'; p++; break; // _7 -> '|' + case '8': result+='.'; p++; break; // _8 -> '.' + case '9': result+='!'; p++; break; // _9 -> '!' + case '0': // 3 character escape + switch (*(p+1)) + { + case '0': result+=','; p+=2; break; // _00 -> ',' + case '1': result+=' '; p+=2; break; // _01 -> ' ' + case '2': result+='{'; p+=2; break; // _02 -> '{' + case '3': result+='}'; p+=2; break; // _03 -> '}' + case '4': result+='?'; p+=2; break; // _04 -> '?' + case '5': result+='^'; p+=2; break; // _05 -> '^' + case '6': result+='%'; p+=2; break; // _06 -> '%' + case '7': result+='('; p+=2; break; // _07 -> '(' + case '8': result+=')'; p+=2; break; // _08 -> ')' + case '9': result+='+'; p+=2; break; // _09 -> '+' + case 'a': result+='='; p+=2; break; // _0a -> '=' + case 'b': result+='$'; p+=2; break; // _0b -> '$' + case 'c': result+='\\'; p+=2; break;// _0c -> '\' + case 'd': result+='@'; p+=2; break; // _0d -> '@' + case 'e': result+=']'; p+=2; break; // _0e -> ']' + case 'f': result+='['; p+=2; break; // _0f -> '[' + default: // unknown escape, just pass underscore character as-is + result+=c; + break; + } + break; + default: + if (!caseSenseNames && c>='a' && c<='z') // lower to upper case escape, _a -> 'A' + { + result+=toupper(*p); + p++; + } + else // unknown escape, pass underscore character as-is + { + result+=c; + } + break; + } + } + else // normal character; pass as is + { + result+=c; + } + } + } + return result; +} + /*! This function determines the file name on disk of an item * given its name, which could be a class name with template * arguments, so special characters need to be escaped. diff --git a/src/util.h b/src/util.h index ad062d0..ac89ccd 100644 --- a/src/util.h +++ b/src/util.h @@ -340,6 +340,7 @@ PageDef *addRelatedPage(const char *name, ); QCString escapeCharsInString(const char *name,bool allowDots,bool allowUnderscore=FALSE); +QCString unescapeCharsInString(const char *s); void addGroupListToTitle(OutputList &ol,const Definition *d); -- cgit v0.12