zinovy.nis created this revision.
zinovy.nis added reviewers: alexfh, bkramer.
zinovy.nis added a project: clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun.
Herald added a reviewer: serge-sans-paille.
Herald added a project: clang.
This patch adds a new `--diff[=2]` option to `run-clang-tidy.py` to run
`clang-tidy` checks against the given diff only, instead of the whole file.
Usage:
git show -U2 | /some/path/1/run-clang-tidy.py --diff=1 -clang-tidy-binary
/some/path/2/clang-tidy.exe -p out/Debug -checks=-*,performance-* option_regex
Repository:
rCTE Clang Tools Extra
https://reviews.llvm.org/D59449
Files:
clang-tidy/tool/run-clang-tidy.py
Index: clang-tidy/tool/run-clang-tidy.py
===================================================================
--- clang-tidy/tool/run-clang-tidy.py
+++ clang-tidy/tool/run-clang-tidy.py
@@ -7,7 +7,6 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===------------------------------------------------------------------------===#
-# FIXME: Integrate with clang-tidy-diff.py
"""
Parallel clang-tidy runner
@@ -56,6 +55,10 @@
else:
import queue as queue
+quote = ""
+if sys.platform != 'win32':
+ quote = "'"
+
def find_compilation_database(path):
"""Adjusts the directory until a compilation database is found."""
result = './'
@@ -73,7 +76,7 @@
return os.path.normpath(os.path.join(directory, f))
-def get_tidy_invocation(f, clang_tidy_binary, checks, tmpdir, build_path,
+def get_tidy_invocation(f, lines, clang_tidy_binary, checks, tmpdir, build_path,
header_filter, extra_arg, extra_arg_before, quiet,
config):
"""Gets a command line for clang-tidy."""
@@ -83,6 +86,12 @@
else:
# Show warnings in all in-project headers by default.
start.append('-header-filter=^' + build_path + '/.*')
+
+ if lines is not None:
+ line_json = json.dumps([{"name": f, "lines": lines}], separators=(',', ':'))
+ # Run clang-tidy on files containing changes.
+ start.append('-line-filter=' + quote + line_json + quote)
+
if checks:
start.append('-checks=' + checks)
if tmpdir is not None:
@@ -155,8 +164,9 @@
def run_tidy(args, tmpdir, build_path, queue, lock, failed_files):
"""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,
+ (name, lines) = queue.get()
+ invocation = get_tidy_invocation(name, lines,
+ args.clang_tidy_binary, args.checks,
tmpdir, build_path, args.header_filter,
args.extra_arg, args.extra_arg_before,
args.quiet, args.config)
@@ -172,11 +182,42 @@
queue.task_done()
+def get_changed_lines(prefix_len):
+ iregex = '^%s$' % r'.*\.(cpp|cc|c\+\+|cxx|c|cl|h|hpp|m|mm|inc)'
+ lines_by_file = {}
+ filename = None
+ for line in sys.stdin:
+ match = re.search('^\+\+\+\ \"?(.*?/){%s}([^ \t\n\"]*)' % prefix_len, line)
+ if match:
+ filename = match.group(2)
+ if filename is None:
+ continue
+
+ if not re.match(iregex, filename, re.IGNORECASE):
+ continue
+
+ match = re.search('^@@.*\+(\d+)(,(\d+))?', line)
+ if match:
+ start_line = int(match.group(1))
+ line_count = 1
+ if match.group(3):
+ line_count = int(match.group(3))
+ if line_count == 0:
+ continue
+ end_line = start_line + line_count - 1
+ lines_by_file.setdefault(filename, []).append([start_line, end_line])
+
+ return lines_by_file
+
+
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('--diff', default=None, const=2, nargs='?', type=int,
+ help='check only the diff read from stdin.'
+ ' Strip the smallest prefix containing DIFF[=2] slashes')
parser.add_argument('-clang-tidy-binary', metavar='PATH',
default='clang-tidy',
help='path to clang-tidy binary')
@@ -244,11 +285,6 @@
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()
@@ -260,6 +296,16 @@
# Build up a big regexy filter from all command line arguments.
file_name_re = re.compile('|'.join(args.files))
+ files = None
+ changed_lines = None
+ if args.diff is not None:
+ changed_lines = get_changed_lines(args.diff)
+ files = [(k, v) for k,v in changed_lines.items() if file_name_re.search(k)]
+ else:
+ # Load the database and extract affected files.
+ database = json.load(open(os.path.join(build_path, db_path)))
+ all_files = (make_absolute(entry['file'], entry['directory']) for entry in database)
+ files = [(x, None) for x in all_files if file_name_re.search(x)]
return_code = 0
try:
@@ -276,8 +322,7 @@
# Fill the queue with files.
for name in files:
- if file_name_re.search(name):
- task_queue.put(name)
+ task_queue.put(name)
# Wait for all threads to be done.
task_queue.join()
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits