| #!/usr/bin/env python3 |
| # Copyright lowRISC contributors. |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. |
| # SPDX-License-Identifier: Apache-2.0 |
| r"""Helper class for parsing lint reports into a generic hjson format. |
| """ |
| import re |
| import hjson |
| |
| from pathlib import Path |
| from typing import List, Dict, Tuple |
| |
| |
| # TODO(#9079): this class will be refactored so that it can be integrated into |
| # the Dvsim core code. |
| class LintParser(): |
| |
| def __init__(self) -> None: |
| self.buckets = { |
| 'flow_warning': [], |
| 'flow_error': [], |
| 'lint_info': [], |
| 'lint_warning': [], |
| 'lint_error': [], |
| # this bucket is temporary and will be removed at the end of the |
| # parsing pass. |
| 'fusesoc-error': [] |
| } |
| self.severities = { |
| 'flow_warning': 'warning', |
| 'flow_error': 'error', |
| 'lint_info': 'info', |
| 'lint_warning': 'warning', |
| 'lint_error': 'error', |
| } |
| |
| def extract_messages(self, log_content: str, patterns: List[str]) -> None: |
| """ |
| This extracts messages from the string buffer log_content. |
| The argument patterns needs to be a list of tuples with |
| (<error_severity>, <pattern_to_match_for>). |
| """ |
| for bucket, pattern in patterns: |
| self.buckets[bucket] += \ |
| re.findall(pattern, log_content, flags=re.MULTILINE) |
| |
| def get_results(self, args: Dict[Path, List[Tuple]]) -> Dict[str, int]: |
| """ |
| Parse report and corresponding logfiles and extract error, warning |
| and info messages for each IP present in the result folder |
| """ |
| |
| # Open all log files |
| for path, patterns in args.items(): |
| try: |
| with path.open() as f: |
| log_content = f.read() |
| self.extract_messages(log_content, patterns) |
| except IOError as err: |
| self.buckets['flow_error'] += \ |
| ["IOError: %s" % err] |
| |
| # If there are no errors or warnings, add the "fusesoc-error" field to |
| # "errors" (which will be reported as tooling errors). Remove the |
| # "fusesoc-error" field either way. |
| num_messages = { |
| 'info': 0, |
| 'warning': 0, |
| 'error': 0 |
| } |
| for key, sev in self.severities.items(): |
| num_messages[sev] += len(self.buckets[key]) |
| if num_messages['error'] == 0 and num_messages['warning'] == 0: |
| self.buckets['flow_error'] = self.buckets['fusesoc-error'] |
| del self.buckets['fusesoc-error'] |
| |
| return num_messages |
| |
| def write_results_as_hjson(self, outpath: Path) -> None: |
| with outpath.open("w") as results_file: |
| # Construct results dict for Hjson file. |
| hjson.dump(self.buckets, |
| results_file, |
| ensure_ascii=False, |
| for_json=True, |
| use_decimal=True) |