diff --git a/.circleci/config.yml b/.circleci/config.yml index 1a133ecdb6..85cee72bc2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -30,7 +30,7 @@ commands: command: | if [[ <> == false ]] then - git config submodule.ethereum-tests.update none + git config submodule.ethereum-tests.update none fi git submodule sync @@ -71,12 +71,13 @@ commands: cmake ../project -DCMAKE_BUILD_TYPE=<> $CONAN_CMAKE_ARGS $TOOLCHAIN_CMAKE_ARGS $BUILD_CMAKE_ARGS - run: name: "Build" - command: | + working_directory: ~/build + command: | if [[ "<>" == "all" ]] then - cmake --build ~/build -j16 + cmake --build . -j16 |& tee build.log else - cmake --build ~/build -j16 --target <> + cmake --build . -j16 --target <> |& tee build.log fi install_conan: @@ -344,6 +345,9 @@ jobs: build_type: Debug compiler_id: clang compiler_version: <> + - run: + name: "Report" + command: tools/lint/clang_tidy_report.sh "$HOME/build/build.log" linux-clang-tidy-diff: environment: diff --git a/.clang-tidy b/.clang-tidy index f0f74cbe0a..219db84f44 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,6 @@ FormatStyle: file HeaderFilterRegex: 'silkworm/(capi|core|db|execution|infra|node|rpc|sentry|sync|wasm)/.+\.hpp$' -WarningsAsErrors: '*' +WarningsAsErrors: 'bugprone-use-after-move' Checks: > abseil-*, boost-*, diff --git a/third_party/clang-tidy-html/LICENSE b/third_party/clang-tidy-html/LICENSE deleted file mode 100644 index 2e0f760e81..0000000000 --- a/third_party/clang-tidy-html/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -https://github.com/austinbhale/clang-tidy-html - -MIT License - -Copyright (c) 2019-2021 Austin Hale - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/third_party/clang-tidy-html/clang_visualizer.py b/third_party/clang-tidy-html/clang_visualizer.py deleted file mode 100644 index 9657950733..0000000000 --- a/third_party/clang-tidy-html/clang_visualizer.py +++ /dev/null @@ -1,558 +0,0 @@ -import argparse -import logging -import re -import sys -from requests import Session -from requests.adapters import HTTPAdapter -from pathlib import Path -from bs4 import BeautifulSoup -import ssl -import certifi - -log = logging.getLogger(__name__) -handler = logging.StreamHandler() -log_format = '%(asctime)s - %(name)12s - %(levelname)8s - %(message)s' -handler.setFormatter(logging.Formatter(log_format)) -log.addHandler(handler) -log.setLevel(logging.DEBUG) - -COLOR_DICT = { - '0': [(88, 88, 88), (88, 88, 88)], - '30': [(0, 0, 0), (0, 0, 0)], - '31': [(255, 0, 0), (128, 0, 0)], - '32': [(0, 255, 0), (0, 128, 0)], - '33': [(255, 255, 0), (128, 128, 0)], - '34': [(0, 0, 255), (0, 0, 128)], - '35': [(255, 0, 255), (128, 0, 128)], - '36': [(0, 255, 255), (0, 128, 128)], - '37': [(255, 255, 255), (128, 128, 128)], -} - -COLOR_REGEX = re.compile( - r'\[(?P\d+)(;(?P\d+)(;(?P\d+))?)?m') - -BOLD_TEMPLATE = '' -LIGHT_TEMPLATE = '' - - -def ansi_to_html(text): - text = text.replace('[0m', '').replace('\033', '') - - def single_sub(match): - argsdict = match.groupdict() - bold = False - color = '0' - for arg in argsdict.values(): - if arg is not None: - val = int(str(arg)) - if val == 0: - bold = False - elif val == 1: - bold = True - elif val >= 30 and val <= 37: - color = arg - if bold: - return BOLD_TEMPLATE.format(COLOR_DICT[color][1]) - return LIGHT_TEMPLATE.format(COLOR_DICT[color][0]) - - return COLOR_REGEX.sub(single_sub, text) - -# You can also import custom clang checks from checks.py below. -# from checks import checks_list - -# Each check will have its own node of information. -class checks: - def __init__(self, dataval=None): - self.name = '' - self.count = 0 - self.data = '' - -# Begin here. -def main(): - # Process command line arguments. - parser = argparse.ArgumentParser() - parser.add_argument('file', type=Path) - parser.add_argument( - '-o', '--out', help="Generated html file name.", nargs='?', const="clang.html", default="clang.html", type=str) - parser.add_argument( - '-d', '--checks_dict_url', help="Override the latest checks list, (e.g., v14.0.0 uses \ - https://releases.llvm.org/14.0.0/tools/clang/tools/extra/docs/clang-tidy/checks/list.html).", nargs='?', type=str) - - try: - args = parser.parse_args() - except: - parser.print_help() - usage() - sys.exit(-1) - - tidy_log_lines: Path = args.file - output_path: Path = Path(args.out) - clang_tidy_visualizer(tidy_log_lines, output_path, args.checks_dict_url) - - -def clang_tidy_visualizer(tidy_log_file: Path, - output_html_file: Path = Path("clang.html"), - checks_dict_url = None): - tidy_log_lines = tidy_log_file.read_text().splitlines() - clang_base_url = "https://clang.llvm.org/extra/clang-tidy/checks/" - global checks_dict - - if checks_dict_url is None: - checks_dict_url = clang_base_url + 'list.html' - - checks_dict = find_checks_dict(checks_dict_url) - if checks_dict is None or len(checks_dict) == 0: - print("Error! Could not retrieve a dictionary of checks.") - exit(0) - checks_list = list(checks_dict.keys()) - checks_list.sort() - - # Updates the newest clang-tidy checks to your checks.py file. - write_checks_file( - checks_list, to_file=output_html_file.parent / "clang-tidy-checks.py") - - checks_used = [0] * len(checks_list) - - # Increments each occurrence of a check. - for line, content in enumerate(tidy_log_lines): - content = content.replace('<', '<') - content = content.replace('>', '>') - for check_name in checks_list: - if content.find(check_name.replace('/', '-')) != -1: - checks_used[checks_list.index(check_name)] += 1 - - # Counts the max number of used checks in the log file. - num_used_checks = 0 - for line, check in enumerate(checks_list): - if checks_used[line] != 0: - num_used_checks += 1 - - names_of_used = [None] * num_used_checks - names_of_usedL = [None] * num_used_checks - - # Creates new check classes for each used check. - used_line = 0 - total_num_checks = 0 - for line, check in enumerate(checks_list): - if checks_used[line] != 0: - new_node = checks(check) - new_node.name = check - new_node.count = checks_used[line] - total_num_checks += checks_used[line] - names_of_used[used_line] = new_node - - names_of_usedL[used_line] = checks_list[line] - used_line += 1 - - # Adds details for each organized check. - for line, content in enumerate(tidy_log_lines): - # Goes through each used check. - for initial_check in names_of_usedL: - # Adds the lines that detail the warning message. - if content.find(initial_check.replace('/', '-')) != -1: - content = content.replace('<', '<') - content = content.replace('>', '>') - names_of_used[names_of_usedL.index( - initial_check)].data += content + '\n' - details = line + 1 - finished = False - while not finished: - # Ensure there is no overflow. - if details >= len(tidy_log_lines): - break - # If the line includes a used Clang-Tidy check name, - # continue to find the next. - for end_check in names_of_usedL: - if tidy_log_lines[details].find(end_check.replace('/', '-')) != -1: - finished = True - break - # Otherwise, add the data to the specific used check - # name for the organization of checks in the HTML file. - if not finished: - names_of_used[names_of_usedL.index( - initial_check)].data += tidy_log_lines[details] + '\n' - details += 1 - - with open(output_html_file, "w") as clang_html: - log.info(f"Writing results to {output_html_file}") - # Functions for writing to the clang.html file. - writeHeader(clang_html) - writeList(clang_html, num_used_checks, names_of_used, - clang_base_url, total_num_checks) - writeSortedLogs(clang_html, tidy_log_lines, - num_used_checks, names_of_used, clang_base_url) - writeScript(clang_html, num_used_checks) - -# adapted from https://github.com/psf/requests/issues/4775#issuecomment-478198879 -class TLSAdapter(HTTPAdapter): - def init_poolmanager(self, *args, **kwargs): - ctx = ssl.create_default_context(cafile=certifi.where()) - kwargs['ssl_context'] = ctx - return super(TLSAdapter, self).init_poolmanager(*args, **kwargs) - -# Scrape data from clang-tidy's official list of current checks. -def find_checks_dict(checks_dict_url: str): - session = Session() - session.mount('https://', TLSAdapter()) - try: - res = session.get(checks_dict_url) - except Exception as e: - print(e) - return None - - soup = BeautifulSoup(res.text, "lxml") - scrape_checks_dict = dict() - clang_check_links = soup.find_all('a', href=True) - - for link in clang_check_links: - match_docs_check_name = re.match( - "^([a-zA-Z0-9].*).html.*$", link['href']) - if match_docs_check_name: - docs_check_name = match_docs_check_name.group(1) - split_docs_check = docs_check_name.split('/') - len_split_docs_check = len(split_docs_check) - if len_split_docs_check > 0 and len_split_docs_check <= 2: - scrape_checks_dict[fromClangDocsName( - docs_check_name)] = split_docs_check[0] - return scrape_checks_dict - -# Optional: Update the checks.py file with the most recent checks. -def write_checks_file(checks_list, to_file): - with open(to_file, 'w') as f: - f.write('checks_list = [') - for check, item in enumerate(checks_list): - if check == len(checks_list) - 1: - f.write("'{}']".format(item)) - else: - f.write("'{}',".format(item)) - -# Helper functions to fix the links of the clang-tidy documentation. -# Referenced in #8 -def toClangDocsName(original_check_name): - checks_category = checks_dict[original_check_name] - match_except_first_hyphen = re.compile(rf'^({checks_category})-(.*)$') - clang_docs_name = match_except_first_hyphen.sub( - r'\1/\2', original_check_name) - return clang_docs_name - -def fromClangDocsName(docs_check_name): - return docs_check_name.replace('/', '-', 1) - -# Prints usage information for the script. -def usage(): - print(""" -***------------------------------------------ Clang HTML Visualizer -----------------------------------------*** - - Generates an html file as a visual for clang-tidy checks. Additionally, it writes a checks.py file that - informs you which checks have been scraped from http://clang.llvm.org/extra/clang-tidy/checks/list.html - - How to use: - - Call the script directly: - 1. clang-tidy-html [logfile.log] - 2. python -m clang_html [logfile.log] - OR - - Import it in your Python terminal: - >>> from pathlib import Path - >>> from clang_html import clang_tidy_visualizer - >>> clang_tidy_visualizer(Path("examples/sample.log")) - - Optional args: - - [-o, --out] or clang_tidy_visualizer(path_to_log: Path, output_path: Path) - - Rename the generated html file. The default filename is stored as "clang.html" in the directory - from where you call the script. - -***----------------------------------------------------------------------------------------------------------***""") - -# Header of the clang.html file. -def writeHeader(f): - f.write(""" - - - - Clang-Tidy Visualizer - - - - - - - - -""") - -# List the used checks found in the source code. -def writeList(f, num_used_checks, names_of_used, clang_base_url, total_num_checks): - f.write(""" - -
- -
-
    -""") - - # Iterates through each used check's details and organizes them into the given
     sections.
    -    f.write("""
    -            
    -                {} Original Log
    -            
    -""".format(total_num_checks))
    -
    -    for line in range(0, num_used_checks):
    -        f.write("""
    -            
    -                {1} {2}
    -            
    -""".format(line, names_of_used[line].count, names_of_used[line].name.replace('/', '-')))
    -
    -    f.write("""
    -        
- - -""") - - for check_idx in range(0, num_used_checks): - collapse_idx = check_idx + 1 - f.write(""" -
-
- -

- {2} -

-""".format(check_idx, collapse_idx, names_of_used[check_idx].name)) - - # Attach a button to the specific check's docs in clang. Link opens in a new tab. - docs_check_name = toClangDocsName(names_of_used[check_idx].name) - clang_check_url = clang_base_url.replace( - '/', '\/') + docs_check_name + '.html' - external_name = 'Documentation' - f.write(""" - - """.format(clang_check_url, external_name)) - - f.write(""" -
-
-""")
-
-        names_of_used[check_idx].data = names_of_used[check_idx].data.replace(
-            '<', '<')
-        names_of_used[check_idx].data = names_of_used[check_idx].data.replace(
-            '>', '>')
-        names_of_used[check_idx].data = ansi_to_html(
-            names_of_used[check_idx].data)
-        f.write("""{}
-            
-
-""".format(names_of_used[check_idx].data)) - - f.write(""" -
- -""") - -# Writes Javascript and JQuery code to the html file for button and grouping functionalities. -def writeScript(f, num_used_checks): - f.write(""" - - - - -""".format(num_used_checks)) diff --git a/tools/lint/clang_tidy_report.sh b/tools/lint/clang_tidy_report.sh new file mode 100755 index 0000000000..77c3959fe3 --- /dev/null +++ b/tools/lint/clang_tidy_report.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +set -e +set -o pipefail + +build_log="$1" + +if [[ ! -f "$build_log" ]] +then + echo "the build log file is not found at '$build_log'" + exit 1 +fi + +function filter_warnings { + grep "warning:" || true +} + +filter_warnings < "$build_log" +warn_count=$(filter_warnings < "$build_log" | wc -l) + +echo +echo "clang-tidy produced $warn_count warnings" +echo "see the build step output for more details" + +if (( warn_count > 50 )) +then + echo "go fix the warnings now!" + exit 2 +fi