From 2eb84d9ef7397e3aa0299aadc0bd0d918e08e231 Mon Sep 17 00:00:00 2001
From: Alberto Nidasio <alberto.nidasio@skywarder.eu>
Date: Sun, 2 Oct 2022 09:28:15 +0200
Subject: [PATCH] [SBS][Linter] Updated cppcheck and copyright output

---
 sbs               | 140 +++++++++++++++++++++++-----------------------
 scripts/linter.py |  94 +++++++++++++++----------------
 2 files changed, 116 insertions(+), 118 deletions(-)

diff --git a/sbs b/sbs
index 5dce172a4..5cecc767b 100755
--- a/sbs
+++ b/sbs
@@ -52,7 +52,7 @@ init_dirs() {
 
 find_deps() {
     ohai "Find dependencies"
-
+    
     command -v cmake               > /dev/null 2>&1 && found_cmake=true
     command -v arm-miosix-eabi-g++ > /dev/null 2>&1 && found_miosixgpp=true
     command -v ccache              > /dev/null 2>&1 && found_ccache=true
@@ -63,7 +63,7 @@ find_deps() {
     command -v clang-format        > /dev/null 2>&1 && found_clangformat=true
     command -v st-flash            > /dev/null 2>&1 && found_stflash=true
     command -v ST-LINK_CLI.exe     > /dev/null 2>&1 && found_stlink=true
-
+    
     printf "Found CMake: ";               [ "$found_cmake" = true ]       && echo "yes" || echo "no"
     printf "Found arm-miosix-eabi-g++: "; [ "$found_miosixgpp" = true ]   && echo "yes" || echo "no"
     printf "Found Ccache: ";              [ "$found_ccache" = true ]      && echo "yes" || echo "no"
@@ -73,8 +73,8 @@ find_deps() {
     printf "Found clang-tidy: ";          [ "$found_clangtidy" = true ]   && echo "yes" || echo "no"
     printf "Found clang-format: ";        [ "$found_clangformat" = true ] && echo "yes" || echo "no"
     printf "Found flasher: ";             [ "$found_stflash" = true ]     && echo "st-flash" \
-                                            || { [ "$found_stlink" = true ] && echo "st-link" || echo "no"; }
-
+    || { [ "$found_stlink" = true ] && echo "st-link" || echo "no"; }
+    
     [ "$found_cmake" = true ]     || { echo "Error: CMake must be installed"; return 1; }
     [ "$found_miosixgpp" = true ] || { echo "Error: arm-miosix-eabi-g++ must be installed"; return 1; }
 }
@@ -83,51 +83,51 @@ find_deps() {
 # See: https://gitlab.kitware.com/cmake/cmake/-/issues/20212
 cmake_disable_excluded_tests() {
     declare build_dir="$1"
-
+    
     [ ! -f "$build_dir/$CTEST_FILENAME" ] || sed -i.bak 's/^subdirs/# subdirs/' "$build_dir/$CTEST_FILENAME"
 }
 
 configure() {
     declare build_dir="$1"
-
+    
     ohai "Configure"
-
+    
     [ -f "$toolchain_file" ] || { echo "Error: CMake Toolchain File for Miosix was not found"; return 1; }
-
+    
     declare -a defs=(-DCMAKE_EXPORT_COMPILE_COMMANDS=ON)
     defs+=(-DCMAKE_C_FLAGS=-fdiagnostics-color=always -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always)
     [ "$config_host" = false ]   && defs+=(-DCMAKE_TOOLCHAIN_FILE="$toolchain_file" -DBUILD_TESTING=OFF)
     [ "$found_ccache" = true ]   && defs+=(-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache)
     [ "$config_debug" = true ]   && defs+=(-DCMAKE_BUILD_TYPE=Debug) || defs+=(-DCMAKE_BUILD_TYPE=Release)
     [ "$config_verbose" = true ] && defs+=(-DCMAKE_VERBOSE_MAKEFILE=ON)
-
+    
     declare gen
     [ "$found_ninja" = true ] && gen=-GNinja || gen=-G"Unix Makefiles"
-
+    
     cmake -B"$build_dir" "${defs[@]}" "$gen" "$source_dir" || return
-
+    
     { [ "$config_debug" = true ]   && touch "$build_dir/$DEBUG_FILENAME";   } || rm -f "$build_dir/$DEBUG_FILENAME"
     { [ "$config_verbose" = true ] && touch "$build_dir/$VERBOSE_FILENAME"; } || rm -f "$build_dir/$VERBOSE_FILENAME"
 }
 
 check_configured() {
     declare build_dir="$1"
-
+    
     declare to_reconfigure=false
     if [ ! -d "$build_dir" ]; then
         to_reconfigure=true
-    elif [ ! -f "$build_dir/$CMAKE_FILENAME" ]; then
+        elif [ ! -f "$build_dir/$CMAKE_FILENAME" ]; then
         rm -rf "$build_dir"
         to_reconfigure=true
     else
         [ -f "$build_dir/$DEBUG_FILENAME" ]   && found_debug=true   || found_debug=false
         [ -f "$build_dir/$VERBOSE_FILENAME" ] && found_verbose=true || found_verbose=false
         if [ "$config_debug" != "$found_debug" ] \
-                || [ "$config_verbose" != "$found_verbose" ]; then
+        || [ "$config_verbose" != "$found_verbose" ]; then
             to_reconfigure=true
         fi
     fi
-
+    
     if [ "$to_reconfigure" = true ]; then
         configure "$build_dir"
     fi
@@ -136,36 +136,36 @@ check_configured() {
 build() {
     declare build_dir="$1"
     declare target="$2"
-
+    
     check_configured "$build_dir" || return
-
+    
     ohai "Build"
-
+    
     declare -a opts
     get_build_opts opts
-
+    
     cmake --build "$build_dir" "${opts[@]}" --target "$target"
 }
 
 build_all() {
     declare build_dir="$build_default_dir"
-
+    
     build "$build_dir" all
 }
 
 clean() {
     declare build_desc="$1"
     declare build_dir="$2"
-
+    
     ohai "Clean ($build_desc)"
-
+    
     if [ -f "$build_dir/$CMAKE_FILENAME" ]; then
         declare -a opts
         get_build_opts opts
-
+        
         cmake --build "$build_dir" "${opts[@]}" --target clean
     fi
-
+    
     echo "Removing build folder..."
     rm -rf "$build_dir"
 }
@@ -178,16 +178,16 @@ clean_all() {
 flash() {
     declare target="$1"
     declare build_dir="$build_default_dir"
-
+    
     build "$build_dir" "$target" || return
-
+    
     ohai "Flash"
-
+    
     [ -f "$build_dir/$target.bin" ] || { echo "Error: target '$target' is not flashable"; return 1; }
-
+    
     if [ "$found_stflash" = true ]; then
         st-flash --reset write "$build_dir/$target.bin" 0x8000000
-    elif [ "$found_stlink" = true ]; then
+        elif [ "$found_stlink" = true ]; then
         ST-LINK_CLI.exe -P "$build_dir/$target.bin" 0x8000000 -V -Rst
     else
         echo "Error: No flashing software found!"
@@ -198,120 +198,120 @@ flash() {
 run_tests() {
     declare target="$1"
     declare build_dir="$build_host_dir"
-
+    
     config_host=true
-
+    
     build "$build_dir" "$target" || return
-
+    
     ohai "Test"
-
+    
     cmake_disable_excluded_tests "$build_dir"
     ( cd "$build_dir" || return; ctest )
 }
 
 list() {
     declare build_dir="$build_default_dir"
-
+    
     check_configured "$build_dir" || return
-
+    
     ohai "List targets"
-
+    
     declare -a opts
     get_build_opts opts
-
+    
     echo "[1/1] All SBS targets available:"
     cmake --build "$build_dir" "${opts[@]}" --target help \
-        | grep -o '^[^/]*\.bin' | cut -f 1 -d '.'
+    | grep -o '^[^/]*\.bin' | cut -f 1 -d '.'
 }
 
 boards() {
     declare build_dir="$build_default_dir"
-
+    
     check_configured "$build_dir" || return
-
+    
     ohai "List boards"
-
+    
     declare -a opts
     get_build_opts opts
-
+    
     cmake --build "$build_dir" "${opts[@]}" --target help-boards
 }
 
 lint_copyright() {
     ohai "Lint (Copyright)"
-
+    
     "$sbs_base/scripts/linter.py" --copyright "$source_dir/src"
 }
 
 lint_find() {
     ohai "Lint (Find)"
-
+    
     "$sbs_base/scripts/linter.py" --find "$source_dir/src"
 }
 
 lint_clangtidy() {
     declare build_dir="$1"
-
+    
     check_configured "$build_dir" || return
-
+    
     ohai "Lint (clang-tidy)"
-
+    
     defs=(--extra-arg=-D_MIOSIX=1 --extra-arg=-D_MIOSIX_GCC_PATCH_MINOR=1 \
-        --extra-arg=-D_MIOSIX_GCC_PATCH_MAJOR=3 --extra-arg=-D__LINT__)
+    --extra-arg=-D_MIOSIX_GCC_PATCH_MAJOR=3 --extra-arg=-D__LINT__)
     IFS=$'\n' read -rd '' -a incs < \
-        <(arm-miosix-eabi-g++ -E -Wp,-v -xc++ /dev/null 2>&1 \
-            | sed -n "s/^ /--extra-arg=-isystem/p")
-
+    <(arm-miosix-eabi-g++ -E -Wp,-v -xc++ /dev/null 2>&1 \
+    | sed -n "s/^ /--extra-arg=-isystem/p")
+    
     declare opts=()
     [ "$to_edit" = true ] && opts+=(--fix-notes --fix-errors)
-
+    
     find "$source_dir/src" \
-        -type f \( -iname "*.cpp" -o -iname "*.h" -o -iname "*.c" \) \
-        -exec clang-tidy --header-filter=".*" -p="$build_dir" "${defs[@]}" \
-        "${incs[@]}" "${opts[@]}" {} \;
+    -type f \( -iname "*.cpp" -o -iname "*.h" -o -iname "*.c" \) \
+    -exec clang-tidy --header-filter=".*" -p="$build_dir" "${defs[@]}" \
+    "${incs[@]}" "${opts[@]}" {} \;
 }
 
 lint_cppcheck() {
     ohai "Lint (Cppcheck)"
-
+    
     declare -a opts=()
     [ -n "$jobs" ] && opts+=("-j $jobs")
-
-    cppcheck --language=c++ --std=c++11 --enable=all --inline-suppr \
-        --suppress=unmatchedSuppression --suppress=unusedFunction \
-        --suppress=missingInclude --error-exitcode=1 "${opts[@]}" \
-        "$source_dir/src"
+    
+    cppcheck --language=c++ --std=c++14 --enable=all --inline-suppr \
+    --suppress=unmatchedSuppression --suppress=unusedFunction \
+    --suppress=missingInclude --error-exitcode=1 -q "${opts[@]}" \
+    "$source_dir/src"
 }
 
 lint_clangformat() {
     declare to_edit="$1"
-
+    
     ohai "Lint (clang-format)"
-
+    
     declare -a opts=(--style=file --Werror)
     [ "$to_edit" = true ] && opts+=(-i) || opts+=(--dry-run)
-
+    
     find "$source_dir/src" \
-        -type f \( -iname "*.cpp" -o -iname "*.h" -o -iname "*.c" \) \
-        -exec clang-format "${opts[@]}" {} \;
+    -type f \( -iname "*.cpp" -o -iname "*.h" -o -iname "*.c" \) \
+    -exec clang-format "${opts[@]}" {} \;
 }
 
 lint() {
     declare to_edit="$1"
-
+    
     if [ "$found_python" = true ]; then
         lint_copyright
         lint_find
     fi
-
+    
     if [ "$found_clangtidy" = true ] && [ "$lint_clangtidy" = true ]; then
         lint_clangtidy "$build_default_dir"
     fi
-
+    
     if [ "$found_cppcheck" = true ]; then
         lint_cppcheck
     fi
-
+    
     if [ "$found_clangformat" = true ]; then
         lint_clangformat "$to_edit"
     fi
diff --git a/scripts/linter.py b/scripts/linter.py
index 4b2e80586..bbc7b2835 100755
--- a/scripts/linter.py
+++ b/scripts/linter.py
@@ -92,10 +92,6 @@ def print_banner():
     print('+------------------------------+')
 
 
-def linter_print(*strings):
-    print('[linter]', *strings)
-
-
 class Colors():
     BLACK = '\033[30m'
     RED = '\033[31m'
@@ -111,7 +107,7 @@ class Colors():
 
 # Checks for the right copyright notice in all .h and .cpp files
 def check_copyright(directory):
-    linter_print(Colors.GREEN + 'Copyright check' + Colors.RESET)
+    print(Colors.GREEN + 'Copyright check' + Colors.RESET)
 
     # Statistics
     totalCheckdFilesCounter = 0
@@ -134,7 +130,7 @@ def check_copyright(directory):
                     filesWithErrorsCounter += 1
 
                     # The file's copyright notice does not match the template!
-                    linter_print(Colors.YELLOW + 'Wrong copyright notice in file {0}'.format(
+                    print(Colors.YELLOW + 'Wrong copyright notice in file {0}'.format(
                         currentFilepath) + Colors.RESET)
                 else:
                     fileAuthors = [a.strip()
@@ -142,10 +138,10 @@ def check_copyright(directory):
 
                     # Check the number of authors against 'Author' or `Authors`
                     if len(fileAuthors) == 1 and match.group(1)[-1] == 's':
-                        linter_print('\'Authors\' should to be changed to \'Author\' in {0}'.format(
+                        print('\'Authors\' should to be changed to \'Author\' in {0}'.format(
                             currentFilepath))
                     if len(fileAuthors) > 1 and match.group(1)[-1] != 's':
-                        linter_print('\'Author\' should to be changed to \'Authors\' in {0}'.format(
+                        print('\'Author\' should to be changed to \'Authors\' in {0}'.format(
                             currentFilepath))
 
                     # Save statistics on authors
@@ -157,28 +153,29 @@ def check_copyright(directory):
                     averageAuthorsPerFile += len(fileAuthors)
     averageAuthorsPerFile /= totalCheckdFilesCounter
 
-    linter_print('Checked {} files'.format(totalCheckdFilesCounter))
+    print('Checked {} files'.format(totalCheckdFilesCounter))
     if filesWithErrorsCounter == 0:
-        linter_print('All the files have the correct copyright notice')
+        print('All the files have the correct copyright notice')
     else:
-        linter_print(Colors.RED + '{:.1f}% ({}/{}) of all analyzed files do not match with the copyright template!'.format(
+        print(Colors.RED + '{:.1f}% ({}/{}) of all analyzed files do not match with the copyright template!'.format(
             100*filesWithErrorsCounter/totalCheckdFilesCounter, filesWithErrorsCounter, totalCheckdFilesCounter) + Colors.RESET)
 
-    if(not args.quiet):
-        linter_print('{:.2} authors per file'.format(
+    if (not args.quiet):
+        print('{:.2} authors per file'.format(
             averageAuthorsPerFile))
-        linter_print('Number of mentions per author:')
-        for author in authors:
-            linter_print('{:3} - {}'.format(authors[author], author))
+
+        print('Number of mentions per author:')
+        for author in sorted(authors.items(), key=lambda item: item[1], reverse=True):
+            print('{:3} - {}'.format(author[1], author[0]))
 
     # Exit if error if at least one file isn't correct
-    if(filesWithErrorsCounter > 0):
+    if (filesWithErrorsCounter > 0):
         exit(-1)
 
 
 # Checks if all .h and .cpp files respects the clang format specified in .clang-format file
 def check_format(directory):
-    linter_print(Colors.GREEN + 'Formatting check' + Colors.RESET)
+    print(Colors.GREEN + 'Formatting check' + Colors.RESET)
 
     # Statistics
     totalCheckdFilesCounter = 0
@@ -197,27 +194,27 @@ def check_format(directory):
                 ['clang-format', '-style=file', '--dry-run', '--Werror', '--ferror-limit=1', currentFilepath], stderr=DEVNULL)
 
             # If and error occurs warn the user
-            if(returnCode != 0):
+            if (returnCode != 0):
                 filesWithErrorsCounter += 1
 
-                if(not args.quiet):
-                    linter_print(Colors.YELLOW + 'Wrong code format for file {1}'.format(
+                if (not args.quiet):
+                    print(Colors.YELLOW + 'Wrong code format for file {1}'.format(
                         returnCode, currentFilepath) + Colors.RESET)
 
-    linter_print('Checked {} files'.format(totalCheckdFilesCounter))
+    print('Checked {} files'.format(totalCheckdFilesCounter))
     if filesWithErrorsCounter == 0:
-        linter_print('All the files match the Skyward formatting style')
+        print('All the files match the Skyward formatting style')
     else:
-        linter_print(Colors.RED + '{:4.1f}% ({}/{}) of all analyzed files do not match Skyward formatting style!'.format(
+        print(Colors.RED + '{:4.1f}% ({}/{}) of all analyzed files do not match Skyward formatting style!'.format(
             100*filesWithErrorsCounter/totalCheckdFilesCounter, filesWithErrorsCounter, totalCheckdFilesCounter), Colors.RESET)
 
     # Exit if error if at least one file isn't correct
-    if(filesWithErrorsCounter > 0):
+    if (filesWithErrorsCounter > 0):
         exit(-1)
 
 
 def find_in_code(directory, searchTerm, extensionFilters=('.cpp', '.h'), pathFilter=None):
-    linter_print(
+    print(
         Colors.GREEN + 'Checking for \'{}\' in code files'.format(searchTerm) + Colors.RESET)
 
     # Statistics
@@ -243,16 +240,16 @@ def find_in_code(directory, searchTerm, extensionFilters=('.cpp', '.h'), pathFil
                     filesWithErrorsCounter += 1
 
                     # The current file has the error
-                    if(not args.quiet):
-                        linter_print(Colors.YELLOW + 'Found \'{}\' in file {}'.format(searchTerm,
-                                                                                      currentFilepath) + Colors.RESET)
+                    if (not args.quiet):
+                        print(Colors.YELLOW + 'Found \'{}\' in file {}'.format(searchTerm,
+                                                                               currentFilepath) + Colors.RESET)
 
-    linter_print('Checked {} files'.format(totalCheckdFilesCounter))
+    print('Checked {} files'.format(totalCheckdFilesCounter))
     if filesWithErrorsCounter == 0:
-        linter_print(
+        print(
             'All the files does not contain \'{}\''.format(searchTerm))
     else:
-        linter_print(Colors.RED + '{:.1f}% ({}/{}) of all analyzed files contain \'{}\'!'.format(
+        print(Colors.RED + '{:.1f}% ({}/{}) of all analyzed files contain \'{}\'!'.format(
             100*filesWithErrorsCounter/totalCheckdFilesCounter, filesWithErrorsCounter, totalCheckdFilesCounter, searchTerm) + Colors.RESET)
 
     return filesWithErrorsCounter
@@ -260,7 +257,8 @@ def find_in_code(directory, searchTerm, extensionFilters=('.cpp', '.h'), pathFil
 
 def check_find(directory):
     sum = find_in_code(directory, r'^using namespace', '.h')
-    sum += find_in_code(directory, r'[^a-zA-Z0-9]printf\(', pathFilter='shared')
+    sum += find_in_code(directory,
+                        r'[^a-zA-Z0-9]printf\(', pathFilter='shared')
     sum += find_in_code(directory, r'( |^)assert\(')
     sum += find_in_code(directory, '^ *throw ', pathFilter='catch')
 
@@ -269,7 +267,7 @@ def check_find(directory):
 
 
 def check_cppcheck(directory):
-    linter_print(Colors.GREEN + 'cppcheck' + Colors.RESET)
+    print(Colors.GREEN + 'cppcheck' + Colors.RESET)
     # Run cppcheck on the directory
     try:
         result = check_output(['cppcheck', '-q', '--language=c++', '--template=gcc', '--std=c++11', '--enable=all', '--inline-suppr',
@@ -280,21 +278,21 @@ def check_cppcheck(directory):
         errors = re.findall(r'\[(\w+)\]', result.decode('utf-8'))
         errors = Counter(errors)
 
-        if(not args.quiet):
-            linter_print('cppcheck found the following errors:')
+        if (not args.quiet):
+            print('cppcheck found the following errors:')
             for error in errors:
-                linter_print('{:3} - {}'.format(errors[error], error))
+                print('{:3} - {}'.format(errors[error], error))
 
         totalErrors = sum(errors.values())
-        if(totalErrors > 0):
-            linter_print(
+        if (totalErrors > 0):
+            print(
                 Colors.RED + 'cppcheck found {} errors in total'.format(totalErrors) + Colors.RESET)
             exit(-1)
         else:
-            linter_print('cppcheck did not find any errors')
+            print('cppcheck did not find any errors')
 
     except CalledProcessError as e:
-        linter_print(e.output.decode('utf-8'))
+        print(e.output.decode('utf-8'))
         exit(-1)
 
 # -------------------------------------------------------------
@@ -305,26 +303,26 @@ def check_cppcheck(directory):
 parser = config_cmd_parser()
 args = parser.parse_args()
 
-if(not args.directory):
-    linter_print('No directory specified')
+if (not args.directory):
+    print('No directory specified')
     print('')
     parser.print_help()
     exit(-1)
 
-if(args.copyright):
+if (args.copyright):
     check_copyright(args.directory)
 
-if(args.format):
+if (args.format):
     check_format(args.directory)
 
-if(args.cppcheck):
+if (args.cppcheck):
     check_cppcheck(args.directory)
 
-if(args.find):
+if (args.find):
     check_find(args.directory)
 
 # Checks everything if no option is specified
-if(not args.copyright and not args.format and not args.find and not args.cppcheck):
+if (not args.copyright and not args.format and not args.find and not args.cppcheck):
     check_copyright(args.directory)
     check_format(args.directory)
     check_find(args.directory)
-- 
GitLab