Skip to content

[clang-tidy] Improve "-quiet" option in tidy-scripts by suppressing progress information #154416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

vbvictor
Copy link
Contributor

@vbvictor vbvictor commented Aug 19, 2025

Progress information bloated output, now run-clang-tidy emits only actual diagnostics, which makes reading its output significantly easier.

@llvmbot
Copy link
Member

llvmbot commented Aug 19, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: Baranov Victor (vbvictor)

Changes

Progress information bloated output, now run-clang-tidy emits only actual diagnostics, which makes reading its output significantly easier.


Full diff: https://github.com/llvm/llvm-project/pull/154416.diff

4 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py (+4-2)
  • (modified) clang-tools-extra/clang-tidy/tool/run-clang-tidy.py (+16-11)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp (+24)
diff --git a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
index d7899e0a18d0c..bb012ceff442b 100755
--- a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
+++ b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
@@ -312,7 +312,8 @@ def main():
     if max_task_count == 0:
         max_task_count = multiprocessing.cpu_count()
     max_task_count = min(len(lines_by_file), max_task_count)
-    print(f"Running clang-tidy in {max_task_count} threads...")
+    if not args.quiet:
+        print(f"Running clang-tidy in {max_task_count} threads...")
 
     combine_fixes = False
     export_fixes_dir = None
@@ -408,7 +409,8 @@ def main():
         return_code = 1
 
     if combine_fixes:
-        print("Writing fixes to " + args.export_fixes + " ...")
+        if not args.quiet:
+            print("Writing fixes to " + args.export_fixes + " ...")
         try:
             merge_replacement_files(export_fixes_dir, args.export_fixes)
         except:
diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
index 670e0a2c7678a..69788b5b15b48 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -681,13 +681,14 @@ async def main() -> None:
     file_name_re = re.compile("|".join(args.files))
     files = {f for f in files if file_name_re.search(f)}
 
-    print(
-        f"Running clang-tidy in {max_task} threads for",
-        len(files),
-        "files out of",
-        number_files_in_database,
-        "in compilation database ...",
-    )
+    if not args.quiet:
+        print(
+            f"Running clang-tidy in {max_task} threads for",
+            len(files),
+            "files out of",
+            number_files_in_database,
+            "in compilation database ...",
+        )
 
     returncode = 0
     semaphore = asyncio.Semaphore(max_task)
@@ -716,13 +717,15 @@ async def main() -> None:
                     result.stderr += f"{result.filename}: terminated by signal {-result.returncode}\n"
             progress = f"[{i + 1: >{len(f'{len(files)}')}}/{len(files)}]"
             runtime = f"[{result.elapsed:.1f}s]"
-            print(f"{progress}{runtime} {' '.join(result.invocation)}")
+            if not args.quiet:
+                print(f"{progress}{runtime} {' '.join(result.invocation)}")
             if result.stdout:
                 print(result.stdout, end=("" if result.stderr else "\n"))
             if result.stderr:
                 print(result.stderr)
     except asyncio.CancelledError:
-        print("\nCtrl-C detected, goodbye.")
+        if not args.quiet:
+            print("\nCtrl-C detected, goodbye.")
         for task in tasks:
             task.cancel()
         if delete_fixes_dir:
@@ -742,7 +745,8 @@ async def main() -> None:
             print("No profiling data found.")
 
     if combine_fixes:
-        print(f"Writing fixes to {args.export_fixes} ...")
+        if not args.quiet:
+            print(f"Writing fixes to {args.export_fixes} ...")
         try:
             assert export_fixes_dir
             merge_replacement_files(export_fixes_dir, args.export_fixes)
@@ -752,7 +756,8 @@ async def main() -> None:
             returncode = 1
 
     if args.fix:
-        print("Applying fixes ...")
+        if not args.quiet:
+            print("Applying fixes ...")
         try:
             assert export_fixes_dir
             apply_fixes(args, clang_apply_replacements_binary, export_fixes_dir)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 388979d9577ba..4473584e9fb26 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -122,6 +122,10 @@ Improvements to clang-tidy
 - Improved :program:`clang-tidy` option `-quiet` by suppressing diagnostic
   count messages.
 
+- Improved :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` 
+  scripts to respect the `-quiet` option by suppressing progress and
+  informational messages.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp
new file mode 100644
index 0000000000000..aec9356f3ad1f
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp
@@ -0,0 +1,24 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
+// RUN: echo "Checks: '-*,readability-magic-numbers'" > %t/.clang-tidy
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: cd "%t"
+
+// RUN: %run_clang_tidy -quiet "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-RUN-QUIET
+// CHECK-RUN-QUIET-NOT: Running clang-tidy in {{[1-9][0-9]*}} threads for
+// CHECK-RUN-QUIET-NOT: {{[0-9]+}} warning{{s?}} generated
+// CHECK-RUN-QUIET-NOT: [1/1]
+// CHECK-RUN-QUIET: 42 is a magic number;
+
+// REQUIRES: shell
+// RUN: sed 's/42/99/' %s > %t-diff.cpp
+
+// RUN: not diff -U0 %s %t-diff.cpp | %clang_tidy_diff -checks=-*,readability-magic-numbers -quiet -- -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-DIFF-QUIET
+// CHECK-DIFF-QUIET-NOT: Running clang-tidy in {{[1-9][0-9]*}} threads...
+// CHECK-DIFF-QUIET-NOT: {{[0-9]+}} warning{{s?}} generated
+// CHECK-DIFF-QUIET: 99 is a magic number;
+
+int main() {
+  int x = 42;
+}

@llvmbot
Copy link
Member

llvmbot commented Aug 19, 2025

@llvm/pr-subscribers-clang-tidy

Author: Baranov Victor (vbvictor)

Changes

Progress information bloated output, now run-clang-tidy emits only actual diagnostics, which makes reading its output significantly easier.


Full diff: https://github.com/llvm/llvm-project/pull/154416.diff

4 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py (+4-2)
  • (modified) clang-tools-extra/clang-tidy/tool/run-clang-tidy.py (+16-11)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp (+24)
diff --git a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
index d7899e0a18d0c..bb012ceff442b 100755
--- a/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
+++ b/clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py
@@ -312,7 +312,8 @@ def main():
     if max_task_count == 0:
         max_task_count = multiprocessing.cpu_count()
     max_task_count = min(len(lines_by_file), max_task_count)
-    print(f"Running clang-tidy in {max_task_count} threads...")
+    if not args.quiet:
+        print(f"Running clang-tidy in {max_task_count} threads...")
 
     combine_fixes = False
     export_fixes_dir = None
@@ -408,7 +409,8 @@ def main():
         return_code = 1
 
     if combine_fixes:
-        print("Writing fixes to " + args.export_fixes + " ...")
+        if not args.quiet:
+            print("Writing fixes to " + args.export_fixes + " ...")
         try:
             merge_replacement_files(export_fixes_dir, args.export_fixes)
         except:
diff --git a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
index 670e0a2c7678a..69788b5b15b48 100755
--- a/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
+++ b/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py
@@ -681,13 +681,14 @@ async def main() -> None:
     file_name_re = re.compile("|".join(args.files))
     files = {f for f in files if file_name_re.search(f)}
 
-    print(
-        f"Running clang-tidy in {max_task} threads for",
-        len(files),
-        "files out of",
-        number_files_in_database,
-        "in compilation database ...",
-    )
+    if not args.quiet:
+        print(
+            f"Running clang-tidy in {max_task} threads for",
+            len(files),
+            "files out of",
+            number_files_in_database,
+            "in compilation database ...",
+        )
 
     returncode = 0
     semaphore = asyncio.Semaphore(max_task)
@@ -716,13 +717,15 @@ async def main() -> None:
                     result.stderr += f"{result.filename}: terminated by signal {-result.returncode}\n"
             progress = f"[{i + 1: >{len(f'{len(files)}')}}/{len(files)}]"
             runtime = f"[{result.elapsed:.1f}s]"
-            print(f"{progress}{runtime} {' '.join(result.invocation)}")
+            if not args.quiet:
+                print(f"{progress}{runtime} {' '.join(result.invocation)}")
             if result.stdout:
                 print(result.stdout, end=("" if result.stderr else "\n"))
             if result.stderr:
                 print(result.stderr)
     except asyncio.CancelledError:
-        print("\nCtrl-C detected, goodbye.")
+        if not args.quiet:
+            print("\nCtrl-C detected, goodbye.")
         for task in tasks:
             task.cancel()
         if delete_fixes_dir:
@@ -742,7 +745,8 @@ async def main() -> None:
             print("No profiling data found.")
 
     if combine_fixes:
-        print(f"Writing fixes to {args.export_fixes} ...")
+        if not args.quiet:
+            print(f"Writing fixes to {args.export_fixes} ...")
         try:
             assert export_fixes_dir
             merge_replacement_files(export_fixes_dir, args.export_fixes)
@@ -752,7 +756,8 @@ async def main() -> None:
             returncode = 1
 
     if args.fix:
-        print("Applying fixes ...")
+        if not args.quiet:
+            print("Applying fixes ...")
         try:
             assert export_fixes_dir
             apply_fixes(args, clang_apply_replacements_binary, export_fixes_dir)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 388979d9577ba..4473584e9fb26 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -122,6 +122,10 @@ Improvements to clang-tidy
 - Improved :program:`clang-tidy` option `-quiet` by suppressing diagnostic
   count messages.
 
+- Improved :program:`run-clang-tidy.py` and :program:`clang-tidy-diff.py` 
+  scripts to respect the `-quiet` option by suppressing progress and
+  informational messages.
+
 New checks
 ^^^^^^^^^^
 
diff --git a/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp
new file mode 100644
index 0000000000000..aec9356f3ad1f
--- /dev/null
+++ b/clang-tools-extra/test/clang-tidy/infrastructure/quiet-flag-scripts.cpp
@@ -0,0 +1,24 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "[{\"directory\":\".\",\"command\":\"clang++ -c %/t/test.cpp\",\"file\":\"%/t/test.cpp\"}]" | sed -e 's/\\/\\\\/g' > %t/compile_commands.json
+// RUN: echo "Checks: '-*,readability-magic-numbers'" > %t/.clang-tidy
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: cd "%t"
+
+// RUN: %run_clang_tidy -quiet "test.cpp" 2>&1 | FileCheck %s --check-prefix=CHECK-RUN-QUIET
+// CHECK-RUN-QUIET-NOT: Running clang-tidy in {{[1-9][0-9]*}} threads for
+// CHECK-RUN-QUIET-NOT: {{[0-9]+}} warning{{s?}} generated
+// CHECK-RUN-QUIET-NOT: [1/1]
+// CHECK-RUN-QUIET: 42 is a magic number;
+
+// REQUIRES: shell
+// RUN: sed 's/42/99/' %s > %t-diff.cpp
+
+// RUN: not diff -U0 %s %t-diff.cpp | %clang_tidy_diff -checks=-*,readability-magic-numbers -quiet -- -std=c++11 2>&1 | FileCheck %s --check-prefix=CHECK-DIFF-QUIET
+// CHECK-DIFF-QUIET-NOT: Running clang-tidy in {{[1-9][0-9]*}} threads...
+// CHECK-DIFF-QUIET-NOT: {{[0-9]+}} warning{{s?}} generated
+// CHECK-DIFF-QUIET: 99 is a magic number;
+
+int main() {
+  int x = 42;
+}

@vbvictor
Copy link
Contributor Author

To be exact, these countless messages are totally gone:

[ 47/446][22.8s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp
64711 warnings generated.

[ 48/446][21.7s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
62350 warnings generated.

[ 49/446][21.5s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemoryComparisonCheck.cpp
62186 warnings generated.

[ 50/446][23.7s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/readability/ElseAfterReturnCheck.cpp
63421 warnings generated.

[ 51/446][18.0s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/readability/SimplifySubscriptExprCheck.cpp
62275 warnings generated.

[ 52/446][17.9s] /usr/bin/clang-tidy -p=build/ -quiet /home/victor/llvm/llvm-project/clang-tools-extra/clang-tidy/android/CloexecSocketCheck.cpp
62172 warnings generated.

@firewave
Copy link

I actually like the progress information (the rest not so much) and it might give an indication if it is stuck or still running. It also contains information (timing) to compare between runs and indicate which files are hot spots.

@vbvictor
Copy link
Contributor Author

I actually like the progress information (the rest not so much) and it might give an indication if it is stuck or still running. It also contains information (timing) to compare between runs and indicate which files are hot spots.

Then to separate -quiet in clang-tidy and scripts we can add --hide-progress flag to suppress timings and other information. I'm not sure about option name though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants