kuhnel created this revision.
Herald added subscribers: carlosgalvezp, usaxena95, kadircet, xazax.hun.
kuhnel requested review of this revision.
Herald added subscribers: cfe-commits, ilya-biryukov.
Herald added a project: clang-tools-extra.

This makes it easier to process the clang-tidy output in other tools.
For far it's only parsing the findings, not the output on stderr.

For testing you can use:

  bash
  ninja clangd
  COMMIT=4dedd82cc99341d757a9cc07a8b7b22c8bb61d19
  git diff $COMMIT~ $COMMIT | python3 
clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py -p1 -json -checks="*"

This is part of the effort towards re-enabling clang-tidy in
pre-merge testing. With JSON output, we can deprecate some local
code in pre-merge testing.

https://github.com/google/llvm-premerge-checks/issues/367


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117773

Files:
  clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py

Index: clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
===================================================================
--- clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
+++ clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
@@ -35,6 +35,7 @@
 import tempfile
 import threading
 import traceback
+from typing import Optional
 
 try:
   import yaml
@@ -49,7 +50,7 @@
     import queue as queue
 
 
-def run_tidy(task_queue, lock, timeout):
+def run_tidy(task_queue, lock, timeout, result_queue: Optional[queue.Queue]):
   watchdog = None
   while True:
     command = task_queue.get()
@@ -65,8 +66,11 @@
       stdout, stderr = proc.communicate()
 
       with lock:
-        sys.stdout.write(stdout.decode('utf-8') + '\n')
-        sys.stdout.flush()
+        if result_queue:
+          parse_clang_tidy_output(result_queue, stdout.decode('utf-8'))
+        else:
+          sys.stdout.write(stdout.decode('utf-8') + '\n')
+          sys.stdout.flush()
         if stderr:
           sys.stderr.write(stderr.decode('utf-8') + '\n')
           sys.stderr.flush()
@@ -83,9 +87,9 @@
       task_queue.task_done()
 
 
-def start_workers(max_tasks, tidy_caller, task_queue, lock, timeout):
+def start_workers(max_tasks, tidy_caller, task_queue, lock, timeout, result_queue):
   for _ in range(max_tasks):
-    t = threading.Thread(target=tidy_caller, args=(task_queue, lock, timeout))
+    t = threading.Thread(target=tidy_caller, args=(task_queue, lock, timeout, result_queue))
     t.daemon = True
     t.start()
 
@@ -115,6 +119,18 @@
     open(mergefile, 'w').close()
 
 
+def parse_clang_tidy_output(result_queue: queue, clang_tidy_output: str):
+  """Parse the clang-tidy output and add them to the result queue."""
+  _regex_pattern = r"^(?P<path>/[^:]+):\W*(?P<line>\d+):\W*(?P<character>\d+):\W*(?P<check>.*)$"
+  for finding in re.finditer(_regex_pattern, clang_tidy_output, re.MULTILINE):
+    result_queue.put({
+        'path': finding['path'],
+        'line': int(finding['line']),
+        'character': int(finding['character']),
+        'check': finding['check'],
+    })
+
+
 def main():
   parser = argparse.ArgumentParser(description=
                                    'Run clang-tidy against changed files, and '
@@ -160,6 +176,8 @@
                       'command line.')
   parser.add_argument('-quiet', action='store_true', default=False,
                       help='Run clang-tidy in quiet mode')
+  parser.add_argument('-json', action='store_true', dest='json_output',
+                      help='Output clang-tidy results in JSON format.')
   clang_tidy_args = []
   argv = sys.argv[1:]
   if '--' in argv:
@@ -214,8 +232,14 @@
   # A lock for console output.
   lock = threading.Lock()
 
+  # if we want JSON output: gather results
+  result_queue = None
+  if args.json_output:
+    result_queue = queue.Queue()
+
   # Run a pool of clang-tidy workers.
-  start_workers(max_task_count, run_tidy, task_queue, lock, args.timeout)
+  start_workers(max_task_count, run_tidy, task_queue,
+                lock, args.timeout, result_queue)
 
   # Form the common args list.
   common_clang_tidy_args = []
@@ -227,7 +251,7 @@
     common_clang_tidy_args.append('-quiet')
   if args.build_path is not None:
     common_clang_tidy_args.append('-p=%s' % args.build_path)
-  if args.use_color:
+  if args.use_color and not args.json_output:
     common_clang_tidy_args.append('--use-color')
   for arg in args.extra_arg:
     common_clang_tidy_args.append('-extra-arg=%s' % arg)
@@ -268,6 +292,8 @@
   if tmpdir:
     shutil.rmtree(tmpdir)
 
-
+  if args.json_output:
+    json_output = {'findings': list(result_queue.queue)} 
+    json.dump(json_output, sys.stdout, indent=2)
 if __name__ == '__main__':
   main()
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to