Skip to content

Commit b0d8ea1

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 b0d8ea1

File tree

6 files changed

+109
-4
lines changed

6 files changed

+109
-4
lines changed

analyzer/codechecker_analyzer/analyzers/clangsa/result_handler.py

Lines changed: 6 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,

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/cppcheck/result_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from codechecker_report_converter.analyzers.cppcheck.analyzer_result import \
1515
AnalyzerResult
1616
from codechecker_report_converter.report import BugPathEvent, \
17-
Range, report_file
17+
Range, report_file, error_file
1818
from codechecker_report_converter.report.hash import get_report_hash, HashType
1919

2020
from codechecker_common.logger import get_logger
@@ -84,3 +84,8 @@ def postprocess_result(
8484
report_file.create(
8585
self.analyzer_result_file, reports, self.checker_labels,
8686
self.analyzer_info)
87+
88+
error_file.create(
89+
self.analyzer_result_file, self.analyzer_returncode,
90+
self.analyzer_info, self.analyzer_cmd,
91+
self.analyzer_stdout, self.analyzer_stderr)

analyzer/codechecker_analyzer/analyzers/infer/result_handler.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from codechecker_report_converter.report.parser.base import AnalyzerInfo
1616
from codechecker_report_converter.analyzers.infer.analyzer_result import \
1717
AnalyzerResult
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
@@ -74,4 +74,9 @@ def postprocess_result(
7474
self.analyzer_result_file, reports, self.checker_labels,
7575
self.analyzer_info)
7676

77+
error_file.create(
78+
self.analyzer_result_file, self.analyzer_returncode,
79+
self.analyzer_info, self.analyzer_cmd,
80+
self.analyzer_stdout, self.analyzer_stderr)
81+
7782
shutil.rmtree(Path(self.workspace, "infer", self.buildaction_hash))

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

@@ -28,6 +29,7 @@
2829

2930

3031
from codechecker_analyzer import analyzer_context, suppress_handler
32+
from codechecker_analyzer.analyzers.analyzer_types import supported_analyzers
3133

3234
from codechecker_common import arg, logger, cmd_config
3335
from codechecker_common.review_status_handler import ReviewStatusHandler
@@ -208,6 +210,14 @@ def add_arguments_to_parser(parser):
208210
help="Filter results by review statuses. Valid "
209211
f"values are: {', '.join(REVIEW_STATUS_VALUES)}")
210212

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

213223
group.add_argument('-i', '--ignore', '--skip',
@@ -263,6 +273,50 @@ def get_metadata(dir_path: str) -> Optional[Dict]:
263273
return None
264274

265275

276+
def print_status(inputs):
277+
if len(inputs) != 1:
278+
LOG.error("Parse status can only be printed "
279+
"for one directory.")
280+
sys.exit(1)
281+
282+
report_dir = inputs[0]
283+
284+
if not os.path.isdir(report_dir):
285+
LOG.error("Input path '%s' is not a directory.",
286+
report_dir)
287+
sys.exit(1)
288+
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 supported_analyzers:
296+
plist_re = re.compile(fr'.*_{analyzer}_[0-9a-f]+\.plist$')
297+
plist_err_re = re.compile(fr'.*_{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) and
303+
f"{file}.err" not 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 supported_analyzers:
312+
LOG.info(" %s: %s", analyzer, successful[analyzer])
313+
314+
LOG.info("Failed to analyze")
315+
for analyzer in supported_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 'status' in args:
369+
print_status(args.input)
370+
return
371+
314372
src_comment_status_filter = args.review_status
315373

316374
suppr_handler = None
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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+
12+
def create(output_path, return_code, analyzer_info,
13+
analyzer_cmd, stdout, stderr):
14+
if return_code == 0:
15+
return
16+
17+
parser = plist.Parser()
18+
19+
data = {
20+
'analyzer_name': analyzer_info.name,
21+
'analyzer_cmd': analyzer_cmd,
22+
'return_code': return_code,
23+
'stdout': stdout,
24+
'stderr': stderr
25+
}
26+
27+
parser.write(data, output_path + ".err")

0 commit comments

Comments
 (0)