Skip to content

Commit 78f72c1

Browse files
Introduce plist.err and parse --status
Currently, it is a problem to determine if the analysis was successful or failed during execution. With this patch, we will create plist.err files to indicate a failed analysis action. The parse --status command was also introduced to get the analysis summary of an existing report directory.
1 parent 1d5c4ff commit 78f72c1

File tree

5 files changed

+98
-2
lines changed

5 files changed

+98
-2
lines changed

analyzer/codechecker_analyzer/analyzers/clangsa/result_handler.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from typing import Optional
1515

1616
from codechecker_report_converter.report.parser.base import AnalyzerInfo
17-
from codechecker_report_converter.report import report_file
17+
from codechecker_report_converter.report import report_file, error_file
1818
from codechecker_report_converter.report.hash import get_report_hash, HashType
1919
from codechecker_common.logger import get_logger
2020
from codechecker_common.skiplist_handler import SkipListHandlers
@@ -43,6 +43,11 @@ def postprocess_result(
4343
Generate analyzer result output file which can be parsed and stored
4444
into the database.
4545
"""
46+
error_file.create(
47+
self.analyzer_result_file, self.analyzer_returncode,
48+
self.analyzer_info, self.analyzer_cmd,
49+
self.analyzer_stdout, self.analyzer_stderr)
50+
4651
if os.path.exists(self.analyzer_result_file):
4752
reports = report_file.get_reports(
4853
self.analyzer_result_file, self.checker_labels,
@@ -66,3 +71,4 @@ def postprocess_result(
6671
report_file.create(
6772
self.analyzer_result_file, reports, self.checker_labels,
6873
self.analyzer_info)
74+

analyzer/codechecker_analyzer/analyzers/clangtidy/result_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
AnalyzerResult
1616
from codechecker_report_converter.analyzers.clang_tidy.parser import Parser
1717
from codechecker_report_converter.report.parser.base import AnalyzerInfo
18-
from codechecker_report_converter.report import report_file
18+
from codechecker_report_converter.report import report_file, error_file
1919
from codechecker_report_converter.report.hash import get_report_hash, HashType
2020

2121
from codechecker_common.logger import get_logger
@@ -76,3 +76,8 @@ def postprocess_result(
7676
report_file.create(
7777
self.analyzer_result_file, reports, self.checker_labels,
7878
self.analyzer_info)
79+
80+
error_file.create(
81+
self.analyzer_result_file, self.analyzer_returncode,
82+
self.analyzer_info, self.analyzer_cmd,
83+
self.analyzer_stdout, self.analyzer_stderr)

analyzer/codechecker_analyzer/analyzers/gcc/result_handler.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,4 @@ def postprocess_result(
118118
report_file.create(
119119
self.analyzer_result_file, reports, self.checker_labels,
120120
self.analyzer_info)
121+

analyzer/codechecker_analyzer/cli/parse.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import argparse
1515
import os
1616
import sys
17+
import re
1718
from typing import Dict, Optional, Set
1819
import fnmatch
1920

@@ -208,6 +209,14 @@ def add_arguments_to_parser(parser):
208209
help="Filter results by review statuses. Valid "
209210
f"values are: {', '.join(REVIEW_STATUS_VALUES)}")
210211

212+
parser.add_argument('--status',
213+
dest="status",
214+
action="store_true",
215+
required=False,
216+
default=argparse.SUPPRESS,
217+
help="Print the number of successful and failed "
218+
"analysis actions.")
219+
211220
group = parser.add_argument_group("file filter arguments")
212221

213222
group.add_argument('-i', '--ignore', '--skip',
@@ -263,6 +272,51 @@ def get_metadata(dir_path: str) -> Optional[Dict]:
263272
return None
264273

265274

275+
def print_status(inputs):
276+
if len(inputs) != 1:
277+
LOG.error("Parse status can only be printed "
278+
"for one directory.")
279+
sys.exit(1)
280+
281+
report_dir = inputs[0]
282+
283+
if not os.path.isdir(report_dir):
284+
LOG.error("Input path '%s' is not a directory.",
285+
report_dir)
286+
sys.exit(1)
287+
288+
analyzers = ["clangsa", "clang-tidy"]
289+
successful = {}
290+
failed = {}
291+
292+
report_dir_files = {os.fsdecode(e) for e in
293+
os.listdir(os.fsencode(report_dir))}
294+
295+
for analyzer in analyzers:
296+
plist_re = re.compile(f'.*_{analyzer}_[0-9a-f]+\.plist$')
297+
plist_err_re = re.compile(f'.*_{analyzer}_[0-9a-f]+\.plist\.err$')
298+
successful[analyzer] = 0
299+
failed[analyzer] = 0
300+
301+
for file in report_dir_files:
302+
if (plist_re.match(file)
303+
and not f"{file}.err" in report_dir_files):
304+
successful[analyzer] += 1
305+
306+
if plist_err_re.match(file):
307+
failed[analyzer] += 1
308+
309+
LOG.info("----==== Summary ====----")
310+
LOG.info("Successfully analyzed")
311+
for analyzer in analyzers:
312+
LOG.info(" %s: %s", analyzer, successful[analyzer])
313+
314+
LOG.info("Failed to analyze")
315+
for analyzer in analyzers:
316+
LOG.info(" %s: %s", analyzer, failed[analyzer])
317+
LOG.info("----=================----")
318+
319+
266320
def main(args):
267321
"""
268322
Entry point for parsing some analysis results and printing them to the
@@ -311,6 +365,10 @@ def main(args):
311365
if isinstance(args.input, str):
312366
args.input = [args.input]
313367

368+
if args.status:
369+
print_status(args.input)
370+
return
371+
314372
src_comment_status_filter = args.review_status
315373

316374
suppr_handler = None
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# -------------------------------------------------------------------------
2+
#
3+
# Part of the CodeChecker project, under the Apache License v2.0 with
4+
# LLVM Exceptions. See LICENSE for license information.
5+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#
7+
# -------------------------------------------------------------------------
8+
9+
from codechecker_report_converter.report.parser import plist
10+
11+
def create(output_path, return_code, analyzer_info,
12+
analyzer_cmd, stdout, stderr):
13+
if return_code == 0:
14+
return
15+
16+
parser = plist.Parser()
17+
18+
data = {
19+
'analyzer_info': analyzer_info,
20+
'analyzer_cmd': analyzer_cmd,
21+
'return_code': return_code,
22+
'stdout': stdout,
23+
'stderr': stderr
24+
}
25+
26+
parser.write(data, output_path + ".err")

0 commit comments

Comments
 (0)