diff --git a/CMakeLists.txt b/CMakeLists.txt index ac2fda2..20a04e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,302 +1,300 @@ # This is the top-level CMakeLists.txt file for the Clazy project. # # To build the man page from POD, run 'make man' after CMake (assumes perl is available) # To install the resulting man page, run 'make install' # The man page is not available on Windows. # project(ClangLazy) cmake_minimum_required(VERSION 3.0) include(FeatureSummary) include(GenerateExportHeader) include("GNUInstallDirs") # Version setup set(CLAZY_VERSION_MAJOR "1") set(CLAZY_VERSION_MINOR "4") set(CLAZY_VERSION_PATCH "0") set(CLAZY_VERSION "${CLAZY_VERSION_MAJOR}.${CLAZY_VERSION_MINOR}.${CLAZY_VERSION_PATCH}") set(CLAZY_PRINT_VERSION "${CLAZY_VERSION_MAJOR}.${CLAZY_VERSION_MINOR}") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake) if (NOT CLAZY_BUILD_WITH_CLANG) find_package(Clang 3.9 MODULE REQUIRED) endif() set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) add_definitions(-D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS) add_definitions(-D_GNU_SOURCE -DHAVE_CLANG_CONFIG_H) option(CLAZY_BUILD_UTILS_LIB "Enable this option to build a library so you can reuse clazy's utility functions" OFF) if(CLAZY_BUILD_UTILS_LIB) add_definitions(-DCLAZY_BUILD_UTILS_LIB) endif() if(NOT CLAZY_BUILD_WITH_CLANG AND MSVC AND NOT CLANG_LIBRARY_IMPORT) message(FATAL_ERROR "\nOn MSVC you need to pass -DCLANG_LIBRARY_IMPORT=C:/path/to/llvm-build/lib/clang.lib to cmake when building Clazy.\nAlso make sure you've built LLVM with -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON") endif() if(MSVC) # disable trigger-happy warnings from Clang/LLVM headers set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267 /wd4244 /wd4291 /wd4800 /wd4141 /wd4146 /wd4251") elseif(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-common -Woverloaded-virtual -Wcast-qual -fno-strict-aliasing -pedantic -Wno-long-long -Wall -W -Wno-unused-parameter -Wwrite-strings -fno-exceptions -fno-rtti") endif() set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-flat_namespace -Wl,-undefined -Wl,suppress") if(WIN32) add_definitions(-D_CRT_SECURE_NO_WARNINGS) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() # Look for std::regex support message("Looking for std::regex support...") try_run(RUN_RESULT COMPILE_RESULT ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_LIST_DIR}/.cmake_has_regex_test.cpp) if(RUN_RESULT EQUAL 0) set(HAS_STD_REGEX TRUE) else() set(HAS_STD_REGEX FALSE) add_definitions(-DNO_STD_REGEX) message("old-style-connect check is disabled due to missing std::regex support") message("Suppressions are disabled due to missing std::regex support") endif() include(ClazySources.cmake) if (NOT CLAZY_BUILD_WITH_CLANG) if(MSVC) string(REPLACE "\\" "/" LLVM_LIBS ${LLVM_LIBS}) endif() string(REPLACE " " ";" LLVM_LIBS_LIST ${LLVM_LIBS}) # Transform into a list set(CLAZY_STANDALONE_LLVM_LIBS ${LLVM_LIBS_LIST}) if(NOT APPLE AND NOT MINGW) # Don't link against LLVMSupport, causes: CommandLine Error: Option 'view-background' registered more than once! list(REMOVE_ITEM LLVM_LIBS_LIST "-lLLVMSupport") # Remove element endif() if(MSVC) list(REMOVE_ITEM CLANG_LIBS "-lFrontend") endif() endif() include_directories(${CMAKE_BINARY_DIR}) include_directories(${CLANG_INCLUDE_DIRS} ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/src) link_directories("${LLVM_INSTALL_PREFIX}/lib" ${LLVM_LIBRARY_DIRS}) macro(link_to_llvm name llvm_libs) foreach(clang_lib ${CLANG_LIBS}) if(MSVC) get_filename_component(LIB_FILENAME ${clang_lib} NAME) if(LIB_FILENAME STREQUAL "clangFrontend.lib") # On MSVC we don't link against clangFrontend.lib, instead we link against clang.exe (via clang.lib) # Otherwise the clazy plugin would have it's own plugin registry and clang wouldn't see it. # This way clazy registers with clang. continue() endif() endif() target_link_libraries(${name} ${clang_lib}) endforeach() foreach(llvm_lib ${llvm_libs}) target_link_libraries(${name} ${llvm_lib}) endforeach() foreach(user_lib ${USER_LIBS}) target_link_libraries(${name} ${user_lib}) endforeach() foreach(llvm_system_lib ${LLVM_SYSTEM_LIBS}) target_link_libraries(${name} ${llvm_system_lib}) endforeach() if(WIN32) target_link_libraries(${name} version.lib) endif() endmacro() macro(add_clang_plugin name) set(srcs ${ARGN}) add_library(${name} SHARED ${srcs}) if(SYMBOL_FILE) set_target_properties(${name} PROPERTIES LINK_FlAGS "-exported_symbols_list ${SYMBOL_FILE}") endif() link_to_llvm(${name} "${LLVM_LIBS_LIST}") if(MSVC) target_link_libraries(${name} ${CLANG_LIBRARY_IMPORT}) # Link against clang.exe to share the plugin registry endif() if(CLAZY_BUILD_UTILS_LIB) target_link_libraries(${name} clazylib) endif() endmacro() if(CLAZY_BUILD_UTILS_LIB) # clazylib version set(clazylib_VERSION_MAJOR 0) set(clazylib_VERSION_MINOR 1) # Enable the full x.y.z version only for release versions set(clazylib_VERSION_PATCH 0) set(clazylib_VERSION ${clazylib_VERSION_MAJOR}.${clazylib_VERSION_MINOR}) add_library(clazylib SHARED ${CLAZY_LIB_SRC}) link_to_llvm(clazylib "${LLVM_LIBS_LIST}") generate_export_header(clazylib) set_target_properties(clazylib PROPERTIES VERSION ${clazylib_VERSION} SOVERSION ${clazylib_VERSION_MAJOR}) install(TARGETS clazylib EXPORT LibClazyExport RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) endif() set(SYMBOL_FILE Lazy.exports) if (NOT CLAZY_BUILD_WITH_CLANG) add_clang_plugin(ClangLazy ${CLAZY_PLUGIN_SRCS}) set_target_properties(ClangLazy PROPERTIES LINKER_LANGUAGE CXX PREFIX "" ) install(TARGETS ClangLazy RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) set(SHARE_INSTALL_DIR ${CMAKE_INSTALL_DATAROOTDIR} CACHE STRING "Share directory name") if(NOT WIN32) configure_file(${CMAKE_CURRENT_LIST_DIR}/clazy.cmake ${CMAKE_BINARY_DIR}/clazy @ONLY) install(FILES ${CMAKE_BINARY_DIR}/clazy DESTINATION bin PERMISSIONS OWNER_WRITE OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) else() install(FILES ${CMAKE_CURRENT_LIST_DIR}/clazy.bat DESTINATION bin PERMISSIONS OWNER_WRITE OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) if(MSVC) install(FILES ${CMAKE_CURRENT_LIST_DIR}/clazy-cl.bat DESTINATION bin PERMISSIONS OWNER_WRITE OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) endif() endif() # Install the explanation README's set(DOC_INSTALL_DIR ${SHARE_INSTALL_DIR}/clazy/doc) - file(GLOB README_LEVEL0_FILES src/checks/level0/README-*) - file(GLOB README_LEVEL1_FILES src/checks/level1/README-*) - file(GLOB README_LEVEL2_FILES src/checks/level2/README-*) - file(GLOB README_LEVEL3_FILES src/checks/level3/README-*) - file(GLOB README_manuallevel_FILES src/checks/manuallevel/README-*) + + include(${CMAKE_CURRENT_LIST_DIR}/readmes.cmake) + install(FILES ${README_LEVEL0_FILES} DESTINATION ${DOC_INSTALL_DIR}/level0) install(FILES ${README_LEVEL1_FILES} DESTINATION ${DOC_INSTALL_DIR}/level1) install(FILES ${README_LEVEL2_FILES} DESTINATION ${DOC_INSTALL_DIR}/level2) install(FILES ${README_LEVEL3_FILES} DESTINATION ${DOC_INSTALL_DIR}/level3) install(FILES ${README_manuallevel_FILES} DESTINATION ${DOC_INSTALL_DIR}/manuallevel) # Install more doc files install(FILES README.md COPYING-LGPL2.txt checks.json DESTINATION ${DOC_INSTALL_DIR}) # Build docs set(MAN_INSTALL_DIR "man/man1") add_subdirectory(docs) if(CLAZY_BUILD_UTILS_LIB) # Install public headers set(CLAZY_LIB_INCLUDES src/AccessSpecifierManager.h src/checkbase.h src/checkmanager.h src/clazy_export.h src/clazy_stl.h src/ContextUtils.h src/FixItUtils.h src/HierarchyUtils.h src/LoopUtils.h src/MacroUtils.h src/QtUtils.h src/SuppressionManager.h src/StmtBodyRange.h src/StringUtils.h src/TemplateUtils.h src/TypeUtils.h src/Utils.h src/ClazyContext.h ) install(FILES ${CLAZY_LIB_INCLUDES} DESTINATION include/clazy) endif() # rpath set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE) set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) list(FIND CMAKE_PLATFORM_IMPLICIT_LINK_DIRECTORIES "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" isSystemDir) if("${isSystemDir}" STREQUAL "-1") set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") endif("${isSystemDir}" STREQUAL "-1") # Build clazy-standalone add_executable(clazy-standalone ${CLAZY_STANDALONE_SRCS}) if(MSVC) # On MSVC clang-standalone crashes with a meaningless backtrace if linked to ClangLazy.dll target_link_libraries(clazy-standalone clangFrontend) else() target_link_libraries(clazy-standalone ClangLazy) endif() link_to_llvm(clazy-standalone "${CLAZY_STANDALONE_LLVM_LIBS}") install(TARGETS clazy-standalone DESTINATION bin PERMISSIONS OWNER_WRITE OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) set(CPACK_PACKAGE_VERSION_MAJOR ${CLAZY_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${CLAZY_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${CLAZY_VERSION_PATCH}) include(CPack) else() set(LLVM_LINK_COMPONENTS Support ) add_clang_library(clazyPlugin ${CLAZY_PLUGIN_SRCS} LINK_LIBS clangFrontend clangDriver clangCodeGen clangSema clangAnalysis clangRewriteFrontend clangRewrite clangAST clangASTMatchers clangParse clangLex clangBasic clangARCMigrate clangEdit clangFrontendTool clangRewrite clangSerialization clangTooling clangStaticAnalyzerCheckers clangStaticAnalyzerCore clangStaticAnalyzerFrontend ) add_executable(clazy-standalone ${CLAZY_STANDALONE_SRCS}) target_link_libraries(clazy-standalone clazyPlugin) install(TARGETS clazy-standalone DESTINATION bin PERMISSIONS OWNER_WRITE OWNER_EXECUTE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_READ WORLD_EXECUTE) endif() diff --git a/README.md b/README.md index eb7a2e3..91f28a6 100644 --- a/README.md +++ b/README.md @@ -1,466 +1,466 @@ *WARNING:* master is the development branch. Please use the v1.3 tag. clazy v1.3 =========== clazy is a compiler plugin which allows clang to understand Qt semantics. You get more than 50 Qt related compiler warnings, ranging from unneeded memory allocations to misusage of API, including fix-its for automatic refactoring. Table of contents ================= * [Source Code](#source-code) * [Build Instructions](#build-instructions) * [Linux](#linux) * [Install dependencies](#install-dependencies) * [Build and install clang](#build-and-install-clang) * [Build clazy](#build-clazy) * [Windows](#windows) * [3rdparty pre-built msvc2015 clang and clazy binaries](#3rdparty-pre-built-msvc2015-clang-and-clazy-binaries) * [Build and install clang](#build-and-install-clang-1) * [Build clazy](#build-clazy-1) * [macOS with MacPorts](#macos-with-macports) * [Install clang](#install-clang) * [Build clazy](#build-clazy-2) * [macOS with Homebrew](#macos-with-homebrew) * [Install clang](#install-clang-1) * [Build clazy](#build-clazy-3) * [Setting up your project to build with clazy](#setting-up-your-project-to-build-with-clazy) * [List of checks](#list-of-checks) * [Selecting which checks to enable](#selecting-which-checks-to-enable) * [Example via env variable](#example-via-env-variable) * [Example via compiler argument](#example-via-compiler-argument) * [clang-standalone and JSON database support](#clang-standalone-and-json-database-support) * [Enabling Fixits](#enabling-fixits) * [Troubleshooting](#troubleshooting) * [Qt4 compatibility mode](#qt4-compatibility-mode) * [Reducing warning noise](#reducing-warning-noise) * [Reporting bugs and wishes](#reporting-bugs-and-wishes) * [Authors](#authors) * [Contributing patches](#contributing-patches) # Source Code You can get clazy from: - - git@git.kde.org:clazy - git://anongit.kde.org/clazy # Build Instructions ## Linux ### Install dependencies - OpenSUSE tumbleweed: `zypper install cmake git-core llvm llvm-devel llvm-clang llvm-clang-devel` - Ubuntu-16.04: `apt install g++ cmake clang llvm-dev git-core libclang-3.8-dev qtbase5-dev` - Archlinux: `pacman -S make llvm clang python2 cmake qt5-base git gcc` - Fedora: be sure to *remove* the llvm-static package and only install the one with dynamic libraries - Other distros: Check llvm/clang build docs. ### Build and install clang clang and LLVM >= 3.9 are required. Use clazy v1.1 if you need 3.7 support, or v1.3 for 3.8 support. If your distro provides clang then you can skip this step. ``` $ git clone https://github.com/llvm-mirror/llvm.git $ cd /tools/ && git clone https://github.com/llvm-mirror/clang.git $ cd /projects && git clone https://github.com/llvm-mirror/compiler-rt.git $ mkdir /build && cd /build $ cmake -DCMAKE_INSTALL_PREFIX= -DLLVM_TARGETS_TO_BUILD=X86 -DCMAKE_BUILD_TYPE=Release .. $ make -jX && make install ``` ### Build clazy ``` $ cd clazy/ $ cmake -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE=Release $ make && make install ``` See troubleshooting section if you have problems. ## Windows ### 3rdparty pre-built msvc2015 clang and clazy binaries Building for Windows is a lengthy and tedious task, therefore the maintainer won't be creating them anymore on his free/KDE time. KDAB however has offered to produce these binaries and they will appear on their website. If you really want to build clang and clazy yourself then read on, otherwise skip the building topic. ### Build and install clang These instructions assume your terminal is suitable for development (msvc2015). jom, nmake, git, cmake and cl should be in your PATH. clang and LLVM >= 4.0 are required. Be sure to pass -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON to CMake when building LLVM, otherwise clazy won't work. ``` > git clone https://github.com/llvm-mirror/llvm.git > cd \tools\ && git clone https://github.com/llvm-mirror/clang.git > git checkout release_40 > cd clang > git checkout release_40 > mkdir \build && cd \build > cmake -DCMAKE_INSTALL_PREFIX=c:\my_install_folder\llvm\ -DLLVM_TARGETS_TO_BUILD="X86" -DLLVM_EXPORT_SYMBOLS_FOR_PLUGINS=ON -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles JOM" .. > jom > nmake install > Add c:\my_install_folder\llvm\bin\ to PATH ``` ### Build clazy Be sure to point CLANG_LIBRARY_IMPORT to clang.lib. It's probably inside your LLVM build dir since it doesn't get installed. ``` > cd clazy\ > cmake -DCMAKE_INSTALL_PREFIX=c:\my_install_folder\llvm\ -DCLANG_LIBRARY_IMPORT=C:\path\to\llvm-build\lib\clang.lib -DCMAKE_BUILD_TYPE=Release -G "NMake Makefiles JOM" > jom && nmake install ``` ## macOS with MacPorts ### Install clang ``` $ sudo port install clang-3.9 llvm-3.9 $ sudo ln -sf /opt/local/bin/llvm-config-mp-3.9 /opt/local/bin/llvm-config $ sudo port select --set clang mp-clang-3.9 ``` ### Build clazy ``` $ export CXX=clang++ $ cmake $ make $ make install ``` ## macOS with Homebrew The recommended way is to build clazy yourself, but alternatively you can try user recipes, such as: ``` $ brew install haraldf/kf5/clazy ``` for stable branch, or for master: ``` $ brew install haraldf/kf5/clazy --HEAD ``` As these are not verified or tested by the clazy developers please don't report bugs to us. For building yourself, read on. You'll have to install clang and build clazy from source. ### Install clang ``` $ brew install --with-clang llvm ``` ### Build clazy ``` $ export CXX=clang++ $ export LLVM_ROOT=/usr/local/opt/llvm $ cmake $ make $ make install ``` # Setting up your project to build with clazy Note: Wherever `clazy` it mentioned, replace with `clazy-cl.bat` if you're on Windows. Note: If you prefer running clazy over a JSON compilation database instead of using it as a plugin, jump to [clazy-standalone](#clang-standalone-and-json-database-support). You should now have the clazy command available to you, in `/bin/`. Compile your programs with it instead of clang++/g++. Note that this command is just a convenience wrapper which calls: `clang++ -Xclang -load -Xclang ClangLazy.so -Xclang -add-plugin -Xclang clang-lazy` If you have multiple versions of clang installed (say clang++-3.8 and clang++-3.9) you can choose which one to use by setting the CLANGXX environment variable, like so: `export CLANGXX=clang++-3.8; clazy` To build a CMake project use: `cmake . -DCMAKE_CXX_COMPILER=clazy` and rebuild. To make it the compiler for qmake projects, just run qmake like: `qmake -spec linux-clang QMAKE_CXX="clazy"` Alternatively, if you want to use clang directly, without the wrapper: `qmake -spec linux-clang QMAKE_CXXFLAGS="-Xclang -load -Xclang ClangLazy.so -Xclang -add-plugin -Xclang clang-lazy"` You can also edit mkspecs/common/clang.conf and change QMAKE_CXX to clazy instead of clang++ and run qmake -spec linux-clang It's recommended that you disable pre-compiled headers and don't use ccache. You're all set, clazy will now run some checks on your project, but not all of them. Read on if you want to enable/disable which checks are run. # List of checks There are many checks and they are divided in levels: - level0: Very stable checks, 99.99% safe, mostly no false-positives, very desirable - level1: The default level. Very similar to level 0, slightly more false-positives but very few. - level2: Also very few false-positives, but contains noisy checks which not everyone agree should be default. - level3: Contains checks with high rate of false-positives. - manual: Checks here need to be enabled explicitly, as they don't belong to any level. Checks here are very stable and have very few false-positives. clazy runs all checks from level1 by default. - Checks from Manual Level: - - [container-inside-loop](src/checks/manuallevel/README-container-inside-loop.md) - - [inefficient-qlist](src/checks/manuallevel/README-inefficient-qlist.md) - - [isempty-vs-count](src/checks/manuallevel/README-isempty-vs-count.md) - - [qhash-with-char-pointer-key](src/checks/manuallevel/README-qhash-with-char-pointer-key.md) - - [qstring-varargs](src/checks/manuallevel/README-qstring-varargs.md) - - [qt-keywords](src/checks/manuallevel/README-qt-keywords.md) (fix-qt-keywords) - - [qt4-qstring-from-array](src/checks/manuallevel/README-qt4-qstring-from-array.md) (fix-qt4-qstring-from-array) - - [tr-non-literal](src/checks/manuallevel/README-tr-non-literal.md) - - [unneeded-cast](src/checks/manuallevel/README-unneeded-cast.md) + - [container-inside-loop](docs/checks/README-container-inside-loop.md) + - [inefficient-qlist](docs/checks/README-inefficient-qlist.md) + - [isempty-vs-count](docs/checks/README-isempty-vs-count.md) + - [qhash-with-char-pointer-key](docs/checks/README-qhash-with-char-pointer-key.md) + - [qstring-varargs](docs/checks/README-qstring-varargs.md) + - [qt-keywords](docs/checks/README-qt-keywords.md) (fix-qt-keywords) + - [qt4-qstring-from-array](docs/checks/README-qt4-qstring-from-array.md) (fix-qt4-qstring-from-array) + - [tr-non-literal](docs/checks/README-tr-non-literal.md) + - [unneeded-cast](docs/checks/README-unneeded-cast.md) - Checks from Level 0: - - [connect-by-name](src/checks/level0/README-connect-by-name.md) - - [connect-non-signal](src/checks/level0/README-connect-non-signal.md) - - [connect-not-normalized](src/checks/level0/README-connect-not-normalized.md) - - [container-anti-pattern](src/checks/level0/README-container-anti-pattern.md) - - [fully-qualified-moc-types](src/checks/level0/README-fully-qualified-moc-types.md) - - [lambda-in-connect](src/checks/level0/README-lambda-in-connect.md) - - [lambda-unique-connection](src/checks/level0/README-lambda-unique-connection.md) - - [mutable-container-key](src/checks/level0/README-mutable-container-key.md) - - [qcolor-from-literal](src/checks/level0/README-qcolor-from-literal.md) - - [qdatetime-utc](src/checks/level0/README-qdatetime-utc.md) (fix-qdatetime-utc) - - [qenums](src/checks/level0/README-qenums.md) - - [qfileinfo-exists](src/checks/level0/README-qfileinfo-exists.md) - - [qgetenv](src/checks/level0/README-qgetenv.md) (fix-qgetenv) - - [qmap-with-pointer-key](src/checks/level0/README-qmap-with-pointer-key.md) - - [qstring-arg](src/checks/level0/README-qstring-arg.md) - - [qstring-insensitive-allocation](src/checks/level0/README-qstring-insensitive-allocation.md) - - [qstring-ref](src/checks/level0/README-qstring-ref.md) (fix-missing-qstringref) - - [qt-macros](src/checks/level0/README-qt-macros.md) - - [qvariant-template-instantiation](src/checks/level0/README-qvariant-template-instantiation.md) - - [strict-iterators](src/checks/level0/README-strict-iterators.md) - - [temporary-iterator](src/checks/level0/README-temporary-iterator.md) - - [unused-non-trivial-variable](src/checks/level0/README-unused-non-trivial-variable.md) - - [writing-to-temporary](src/checks/level0/README-writing-to-temporary.md) - - [wrong-qevent-cast](src/checks/level0/README-wrong-qevent-cast.md) - - [wrong-qglobalstatic](src/checks/level0/README-wrong-qglobalstatic.md) + - [connect-by-name](docs/checks/README-connect-by-name.md) + - [connect-non-signal](docs/checks/README-connect-non-signal.md) + - [connect-not-normalized](docs/checks/README-connect-not-normalized.md) + - [container-anti-pattern](docs/checks/README-container-anti-pattern.md) + - [fully-qualified-moc-types](docs/checks/README-fully-qualified-moc-types.md) + - [lambda-in-connect](docs/checks/README-lambda-in-connect.md) + - [lambda-unique-connection](docs/checks/README-lambda-unique-connection.md) + - [mutable-container-key](docs/checks/README-mutable-container-key.md) + - [qcolor-from-literal](docs/checks/README-qcolor-from-literal.md) + - [qdatetime-utc](docs/checks/README-qdatetime-utc.md) (fix-qdatetime-utc) + - [qenums](docs/checks/README-qenums.md) + - [qfileinfo-exists](docs/checks/README-qfileinfo-exists.md) + - [qgetenv](docs/checks/README-qgetenv.md) (fix-qgetenv) + - [qmap-with-pointer-key](docs/checks/README-qmap-with-pointer-key.md) + - [qstring-arg](docs/checks/README-qstring-arg.md) + - [qstring-insensitive-allocation](docs/checks/README-qstring-insensitive-allocation.md) + - [qstring-ref](docs/checks/README-qstring-ref.md) (fix-missing-qstringref) + - [qt-macros](docs/checks/README-qt-macros.md) + - [qvariant-template-instantiation](docs/checks/README-qvariant-template-instantiation.md) + - [strict-iterators](docs/checks/README-strict-iterators.md) + - [temporary-iterator](docs/checks/README-temporary-iterator.md) + - [unused-non-trivial-variable](docs/checks/README-unused-non-trivial-variable.md) + - [writing-to-temporary](docs/checks/README-writing-to-temporary.md) + - [wrong-qevent-cast](docs/checks/README-wrong-qevent-cast.md) + - [wrong-qglobalstatic](docs/checks/README-wrong-qglobalstatic.md) - Checks from Level 1: - - [auto-unexpected-qstringbuilder](src/checks/level1/README-auto-unexpected-qstringbuilder.md) (fix-auto-unexpected-qstringbuilder) - - [child-event-qobject-cast](src/checks/level1/README-child-event-qobject-cast.md) - - [connect-3arg-lambda](src/checks/level1/README-connect-3arg-lambda.md) - - [const-signal-or-slot](src/checks/level1/README-const-signal-or-slot.md) - - [detaching-temporary](src/checks/level1/README-detaching-temporary.md) - - [foreach](src/checks/level1/README-foreach.md) - - [incorrect-emit](src/checks/level1/README-incorrect-emit.md) - - [inefficient-qlist-soft](src/checks/level1/README-inefficient-qlist-soft.md) - - [install-event-filter](src/checks/level1/README-install-event-filter.md) - - [non-pod-global-static](src/checks/level1/README-non-pod-global-static.md) - - [overridden-signal](src/checks/level1/README-overridden-signal.md) - - [post-event](src/checks/level1/README-post-event.md) - - [qdeleteall](src/checks/level1/README-qdeleteall.md) - - [qhash-namespace](src/checks/level1/README-qhash-namespace.md) - - [qlatin1string-non-ascii](src/checks/level1/README-qlatin1string-non-ascii.md) - - [qproperty-without-notify](src/checks/level1/README-qproperty-without-notify.md) - - [qstring-left](src/checks/level1/README-qstring-left.md) - - [range-loop](src/checks/level1/README-range-loop.md) - - [returning-data-from-temporary](src/checks/level1/README-returning-data-from-temporary.md) - - [rule-of-two-soft](src/checks/level1/README-rule-of-two-soft.md) - - [skipped-base-method](src/checks/level1/README-skipped-base-method.md) - - [virtual-signal](src/checks/level1/README-virtual-signal.md) + - [auto-unexpected-qstringbuilder](docs/checks/README-auto-unexpected-qstringbuilder.md) (fix-auto-unexpected-qstringbuilder) + - [child-event-qobject-cast](docs/checks/README-child-event-qobject-cast.md) + - [connect-3arg-lambda](docs/checks/README-connect-3arg-lambda.md) + - [const-signal-or-slot](docs/checks/README-const-signal-or-slot.md) + - [detaching-temporary](docs/checks/README-detaching-temporary.md) + - [foreach](docs/checks/README-foreach.md) + - [incorrect-emit](docs/checks/README-incorrect-emit.md) + - [inefficient-qlist-soft](docs/checks/README-inefficient-qlist-soft.md) + - [install-event-filter](docs/checks/README-install-event-filter.md) + - [non-pod-global-static](docs/checks/README-non-pod-global-static.md) + - [overridden-signal](docs/checks/README-overridden-signal.md) + - [post-event](docs/checks/README-post-event.md) + - [qdeleteall](docs/checks/README-qdeleteall.md) + - [qhash-namespace](docs/checks/README-qhash-namespace.md) + - [qlatin1string-non-ascii](docs/checks/README-qlatin1string-non-ascii.md) + - [qproperty-without-notify](docs/checks/README-qproperty-without-notify.md) + - [qstring-left](docs/checks/README-qstring-left.md) + - [range-loop](docs/checks/README-range-loop.md) + - [returning-data-from-temporary](docs/checks/README-returning-data-from-temporary.md) + - [rule-of-two-soft](docs/checks/README-rule-of-two-soft.md) + - [skipped-base-method](docs/checks/README-skipped-base-method.md) + - [virtual-signal](docs/checks/README-virtual-signal.md) - Checks from Level 2: - - [base-class-event](src/checks/level2/README-base-class-event.md) - - [copyable-polymorphic](src/checks/level2/README-copyable-polymorphic.md) - - [ctor-missing-parent-argument](src/checks/level2/README-ctor-missing-parent-argument.md) - - [function-args-by-ref](src/checks/level2/README-function-args-by-ref.md) - - [function-args-by-value](src/checks/level2/README-function-args-by-value.md) - - [global-const-char-pointer](src/checks/level2/README-global-const-char-pointer.md) - - [implicit-casts](src/checks/level2/README-implicit-casts.md) - - [missing-qobject-macro](src/checks/level2/README-missing-qobject-macro.md) - - [missing-typeinfo](src/checks/level2/README-missing-typeinfo.md) - - [old-style-connect](src/checks/level2/README-old-style-connect.md) (fix-old-style-connect) - - [qstring-allocations](src/checks/level2/README-qstring-allocations.md) (fix-qlatin1string-allocations,fix-fromLatin1_fromUtf8-allocations,fix-fromCharPtrAllocations) - - [returning-void-expression](src/checks/level2/README-returning-void-expression.md) - - [rule-of-three](src/checks/level2/README-rule-of-three.md) - - [static-pmf](src/checks/level2/README-static-pmf.md) - - [virtual-call-ctor](src/checks/level2/README-virtual-call-ctor.md) + - [base-class-event](docs/checks/README-base-class-event.md) + - [copyable-polymorphic](docs/checks/README-copyable-polymorphic.md) + - [ctor-missing-parent-argument](docs/checks/README-ctor-missing-parent-argument.md) + - [function-args-by-ref](docs/checks/README-function-args-by-ref.md) + - [function-args-by-value](docs/checks/README-function-args-by-value.md) + - [global-const-char-pointer](docs/checks/README-global-const-char-pointer.md) + - [implicit-casts](docs/checks/README-implicit-casts.md) + - [missing-qobject-macro](docs/checks/README-missing-qobject-macro.md) + - [missing-typeinfo](docs/checks/README-missing-typeinfo.md) + - [old-style-connect](docs/checks/README-old-style-connect.md) (fix-old-style-connect) + - [qstring-allocations](docs/checks/README-qstring-allocations.md) (fix-qlatin1string-allocations,fix-fromLatin1_fromUtf8-allocations,fix-fromCharPtrAllocations) + - [returning-void-expression](docs/checks/README-returning-void-expression.md) + - [rule-of-three](docs/checks/README-rule-of-three.md) + - [static-pmf](docs/checks/README-static-pmf.md) + - [virtual-call-ctor](docs/checks/README-virtual-call-ctor.md) - Checks from Level 3: - - [assert-with-side-effects](src/checks/level3/README-assert-with-side-effects.md) - - [detaching-member](src/checks/level3/README-detaching-member.md) - - [reserve-candidates](src/checks/level3/README-reserve-candidates.md) - - [thread-with-slots](src/checks/level3/README-thread-with-slots.md) + - [assert-with-side-effects](docs/checks/README-assert-with-side-effects.md) + - [detaching-member](docs/checks/README-detaching-member.md) + - [reserve-candidates](docs/checks/README-reserve-candidates.md) + - [thread-with-slots](docs/checks/README-thread-with-slots.md) # Selecting which checks to enable You may want to choose which checks to enable before starting to compile. If you don't specify anything then all checks from level0 and level1 will run. To specify a list of checks to run, or to choose a level, you can use the `CLAZY_CHECKS` env variable or pass arguments to the compiler. You can disable checks by prefixing with `no-`, in case you don't want all checks from a given level. ## Example via env variable ``` export CLAZY_CHECKS="unneeded-cast,qmap-with-key-pointer,virtual-call-ctor" # Enables only these 3 checks export CLAZY_CHECKS="level0,no-qenums" # Enables all checks from level0, except for qenums export CLAZY_CHECKS="level0,detaching-temporary" # Enables all from level0 and also detaching-temporary ``` ## Example via compiler argument `clazy -Xclang -plugin-arg-clang-lazy -Xclang level0,detaching-temporary` Don't forget to re-run cmake/qmake/etc if you altered the c++ flags to specify flags. # clang-standalone and JSON database support The `clazy-standalone` binary allows you to run clazy over a compilation database JSON file, in the same way you would use `clang-tidy` or other clang tooling. This way you don't need to build your application, only the static analysis is performed. `clazy-standalone` supports the same env variables as the clazy plugin. You can also specify a list of checks via the `-checks` argument. Running on one cpp file: `clazy-standalone -checks=install-event-filter,qmap-with-pointer-key,level0 -p compile_commands.json my.file.cpp` Running on all cpp files: `find . -name "*cpp" | xargs clazy-standalone -checks=level2 -p default/compile_commands.json` See https://clang.llvm.org/docs/JSONCompilationDatabase.html for how to generate the compile_commands.json file. Basically it's generated by passing `-DCMAKE_EXPORT_COMPILE_COMMANDS` to CMake, or using [Bear](https://github.com/rizsotto/Bear) to intercept compiler commands, or, if you're using `qbs`: `qbs generate --generator clangdb` **Note:** Be sure the clazy-standalone binary is located in the same folder as the clang binary, otherwise it will have trouble finding builtin headers, like stddef.h. Alternatively, you can symlink to the folder containing the builtin headers: (Assuming clazy was built with `-DCMAKE_INSTALL_PREFIX=/myprefix/`) ``` $ touch foo.c && clang++ '-###' -c foo.c 2>&1 | tr ' ' '\n' | grep -A1 resource "-resource-dir" "/usr/bin/../lib/clang/4.0.1" # this is the interesting path (without the version) $ ln -sf /usr/bin/../lib/clang/ /myprefix/lib/clang $ ln -sf /usr/bin/../include/c++/ /myprefix/include/c++ # Required on macOS ``` If that doesn't work, run `clang -v` and check what's the InstalledDir. Move clazy-standalone to that folder. `clang-tidy` support will be added after is fixed. # Enabling Fixits Some checks support fixits, in which clazy will re-write your source files whenever it can fix something. You can enable a fixit through the env variable, for example: `export CLAZY_FIXIT="fix-qlatin1string-allocations"` Only one fixit can be enabled each time. **WARNING**: Backup your code, don't blame me if a fixit is not applied correctly. For better results don't use parallel builds, otherwise a fixit being applied in an header file might be done twice. # Troubleshooting - clang: symbol lookup error: `/usr/lib/x86_64-linux-gnu/ClangLazy.so: undefined symbol: _ZNK5clang15DeclarationName11getAsStringEv`. This is due to mixing ABIs. Your clang/llvm was compiled with the [new gcc c++ ABI][1] but you compiled the clazy plugin with clang (which uses [the old ABI][2]). The solution is to build the clazy plugin with gcc or use a distro which hasn't migrated to gcc5 ABI yet, such as archlinux. [1]: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html [2]: https://llvm.org/bugs/show_bug.cgi?id=23529 - [Fedora] cmake can't find LLVM ? Try building llvm/clang yourself (There are reports that /usr/share/llvm/cmake/LLVM-Config.cmake is buggy). - [Fedora] CommandLine Error: `Option 'opt-bisect-limit' registered more than once!` Remove the llvm-static package and use the dynamically linked libraries instead - Some checks are mysteriously not producing warnings or not applying fixits ? Check if you have ccache interfering and turn it off. - fatal error: 'stddef.h' file not found, while using `clazy-standalone` Be sure the clazy-standalone binary is located in the same folder as the clang binary. - Be sure to disble pch. - macOS: Be sure you're not using Apple Clang - Windows: fatal error LNK1112: module machine type ‘X86’ conflicts with target machine type ‘x64’ If you're building in 32-bit, open clazy-cl.bat and insert a -m32 argument. Should read: %~dp0\clang\clang.exe –driver-mode=cl -m32 (...) # Qt4 compatibility mode When running on codebases that must still compile with Qt4, you can pass `--qt4compat` (a convenience option equivalent to passing `-Xclang -plugin-arg-clang-lazy -Xclang qt4-compat`) to disable checks that only make sense with Qt5. For example, to build a CMake project with Qt4 compatibility use: `CXX="clazy --qt4compat"; cmake .` and rebuild. # Reducing warning noise If you think you found a false-positive, file a bug report. But do make sure to test first without icecc/distcc enabled. If you want to suppress warnings from headers of Qt or 3rd party code, include them with `-isystem` instead of `-I`. Alternatively you can set the CLAZY_HEADER_FILTER env variable to a regexp matching the path where you want warnings. You can also suppress individual warnings by file or by line by inserting comments: - To disable clazy in a specific source file, insert this comment, anywhere in the file: `// clazy:skip` - To disable specific checks in a source file, insert a comment such as `// clazy:excludeall=check1,check2` - To disable specific checks in specific source lines, insert a comment in the same line as the warning: `(...) // clazy:exclude=check1,check2` Don't include the `clazy-` prefix. If, for example, you want to disable qstring-allocations you would write: `// clazy:exclude=qstring-allocations` not `clazy-qstring-allocations`. # Reporting bugs and wishes - bug tracker: - IRC: #kde-clazy (freenode) - E-mail: # Authors - Sérgio Martins with contributions from: - Allen Winter - Kevin Funk - Mathias Hasselmann - Laurent Montel - Albert Astals Cid - Aurélien Gâteau - Hannah von Reth - Volker Krause - Christian Ehrlicher and thanks to: - Klarälvdalens Datakonsult AB (), for letting me work on clazy as a research project # Contributing patches New features go to master and bug fixes go to 1.3 branch. The prefered way to contributing is by using KDE's phabricator, see: - - If you rather just create a pull request in https://github.com/KDE/clazy for a drive-by change, it's also fine, but beware that the maintainer might forget to check on github and the KDE bot will close the PR. In that case just send a reminder to the maintainer (smartins at kde.org). diff --git a/dev-scripts/generate.py b/dev-scripts/generate.py index e63ae84..1b7633e 100755 --- a/dev-scripts/generate.py +++ b/dev-scripts/generate.py @@ -1,510 +1,548 @@ #!/usr/bin/env python _license_text = \ """/* This file is part of the clazy static checker. Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: Sérgio Martins This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ """ import sys, os, json, argparse, datetime, io from shutil import copyfile CHECKS_FILENAME = 'checks.json' _checks = [] _specified_check_names = [] _available_categories = [] def checkSortKey(check): return str(check.level) + check.name def level_num_to_enum(n): if n == -1: return 'ManualCheckLevel' if n >= 0 and n <= 3: return 'CheckLevel' + str(n) return 'CheckLevelUndefined' def level_num_to_name(n): if n == -1: return 'Manual Level' if n >= 0 and n <= 3: return 'Level ' + str(n) return 'undefined' +def level_num_to_cmake_readme_variable(n): + if n == -1: + return 'README_manuallevel_FILES' + if n >= 0 and n <= 3: + return 'README_LEVEL%s_FILES' % str(n) + + return 'undefined' + def clazy_source_path(): return os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/..") + "/" def templates_path(): return clazy_source_path() + "dev-scripts/templates/" +def docs_relative_path(): + return "docs/checks/" + +def docs_path(): + return clazy_source_path() + docs_relative_path() + def read_file(filename): f = io.open(filename, 'r', newline='\n', encoding='utf8') contents = f.read() f.close() return contents def write_file(filename, contents): f = io.open(filename, 'w', newline='\n', encoding='utf8') f.write(contents) f.close() def get_copyright(): year = datetime.datetime.now().year author = os.getenv('GIT_AUTHOR_NAME', 'Author') email = os.getenv('GIT_AUTHOR_EMAIL', 'your@email') return "Copyright (C) %s %s <%s>" % (year, author, email) class Check: def __init__(self): self.name = "" self.class_name = "" self.level = 0 self.categories = [] self.minimum_qt_version = 40000 # Qt 4.0.0 self.fixits = [] self.visits_stmts = False self.visits_decls = False self.ifndef = "" def include(self): # Returns for example: "returning-void-expression.h" oldstyle_headername = (self.name + ".h").replace('-', '') if os.path.exists(self.path() + oldstyle_headername): return oldstyle_headername return self.name + '.h' def qualified_include(self): # Returns for example: "checks/level2/returning-void-expression.h" return self.basedir() + self.include() def qualified_cpp_filename(self): # Returns for example: "checks/level2/returning-void-expression.cpp" return self.basedir() + self.cpp_filename() def cpp_filename(self): # Returns for example: "returning-void-expression.cpp" filename = self.include() filename = filename.replace(".h", ".cpp") return filename def path(self): return clazy_source_path() + self.basedir(True) + "/" def basedir(self, with_src=False): level = 'level' + str(self.level) if self.level == -1: level = 'manuallevel' if with_src: return "src/checks/" + level + '/' return "checks/" + level + '/' def readme_name(self): return "README-" + self.name + ".md" def readme_path(self): - return clazy_source_path() + self.basedir(True) + self.readme_name() + return docs_path() + self.readme_name() def supportsQt4(self): return self.minimum_qt_version < 50000 def get_class_name(self): if self.class_name: return self.class_name # Deduce the class name splitted = self.name.split('-') classname = "" for word in splitted: if word == 'qt': word = 'Qt' else: word = word.title() if word.startswith('Q'): word = 'Q' + word[1:].title() classname += word return classname def valid_name(self): if self.name in ['clazy']: return False if self.name.startswith('level'): return False if self.name.startswith('fix'): return False return True def fixits_text(self): if not self.fixits: return "" text = "" fixitnames = [] for f in self.fixits: fixitnames.append("fix-" + f) text = ','.join(fixitnames) return "(" + text + ")" def include_guard(self): guard = self.name.replace('-', '_') return guard.upper() def load_json(filename): jsonContents = read_file(filename) decodedJson = json.loads(jsonContents) if 'checks' not in decodedJson: print("No checks found in " + filename) return False checks = decodedJson['checks'] global _available_categories, _checks, _specified_check_names if 'available_categories' in decodedJson: _available_categories = decodedJson['available_categories'] for check in checks: c = Check() try: c.name = check['name'] c.level = check['level'] if 'categories' in check: c.categories = check['categories'] for cat in c.categories: if cat not in _available_categories: print('Unknown category ' + cat) return False except KeyError: print("Missing mandatory field while processing " + str(check)) return False if _specified_check_names and c.name not in _specified_check_names: continue if 'class_name' in check: c.class_name = check['class_name'] if 'ifndef' in check: c.ifndef = check['ifndef'] if 'minimum_qt_version' in check: c.minimum_qt_version = check['minimum_qt_version'] if 'visits_stmts' in check: c.visits_stmts = check['visits_stmts'] if 'visits_decls' in check: c.visits_decls = check['visits_decls'] if 'fixits' in check: for fixit in check['fixits']: if 'name' not in fixit: print('fixit doesnt have a name. check=' + str(check)) return False c.fixits.append(fixit['name']) if not c.valid_name(): print("Invalid check name: %s" % (c.name())) return False _checks.append(c) _checks = sorted(_checks, key=checkSortKey) return True def print_checks(checks): for c in checks: print(c.name + " " + str(c.level) + " " + str(c.categories)) #------------------------------------------------------------------------------- def generate_register_checks(checks): text = '#include "checkmanager.h"\n' for c in checks: text += '#include "' + c.qualified_include() + '"\n' text += \ """ template RegisteredCheck check(const char *name, CheckLevel level, RegisteredCheck::Options options = RegisteredCheck::Option_None) { auto factoryFuntion = [name](ClazyContext *context){ return new T(name, context); }; return RegisteredCheck{name, level, factoryFuntion, options}; } void CheckManager::registerChecks() { """ for c in checks: qt4flag = "RegisteredCheck::Option_None" if not c.supportsQt4(): qt4flag = "RegisteredCheck::Option_Qt4Incompatible" if c.visits_stmts: qt4flag += " | RegisteredCheck::Option_VisitsStmts" if c.visits_decls: qt4flag += " | RegisteredCheck::Option_VisitsDecls" qt4flag = qt4flag.replace("RegisteredCheck::Option_None |", "") if c.ifndef: text += "#ifndef " + c.ifndef + "\n" text += ' registerCheck(check<%s>("%s", %s, %s));\n' % (c.get_class_name(), c.name, level_num_to_enum(c.level), qt4flag) fixitID = 1 for fixit in c.fixits: text += ' registerFixIt(%d, "%s", "%s");\n' % (fixitID, "fix-" + fixit, c.name) fixitID = fixitID * 2 if c.ifndef: text += "#endif" + "\n" text += "}\n" comment_text = \ """ /** * To add a new check you can either edit this file, or use the python script: * dev-scripts/generate.py > src/Checks.h */ """ text = _license_text + '\n' + comment_text + '\n' + text filename = clazy_source_path() + "src/Checks.h" old_text = read_file(filename) if old_text != text: write_file(filename, text) print("Generated " + filename) return True return False #------------------------------------------------------------------------------- def generate_cmake_file(checks): text = "set(CLAZY_CHECKS_SRCS ${CLAZY_CHECKS_SRCS}\n" checks_with_regexp = [] for level in [-1, 0, 1, 2, 3]: for check in checks: if check.level == level: text += " ${CMAKE_CURRENT_LIST_DIR}/src/" + check.qualified_cpp_filename() + "\n" if check.ifndef == "NO_STD_REGEX": checks_with_regexp.append(check) text += ")\n" if checks_with_regexp: text += "\nif(HAS_STD_REGEX OR CLAZY_BUILD_WITH_CLANG)\n" for check in checks_with_regexp: text += " set(CLAZY_CHECKS_SRCS ${CLAZY_CHECKS_SRCS} ${CMAKE_CURRENT_LIST_DIR}/src/" + check.qualified_cpp_filename() + ")\n" text += "endif()\n" filename = clazy_source_path() + "CheckSources.cmake" old_text = read_file(filename) if old_text != text: write_file(filename, text) print("Generated " + filename) return True return False #------------------------------------------------------------------------------- def create_readmes(checks): generated = False for check in checks: if not os.path.exists(check.readme_path()): existing_readme = search_in_all_levels(check.readme_name()) if existing_readme: contents = read_file(existing_readme) write_file(check.readme_path(), contents) os.remove(existing_readme) print("Moved " + check.readme_name()) else: - contents = read_file(templates_path() + "check-readme.md") contents = contents.replace('[check-name]', check.name) write_file(check.readme_path(), contents) print("Created " + check.readme_path()) generated = True return generated #------------------------------------------------------------------------------- def create_unittests(checks): generated = False for check in checks: unittest_folder = clazy_source_path() + "tests/" + check.name if not os.path.exists(unittest_folder): os.mkdir(unittest_folder) print("Created " + unittest_folder) generated = True configjson_file = unittest_folder + "/config.json" if not os.path.exists(configjson_file): copyfile(templates_path() + "test-config.json", configjson_file) print("Created " + configjson_file) generated = True testmain_file = unittest_folder + "/main.cpp" if not os.path.exists(testmain_file) and check.name != 'non-pod-global-static': copyfile(templates_path() + "test-main.cpp", testmain_file) print("Created " + testmain_file) generated = True return generated #------------------------------------------------------------------------------- def search_in_all_levels(filename): for level in ['manuallevel', 'level0', 'level1', 'level2', 'level3']: complete_filename = clazy_source_path() + 'src/checks/' + level + '/' + filename if os.path.exists(complete_filename): return complete_filename return "" #------------------------------------------------------------------------------- def create_checks(checks): generated = False edit_changelog = False for check in checks: include_file = check.path() + check.include() cpp_file = check.path() + check.cpp_filename() copyright = get_copyright() include_missing = not os.path.exists(include_file) cpp_missing = not os.path.exists(cpp_file) if include_missing: existing_include_path = search_in_all_levels(check.include()) if existing_include_path: # File already exists, but is in another level. Just move it: contents = read_file(existing_include_path) write_file(include_file, contents) os.remove(existing_include_path) print("Moved " + check.include()) else: contents = read_file(templates_path() + 'check.h') contents = contents.replace('%1', check.include_guard()) contents = contents.replace('%2', check.get_class_name()) contents = contents.replace('%3', check.name) contents = contents.replace('%4', copyright) write_file(include_file, contents) print("Created " + include_file) edit_changelog = True generated = True if cpp_missing: existing_cpp_path = search_in_all_levels(check.cpp_filename()) if existing_cpp_path: # File already exists, but is in another level. Just move it: contents = read_file(existing_cpp_path) write_file(cpp_file, contents) os.remove(existing_cpp_path) print("Moved " + check.cpp_filename()) else: contents = read_file(templates_path() + 'check.cpp') contents = contents.replace('%1', check.include()) contents = contents.replace('%2', check.get_class_name()) contents = contents.replace('%3', copyright) write_file(cpp_file, contents) print("Created " + cpp_file) generated = True if edit_changelog: # We created a new check, let's also edit the ChangeLog changelog_file = clazy_source_path() + 'Changelog' contents = read_file(changelog_file) contents += '\n - \n' write_file(changelog_file, contents) print('Edited Changelog') return generated #------------------------------------------------------------------------------- def generate_readme(checks): - filename = clazy_source_path() + "README.md" f = io.open(filename, 'r', newline='\n', encoding='utf8') old_contents = f.readlines(); f.close(); new_text_to_insert = "" for level in ['-1', '0', '1', '2', '3']: new_text_to_insert += "- Checks from %s:" % level_num_to_name(int(level)) + "\n" for c in checks: if str(c.level) == level: fixits_text = c.fixits_text() if fixits_text: fixits_text = " " + fixits_text - new_text_to_insert += " - [%s](%sREADME-%s.md)%s" % (c.name, c.basedir(True), c.name, fixits_text) + "\n" + new_text_to_insert += " - [%s](%sREADME-%s.md)%s" % (c.name, docs_relative_path(), c.name, fixits_text) + "\n" new_text_to_insert += "\n" f = io.open(filename, 'w', newline='\n', encoding='utf8') skip = False for line in old_contents: if skip and line.startswith("#"): skip = False if skip: continue if line.startswith("- Checks from Manual Level:"): skip = True f.write(new_text_to_insert) continue f.write(line) f.close() f = io.open(filename, 'r', newline='\n', encoding='utf8') new_contents = f.readlines(); f.close(); if old_contents != new_contents: print("Generated " + filename) return True return False #------------------------------------------------------------------------------- +def generate_readmes_cmake_install(checks): + old_contents = "" + filename = clazy_source_path() + 'readmes.cmake' + if os.path.exists(filename): + f = io.open(filename, 'r', newline='\n', encoding='utf8') + old_contents = f.readlines(); + f.close(); + + new_text_to_insert = "" + for level in ['-1', '0', '1', '2', '3']: + new_text_to_insert += 'SET(' + level_num_to_cmake_readme_variable(int(level)) + "\n" + for c in checks: + if str(c.level) == level: + new_text_to_insert += ' ${CMAKE_CURRENT_LIST_DIR}/docs/checks/' + c.readme_name() + '\n' + new_text_to_insert += ')\n\n' + + if old_contents == new_text_to_insert: + return False + + f = io.open(filename, 'w', newline='\n', encoding='utf8') + f.write(new_text_to_insert) + f.close() + return True + +#------------------------------------------------------------------------------- complete_json_filename = clazy_source_path() + CHECKS_FILENAME if not os.path.exists(complete_json_filename): print("File doesn't exist: " + complete_json_filename) exit(1) parser = argparse.ArgumentParser() parser.add_argument("--generate", action='store_true', help="Generate src/Checks.h, CheckSources.cmake and README.md") parser.add_argument("checks", nargs='*', help="Optional check names to build. Useful to speedup builds during development, by building only the specified checks. Default is to build all checks.") args = parser.parse_args() _specified_check_names = args.checks if not load_json(complete_json_filename): exit(1) if args.generate: generated = False generated = generate_register_checks(_checks) or generated generated = generate_cmake_file(_checks) or generated generated = generate_readme(_checks) or generated generated = create_readmes(_checks) or generated generated = create_unittests(_checks) or generated generated = create_checks(_checks) or generated + generated = generate_readmes_cmake_install(_checks) or generated if not generated: print("Nothing to do, everything is OK") else: parser.print_help(sys.stderr) diff --git a/src/checks/level3/README-assert-with-side-effects.md b/docs/checks/README-assert-with-side-effects.md similarity index 100% rename from src/checks/level3/README-assert-with-side-effects.md rename to docs/checks/README-assert-with-side-effects.md diff --git a/src/checks/level1/README-auto-unexpected-qstringbuilder.md b/docs/checks/README-auto-unexpected-qstringbuilder.md similarity index 100% rename from src/checks/level1/README-auto-unexpected-qstringbuilder.md rename to docs/checks/README-auto-unexpected-qstringbuilder.md diff --git a/src/checks/level2/README-base-class-event.md b/docs/checks/README-base-class-event.md similarity index 100% rename from src/checks/level2/README-base-class-event.md rename to docs/checks/README-base-class-event.md diff --git a/src/checks/level1/README-child-event-qobject-cast.md b/docs/checks/README-child-event-qobject-cast.md similarity index 100% rename from src/checks/level1/README-child-event-qobject-cast.md rename to docs/checks/README-child-event-qobject-cast.md diff --git a/src/checks/level1/README-connect-3arg-lambda.md b/docs/checks/README-connect-3arg-lambda.md similarity index 100% rename from src/checks/level1/README-connect-3arg-lambda.md rename to docs/checks/README-connect-3arg-lambda.md diff --git a/src/checks/level0/README-connect-by-name.md b/docs/checks/README-connect-by-name.md similarity index 100% rename from src/checks/level0/README-connect-by-name.md rename to docs/checks/README-connect-by-name.md diff --git a/src/checks/level0/README-connect-non-signal.md b/docs/checks/README-connect-non-signal.md similarity index 100% rename from src/checks/level0/README-connect-non-signal.md rename to docs/checks/README-connect-non-signal.md diff --git a/src/checks/level0/README-connect-not-normalized.md b/docs/checks/README-connect-not-normalized.md similarity index 100% rename from src/checks/level0/README-connect-not-normalized.md rename to docs/checks/README-connect-not-normalized.md diff --git a/src/checks/level1/README-const-signal-or-slot.md b/docs/checks/README-const-signal-or-slot.md similarity index 100% rename from src/checks/level1/README-const-signal-or-slot.md rename to docs/checks/README-const-signal-or-slot.md diff --git a/src/checks/level0/README-container-anti-pattern.md b/docs/checks/README-container-anti-pattern.md similarity index 100% rename from src/checks/level0/README-container-anti-pattern.md rename to docs/checks/README-container-anti-pattern.md diff --git a/src/checks/manuallevel/README-container-inside-loop.md b/docs/checks/README-container-inside-loop.md similarity index 100% rename from src/checks/manuallevel/README-container-inside-loop.md rename to docs/checks/README-container-inside-loop.md diff --git a/src/checks/level2/README-copyable-polymorphic.md b/docs/checks/README-copyable-polymorphic.md similarity index 100% rename from src/checks/level2/README-copyable-polymorphic.md rename to docs/checks/README-copyable-polymorphic.md diff --git a/src/checks/level2/README-ctor-missing-parent-argument.md b/docs/checks/README-ctor-missing-parent-argument.md similarity index 100% rename from src/checks/level2/README-ctor-missing-parent-argument.md rename to docs/checks/README-ctor-missing-parent-argument.md diff --git a/src/checks/level3/README-detaching-member.md b/docs/checks/README-detaching-member.md similarity index 100% rename from src/checks/level3/README-detaching-member.md rename to docs/checks/README-detaching-member.md diff --git a/src/checks/level1/README-detaching-temporary.md b/docs/checks/README-detaching-temporary.md similarity index 100% rename from src/checks/level1/README-detaching-temporary.md rename to docs/checks/README-detaching-temporary.md diff --git a/src/checks/level1/README-foreach.md b/docs/checks/README-foreach.md similarity index 100% rename from src/checks/level1/README-foreach.md rename to docs/checks/README-foreach.md diff --git a/src/checks/level0/README-fully-qualified-moc-types.md b/docs/checks/README-fully-qualified-moc-types.md similarity index 100% rename from src/checks/level0/README-fully-qualified-moc-types.md rename to docs/checks/README-fully-qualified-moc-types.md diff --git a/src/checks/level2/README-function-args-by-ref.md b/docs/checks/README-function-args-by-ref.md similarity index 100% rename from src/checks/level2/README-function-args-by-ref.md rename to docs/checks/README-function-args-by-ref.md diff --git a/src/checks/level2/README-function-args-by-value.md b/docs/checks/README-function-args-by-value.md similarity index 100% rename from src/checks/level2/README-function-args-by-value.md rename to docs/checks/README-function-args-by-value.md diff --git a/src/checks/level2/README-global-const-char-pointer.md b/docs/checks/README-global-const-char-pointer.md similarity index 100% rename from src/checks/level2/README-global-const-char-pointer.md rename to docs/checks/README-global-const-char-pointer.md diff --git a/src/checks/level2/README-implicit-casts.md b/docs/checks/README-implicit-casts.md similarity index 100% rename from src/checks/level2/README-implicit-casts.md rename to docs/checks/README-implicit-casts.md diff --git a/src/checks/level1/README-incorrect-emit.md b/docs/checks/README-incorrect-emit.md similarity index 100% rename from src/checks/level1/README-incorrect-emit.md rename to docs/checks/README-incorrect-emit.md diff --git a/src/checks/level1/README-inefficient-qlist-soft.md b/docs/checks/README-inefficient-qlist-soft.md similarity index 100% rename from src/checks/level1/README-inefficient-qlist-soft.md rename to docs/checks/README-inefficient-qlist-soft.md diff --git a/src/checks/manuallevel/README-inefficient-qlist.md b/docs/checks/README-inefficient-qlist.md similarity index 100% rename from src/checks/manuallevel/README-inefficient-qlist.md rename to docs/checks/README-inefficient-qlist.md diff --git a/src/checks/level1/README-install-event-filter.md b/docs/checks/README-install-event-filter.md similarity index 100% rename from src/checks/level1/README-install-event-filter.md rename to docs/checks/README-install-event-filter.md diff --git a/src/checks/manuallevel/README-isempty-vs-count.md b/docs/checks/README-isempty-vs-count.md similarity index 100% rename from src/checks/manuallevel/README-isempty-vs-count.md rename to docs/checks/README-isempty-vs-count.md diff --git a/src/checks/level0/README-lambda-in-connect.md b/docs/checks/README-lambda-in-connect.md similarity index 100% rename from src/checks/level0/README-lambda-in-connect.md rename to docs/checks/README-lambda-in-connect.md diff --git a/src/checks/level0/README-lambda-unique-connection.md b/docs/checks/README-lambda-unique-connection.md similarity index 100% rename from src/checks/level0/README-lambda-unique-connection.md rename to docs/checks/README-lambda-unique-connection.md diff --git a/src/checks/level2/README-missing-qobject-macro.md b/docs/checks/README-missing-qobject-macro.md similarity index 100% rename from src/checks/level2/README-missing-qobject-macro.md rename to docs/checks/README-missing-qobject-macro.md diff --git a/src/checks/level2/README-missing-typeinfo.md b/docs/checks/README-missing-typeinfo.md similarity index 100% rename from src/checks/level2/README-missing-typeinfo.md rename to docs/checks/README-missing-typeinfo.md diff --git a/src/checks/level0/README-mutable-container-key.md b/docs/checks/README-mutable-container-key.md similarity index 100% rename from src/checks/level0/README-mutable-container-key.md rename to docs/checks/README-mutable-container-key.md diff --git a/src/checks/level1/README-non-pod-global-static.md b/docs/checks/README-non-pod-global-static.md similarity index 100% rename from src/checks/level1/README-non-pod-global-static.md rename to docs/checks/README-non-pod-global-static.md diff --git a/src/checks/level2/README-old-style-connect.md b/docs/checks/README-old-style-connect.md similarity index 100% rename from src/checks/level2/README-old-style-connect.md rename to docs/checks/README-old-style-connect.md diff --git a/src/checks/level1/README-overridden-signal.md b/docs/checks/README-overridden-signal.md similarity index 100% rename from src/checks/level1/README-overridden-signal.md rename to docs/checks/README-overridden-signal.md diff --git a/src/checks/level1/README-post-event.md b/docs/checks/README-post-event.md similarity index 100% rename from src/checks/level1/README-post-event.md rename to docs/checks/README-post-event.md diff --git a/src/checks/level0/README-qcolor-from-literal.md b/docs/checks/README-qcolor-from-literal.md similarity index 100% rename from src/checks/level0/README-qcolor-from-literal.md rename to docs/checks/README-qcolor-from-literal.md diff --git a/src/checks/level0/README-qdatetime-utc.md b/docs/checks/README-qdatetime-utc.md similarity index 100% rename from src/checks/level0/README-qdatetime-utc.md rename to docs/checks/README-qdatetime-utc.md diff --git a/src/checks/level1/README-qdeleteall.md b/docs/checks/README-qdeleteall.md similarity index 100% rename from src/checks/level1/README-qdeleteall.md rename to docs/checks/README-qdeleteall.md diff --git a/src/checks/level0/README-qenums.md b/docs/checks/README-qenums.md similarity index 100% rename from src/checks/level0/README-qenums.md rename to docs/checks/README-qenums.md diff --git a/src/checks/level0/README-qfileinfo-exists.md b/docs/checks/README-qfileinfo-exists.md similarity index 100% rename from src/checks/level0/README-qfileinfo-exists.md rename to docs/checks/README-qfileinfo-exists.md diff --git a/src/checks/level0/README-qgetenv.md b/docs/checks/README-qgetenv.md similarity index 100% rename from src/checks/level0/README-qgetenv.md rename to docs/checks/README-qgetenv.md diff --git a/src/checks/level1/README-qhash-namespace.md b/docs/checks/README-qhash-namespace.md similarity index 100% rename from src/checks/level1/README-qhash-namespace.md rename to docs/checks/README-qhash-namespace.md diff --git a/src/checks/manuallevel/README-qhash-with-char-pointer-key.md b/docs/checks/README-qhash-with-char-pointer-key.md similarity index 100% rename from src/checks/manuallevel/README-qhash-with-char-pointer-key.md rename to docs/checks/README-qhash-with-char-pointer-key.md diff --git a/src/checks/level1/README-qlatin1string-non-ascii.md b/docs/checks/README-qlatin1string-non-ascii.md similarity index 100% rename from src/checks/level1/README-qlatin1string-non-ascii.md rename to docs/checks/README-qlatin1string-non-ascii.md diff --git a/src/checks/level0/README-qmap-with-pointer-key.md b/docs/checks/README-qmap-with-pointer-key.md similarity index 100% rename from src/checks/level0/README-qmap-with-pointer-key.md rename to docs/checks/README-qmap-with-pointer-key.md diff --git a/src/checks/level1/README-qproperty-without-notify.md b/docs/checks/README-qproperty-without-notify.md similarity index 100% rename from src/checks/level1/README-qproperty-without-notify.md rename to docs/checks/README-qproperty-without-notify.md diff --git a/src/checks/level2/README-qstring-allocations.md b/docs/checks/README-qstring-allocations.md similarity index 100% rename from src/checks/level2/README-qstring-allocations.md rename to docs/checks/README-qstring-allocations.md diff --git a/src/checks/level0/README-qstring-arg.md b/docs/checks/README-qstring-arg.md similarity index 100% rename from src/checks/level0/README-qstring-arg.md rename to docs/checks/README-qstring-arg.md diff --git a/src/checks/level0/README-qstring-insensitive-allocation.md b/docs/checks/README-qstring-insensitive-allocation.md similarity index 100% rename from src/checks/level0/README-qstring-insensitive-allocation.md rename to docs/checks/README-qstring-insensitive-allocation.md diff --git a/src/checks/level1/README-qstring-left.md b/docs/checks/README-qstring-left.md similarity index 100% rename from src/checks/level1/README-qstring-left.md rename to docs/checks/README-qstring-left.md diff --git a/src/checks/level0/README-qstring-ref.md b/docs/checks/README-qstring-ref.md similarity index 100% rename from src/checks/level0/README-qstring-ref.md rename to docs/checks/README-qstring-ref.md diff --git a/src/checks/manuallevel/README-qstring-varargs.md b/docs/checks/README-qstring-varargs.md similarity index 100% rename from src/checks/manuallevel/README-qstring-varargs.md rename to docs/checks/README-qstring-varargs.md diff --git a/src/checks/manuallevel/README-qt-keywords.md b/docs/checks/README-qt-keywords.md similarity index 100% rename from src/checks/manuallevel/README-qt-keywords.md rename to docs/checks/README-qt-keywords.md diff --git a/src/checks/level0/README-qt-macros.md b/docs/checks/README-qt-macros.md similarity index 100% rename from src/checks/level0/README-qt-macros.md rename to docs/checks/README-qt-macros.md diff --git a/src/checks/manuallevel/README-qt4-qstring-from-array.md b/docs/checks/README-qt4-qstring-from-array.md similarity index 100% rename from src/checks/manuallevel/README-qt4-qstring-from-array.md rename to docs/checks/README-qt4-qstring-from-array.md diff --git a/src/checks/level0/README-qvariant-template-instantiation.md b/docs/checks/README-qvariant-template-instantiation.md similarity index 100% rename from src/checks/level0/README-qvariant-template-instantiation.md rename to docs/checks/README-qvariant-template-instantiation.md diff --git a/src/checks/level1/README-range-loop.md b/docs/checks/README-range-loop.md similarity index 100% rename from src/checks/level1/README-range-loop.md rename to docs/checks/README-range-loop.md diff --git a/src/checks/level3/README-reserve-candidates.md b/docs/checks/README-reserve-candidates.md similarity index 100% rename from src/checks/level3/README-reserve-candidates.md rename to docs/checks/README-reserve-candidates.md diff --git a/src/checks/level1/README-returning-data-from-temporary.md b/docs/checks/README-returning-data-from-temporary.md similarity index 100% rename from src/checks/level1/README-returning-data-from-temporary.md rename to docs/checks/README-returning-data-from-temporary.md diff --git a/src/checks/level2/README-returning-void-expression.md b/docs/checks/README-returning-void-expression.md similarity index 100% rename from src/checks/level2/README-returning-void-expression.md rename to docs/checks/README-returning-void-expression.md diff --git a/src/checks/level2/README-rule-of-three.md b/docs/checks/README-rule-of-three.md similarity index 100% rename from src/checks/level2/README-rule-of-three.md rename to docs/checks/README-rule-of-three.md diff --git a/src/checks/level1/README-rule-of-two-soft.md b/docs/checks/README-rule-of-two-soft.md similarity index 100% rename from src/checks/level1/README-rule-of-two-soft.md rename to docs/checks/README-rule-of-two-soft.md diff --git a/src/checks/level1/README-skipped-base-method.md b/docs/checks/README-skipped-base-method.md similarity index 100% rename from src/checks/level1/README-skipped-base-method.md rename to docs/checks/README-skipped-base-method.md diff --git a/src/checks/level2/README-static-pmf.md b/docs/checks/README-static-pmf.md similarity index 100% rename from src/checks/level2/README-static-pmf.md rename to docs/checks/README-static-pmf.md diff --git a/src/checks/level0/README-strict-iterators.md b/docs/checks/README-strict-iterators.md similarity index 100% rename from src/checks/level0/README-strict-iterators.md rename to docs/checks/README-strict-iterators.md diff --git a/src/checks/level0/README-temporary-iterator.md b/docs/checks/README-temporary-iterator.md similarity index 100% rename from src/checks/level0/README-temporary-iterator.md rename to docs/checks/README-temporary-iterator.md diff --git a/src/checks/level3/README-thread-with-slots.md b/docs/checks/README-thread-with-slots.md similarity index 100% rename from src/checks/level3/README-thread-with-slots.md rename to docs/checks/README-thread-with-slots.md diff --git a/src/checks/manuallevel/README-tr-non-literal.md b/docs/checks/README-tr-non-literal.md similarity index 100% rename from src/checks/manuallevel/README-tr-non-literal.md rename to docs/checks/README-tr-non-literal.md diff --git a/src/checks/manuallevel/README-unneeded-cast.md b/docs/checks/README-unneeded-cast.md similarity index 100% rename from src/checks/manuallevel/README-unneeded-cast.md rename to docs/checks/README-unneeded-cast.md diff --git a/src/checks/level0/README-unused-non-trivial-variable.md b/docs/checks/README-unused-non-trivial-variable.md similarity index 100% rename from src/checks/level0/README-unused-non-trivial-variable.md rename to docs/checks/README-unused-non-trivial-variable.md diff --git a/src/checks/level2/README-virtual-call-ctor.md b/docs/checks/README-virtual-call-ctor.md similarity index 100% rename from src/checks/level2/README-virtual-call-ctor.md rename to docs/checks/README-virtual-call-ctor.md diff --git a/src/checks/level1/README-virtual-signal.md b/docs/checks/README-virtual-signal.md similarity index 100% rename from src/checks/level1/README-virtual-signal.md rename to docs/checks/README-virtual-signal.md diff --git a/src/checks/level0/README-writing-to-temporary.md b/docs/checks/README-writing-to-temporary.md similarity index 100% rename from src/checks/level0/README-writing-to-temporary.md rename to docs/checks/README-writing-to-temporary.md diff --git a/src/checks/level0/README-wrong-qevent-cast.md b/docs/checks/README-wrong-qevent-cast.md similarity index 100% rename from src/checks/level0/README-wrong-qevent-cast.md rename to docs/checks/README-wrong-qevent-cast.md diff --git a/src/checks/level0/README-wrong-qglobalstatic.md b/docs/checks/README-wrong-qglobalstatic.md similarity index 100% rename from src/checks/level0/README-wrong-qglobalstatic.md rename to docs/checks/README-wrong-qglobalstatic.md diff --git a/readmes.cmake b/readmes.cmake new file mode 100644 index 0000000..70513fa --- /dev/null +++ b/readmes.cmake @@ -0,0 +1,90 @@ +SET(README_manuallevel_FILES + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-container-inside-loop.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-inefficient-qlist.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-isempty-vs-count.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qhash-with-char-pointer-key.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-varargs.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qt-keywords.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qt4-qstring-from-array.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-tr-non-literal.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-unneeded-cast.md +) + +SET(README_LEVEL0_FILES + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-connect-by-name.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-connect-non-signal.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-connect-not-normalized.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-container-anti-pattern.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-fully-qualified-moc-types.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-lambda-in-connect.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-lambda-unique-connection.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-mutable-container-key.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qcolor-from-literal.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qdatetime-utc.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qenums.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qfileinfo-exists.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qgetenv.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qmap-with-pointer-key.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-arg.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-insensitive-allocation.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-ref.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qt-macros.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qvariant-template-instantiation.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-strict-iterators.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-temporary-iterator.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-unused-non-trivial-variable.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-writing-to-temporary.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-wrong-qevent-cast.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-wrong-qglobalstatic.md +) + +SET(README_LEVEL1_FILES + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-auto-unexpected-qstringbuilder.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-child-event-qobject-cast.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-connect-3arg-lambda.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-const-signal-or-slot.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-detaching-temporary.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-foreach.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-incorrect-emit.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-inefficient-qlist-soft.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-install-event-filter.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-non-pod-global-static.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-overridden-signal.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-post-event.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qdeleteall.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qhash-namespace.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qlatin1string-non-ascii.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qproperty-without-notify.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-left.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-range-loop.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-returning-data-from-temporary.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-rule-of-two-soft.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-skipped-base-method.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-virtual-signal.md +) + +SET(README_LEVEL2_FILES + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-base-class-event.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-copyable-polymorphic.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-ctor-missing-parent-argument.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-function-args-by-ref.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-function-args-by-value.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-global-const-char-pointer.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-implicit-casts.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-missing-qobject-macro.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-missing-typeinfo.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-old-style-connect.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-qstring-allocations.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-returning-void-expression.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-rule-of-three.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-static-pmf.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-virtual-call-ctor.md +) + +SET(README_LEVEL3_FILES + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-assert-with-side-effects.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-detaching-member.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-reserve-candidates.md + ${CMAKE_CURRENT_LIST_DIR}/docs/checks/README-thread-with-slots.md +) +