diff --git a/.clang-tidy b/.clang-tidy index 92d0c1a8e..b044a7204 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,14 +1,15 @@ Checks: " -*, - modernize-use-*, -modernize-use-trailing-return-type*, - performance-*, - mpi-*, - openmp-*, - -bugprone-*, - readability-*, -readability-magic-numbers, -readability-redundant-access-specifiers, -readability-convert-member-functions-to-static, - -clang-analyzer-*, - -clang-diagnostic-*, + + modernize-use-*, + -modernize-use-trailing-return-type*, + + readability-*, + -readability-magic-numbers, + -readability-redundant-access-specifiers, + -readability-convert-member-functions-to-static, + -readability-isolate-declaration, " AnalyzeTemporaryDtors: false HeaderFilterRegex: 'src/.*' FormatStyle: file diff --git a/.codeclimate.yml b/.codeclimate.yml index e72a3e9cf..94e9be545 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -1,50 +1,55 @@ checks: duplicate: enabled: true exclude_patterns: - "test/" - "examples/" structure: enabled: true exclude_patterns: - "test/" plugins: editorconfig: enabled: false config: editorconfig: .editorconfig exclude_patterns: - ".clangd/" - ".cache/" pep8: enabled: true exclude_patterns: - "test/test_fe_engine/py_engine/py_engine.py" cppcheck: enabled: false project: compile_commands.json language: c++ check: warning, style, performance stds: [c++14] fixme: enabled: true exclude_patterns: - "doc/" clang-tidy: enabled: true + checks: extra-arg: - -std=c++14 - -Ithird-party/akantu_iterators/include - -Ithird-party/iohelper/src - -Itest/ci/includes_for_ci - -Isrc/mesh + checks: + - '-*' + - 'modernize-*' exclude_patterns: - - "test/" - - "cmake/" - - "examples/" - - "extra_packages/" + - test/ + - cmake/ + - examples/ + - extra_packages/ + - .clangd/ exclude_patterns: - "third-party/" - "build*/" diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py index 8e5141f14..ad8c6de0e 100644 --- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/command.py @@ -1,73 +1,74 @@ import json import os import re class Command: """Returns command line arguments by parsing codeclimate config file.""" def __init__(self, config, workspace): self.config = config self._workspace = workspace def build(self): command = ['/usr/src/app/bin/run-clang-tidy', '-clang-tidy-binary', '/usr/bin/clang-tidy'] if 'checks' in self.config: - command.extend( - ['-checks', self.config["checks"]]) + checks = self.config["checks"] + if not isinstance(checks, list): + command.extend(['-checks', f'\'{checks}\'']) + else: + command.extend(['-checks', f'\'{",".join(checks)}\'']) if 'config' in self.config: - command.extend( - ['-config', self.config["config"]]) + command.extend(['-config', self.config["config"]]) if 'header-filter' in self.config: - command.extend( - ['-header-filter', self.config["header-file"]]) + command.extend(['-header-filter', self.config["header-file"]]) extra_args = [] if 'extra-arg' in self.config: tmp_extra_args = self.config['extra-arg'] if not isinstance(extra_args, list): tmp_extra_args = [extra_args] extra_args = [] includes_re = re.compile(r'-I(.*)') for arg in tmp_extra_args: match = includes_re.match(arg) if match: path = os.path.abspath(match.group(1)) extra_args.append(f'-I{path}') else: extra_args.append(arg) if 'compilation-database-path' in self.config: for arg in extra_args: command.extend(['-extra-arg', arg]) if 'compilation-database-path' in self.config: - command.extend( - ['-p', self.config['compilation-database-path']]) + command.extend(['-p', self.config['compilation-database-path']]) else: include_flags = ' -I'.join(self._workspace.include_paths) compile_commands = [] for file_ in self._workspace.files: cmd = { 'directory': os.path.dirname(file_), 'file': file_, 'command': f'/usr/bin/clang++ {include_flags} {" ".join(extra_args)} -c {file_} -o dummy.o', # noqa } compile_commands.append(cmd) location = '/tmp' compile_database = os.path.join(location, 'compile_commands.json') with open(compile_database, 'w') as db: json.dump(compile_commands, db) command.extend(['-p', location]) - command.extend([f'{path}*' for path in self._workspace.paths]) + command.extend([f'{path}.*' if os.path.isdir(path) else path + for path in self._workspace.paths]) return command diff --git a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py index d25a2e223..eed340983 100644 --- a/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py +++ b/test/ci/codeclimate/codeclimate-clang-tidy/lib/runner.py @@ -1,102 +1,102 @@ import json import subprocess import sys import re import os try: from termcolor import colored except ImportError: def colored(text, color): return text from command import Command from issue_formatter import IssueFormatter from workspace import Workspace class Runner: CONFIG_FILE_PATH = '/config.json' """Runs clang-tidy, collects and reports results.""" def __init__(self): self._config_file_path = self.CONFIG_FILE_PATH self._config = {} self._decode_config() self._ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])') self._issue_parse = re.compile(r'(?P.*\.(cc|hh)):(?P[0-9]+):(?P[0-9]+): (warning|error): (?P.*) \[(?P.*)\]') # noqa self._issues_fpr = [] self._workspace = Workspace(self._config.get('include_paths', [])) self._files = self._workspace.files self._include_paths = self._workspace.include_paths def run(self): if not len(self._files) > 0: return self._print_debug(f'[clang-tidy] analyzing {len(self._files)} files') command = Command(self._config, self._workspace).build() self._print_debug(f'[clang-tidy] command: {command}') + self._generate_issues(command) def _decode_config(self): self._print_debug(f"Decoding config file {self._config_file_path}") contents = "" with open(self._config_file_path, "r") as config: contents = config.read() self._config = json.loads(contents) self._print_debug(f'[clang-tidy] config: {self._config}') def _print_issue(self, issue): issue_ = IssueFormatter(issue).format() path = os.path.dirname(os.path.abspath(issue_["location"]["path"])) if path not in self._include_paths: return if issue_['fingerprint'] in self._issues_fpr: return self._issues_fpr.append(issue_['fingerprint']) print('{}\0'.format(json.dumps(issue_))) def _generate_issues(self, command): issue = None for line in self._run_command(command): clean_line = self._ansi_escape.sub('', line) match = self._issue_parse.match(clean_line) if match: if issue is not None: self._print_issue(issue) issue = match.groupdict() elif issue: if 'content' in issue: issue['content'].append(line) else: issue['content'] = [line] self._print_issue(issue) def _run_command(self, command): popen = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True) for stdout_line in iter(popen.stdout.readline, ""): self._print_debug(stdout_line) yield stdout_line popen.stdout.close() return_code = popen.wait() if return_code: self._print_debug( f"[clang-tidy] {command} ReturnCode {return_code}") # raise subprocess.CalledProcessError(return_code, command) def _print_debug(self, message): - if 'debug' in self._config and self._config['debug'] == 1: - print(message, file=sys.stderr) + print(message, file=sys.stderr, flush=True)