From 57730818727420a23e63917e3d035df3926b958f Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 22 May 2020 16:08:39 +0200 Subject: Refactoring: Removed creation of MemberDef's for macro definitions from pre.l --- CMakeLists.txt | 2 + addon/CMakeLists.txt | 4 +- addon/doxmlparser/examples/metrics/CMakeLists.txt | 2 + addon/doxmlparser/test/CMakeLists.txt | 1 + addon/doxyapp/CMakeLists.txt | 1 + addon/doxyparse/CMakeLists.txt | 1 + addon/doxysearch/CMakeLists.txt | 1 + cmake/CompilerWarnings.cmake | 4 +- cmake/Coverage.cmake | 39 ++++++++++++++ cmake/SearchReplace.cmake | 4 ++ src/CMakeLists.txt | 34 ++++++++++-- src/define.cpp | 54 ------------------- src/define.h | 32 ++++------- src/doxygen.cpp | 35 ++++++++++++ src/doxygen.h | 3 +- src/pre.l | 66 ++++++++++------------- 16 files changed, 161 insertions(+), 122 deletions(-) create mode 100644 cmake/Coverage.cmake create mode 100644 cmake/SearchReplace.cmake delete mode 100644 src/define.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 20c87dc..16c0454 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,6 +26,7 @@ option(use_libclang "Add support for libclang parsing." OFF) option(win_static "Link with /MT in stead of /MD on windows" OFF) option(english_only "Only compile in support for the English language" OFF) option(force_qt4 "Forces doxywizard to build using Qt4 even if Qt5 is installed" OFF) +option(enable_coverage "Enable coverage reporting for gcc/clang [development]" OFF) SET(enlarge_lex_buffers "262144" CACHE INTERNAL "Sets the lex input and read buffers to the specified size") @@ -159,6 +160,7 @@ if (win_static) endif() include(cmake/CompilerWarnings.cmake) +include(cmake/Coverage.cmake) add_subdirectory(libmd5) add_subdirectory(liblodepng) diff --git a/addon/CMakeLists.txt b/addon/CMakeLists.txt index fd8c73f..ec4706b 100644 --- a/addon/CMakeLists.txt +++ b/addon/CMakeLists.txt @@ -1,4 +1,6 @@ -add_subdirectory(doxmlparser) +if (build_xmlparser) + add_subdirectory(doxmlparser) +endif () if (build_app) add_subdirectory(doxyapp) diff --git a/addon/doxmlparser/examples/metrics/CMakeLists.txt b/addon/doxmlparser/examples/metrics/CMakeLists.txt index 8e03246..255ae0e 100644 --- a/addon/doxmlparser/examples/metrics/CMakeLists.txt +++ b/addon/doxmlparser/examples/metrics/CMakeLists.txt @@ -11,4 +11,6 @@ main.cpp target_link_libraries(doxmlparser_metrics doxmlparser qtools + ${COVERAGE_LINKER_FLAGS} ) + diff --git a/addon/doxmlparser/test/CMakeLists.txt b/addon/doxmlparser/test/CMakeLists.txt index c38c8a5..2d92b72 100644 --- a/addon/doxmlparser/test/CMakeLists.txt +++ b/addon/doxmlparser/test/CMakeLists.txt @@ -12,4 +12,5 @@ main.cpp target_link_libraries(doxmlparser_test doxmlparser qtools + ${COVERAGE_LINKER_FLAGS} ) diff --git a/addon/doxyapp/CMakeLists.txt b/addon/doxyapp/CMakeLists.txt index af4590d..9d74fbc 100644 --- a/addon/doxyapp/CMakeLists.txt +++ b/addon/doxyapp/CMakeLists.txt @@ -31,6 +31,7 @@ ${CMAKE_THREAD_LIBS_INIT} ${SQLITE3_LIBRARIES} ${EXTRA_LIBS} ${CLANG_LIBS} +${COVERAGE_LINKER_FLAGS} ) install(TARGETS doxyapp DESTINATION bin) diff --git a/addon/doxyparse/CMakeLists.txt b/addon/doxyparse/CMakeLists.txt index d2a8f63..8e0ad49 100644 --- a/addon/doxyparse/CMakeLists.txt +++ b/addon/doxyparse/CMakeLists.txt @@ -31,6 +31,7 @@ ${CMAKE_THREAD_LIBS_INIT} ${SQLITE3_LIBRARIES} ${EXTRA_LIBS} ${CLANG_LIBS} +${COVERAGE_LINKER_FLAGS} ) install(TARGETS doxyparse DESTINATION bin) diff --git a/addon/doxysearch/CMakeLists.txt b/addon/doxysearch/CMakeLists.txt index 54794a6..7a1e1c1 100644 --- a/addon/doxysearch/CMakeLists.txt +++ b/addon/doxysearch/CMakeLists.txt @@ -17,6 +17,7 @@ target_link_libraries(doxyindexer ${XAPIAN_LIBRARIES} ${ZLIB_LIBRARIES} ${WIN_EXTRA_LIBS} + ${COVERAGE_LINKER_FLAGS} qtools ) diff --git a/cmake/CompilerWarnings.cmake b/cmake/CompilerWarnings.cmake index e6c1539..8137f6f 100644 --- a/cmake/CompilerWarnings.cmake +++ b/cmake/CompilerWarnings.cmake @@ -100,9 +100,9 @@ function(set_project_warnings project_name) if(MSVC) set(PROJECT_WARNINGS ${MSVC_WARNINGS}) - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + elseif(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang") # e.g. Clang or AppleClang set(PROJECT_WARNINGS ${CLANG_WARNINGS}) - else() + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "7.0.0") set(GCC_EXTRA_WARNINGS -Wno-implicit-fallthrough diff --git a/cmake/Coverage.cmake b/cmake/Coverage.cmake new file mode 100644 index 0000000..31f8341 --- /dev/null +++ b/cmake/Coverage.cmake @@ -0,0 +1,39 @@ +if(enable_coverage) + FIND_PROGRAM( LCOV_PATH lcov ) + FIND_PROGRAM( GENHTML_PATH genhtml ) + set(COVERAGE_COMPILER_FLAGS -g --coverage -O0 + CACHE INTERNAL "") + set(COVERAGE_LINKER_FLAGS --coverage + CACHE INTERNAL "") + add_custom_target(coverage-clean + COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --zerocounters + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_target(coverage + COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --directory . --capture --output-file cov.info + COMMAND ${LCOV_PATH} --rc lcov_branch_coverage=1 --remove cov.info '*/c++/*' '*/_ctype.h' '*/generated_src/*' --output-file cov.info.cleaned + COMMAND ${CMAKE_COMMAND} -Dsearch=${CMAKE_BINARY_DIR} + -Dreplace=${CMAKE_SOURCE_DIR} + -Dsrc=cov.info.cleaned + -Ddst=cov.info.final + -P ${CMAKE_SOURCE_DIR}/cmake/SearchReplace.cmake + COMMAND ${GENHTML_PATH} --rc genhtml_branch_coverage=1 + --function-coverage --branch-coverage + --title "Doxygen Coverage Report" --num-spaces 2 + --legend --prefix ${CMAKE_SOURCE_DIR} --demangle-cpp + --output-directory cov_output cov.info.final + COMMAND ${CMAKE_COMMAND} -E remove cov.info cov.info.cleaned cov.info.final + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + ) + add_custom_command(TARGET coverage POST_BUILD + COMMAND ; + COMMENT "Open ./cov_output/index.html in your browser to view the coverage report" + ) +endif() + +function(set_project_coverage project_name) + if(enable_coverage) + target_compile_options(${project_name} PRIVATE ${COVERAGE_COMPILER_FLAGS}) + endif() +endfunction() + diff --git a/cmake/SearchReplace.cmake b/cmake/SearchReplace.cmake new file mode 100644 index 0000000..116cd71 --- /dev/null +++ b/cmake/SearchReplace.cmake @@ -0,0 +1,4 @@ +message("Replacing ${search} by ${replace} in file ${src} and writing to ${dst}...") +file(READ ${src} file_contents) +string(REPLACE "${search}" "${replace}" file_contents ${file_contents}) +file(WRITE ${dst} ${file_contents}) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fec251e..a002ff8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -128,12 +128,30 @@ foreach(lex_file ${LEX_FILES}) OUTPUT ${GENERATED_SRC}/${lex_file}.l.h ) set_source_files_properties(${GENERATED_SRC}/${lex_file}.l.h PROPERTIES GENERATED 1) + # for code coverage we need the flex sources in the build src directory + add_custom_command( + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/${lex_file}.l ${CMAKE_BINARY_DIR}/src/${lex_file}.l + DEPENDS ${CMAKE_SOURCE_DIR}/src/${lex_file}.l + OUTPUT ${CMAKE_BINARY_DIR}/src/${lex_file}.l + ) - FLEX_TARGET(${lex_file} ${lex_file}.l ${GENERATED_SRC}/${lex_file}.cpp COMPILE_FLAGS "${LEX_FLAGS}") + FLEX_TARGET(${lex_file} + ${lex_file}.l + ${GENERATED_SRC}/${lex_file}.cpp + COMPILE_FLAGS "${LEX_FLAGS}") endforeach() -BISON_TARGET(constexp constexp.y ${GENERATED_SRC}/ce_parse.cpp COMPILE_FLAGS "${YACC_FLAGS}") +BISON_TARGET(constexp + constexp.y + ${GENERATED_SRC}/ce_parse.cpp + COMPILE_FLAGS "${YACC_FLAGS}") + +add_custom_command( + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/src/constexp.y ${CMAKE_BINARY_DIR}/src + DEPENDS ${CMAKE_SOURCE_DIR}/src/constexp.y + OUTPUT ${CMAKE_BINARY_DIR}/src/constexp.y +) add_library(doxycfg STATIC ${GENERATED_SRC}/lang_cfg.h @@ -204,7 +222,6 @@ add_library(doxymain STATIC context.cpp cppvalue.cpp defgen.cpp - define.cpp definition.cpp dia.cpp diagram.cpp @@ -291,8 +308,9 @@ endif() ##add_library(doxymain STATIC ${GENERATED_SRC}/${lex_file}.l.h) ##endforeach() -add_executable(doxygen main.cpp) - +add_executable(doxygen + main.cpp +) if (use_libclang) find_package(LLVM REQUIRED CONFIG) @@ -328,6 +346,7 @@ target_link_libraries(doxygen ${CMAKE_THREAD_LIBS_INIT} ${EXTRA_LIBS} ${CLANG_LIBS} + ${COVERAGE_LINKER_FLAGS} ${DOXYGEN_EXTRA_LINK_OPTIONS} ) @@ -335,5 +354,10 @@ set_project_warnings(doxycfg) set_project_warnings(doxymain) set_project_warnings(doxygen) +set_project_coverage(qtools) +set_project_coverage(doxycfg) +set_project_coverage(doxymain) +set_project_coverage(doxygen) + install(TARGETS doxygen DESTINATION bin) diff --git a/src/define.cpp b/src/define.cpp deleted file mode 100644 index b5d9170..0000000 --- a/src/define.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/****************************************************************************** - * - * - * - * Copyright (C) 1997-2015 by Dimitri van Heesch. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation under the terms of the GNU General Public License is hereby - * granted. No representations are made about the suitability of this software - * for any purpose. It is provided "as is" without express or implied warranty. - * See the GNU General Public License for more details. - * - * Documents produced by Doxygen are derivative works derived from the - * input used in their production; they are not affected by this license. - * - */ - -#include "define.h" -#include "config.h" - -Define::Define() -{ - fileDef=0; - lineNr=1; - columnNr=1; - nargs=-1; - undef=FALSE; - varArgs=FALSE; - isPredefined=FALSE; - nonRecursive=FALSE; -} - -Define::Define(const Define &d) - : name(d.name),definition(d.definition),fileName(d.fileName) -{ - //name=d.name; definition=d.definition; fileName=d.fileName; - lineNr=d.lineNr; - columnNr=d.columnNr; - nargs=d.nargs; - undef=d.undef; - varArgs=d.varArgs; - isPredefined=d.isPredefined; - nonRecursive=d.nonRecursive; - fileDef=0; -} - -Define::~Define() -{ -} - -bool Define::hasDocumentation() -{ - return definition && (doc || Config_getBool(EXTRACT_ALL)); -} diff --git a/src/define.h b/src/define.h index 3627140..0a3d62c 100644 --- a/src/define.h +++ b/src/define.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright (C) 1997-2015 by Dimitri van Heesch. + * Copyright (C) 1997-2020 by Dimitri van Heesch. * * Permission to use, copy, modify, and distribute this software and its * documentation under the terms of the GNU General Public License is hereby @@ -28,31 +28,21 @@ class FileDef; class Define { public: - Define(); - Define(const Define &d); - ~Define(); - bool hasDocumentation(); QCString name; QCString definition; QCString fileName; - QCString doc; - QCString brief; QCString args; - QCString anchor; - FileDef *fileDef; - int lineNr; - int columnNr; - int nargs; - bool undef; - bool varArgs; - bool isPredefined; - bool nonRecursive; + FileDef *fileDef = 0; + int lineNr = 1; + int columnNr = 1; + int nargs = -1; + bool undef = FALSE; + bool varArgs = FALSE; + bool isPredefined = FALSE; + bool nonRecursive = FALSE; }; -/** A dictionary of references to Define objects. */ -typedef std::map< std::string,Define* > DefineMapRef; - -/** A dictionary of managed Define objects. */ -typedef std::map< std::string,std::unique_ptr > DefineMapOwning; +/** List of all macro definitions */ +using DefineList = std::vector< std::unique_ptr >; #endif diff --git a/src/doxygen.cpp b/src/doxygen.cpp index 5f324fd..c7c9b45 100644 --- a/src/doxygen.cpp +++ b/src/doxygen.cpp @@ -160,6 +160,7 @@ bool Doxygen::generatingXmlOutput = FALSE; bool Doxygen::markdownSupport = TRUE; GenericsSDict *Doxygen::genericsDict; Preprocessor *Doxygen::preprocessor = 0; +DefineList Doxygen::macroDefinitions; // locally accessible globals static std::unordered_map< std::string, const Entry* > g_classEntries; @@ -7698,6 +7699,36 @@ static void addSourceReferences() //---------------------------------------------------------------------------- +// add the macro definitions found during preprocessing as file members +static void buildDefineList() +{ + for (const auto &def : Doxygen::macroDefinitions) + { + std::unique_ptr md { createMemberDef( + def->fileName,def->lineNr,def->columnNr, + "#define",def->name,def->args,0, + Public,Normal,FALSE,Member,MemberType_Define, + ArgumentList(),ArgumentList(),"") }; + + if (!def->args.isEmpty()) + { + md->moveArgumentList(stringToArgumentList(SrcLangExt_Cpp, def->args)); + } + md->setInitializer(def->definition); + md->setFileDef(def->fileDef); + md->setDefinition("#define "+def->name); + + MemberName *mn=Doxygen::functionNameLinkedMap->add(def->name); + if (def->fileDef) + { + def->fileDef->insertMember(md.get()); + } + mn->push_back(std::move(md)); + } +} + +//---------------------------------------------------------------------------- + static void sortMemberLists() { // sort class member lists @@ -10876,6 +10907,10 @@ void parseInput() * Gather information * **************************************************************************/ + g_s.begin("Building macro definition list...\n"); + buildDefineList(); + g_s.end(); + g_s.begin("Building group list...\n"); buildGroupList(root.get()); organizeSubGroups(root.get()); diff --git a/src/doxygen.h b/src/doxygen.h index d8cd1fc..b824b54 100644 --- a/src/doxygen.h +++ b/src/doxygen.h @@ -28,6 +28,7 @@ #include "membergroup.h" #include "dirdef.h" #include "memberlist.h" +#include "define.h" class RefList; class PageSList; @@ -107,7 +108,6 @@ class Doxygen static FileNameLinkedMap *diaFileNameLinkedMap; static MemberNameLinkedMap *memberNameLinkedMap; static MemberNameLinkedMap *functionNameLinkedMap; - static QStrList tagfileList; static StringUnorderedMap namespaceAliasMap; static GroupSDict *groupSDict; static NamespaceSDict *namespaceSDict; @@ -139,6 +139,7 @@ class Doxygen static bool markdownSupport; static GenericsSDict *genericsDict; static Preprocessor *preprocessor; + static DefineList macroDefinitions; }; void initDoxygen(); diff --git a/src/pre.l b/src/pre.l index da67db5..ef97f0a 100644 --- a/src/pre.l +++ b/src/pre.l @@ -57,8 +57,6 @@ #include "condparser.h" #include "config.h" #include "filedef.h" -#include "memberdef.h" -#include "membername.h" #define YY_NO_UNISTD_H 1 @@ -93,6 +91,12 @@ struct FileState QCString fileName; }; +/** A dictionary of references to Define objects. */ +typedef std::map< std::string,Define* > DefineMapRef; + +/** A dictionary of managed Define objects. */ +typedef std::map< std::string,std::unique_ptr > DefineMapOwning; + /** @brief Singleton that manages the defines available while * preprocessing files. */ @@ -415,7 +419,7 @@ static bool otherCaseDone(yyscan_t yyscanner); static bool computeExpression(yyscan_t yyscanner,const QCString &expr); static void startCondSection(yyscan_t yyscanner,const char *sectId); static void endCondSection(yyscan_t yyscanner); -static void addDefine(yyscan_t yyscanner); +static void addMacroDefinition(yyscan_t yyscanner); static std::unique_ptr newDefine(yyscan_t yyscanner); static void setFileName(yyscan_t yyscanner,const char *name); static yy_size_t yyread(yyscan_t yyscanner,char *buf,yy_size_t max_size); @@ -1540,7 +1544,7 @@ CHARLIT (("'"\\[0-7]{1,3}"'")|("'"\\."'")|("'"[^'\\\n]{1,4}"'")) //printf("Define name='%s' text='%s' litTexti='%s'\n",yyextra->defName.data(),yyextra->defText.data(),yyextra->defLitText.data()); if (yyextra->includeStack.empty() || yyextra->curlyCount>0) { - addDefine(yyscanner); + addMacroDefinition(yyscanner); } def=g_defineManager.isDefined(yyextra->defName); if (def==0) // new define @@ -2787,60 +2791,46 @@ static std::unique_ptr newDefine(yyscan_t yyscanner) return def; } -static void addDefine(yyscan_t yyscanner) +static void addMacroDefinition(yyscan_t yyscanner) { YY_EXTRA_TYPE state = preYYget_extra(yyscanner); if (state->skip) return; // do not add this define as it is inside a // conditional section (cond command) that is disabled. - //printf("addDefine '%s' '%s'\n",state->defName.data(),state->defArgsStr.data()); - //ArgumentList *al = new ArgumentList; - //stringToArgumentList(state->defArgsStr,al); - std::unique_ptr md { createMemberDef( - state->yyFileName,state->yyLineNr-state->yyMLines,state->yyColNr, - "#define",state->defName,state->defArgsStr,0, - Public,Normal,FALSE,Member,MemberType_Define,ArgumentList(),ArgumentList(),"") }; - if (!state->defArgsStr.isEmpty()) - { - //printf("addDefine() state->defName='%s' state->defArgsStr='%s'\n",state->defName.data(),state->defArgsStr.data()); - md->moveArgumentList(stringToArgumentList(SrcLangExt_Cpp, state->defArgsStr)); - } - //printf("Setting initializer for '%s' to '%s'\n",state->defName.data(),state->defText.data()); - int l=state->defLitText.find('\n'); - if (l>0 && state->defLitText.left(l).stripWhiteSpace()=="\\") + auto define = std::make_unique(); + define->fileName = state->yyFileName; + define->lineNr = state->yyLineNr - state->yyMLines; + define->columnNr = state->yyColNr; + define->name = state->defName; + define->args = state->defArgsStr; + define->fileDef = state->inputFileDef; + + QCString litText = state->defLitText; + int l=litText.find('\n'); + if (l>0 && litText.left(l).stripWhiteSpace()=="\\") { // strip first line if it only contains a slash - state->defLitText = state->defLitText.right(state->defLitText.length()-l-1); + litText = litText.right(litText.length()-l-1); } else if (l>0) { // align the items on the first line with the items on the second line int k=l+1; - const char *p=state->defLitText.data()+k; + const char *p=litText.data()+k; char c; while ((c=*p++) && (c==' ' || c=='\t')) k++; - state->defLitText=state->defLitText.mid(l+1,k-l-1)+state->defLitText.stripWhiteSpace(); + litText=litText.mid(l+1,k-l-1)+litText.stripWhiteSpace(); } - QCString defLitTextStripped = state->defLitText.stripWhiteSpace(); - if (defLitTextStripped.contains('\n')>=1) + QCString litTextStripped = state->defLitText.stripWhiteSpace(); + if (litTextStripped.contains('\n')>=1) { - md->setInitializer(state->defLitText); + define->definition = litText; } else { - md->setInitializer(defLitTextStripped); - } - - //printf("pre.l: md->setFileDef(%p)\n",state->inputFileDef); - md->setFileDef(state->inputFileDef); - md->setDefinition("#define "+state->defName); - - MemberName *mn=Doxygen::functionNameLinkedMap->add(state->defName); - if (state->yyFileDef) - { - state->yyFileDef->insertMember(md.get()); + define->definition = litTextStripped; } - mn->push_back(std::move(md)); + Doxygen::macroDefinitions.push_back(std::move(define)); } static inline void outputChar(yyscan_t yyscanner,char c) -- cgit v0.12