diff --git a/.ci/generate_bear_metadata.py b/.ci/generate_bear_metadata.py index d6389145bb..bcc8e5567b 100755 --- a/.ci/generate_bear_metadata.py +++ b/.ci/generate_bear_metadata.py @@ -322,11 +322,6 @@ def get_bear_tags(bear, metadata): tags.remove('java') tags.add('opam') - elif bear.name == 'CPDBear': - # Has no requirements defined yet - tags.remove('noreqs') - tags.add('java') - elif bear.name == 'LanguageToolBear': # Has no requirements defined yet tags.add('java') @@ -337,8 +332,7 @@ def get_bear_tags(bear, metadata): tags.add('pmd') elif bear.name == 'CPDBear': - # Has no executable defined - tags.add('cpd') + tags.add('java') elif bear.name == 'VHDLLintBear': # Has no executable defined diff --git a/bear-metadata.yaml b/bear-metadata.yaml index 6cb7f2a783..d0bf16f0b3 100644 --- a/bear-metadata.yaml +++ b/bear-metadata.yaml @@ -154,6 +154,9 @@ bear_metadata: subdir: general filename: CPDBear.py requirements: + exe: + cpd: + run.sh: languages: - C# - CPP @@ -174,8 +177,11 @@ bear_metadata: - Scala - Swift tags: + - cpd + - exe - general - java + - run.sh CPPCheckBear: name: CPPCheckBear subdir: c_languages diff --git a/bears/general/CPDBear.py b/bears/general/CPDBear.py index 4914194646..c50c51833a 100644 --- a/bears/general/CPDBear.py +++ b/bears/general/CPDBear.py @@ -1,6 +1,11 @@ from shutil import which from xml.etree import ElementTree +from dependency_management.requirements.AnyOneOfRequirements import ( + AnyOneOfRequirements) +from dependency_management.requirements.ExecutableRequirement import ( + ExecutableRequirement) + from coalib.bears.GlobalBear import GlobalBear from coalib.misc.Shell import run_shell_command from coalib.results.Result import Result @@ -30,21 +35,18 @@ class CPDBear(GlobalBear): 'Swift': 'swift'} LANGUAGES = set(language_dict.keys()) + REQUIREMENTS = { + AnyOneOfRequirements( + [ExecutableRequirement('cpd'), + ExecutableRequirement('run.sh'), + ] + ), + } AUTHORS = {'The coala developers'} AUTHORS_EMAILS = {'coala-devel@googlegroups.com'} LICENSE = 'AGPL-3.0' CAN_DETECT = {'Duplication'} - @classmethod - def check_prerequisites(cls): - if which('bash') is None: - return 'bash is not installed.' - if which('pmd') is None and which('run.sh') is None: - return ('PMD is missing. Make sure to install it from ' - '<https://pmd.github.io/>.') - else: - return True - def run(self, language: language, minimum_tokens: int = 20, ignore_annotations: bool = False, @@ -93,8 +95,11 @@ def run(self, language: language, '--skip-duplicate-files': skip_duplicate_files} files = ','.join(self.file_dict.keys()) - executable = which('pmd') or which('run.sh') - arguments = ('bash', executable, 'cpd', '--skip-lexical-errors', + executable = which('cpd') or which('run.sh') + executable = tuple([executable] if not executable.endswith('run.sh') + else [executable, 'cpd']) + + arguments = ('--skip-lexical-errors', '--minimum-tokens', str(minimum_tokens), '--language', cpd_language, '--files', files, @@ -104,6 +109,7 @@ def run(self, language: language, for option, enable in options.items() if enable is True) + arguments = executable + arguments stdout_output, _ = run_shell_command(arguments) if stdout_output: diff --git a/tests/general/CPDBearTest.py b/tests/general/CPDBearTest.py index aa33e08b68..3984febdd9 100644 --- a/tests/general/CPDBearTest.py +++ b/tests/general/CPDBearTest.py @@ -1,6 +1,5 @@ import os import unittest -from unittest import mock from queue import Queue import logging @@ -68,14 +67,3 @@ def test_unsupported_language(self): self.uut.message_queue.queue[0].log_level, logging.ERROR) self.assertIn('Hypertext Markup Language', self.uut.message_queue.queue[0].message) - - def test_check_prerequisites(self): - with mock.patch('bears.general.CPDBear.which') as mock_which: - mock_which.side_effect = [None, None, None] - self.assertEqual(CPDBear.check_prerequisites(), - 'bash is not installed.') - - mock_which.side_effect = ['path/to/bash', None, None] - self.assertEqual(CPDBear.check_prerequisites(), - 'PMD is missing. Make sure to install it ' - 'from <https://pmd.github.io/>.')