diff --git a/.clang-format b/.clang-format index 96b776d99..22729e92b 100644 --- a/.clang-format +++ b/.clang-format @@ -104,6 +104,7 @@ AccessModifierOffset: -4 IndentWidth: 4 InsertBraces: true InsertNewlineAtEOF: true +DerivePointerAlignment: true SpaceBeforeInheritanceColon: true SpaceBeforeParens: ControlStatements SortIncludes: Never diff --git a/.github/workflows/format_check.yml b/.github/workflows/format_check.yml index eb716b5cf..631a92afb 100644 --- a/.github/workflows/format_check.yml +++ b/.github/workflows/format_check.yml @@ -1,23 +1,23 @@ +# Copyright ARDUINO SRL (https://www.arduino.cc) +# SPDX-License-Identifier: Apache-2.0 + +# CI workflow to check formatting name: 'Format Check' on: push: - branches: - - 'main' - pull_request: - types: - - opened - - edited - - reopened - - synchronize - branches: - - 'main' jobs: verify-format: runs-on: ubuntu-latest steps: + - name: Install clang + working-directory: /opt + run: | + sudo apt-get remove --purge man-db -y # skips the mandb triggers + sudo apt-get update + sudo apt-get install -y --no-install-recommends clang-19 - name: Checkout code uses: actions/checkout@v4 with: @@ -33,21 +33,17 @@ jobs: libraries/**/*.{c,cpp,h,hpp} files_ignore: | cores/arduino/api/** - loader/llext_exports.c loader/blobs/4343WA1_*.c loader/blobs/wifi_nvram_image.h libraries/examples/** libraries/extras/** libraries/ea_malloc/** json: true - - name: Export changed files in a text file, one per line + - name: Run clang-format checks if: steps.changed-files.outputs.any_changed == 'true' + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_NUMBER: ${{ github.event.pull_request.number }} run: | echo ${{ steps.changed-files.outputs.all_changed_files }} | jq -r '.[]' > all_changed_files.txt - cat all_changed_files.txt - - name: Run clang-format check - if: steps.changed-files.outputs.any_changed == 'true' - uses: pillo79/clang-format-action@05f671e71f0758aba4d3c9dbb0ee81bc5f0137c6 - with: - clang-format-version: '19' - check-files-from: all_changed_files.txt + ./extra/ci_clang_check.sh -f all_changed_files.txt diff --git a/extra/ci_clang_check.sh b/extra/ci_clang_check.sh new file mode 100755 index 000000000..13efcf8af --- /dev/null +++ b/extra/ci_clang_check.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash + +# Copyright ARDUINO SRL +# SPDX-License-Identifier: Apache-2.0 + +# parse arguments +while getopts "p:f:o:r:e:i:" opt; do + case $opt in + p) CHECK_PATH="$OPTARG" ;; + f) CHECK_FILES_FROM="$OPTARG" ;; + e) EXCLUDE_REGEX="$OPTARG" ;; + i) INCLUDE_REGEX="$OPTARG" ;; + *) echo "Invalid option: -$OPTARG" >&2 ; exit 1 ;; + esac +done + +if [[ -z "$CHECK_FILES_FROM" ]] && [[ -z "$CHECK_PATH" ]]; then + echo "No source input provided. Fallback to all files." >&2 + CHECK_PATH="." +elif [[ -f "$CHECK_FILES_FROM" ]]; then + echo "Checking files listed in 'check-files-from'." >&2 +elif [[ ! -z "$CHECK_PATH" ]] && [[ -d "$CHECK_PATH" ]]; then + echo "Checking directory specified by 'check-path'." >&2 +else + echo "::warning::Invalid inputs provided. Fallback to all files." >&2 + CHECK_FILES_FROM="" + CHECK_PATH="." +fi + +# Set the regex to an empty string regex if nothing was provided +if [[ -z $EXCLUDE_REGEX ]]; then + EXCLUDE_REGEX="^$" +fi + +# Set the filetype regex if nothing was provided. +# Find all C/C++/Protobuf/CUDA files: +# h, H, hpp, hh, h++, hxx +# c, C, cpp, cc, c++, cxx +# ino, pde +# proto +# cu +if [[ -z $INCLUDE_REGEX ]]; then + INCLUDE_REGEX='^.*\.((((c|C)(c|pp|xx|\+\+)?$)|((h|H)h?(pp|xx|\+\+)?$))|(ino|pde|proto|cu))$' +fi + +cd "$GITHUB_WORKSPACE" || exit 2 + +if [[ -f "$CHECK_FILES_FROM" ]]; then + # Use the provided list of files to check. + src_files=$(grep -E "$INCLUDE_REGEX" "$CHECK_FILES_FROM") +else + # Find all source files in the provided path, excluding .git directories. + src_files=$(find "$CHECK_PATH" -name .git -prune -o -regextype posix-egrep -regex "$INCLUDE_REGEX" -print) +fi + +exit_code=0 +IFS=$'\n' # Loop below should separate on new lines, not spaces. +for file in $src_files; do + # Only check formatting if the path doesn't match the regex + [[ ${file} =~ $EXCLUDE_REGEX ]] && continue + + clang-format -i -style=file "${file}" 2>&1 + changes=$(git diff -U0 --color=always ${file}) + [ -z "$changes" ] && continue + + exit_code=1 + echo "$changes" | tail -n +5 | while IFS= read -r line ; do + if [[ $line =~ @@\ -([0-9]+),?([0-9]*)\ \+([0-9]+),?([0-9]*)\ @@ ]]; then + # Extract the line numbers from the diff output + git_start_line=${BASH_REMATCH[1]} + git_line_count=${BASH_REMATCH[2]:-1} + # fixed_start_line=${BASH_REMATCH[3]} + # fixed_line_count=${BASH_REMATCH[4]:-1} + + git_end_line=$((git_start_line + git_line_count - 1)) + + echo "---" + echo "::error file=${file},line=${git_start_line},endLine=${git_end_line},title=Fix this formatting::${file}, lines ${git_start_line}-${git_end_line}:" + else + # diff line, print it as is (with color) + echo "$line" + fi + done +done + +[ "$exit_code" -ne 0 ] && echo "---" + +exit $exit_code