From 3c371491a2d5023060391ff54b924bf1c7a0c41f Mon Sep 17 00:00:00 2001 From: Siddhartha Bagaria Date: Mon, 30 Mar 2020 14:20:58 -0400 Subject: [PATCH] Setup clang-format as an Arcanist linter Summary: This uses clang-format-diff as a linter for Arcanist. `arc lint` flow, also run as part of `arc diff` unless skipped with `--nolint`, will now run the linter shell script on the changed files, and prompt the user to accept the suggested changes. Message when clang-format-diff is not installed: {F6654094} Example of the noise during code review when clang-format-diff is not installed: https://reviews.llvm.org/differential/changeset/?ref=1115809 Prompt when clang-format-diff is installed and suggests edits: {F6650223} Reviewers: probinson, scott.linder Reviewed By: scott.linder Subscribers: scott.linder, MyDeveloperDay, JonasToth, danilaml, JDevlieghere, dberris, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D49116 --- .arclint | 12 +++++++ utils/arcanist/clang-format.sh | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) create mode 100644 .arclint create mode 100755 utils/arcanist/clang-format.sh diff --git a/.arclint b/.arclint new file mode 100644 index 000000000000..01de1ee897ad --- /dev/null +++ b/.arclint @@ -0,0 +1,12 @@ +{ + "linters": { + "clang-format": { + "type": "script-and-regex", + "script-and-regex.script": "utils/arcanist/clang-format.sh", + "script-and-regex.regex": "/^(?P[[:alpha:]]+)\n(?P[^\n]+)\n(====|(?P\\d),(?P\\d)\n(?P.*)>>>>\n(?P.*)<<<<\n)$/s", + "include": [ + "(\\.(cc|cpp|h)$)" + ] + } + } +} diff --git a/utils/arcanist/clang-format.sh b/utils/arcanist/clang-format.sh new file mode 100755 index 000000000000..7ba70681bc15 --- /dev/null +++ b/utils/arcanist/clang-format.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -euo pipefail + +# "script-and-regex.regex": "/^(?P.*?)\n(?P.*?)\n(?P\\d),(?P\\d)(\n(?P.*?)>>>>\n(?P.*?)<<</dev/null; then + # advice severity level is completely non-disruptive. + # switch to warning or error if you want to prompt the user. + echo "advice" + echo "clang-format-diff not found in user's PATH; not linting file." + echo "====" + exit 0 +fi + +src_file="${1}" +original_file="$(mktemp)" +formatted_file="$(mktemp)" +readonly src_file +readonly original_file +readonly formatted_file +cp -p "${src_file}" "${original_file}" +cp -p "${src_file}" "${formatted_file}" + +cleanup() { + rc=$? + rm "${formatted_file}" "${original_file}" + exit ${rc} +} +trap 'cleanup' INT HUP QUIT TERM EXIT + +# Arcanist can filter out lint messages for unchanged lines, but for that, we +# need to generate line by line lint messages. Instead, we generate one lint +# message on line 1, char 1 with file content edited using clang-format-diff. +if git rev-parse --git-dir >/dev/null; then + arc_base_commit=$(arc which --show-base) + # An alternative is to use git-clang-format. + git diff -U0 --no-color "${arc_base_commit}"| clang-format-diff -style LLVM -i -p1 +else + svn diff --diff-cmd=diff -x -U0 "${src_file}" | clang-format-diff -style LLVM -i +fi + +cp -p "${src_file}" "${formatted_file}" +cp -p "${original_file}" "${src_file}" +if ! diff -q "${src_file}" "${formatted_file}" > /dev/null ; then + echo "autofix" + echo "clang-format suggested style edits found:" + echo "1,1" # line,char of start of replacement. + cat "${src_file}" + echo ">>>>" + cat "${formatted_file}" + echo "<<<<" +fi