Mercurial > irccd
changeset 510:6ec510722582
CMake: enable vera++ as code checking, closes #603
author | David Demelier <markand@malikania.fr> |
---|---|
date | Thu, 19 Oct 2017 13:01:39 +0200 |
parents | c9a6d9df083f |
children | f912379cc1a3 |
files | CMakeLists.txt cmake/IrccdOptions.cmake cmake/function/IrccdDefineExecutable.cmake cmake/function/IrccdDefineLibrary.cmake cmake/function/IrccdDefineTest.cmake cmake/function/IrccdVeraCheck.cmake extern/libircclient/CMakeLists.txt vera/profiles/default vera/rules/L001.tcl vera/rules/L002.tcl vera/rules/L003.tcl vera/rules/L004.tcl vera/rules/L005.tcl vera/rules/T003.tcl vera/rules/T004.tcl vera/rules/T005.tcl vera/rules/T006.tcl vera/rules/T008.tcl vera/rules/T017.tcl vera/rules/T018.tcl |
diffstat | 20 files changed, 415 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/CMakeLists.txt Mon Oct 16 13:47:05 2017 +0200 +++ b/CMakeLists.txt Thu Oct 19 13:01:39 2017 +0200 @@ -119,6 +119,7 @@ message(" User docs: ${WITH_HTML_MSG}") message(" Doxygen: ${WITH_DOXYGEN_MSG}") message(" Package: ${IRCCD_PACKAGE_MSG}") +message(" Vera: ${WITH_VERA_MSG}") message("") message("Installing plugins:")
--- a/cmake/IrccdOptions.cmake Mon Oct 16 13:47:05 2017 +0200 +++ b/cmake/IrccdOptions.cmake Thu Oct 19 13:01:39 2017 +0200 @@ -29,6 +29,7 @@ # WITH_MAN Install manpages (default: on, off for Windows) # WITH_PKGCONFIG Install pkg-config files (default: on, off for Windows (except MinGW)) # WITH_PLUGIN_<NAME> Enable or disable the specified plugin (default: on) +# WITH_VERA Enable style checking using vera (default: on) # # Note: the option() commands for WITH_PLUGIN_<name> variables are defined automatically from the IRCCD_PLUGINS # list. @@ -79,6 +80,7 @@ option(WITH_DOXYGEN "Enable doxygen" Off) option(WITH_MAN "Install man pages" ${DEFAULT_MAN}) option(WITH_PKGCONFIG "Enable pkg-config file" ${DEFAULT_PKGCONFIG}) +option(WITH_VERA "Enable vera++" On) # # Installation paths. @@ -164,6 +166,30 @@ set(WITH_HTML FALSE) endif () +find_program(VERA_EXECUTABLE vera++) + +if (VERA_EXECUTABLE) + if (WITH_VERA) + execute_process( + COMMAND ${VERA_EXECUTABLE} --version + OUTPUT_VARIABLE VERA_VERSION + ) + + if (${VERA_VERSION} VERSION_LESS "1.3.0") + set(WITH_VERA Off) + set(WITH_VERA_MSG "No (1.3.0 or greater required)") + else () + set(WITH_VERA_MSG "Yes") + endif () + else () + set(WITH_VERA Off) + set(WITH_VERA_MSG "No (disabled by user)") + endif () +else () + set(WITH_VERA Off) + set(WITH_VERA_MSG "No (vera++ not found)") +endif () + # # Determine if allowed to package. # -------------------------------------------------------------------
--- a/cmake/function/IrccdDefineExecutable.cmake Mon Oct 16 13:47:05 2017 +0200 +++ b/cmake/function/IrccdDefineExecutable.cmake Thu Oct 19 13:01:39 2017 +0200 @@ -32,6 +32,8 @@ # Create an executable that can be installed or not. # +include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake) + function(irccd_define_executable) set(options "") set(oneValueArgs DESCRIPTION TARGET) @@ -79,4 +81,6 @@ setg(CPACK_COMPONENT_${CMP}_DISPLAY_NAME "${EXE_TARGET} executable") setg(CPACK_COMPONENT_${CMP}_DESCRIPTION ${EXE_DESCRIPTION}) setg(CPACK_COMPONENT_${CMP}_GROUP "Applications") + + irccd_vera_check(${EXE_TARGET} "${EXE_SOURCES}") endfunction()
--- a/cmake/function/IrccdDefineLibrary.cmake Mon Oct 16 13:47:05 2017 +0200 +++ b/cmake/function/IrccdDefineLibrary.cmake Thu Oct 19 13:01:39 2017 +0200 @@ -24,6 +24,7 @@ # TARGET target name # SOURCES src1, src2, srcn # LOCAL (Optional) set to true to build a static library +# EXTERNAL (Optional) set to true if library is third party # FLAGS (Optional) C/C++ flags (without -D) # LIBRARIES (Optional) libraries to link # LOCAL_INCLUDES (Optional) local includes for the target only @@ -33,8 +34,10 @@ # Create a static library for internal use. # +include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake) + function(irccd_define_library) - set(options LOCAL) + set(options EXTERNAL LOCAL) set(oneValueArgs TARGET) set(multiValueArgs SOURCES FLAGS LIBRARIES LOCAL_INCLUDES PUBLIC_INCLUDES) set(mandatory TARGET SOURCES) @@ -69,4 +72,8 @@ RUNTIME_OUTPUT_DIRECTORY_${cu} ${CMAKE_BINARY_DIR}/bin/${c} ) endforeach() + + if (NOT ${LIB_EXTERNAL}) + irccd_vera_check(${LIB_TARGET} "${LIB_SOURCES}") + endif () endfunction()
--- a/cmake/function/IrccdDefineTest.cmake Mon Oct 16 13:47:05 2017 +0200 +++ b/cmake/function/IrccdDefineTest.cmake Thu Oct 19 13:01:39 2017 +0200 @@ -34,6 +34,8 @@ find_package(Boost REQUIRED COMPONENTS unit_test_framework) +include(${CMAKE_CURRENT_LIST_DIR}/IrccdVeraCheck.cmake) + function(irccd_define_test) set(oneValueArgs NAME) set(multiValueArgs SOURCES LIBRARIES FLAGS) @@ -104,4 +106,6 @@ COMMAND test-${TEST_NAME} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tests ) + + irccd_vera_check(test-${TEST_NAME} "${TEST_SOURCES}") endfunction()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmake/function/IrccdVeraCheck.cmake Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,56 @@ +# +# IrccdVeraCheck.cmake -- CMake build system for irccd +# +# Copyright (c) 2013-2017 David Demelier <markand@malikania.fr> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# + +# +# irccd_vera_check +# ---------------- +# +# irccd_vera_check(target sources) +# +# Check the style source code using vera++. +# +# No-op if WITH_VERA is Off. +# +# This macro add a post-build command to call vera++ program on the specified +# sources file for the given target. +# + +function(irccd_vera_check target sources) + if (WITH_VERA) + set(valid ".cpp;.c;.hpp;.h") + + # Cleanup non relevant files. + foreach (s ${sources}) + get_filename_component(ext ${s} EXT) + + foreach (e ${valid}) + if (${ext} STREQUAL ${e}) + list(APPEND newsources ${s}) + endif () + endforeach () + endforeach () + + add_custom_command( + TARGET ${target} + COMMAND + ${VERA_EXECUTABLE} -w --root ${CMAKE_SOURCE_DIR}/vera ${newsources} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM + ) + endif () +endfunction()
--- a/extern/libircclient/CMakeLists.txt Mon Oct 16 13:47:05 2017 +0200 +++ b/extern/libircclient/CMakeLists.txt Thu Oct 19 13:01:39 2017 +0200 @@ -51,7 +51,7 @@ endif () irccd_define_library( - LOCAL + LOCAL EXTERNAL TARGET extern-ircclient SOURCES src/libircclient.c FLAGS ${FLAGS} @@ -65,4 +65,4 @@ PROPERTIES PROJECT_LABEL libircclient FOLDER extern -) \ No newline at end of file +)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/profiles/default Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,14 @@ +rule=L001 +rule=L002 +rule=L003 +rule=L004 +parameter=max-line-length=120 +rule=L005 +parameter=max-consecutive-empty-lines=1 +rule=T003 +rule=T004 +rule=T005 +rule=T006 +rule=T008 +rule=T017 +rule=T018
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/L001.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,24 @@ +#!/usr/bin/tclsh +# No trailing whitespace + +set strictMode [getParameter "strict-trailing-space" 0] + +foreach f [getSourceFileNames] { + set lineNumber 1 + set previousIndent "" + foreach line [getAllLines $f] { + + if [regexp {^.*\r$} $line] { + report $f $lineNumber "CRLF line ending" + set line [string range $line 0 end-1] + } + if [regexp {^.*[[:space:]]+$} $line] { + if {$strictMode || [string trim $line] != "" || $line != $previousIndent} { + report $f $lineNumber "trailing whitespace" + } + } + + regexp {^([[:space:]]*).*$} $line dummy previousIndent + incr lineNumber + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/L002.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,14 @@ +#!/usr/bin/tclsh +# Don't use tab characters + +foreach f [getSourceFileNames] { + set lineNumber 1 + foreach line [getAllLines $f] { + + if [regexp {\t} $line] { + report $f $lineNumber "horizontal tab used" + } + + incr lineNumber + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/L003.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,17 @@ +#!/usr/bin/tclsh +# No leading and no trailing empty lines + +foreach f [getSourceFileNames] { + set lineCount [getLineCount $f] + if {$lineCount > 0} { + set firstLine [getLine $f 1] + if {[string trim $firstLine] == ""} { + report $f 1 "leading empty line(s)" + } + + set lastLine [getLine $f $lineCount] + if {[string trim $lastLine] == ""} { + report $f $lineCount "trailing empty line(s)" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/L004.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,14 @@ +#!/usr/bin/tclsh +# Line cannot be too long + +set maxLength [getParameter "max-line-length" 100] + +foreach f [getSourceFileNames] { + set lineNumber 1 + foreach line [getAllLines $f] { + if {[string length $line] > $maxLength} { + report $f $lineNumber "line is longer than ${maxLength} characters" + } + incr lineNumber + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/L005.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,23 @@ +#!/usr/bin/tclsh +# There should not be too many consecutive empty lines + +set maxEmptyLines [getParameter "max-consecutive-empty-lines" 2] + +foreach f [getSourceFileNames] { + set lineNumber 1 + set emptyCount 0 + set reported false + foreach line [getAllLines $f] { + if {[string trim $line] == ""} { + incr emptyCount + if {$emptyCount > $maxEmptyLines && $reported == "false"} { + report $f $lineNumber "too many consecutive empty lines" + set reported true + } + } else { + set emptyCount 0 + set reported false + } + incr lineNumber + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T003.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,47 @@ +#!/usr/bin/tclsh +# Some keywords should be followed by a single space + +set keywords { + case + class + enum + explicit + extern + goto + new + struct + union + using +} + +proc isKeyword {s} { + global keywords + return [expr [lsearch $keywords $s] != -1] +} + +set state "other" +foreach f [getSourceFileNames] { + foreach t [getTokens $f 1 0 -1 -1 {}] { + set tokenValue [lindex $t 0] + set tokenName [lindex $t 3] + if {$state == "keyword"} { + if {$tokenName == "space" && $tokenValue == " "} { + set state "space" + } else { + report $f $lineNumber "keyword \'${keywordValue}\' not followed by a single space" + set state "other" + } + } elseif {$state == "space"} { + if {$tokenName == "newline"} { + report $f $lineNumber "keyword \'${keywordValue}\' not followed by a single space" + } + set state "other" + } else { + if [isKeyword $tokenName] { + set state "keyword" + set lineNumber [lindex $t 1] + set keywordValue [lindex $t 0] + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T004.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,51 @@ +#!/usr/bin/tclsh +# Some keywords should be immediately followed by a colon + +set keywords { + default + private + protected + public +} + +proc isKeyword {s} { + global keywords + return [expr [lsearch $keywords $s] != -1] +} + +foreach f [getSourceFileNames] { + set lastKeywordLine 0 + set lastKeywordColumn 0 + set lastKeywordValue "" + set last "" + foreach t [getTokens $f 1 0 -1 -1 [concat $keywords colon]] { + set tokenValue [lindex $t 0] + set tokenName [lindex $t 3] + if {$tokenName == "colon"} { + if {$last == "keyword" && $lastKeywordLine != 0} { + set line [lindex $t 1] + set column [lindex $t 2] + if {$line != $lastKeywordLine || + $column != [expr $lastKeywordColumn + [string length $lastKeywordValue]]} { + set nonWhiteFound "false" + foreach tb [getTokens $f $lastKeywordLine [expr $lastKeywordColumn + 1] $line $column {}] { + set tbName [lindex $tb 3] + if {[lsearch {space newline ccomment cppcomment} $tbName] == -1} { + set nonWhiteFound "true" + break + } + } + if {$nonWhiteFound == "false"} { + report $f $line "colon not immediately after the \'$lastKeywordValue\' keyword" + } + } + } + set last "colon" + } else { + set lastKeywordLine [lindex $t 1] + set lastKeywordColumn [lindex $t 2] + set lastKeywordValue $tokenValue + set last "keyword" + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T005.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,19 @@ +#!/usr/bin/tclsh +# Keywords break and continue should be immediately followed by a semicolon + +foreach f [getSourceFileNames] { + foreach t [getTokens $f 1 0 -1 -1 {break continue}] { + set keyword [lindex $t 0] + set line [lindex $t 1] + set column [lindex $t 2] + set semicolons [getTokens $f $line [expr $column + [string length $keyword]] [expr $line + 1] 0 {semicolon}] + if {$semicolons == {}} { + report $f $line "keyword '${keyword}' not immediately followed by a semicolon" + } else { + set semColumn [lindex [lindex $semicolons 0] 2] + if {$semColumn != $column + [string length $keyword]} { + report $f $line "keyword '${keyword}' not immediately followed by a semicolon" + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T006.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,21 @@ +#!/usr/bin/tclsh +# Keywords return and throw should be immediately followed by a semicolon or a single space + +foreach f [getSourceFileNames] { + foreach t [getTokens $f 1 0 -1 -1 {return throw}] { + set keyword [lindex $t 0] + set line [lindex $t 1] + set column [lindex $t 2] + set followingTokens [getTokens $f $line [expr $column + [string length $keyword]] [expr $line + 1] 0 {}] + if {$followingTokens == {}} { + report $f $line "keyword '${keyword}' not immediately followed by a semicolon or a single space" + } else { + set first [lindex [lindex $followingTokens 0] 0] + if {$first != ";" && $first != " "} { + if {!([llength $followingTokens] >= 2 && $keyword == "throw" && $first == "(" && [lindex [lindex $followingTokens 1] 0] == ")")} { + report $f $line "keyword '${keyword}' not immediately followed by a semicolon or a single space" + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T008.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,24 @@ +#!/usr/bin/tclsh +# Keywords catch, for, if and while should be followed by a single space + +foreach f [getSourceFileNames] { + set pp_pragma_line -1 + foreach t [getTokens $f 1 0 -1 -1 {catch for if switch while pp_pragma}] { + set keyword [lindex $t 0] + set line [lindex $t 1] + set column [lindex $t 2] + set type [lindex $t 3] + if {$type == "pp_pragma"} { + set pp_pragma_line $line + } elseif {$pp_pragma_line != $line} { + set followingTokens [getTokens $f $line [expr $column + [string length $keyword]] [expr $line + 1] -1 {}] + if {[llength $followingTokens] < 2} { + report $f $line "keyword '${keyword}' not followed by a single space" + } else { + if {[list [lindex [lindex $followingTokens 0] 0] [lindex [lindex $followingTokens 1] 0]] != [list " " "("]} { + report $f $line "keyword '${keyword}' not followed by a single space" + } + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T017.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,23 @@ +#!/usr/bin/tclsh +# Unnamed namespaces are not allowed in header files + +foreach fileName [getSourceFileNames] { + set extension [file extension $fileName] + if {[lsearch {.h .hh .hpp .hxx .ipp} $extension] != -1} { + + set state "start" + foreach token [getTokens $fileName 1 0 -1 -1 {namespace identifier leftbrace}] { + set type [lindex $token 3] + + if {$state == "namespace" && $type == "leftbrace"} { + report $fileName $namespaceLine "unnamed namespace not allowed in header file" + } + + if {$type == "namespace"} { + set namespaceLine [lindex $token 1] + } + + set state $type + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/vera/rules/T018.tcl Thu Oct 19 13:01:39 2017 +0200 @@ -0,0 +1,23 @@ +#!/usr/bin/tclsh +# using namespace are not allowed in header files + +foreach fileName [getSourceFileNames] { + set extension [file extension $fileName] + if {[lsearch {.h .hh .hpp .hxx .ipp} $extension] != -1} { + + set state "start" + foreach token [getTokens $fileName 1 0 -1 -1 {using namespace identifier}] { + set type [lindex $token 3] + + if {$state == "using" && $type == "namespace"} { + report $fileName $usingLine "using namespace not allowed in header file" + } + + if {$type == "using"} { + set usingLine [lindex $token 1] + } + + set state $type + } + } +}