1#!/bin/bash
2#
3# Copyright (C) 2018 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18function _log()
19{
20    echo -e "$*" >&2
21}
22
23function _eval()
24{
25    local label="$1"
26    local cmd="$2"
27    local red="\e[31m"
28    local green="\e[32m"
29    local reset="\e[0m"
30
31    _log "${green}[ RUN      ]${reset} ${label}"
32    local output="$(eval "$cmd")"
33    if [[ -z "${output}" ]]; then
34        _log "${green}[       OK ]${reset} ${label}"
35        return 0
36    else
37        echo "${output}"
38        _log "${red}[  FAILED  ]${reset} ${label}"
39        errors=$((errors + 1))
40        return 1
41    fi
42}
43
44function _clang_format()
45{
46    local path
47    local errors=0
48
49    for path in $cpp_files; do
50        local output="$(clang-format -style=file "$path" | diff $path -)"
51        if [[ "$output" ]]; then
52            echo "$path"
53            echo "$output"
54            errors=1
55        fi
56    done
57    return $errors
58}
59
60function _bpfmt()
61{
62    local output="$(bpfmt -d $bp_files)"
63    if [[ "$output" ]]; then
64        echo "$output"
65        return 1
66    fi
67    return 0
68}
69
70function _cpplint()
71{
72    local cpplint="${ANDROID_BUILD_TOP}/tools/repohooks/tools/cpplint.py"
73    local output="$($cpplint --quiet $cpp_files 2>&1 >/dev/null | grep -v \
74        -e 'Found C system header after C++ system header.' \
75        -e 'Unknown NOLINT error category: cert-dcl50-cpp' \
76        -e 'Unknown NOLINT error category: misc-non-private-member-variables-in-classes' \
77        -e 'Unknown NOLINT error category: performance-unnecessary-copy-initialization' \
78    )"
79    if [[ "$output" ]]; then
80        echo "$output"
81        return 1
82    fi
83    return 0
84}
85
86function _parse_args()
87{
88    local opts
89
90    opts="$(getopt -o cfh --long check,fix,help -- "$@")"
91    if [[ $? -ne 0 ]]; then
92        exit 1
93    fi
94    eval set -- "$opts"
95    while true; do
96        case "$1" in
97            -c|--check) opt_mode="check"; shift ;;
98            -f|--fix) opt_mode="fix"; shift ;;
99            -h|--help) opt_mode="help"; shift ;;
100            *) break ;;
101        esac
102    done
103}
104
105errors=0
106script="$(readlink -f "$BASH_SOURCE")"
107prefix="$(dirname "$script")"
108cpp_files="$(find "$prefix" -name '*.cpp' -or -name '*.h')"
109bp_files="$(find "$prefix" -name 'Android.bp')"
110opt_mode="check"
111
112_parse_args "$@"
113if [[ $opt_mode == "check" ]]; then
114    _eval "clang-format" "_clang_format"
115    _eval "bpfmt" "_bpfmt"
116    _eval "cpplint" "_cpplint"
117    exit $errors
118elif [[ $opt_mode == "fix" ]]; then
119    clang-format -style=file -i $cpp_files
120    bpfmt -w $bp_files
121    exit 0
122elif [[ $opt_mode == "help" ]]; then
123    echo "Run static analysis tools such as clang-format and cpplint on the idmap2"
124    echo "module. Optionally fix some of the issues found (--fix). Intended to be run"
125    echo "before merging any changes."
126    echo
127    echo "usage: $(basename $script) [--check|--fix|--help]"
128    exit 0
129else
130    exit 1
131fi
132