Skip to content

Commit

Permalink
CPDBear: Detect appropriate linter executable
Browse files Browse the repository at this point in the history
Describe current executable requirements of cpd or run.sh,
replacing check_prerequisites with Requirement classes.

Also remove explicit invocation using `bash`, which was
ineffective as which('run.sh') would only be successful
if the script was executable, and the run.sh script is not
written to be compatible with invocation on Windows.

This de-supports any usage where `pmd` existed and was a script
which could invoke `cpd`.  It fixes usage where `pmd` is not a
script, like it is an executable shim when installed with choco.

Also remove duplication of `CPDBear` in generate_bear_metadata.py
which was intended to make 'cpd' deselectable, but was broken.
It is now mostly unnecessary as the ExecutableRequirement classes
provide the `cpd` tag, however the `java` tag is still manual.

Reduce the required coverage percentage to 98%.

Fixes coala#2937
Related to coala#2908
  • Loading branch information
jayvdb committed Aug 6, 2019
1 parent 3ca00c9 commit a0f5a9e
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 31 deletions.
8 changes: 1 addition & 7 deletions .ci/generate_bear_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions .ci/generate_coverage_thresholds.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ def main():
bear = bear.replace('/', '\\\\')
if 'CheckstyleBear' in bear or 'CMakeLintBear' in bear:
threshold = 90
elif 'CPDBear' in bear:
threshold = 98

thresholds[bear] = threshold

Expand Down
6 changes: 6 additions & 0 deletions bear-metadata.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ bear_metadata:
subdir: general
filename: CPDBear.py
requirements:
exe:
cpd:
run.sh:
languages:
- C#
- CPP
Expand All @@ -174,8 +177,11 @@ bear_metadata:
- Scala
- Swift
tags:
- cpd
- exe
- general
- java
- run.sh
CPPCheckBear:
name: CPPCheckBear
subdir: c_languages
Expand Down
30 changes: 18 additions & 12 deletions bears/general/CPDBear.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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 = {'[email protected]'}
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,
Expand Down Expand Up @@ -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,
Expand All @@ -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:
Expand Down
12 changes: 0 additions & 12 deletions tests/general/CPDBearTest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import os
import unittest
from unittest import mock

from queue import Queue
import logging
Expand Down Expand Up @@ -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/>.')

0 comments on commit a0f5a9e

Please sign in to comment.