Skip to content
5 changes: 5 additions & 0 deletions web/client/codechecker_client/cli/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,11 @@ def add_arguments_to_parser(parser):
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
description="List the analysis runs available on the server.",
help="List the available analysis runs.")

runs.add_argument(
'--enabled-checkers',
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if the introduction of this new flag is a good idea. If no run name is specified, then the current implementation lists the union of all checkers enabled in any of the runs:
CodeChecker cmd runs --enabled-checkers
What is the use of such a query? At least the --name flag should be mandatory

I would say that the list of enabled checkers belongs to the given runs, so they should be listed per run. The default output format of CodeChecker cmd runs is an ASCII-art table that is not convenient to display this long information. My suggestion is to put this checker list in the JSON format only as @dkrupp mentioned.

The following functional test could be extended to test this feature in entirety:

def test_runs_analysis_statistics(self):

Ps.:
In a later and independent discussion we could talk about whether --details flag and other output formats like plaintext, table (these are the same, by the way), csv, etc. are necessary.

Copy link
Copy Markdown
Member

@dkrupp dkrupp Feb 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussing with @bruntib we have the following proposal:

Remove the --details flag and the --enabled-checkers flags from the CodeChecker cmd runs command.

The enabled checker list should always be printed in the -o json mode, but not in the plaintext, csv, and table modes.

So the user would use the command like
CodeChecker cmd runs -n <run_name> or without the run name selector, like
CodeChecker cmd runs when all runs are printed.

Make sure that the json output is not null for any fields like runCmd.

The json format is okay like this

[INFO 2026-02-13 15:50] - Checking for local valid sessions.
[
{
"tinyxmls" : {
   "analyzerStatistics" : {
   "clang-tidy" : {
    "enabledCheckers":["checker1","checker2"]
   "failed" : 0,
"failedFilePaths" : [],
"successful" : 2,
"version" : "18.1.3"
},

Make sure that the json output is indented properly.

action='store_true',
help='List all enabled checkers for the specified runs.')
__register_runs(runs)
runs.set_defaults(func=cmd_line_client.handle_list_runs)
__add_common_arguments(runs, output_formats=DEFAULT_OUTPUT_FORMATS)
Expand Down
43 changes: 43 additions & 0 deletions web/client/codechecker_client/cmd_line_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import sys
import shutil
import time
import json
from typing import Dict, Iterable, List, Optional, Set, Tuple

from codechecker_api.codeCheckerDBAccess_v6 import constants, ttypes
Expand Down Expand Up @@ -639,6 +640,47 @@ def handle_list_runs(args):

runs = get_run_data(client, run_filter, sort_mode)

if hasattr(args, 'enabled_checkers') and args.enabled_checkers:
enabled_checkers: Dict[str, List[str]] = {}
for run in runs:
info_list: List[ttypes.AnalysisInfo] = client.getAnalysisInfo(
ttypes.AnalysisInfoFilter(runId=run.runId),
constants.MAX_QUERY_SIZE,
0)
for info in info_list:
for analyzer in info.checkers:
if analyzer not in enabled_checkers:
enabled_checkers[analyzer] = []

checkers = info.checkers.get(analyzer, {})
for checker in checkers:
if checkers[checker].enabled:
enabled_checkers[analyzer].append(checker)

if args.output_format == 'plaintext':
for analyzer, checkers in enabled_checkers.items():
print(analyzer + ":")
for checker in checkers:
print(" " + checker)
elif args.output_format == 'csv':
separator = ';'
print("Analyzer" + separator + "Checker")
for analyzer, checkers in enabled_checkers.items():
for checker in checkers:
print(analyzer + separator + checker)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, use the standard csv module instead.

elif args.output_format == 'json':
print(json.dumps(enabled_checkers, indent=4))
elif args.output_format == 'table':
header = ['Analyzer', 'Checker']
rows = [
(analyzer, checker)
for analyzer, checkers in enabled_checkers.items()
for checker in checkers]
print(twodim.to_str(args.output_format, header, rows))
else:
LOG.error("Unsupported output format: %s", args.output_format)
return
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding return here is totally unnecessary.

Suggested change
return

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xb058t Please do as @cservakt suggested and merge the enabled-checkers processing starting at line 684.

Also please add the enabled checkers list when CodeChecker cmd runs --details -o json is invoked by the user.

[INFO 2026-02-13 15:50] - Checking for local valid sessions.
[
{
"tinyxmls" : {
"analyzerStatistics" : {
"clang-tidy" : {
"enabledCheckers":["checker1","checker2"]
"failed" : 0,
"failedFilePaths" : [],
"successful" : 2,
"version" : "18.1.3"
},
`


if args.output_format == 'json':
# This json is different from the json format printed by the
# parse command. This json converts the ReportData type report
Expand Down Expand Up @@ -682,6 +724,7 @@ def handle_list_runs(args):
codechecker_version))

print(twodim.to_str(args.output_format, header, rows))
return
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The explicit 'return' at the end of the function is unnecessary in Python.

Suggested change
return



def handle_list_results(args):
Expand Down
4 changes: 4 additions & 0 deletions web/client/codechecker_client/helpers/results.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,7 @@ def getAnalysisStatistics(self, run_id, run_history_id):
@thrift_client_call
def storeAnalysisStatistics(self, run_name, zip_file):
pass

@thrift_client_call
def getAnalysisInfo(self, analysis_info_filter, limit, offset):
pass