From 913da3d054c0d829bf83d15c9f2cf9d4240dd12d Mon Sep 17 00:00:00 2001 From: allonli Date: Sun, 20 May 2018 18:26:21 +0800 Subject: [PATCH] using cpplint check code style --- .clang-tidy | 2 +- .pre-commit-config.yaml | 24 +- tools/pre-commit.hooks/.clang-format.hook | 24 +- tools/pre-commit.hooks/.clang-tidy.hook | 8 +- tools/pre-commit.hooks/.cpplint.hook | 11 + tools/pre-commit.hooks/copyright.py | 143 ----------- tools/pre-commit.hooks/run-clang-tidy.py | 296 ---------------------- 7 files changed, 46 insertions(+), 462 deletions(-) create mode 100644 tools/pre-commit.hooks/.cpplint.hook delete mode 100755 tools/pre-commit.hooks/copyright.py delete mode 100755 tools/pre-commit.hooks/run-clang-tidy.py diff --git a/.clang-tidy b/.clang-tidy index 7e57ba312f..c788efe69d 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -39,7 +39,7 @@ Checks: > -modernize-use-default-member-init -clang-diagnostic-* -clang-analyzer-* -WarningsAsErrors: '' +WarningsAsErrors: '*' HeaderFilterRegex: '' AnalyzeTemporaryDtors: false FormatStyle: none diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8c8dfb2c0b..993405142b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -27,17 +27,27 @@ repos: description: Format files with ClangFormat. entry: bash ./tools/pre-commit.hooks/.clang-format.hook -i language: system - files: \.(c|cc|cxx|cpp|h|hpp|hxx)$ + files: (src).*\.(c|cc|cxx|cpp|h|hpp|hxx)$ + +# +#- repo: local +# hooks: +# - id: clang-tidy +# name: clang-tidy +# description: Check C++ code style using clang-tidy. +# entry: bash ./tools/pre-commit.hooks/.clang-tidy.hook -i +# language: system +# files: (src).*\.(c|cc|cxx|cpp|h|hpp|hxx)$ - repo: local hooks: - - id: clang-tidy - name: clang-tidy - description: Check C++ code style using clang-tidy. - entry: bash ./tools/pre-commit.hooks/.clang-tidy.hook -i + - id: cpplint + name: cpplint + description: Check C++ code style using cpplint. + entry: bash ./tools/pre-commit.hooks/.cpplint.hook language: system - files: (src).*\.(c|cc|cxx|cpp|h|hpp|hxx)$ -# + files: (src).*\.(c|cc|cxx|cpp|cu|h|hpp|hxx)$ + exclude: (?!.*third_party)^.*$ | (?!.*book)^.*$i | *\.pb\.cpp #- repo: local # hooks: # - id: copyright_checker diff --git a/tools/pre-commit.hooks/.clang-format.hook b/tools/pre-commit.hooks/.clang-format.hook index b56c5e7fa7..406850d1a2 100644 --- a/tools/pre-commit.hooks/.clang-format.hook +++ b/tools/pre-commit.hooks/.clang-format.hook @@ -1,15 +1,15 @@ #!/bin/bash -#set -e -# -#readonly VERSION="3.8" -# -#version=$(clang-format -version) -# -#if ! [[ $version == *"$VERSION"* ]]; then -# echo "clang-format version check failed." -# echo "a version contains '$VERSION' is needed, but get '$version'" -# echo "you can install the right version, and make an soft-link to '\$PATH' env" -# exit -1 -#fi +set -e + +readonly VERSION="5.0" + +version=$(clang-format -version) + +if ! [[ $version == *"$VERSION"* ]]; then + echo "clang-format version check failed." + echo "a version contains '$VERSION' is needed, but get '$version'" + echo "you can install the right version, and make an soft-link to '\$PATH' env" + exit -1 +fi clang-format $@ diff --git a/tools/pre-commit.hooks/.clang-tidy.hook b/tools/pre-commit.hooks/.clang-tidy.hook index 3b0445e20f..2d7847c330 100755 --- a/tools/pre-commit.hooks/.clang-tidy.hook +++ b/tools/pre-commit.hooks/.clang-tidy.hook @@ -5,12 +5,14 @@ bash -c "cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" TOTAL_ERRORS=0 # The trick to remove deleted files: https://stackoverflow.com/a/2413151 -for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}' | grep -v "third-party/" | grep -v ".pb."); do - bash -c "python ./tools/pre-commit.hooks/run-clang-tidy.py $file -fix"; +for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}' | grep "src/" | grep -v ".pb." | grep -v ".h"); do + echo "clang-tidy check $file"; + clang-tidy $file --fix --fix-errors --header-filter=.* TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?); + echo "clang-tidy error TOTAL_ERRORS = $TOTAL_ERRORS . " done -rm -f compile_commands.json +rm -f compile_commands.json exit $TOTAL_ERRORS diff --git a/tools/pre-commit.hooks/.cpplint.hook b/tools/pre-commit.hooks/.cpplint.hook new file mode 100644 index 0000000000..15541fc0be --- /dev/null +++ b/tools/pre-commit.hooks/.cpplint.hook @@ -0,0 +1,11 @@ +#!/bin/bash + +TOTAL_ERRORS=0 + +# The trick to remove deleted files: https://stackoverflow.com/a/2413151 +for file in $(git diff --cached --name-status | awk '$1 != "D" {print $2}' | grep -v ".pb.cpp" | grep -v ".pb.h"); do + cpplint $file; + TOTAL_ERRORS=$(expr $TOTAL_ERRORS + $?); +done + +exit $TOTAL_ERRORS diff --git a/tools/pre-commit.hooks/copyright.py b/tools/pre-commit.hooks/copyright.py deleted file mode 100755 index 50fc860ee2..0000000000 --- a/tools/pre-commit.hooks/copyright.py +++ /dev/null @@ -1,143 +0,0 @@ -# Copyright (c) 2016 Baidu, Inc. All Rights Reserved. -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import -from __future__ import print_function -from __future__ import unicode_literals - -import argparse -import io, re -import sys, os -import subprocess -import platform - -COPYRIGHT = ''' -/* Copyright (c) 2016 Baidu, Inc. All Rights Reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -==============================================================================*/ -''' - -LANG_COMMENT_MARK = None - -NEW_LINE_MARK = None - -COPYRIGHT_HEADER = None - -if platform.system() == "Windows": - NEW_LINE_MARK = "\r\n" -else: - NEW_LINE_MARK = '\n' - COPYRIGHT_HEADER = COPYRIGHT.split(NEW_LINE_MARK)[1] - p = re.search('(\d{4})', COPYRIGHT_HEADER).group(0) - process = subprocess.Popen(["date", "+%Y"], stdout=subprocess.PIPE) - date, err = process.communicate() - date = date.decode("utf-8").rstrip("\n") - COPYRIGHT_HEADER = COPYRIGHT_HEADER.replace(p, date) - - -def generate_copyright(template, lang='C'): - if lang == 'Python': - LANG_COMMENT_MARK = '#' - else: - LANG_COMMENT_MARK = "//" - - lines = template.split(NEW_LINE_MARK) - BLANK = " " - ans = LANG_COMMENT_MARK + BLANK + COPYRIGHT_HEADER + NEW_LINE_MARK - for lino, line in enumerate(lines): - if lino == 0 or lino == 1 or lino == len(lines) - 1: continue - if len(line) == 0: - BLANK = "" - else: - BLANK = " " - ans += LANG_COMMENT_MARK + BLANK + line + NEW_LINE_MARK - - return ans + "\n" - - -def lang_type(filename): - if filename.endswith(".py"): - return "Python" - elif filename.endswith(".h"): - return "C" - elif filename.endswith(".c"): - return "C" - elif filename.endswith(".hpp"): - return "C" - elif filename.endswith(".cc"): - return "C" - elif filename.endswith(".cpp"): - return "C" - elif filename.endswith(".cu"): - return "C" - elif filename.endswith(".cuh"): - return "C" - elif filename.endswith(".go"): - return "C" - elif filename.endswith(".proto"): - return "C" - else: - print("Unsupported filetype %s", filename) - exit(0) - - -PYTHON_ENCODE = re.compile("^[ \t\v]*#.*?coding[:=][ \t]*([-_.a-zA-Z0-9]+)") - - -def main(argv=None): - parser = argparse.ArgumentParser( - description='Checker for copyright declaration.') - parser.add_argument('filenames', nargs='*', help='Filenames to check') - args = parser.parse_args(argv) - - retv = 0 - for filename in args.filenames: - fd = io.open(filename, encoding="utf-8") - first_line = fd.readline() - second_line = fd.readline() - if "COPYRIGHT " in first_line.upper(): continue - if first_line.startswith("#!") or PYTHON_ENCODE.match( - second_line) != None or PYTHON_ENCODE.match( - first_line) != None: - continue - original_contents = io.open(filename, encoding="utf-8").read() - new_contents = generate_copyright( - COPYRIGHT, lang_type(filename)) + original_contents - print('Auto Insert Copyright Header {}'.format(filename)) - retv = 1 - with io.open(filename, 'w') as output_file: - output_file.write(new_contents) - - return retv - - -if __name__ == '__main__': - exit(main()) diff --git a/tools/pre-commit.hooks/run-clang-tidy.py b/tools/pre-commit.hooks/run-clang-tidy.py deleted file mode 100755 index 379ad713be..0000000000 --- a/tools/pre-commit.hooks/run-clang-tidy.py +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env python -# -#===- run-clang-tidy.py - Parallel clang-tidy runner ---------*- python -*--===# -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -#===------------------------------------------------------------------------===# -# FIXME: Integrate with clang-tidy-diff.py - -""" -Parallel clang-tidy runner -========================== - -Runs clang-tidy over all files in a compilation database. Requires clang-tidy -and clang-apply-replacements in $PATH. - -Example invocations. -- Run clang-tidy on all files in the current working directory with a default - set of checks and show warnings in the cpp files and all project headers. - run-clang-tidy.py $PWD - -- Fix all header guards. - run-clang-tidy.py -fix -checks=-*,llvm-header-guard - -- Fix all header guards included from clang-tidy and header guards - for clang-tidy headers. - run-clang-tidy.py -fix -checks=-*,llvm-header-guard extra/clang-tidy \ - -header-filter=extra/clang-tidy - -Compilation database setup: -http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html -""" - -from __future__ import print_function - -import argparse -import glob -import json -import multiprocessing -import os -import re -import shutil -import subprocess -import sys -import tempfile -import threading -import traceback -import yaml - -is_py2 = sys.version[0] == '2' - -if is_py2: - import Queue as queue -else: - import queue as queue - -def find_compilation_database(path): - """Adjusts the directory until a compilation database is found.""" - result = './' - while not os.path.isfile(os.path.join(result, path)): - if os.path.realpath(result) == '/': - print('Error: could not find compilation database.') - sys.exit(1) - result += '../' - return os.path.realpath(result) - - -def make_absolute(f, directory): - if os.path.isabs(f): - return f - return os.path.normpath(os.path.join(directory, f)) - - -def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path, - header_filter, extra_arg, extra_arg_before, quiet): - """Gets a command line for clang-tidy.""" - start = [clang_tidy_binary] - if header_filter is not None: - start.append('-header-filter=' + header_filter) - else: - # Show warnings in all in-project headers by default. - start.append('-header-filter=^' + build_path + '/.*') - if checks: - start.append('-checks=' + checks) - if tmpdir is not None: - start.append('-export-fixes') - # Get a temporary file. We immediately close the handle so clang-tidy can - # overwrite it. - (handle, name) = tempfile.mkstemp(suffix='.yaml', dir=tmpdir) - os.close(handle) - start.append(name) - for arg in extra_arg: - start.append('-extra-arg=%s' % arg) - for arg in extra_arg_before: - start.append('-extra-arg-before=%s' % arg) - start.append('-p=' + build_path) - if quiet: - start.append('-quiet') - start.append(f) - return start - - -def merge_replacement_files(tmpdir, mergefile): - """Merge all replacement files in a directory into a single file""" - # The fixes suggested by clang-tidy >= 4.0.0 are given under - # the top level key 'Diagnostics' in the output yaml files - mergekey="Diagnostics" - merged=[] - for replacefile in glob.iglob(os.path.join(tmpdir, '*.yaml')): - content = yaml.safe_load(open(replacefile, 'r')) - if not content: - continue # Skip empty files. - merged.extend(content.get(mergekey, [])) - - if merged: - # MainSourceFile: The key is required by the definition inside - # include/clang/Tooling/ReplacementsYaml.h, but the value - # is actually never used inside clang-apply-replacements, - # so we set it to '' here. - output = { 'MainSourceFile': '', mergekey: merged } - with open(mergefile, 'w') as out: - yaml.safe_dump(output, out) - else: - # Empty the file: - open(mergefile, 'w').close() - - -def check_clang_apply_replacements_binary(args): - """Checks if invoking supplied clang-apply-replacements binary works.""" - try: - subprocess.check_call([args.clang_apply_replacements_binary, '--version']) - except: - print('Unable to run clang-apply-replacements. Is clang-apply-replacements ' - 'binary correctly specified?', file=sys.stderr) - traceback.print_exc() - sys.exit(1) - - -def apply_fixes(args, tmpdir): - """Calls clang-apply-fixes on a given directory.""" - invocation = [args.clang_apply_replacements_binary] - if args.format: - invocation.append('-format') - if args.style: - invocation.append('-style=' + args.style) - invocation.append(tmpdir) - subprocess.call(invocation) - - -def run_tidy(args, tmpdir, build_path, queue): - """Takes filenames out of queue and runs clang-tidy on them.""" - while True: - name = queue.get() - invocation = get_tidy_invocation(name, args.clang_tidy_binary, args.checks, - tmpdir, build_path, args.header_filter, - args.extra_arg, args.extra_arg_before, - args.quiet) - sys.stdout.write(' '.join(invocation) + '\n') - subprocess.call(invocation) - queue.task_done() - - -def main(): - parser = argparse.ArgumentParser(description='Runs clang-tidy over all files ' - 'in a compilation database. Requires ' - 'clang-tidy and clang-apply-replacements in ' - '$PATH.') - parser.add_argument('-clang-tidy-binary', metavar='PATH', - default='clang-tidy', - help='path to clang-tidy binary') - parser.add_argument('-clang-apply-replacements-binary', metavar='PATH', - default='clang-apply-replacements', - help='path to clang-apply-replacements binary') - parser.add_argument('-checks', default=None, - help='checks filter, when not specified, use clang-tidy ' - 'default') - parser.add_argument('-header-filter', default=None, - help='regular expression matching the names of the ' - 'headers to output diagnostics from. Diagnostics from ' - 'the main file of each translation unit are always ' - 'displayed.') - parser.add_argument('-export-fixes', metavar='filename', dest='export_fixes', - help='Create a yaml file to store suggested fixes in, ' - 'which can be applied with clang-apply-replacements.') - parser.add_argument('-j', type=int, default=0, - help='number of tidy instances to be run in parallel.') - parser.add_argument('files', nargs='*', default=['.*'], - help='files to be processed (regex on path)') - parser.add_argument('-fix', action='store_true', help='apply fix-its') - parser.add_argument('-format', action='store_true', help='Reformat code ' - 'after applying fixes') - parser.add_argument('-style', default='file', help='The style of reformat ' - 'code after applying fixes') - parser.add_argument('-p', dest='build_path', - help='Path used to read a compile command database.') - parser.add_argument('-extra-arg', dest='extra_arg', - action='append', default=[], - help='Additional argument to append to the compiler ' - 'command line.') - parser.add_argument('-extra-arg-before', dest='extra_arg_before', - action='append', default=[], - help='Additional argument to prepend to the compiler ' - 'command line.') - parser.add_argument('-quiet', action='store_true', - help='Run clang-tidy in quiet mode') - args = parser.parse_args() - - db_path = 'compile_commands.json' - - if args.build_path is not None: - build_path = args.build_path - else: - # Find our database - build_path = find_compilation_database(db_path) - - try: - invocation = [args.clang_tidy_binary, '-list-checks'] - invocation.append('-p=' + build_path) - if args.checks: - invocation.append('-checks=' + args.checks) - invocation.append('-') - subprocess.check_call(invocation) - except: - print("Unable to run clang-tidy.", file=sys.stderr) - sys.exit(1) - - # Load the database and extract all files. - database = json.load(open(os.path.join(build_path, db_path))) - files = [make_absolute(entry['file'], entry['directory']) - for entry in database] - - max_task = args.j - if max_task == 0: - max_task = multiprocessing.cpu_count() - - tmpdir = None - if args.fix or args.export_fixes: - check_clang_apply_replacements_binary(args) - tmpdir = tempfile.mkdtemp() - - # Build up a big regexy filter from all command line arguments. - file_name_re = re.compile('|'.join(args.files)) - - try: - # Spin up a bunch of tidy-launching threads. - task_queue = queue.Queue(max_task) - for _ in range(max_task): - t = threading.Thread(target=run_tidy, - args=(args, tmpdir, build_path, task_queue)) - t.daemon = True - t.start() - - # Fill the queue with files. - for name in files: - if file_name_re.search(name): - task_queue.put(name) - - # Wait for all threads to be done. - task_queue.join() - - except KeyboardInterrupt: - # This is a sad hack. Unfortunately subprocess goes - # bonkers with ctrl-c and we start forking merrily. - print('\nCtrl-C detected, goodbye.') - if tmpdir: - shutil.rmtree(tmpdir) - os.kill(0, 9) - - return_code = 0 - if args.export_fixes: - print('Writing fixes to ' + args.export_fixes + ' ...') - try: - merge_replacement_files(tmpdir, args.export_fixes) - except: - print('Error exporting fixes.\n', file=sys.stderr) - traceback.print_exc() - return_code=1 - - if args.fix: - print('Applying fixes ...') - try: - apply_fixes(args, tmpdir) - except: - print('Error applying fixes.\n', file=sys.stderr) - traceback.print_exc() - return_code=1 - - if tmpdir: - shutil.rmtree(tmpdir) - sys.exit(return_code) - -if __name__ == '__main__': - main() -- GitLab