diff --git a/bears/rust/RustClippyLintBear.py b/bears/rust/RustClippyLintBear.py new file mode 100644 index 0000000000..0826455f05 --- /dev/null +++ b/bears/rust/RustClippyLintBear.py @@ -0,0 +1,63 @@ +import json +from os import linesep +from shutil import which + +from coalib.bears.GlobalBear import GlobalBear +from coalib.misc.Shell import run_shell_command +from coalib.results.Result import Result +from coalib.results.RESULT_SEVERITY import RESULT_SEVERITY + + +class RustClippyLintBear(GlobalBear): + LANGUAGES = {'Rust'} + AUTHORS = {'The coala developers'} + AUTHORS_EMAILS = {'coala-devel@googlegroups.com'} + LICENSE = 'AGPL-3.0' + CAN_DETECT = { + 'Formatting', + 'Unused Code', + 'Syntax', + 'Unreachable Code', + 'Smell', + 'Code Simplification' + } + EXECUTABLE = 'cargo' + SEVERITY_MAP = { + # TODO: are there more? + 'warning': RESULT_SEVERITY.NORMAL, + 'error': RESULT_SEVERITY.MAJOR, + } + + @classmethod + def check_prerequisites(cls): + # TODO: - check for clippy itself + # - clippy also works via rustup nightly, so also check that. + if which('cargo') is None: + return 'cargo is not installed.' + else: + return True + + def run(self): + args = ('clippy', '--quiet', '--color', 'never', + '--', '-Z', 'unstable-options', '--error-format', 'json', + '--test') + _, stderr_output = run_shell_command( + (self.EXECUTABLE,) + args, + cwd=self.get_config_dir(), + universal_newlines=True) + for line in stderr_output.split(linesep): + if not line: + continue + yield self.new_result(json.loads(line)) + + def new_result(self, issue): + span = issue['spans'][0] + return Result.from_values( + origin=self.__class__.__name__, + message=issue['message'], + file=span['file_name'], + line=span['line_start'], + end_line=span['line_end'], + column=span['column_start'], + end_column=span['column_end'], + severity=self.SEVERITY_MAP[issue['level']]) diff --git a/bears/rust/__init__.py b/bears/rust/__init__.py new file mode 100644 index 0000000000..e69de29bb2