Skip to content

Commit

Permalink
bears/php: Add PHPMessDetectorBear
Browse files Browse the repository at this point in the history
Closes #22
  • Loading branch information
yash-nisar committed Apr 16, 2017
1 parent 72bc27f commit 95f0b60
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 1 deletion.
8 changes: 8 additions & 0 deletions .ci/deps.sh
Expand Up @@ -177,3 +177,11 @@ if [ ! -e ~/.local/tailor/tailor-latest ]; then
# Provide a constant path for the executable
ln -s ~/.local/tailor/tailor-* ~/.local/tailor/tailor-latest
fi

# PHPMD installation
if [ ! -e ~/phpmd/phpmd ]; then
mkdir -p ~/phpmd
curl -fsSL -o phpmd.phar http://static.phpmd.org/php/latest/phpmd.phar
sudo chmod +x phpmd.phar
sudo mv phpmd.phar ~/phpmd/phpmd
fi
3 changes: 2 additions & 1 deletion .travis.yml
Expand Up @@ -66,14 +66,15 @@ cache:
- ~/elm-format-0.18
- ~/dart-sdk/bin
- ~/.local/tailor/
- ~/phpmd

env:
global:
- CIRCLE_NODE_INDEX=-1 # Avoid accidentially being a CircleCI worker
- USE_PPAS="marutter/rdev staticfloat/juliareleases ondrej/golang"
- R_LIB_USER=~/R/Library
- LINTR_COMMENT_BOT=false
- PATH="/opt/cabal/1.24/bin:$PATH:$TRAVIS_BUILD_DIR/node_modules/.bin:$TRAVIS_BUILD_DIR/vendor/bin:$HOME/dart-sdk/bin:$HOME/.cabal/bin:$HOME/infer-linux64-v0.7.0/infer/bin:$HOME/pmd-bin-5.4.1/bin:$HOME/bakalint-0.4.0:$HOME/elm-format-0.18:$HOME/.local/tailor/tailor-latest/bin"
- PATH="/opt/cabal/1.24/bin:$PATH:$TRAVIS_BUILD_DIR/node_modules/.bin:$TRAVIS_BUILD_DIR/vendor/bin:$HOME/dart-sdk/bin:$HOME/.cabal/bin:$HOME/infer-linux64-v0.7.0/infer/bin:$HOME/pmd-bin-5.4.1/bin:$HOME/bakalint-0.4.0:$HOME/elm-format-0.18:$HOME/.local/tailor/tailor-latest/bin:$HOME/phpmd"

before_install:
# Remove Ruby directive from Gemfile as this image has 2.2.5
Expand Down
43 changes: 43 additions & 0 deletions bears/php/PHPMessDetectorBear.py
@@ -0,0 +1,43 @@
from coalib.settings.Setting import typed_list
from coalib.bearlib.abstractions.Linter import linter
from dependency_management.requirements.DistributionRequirement import \
DistributionRequirement


@linter(executable='phpmd',
output_format='regex',
output_regex=r'(?P<filename>.*):(?P<line>\d+)(?P<message>.*)')
class PHPMessDetectorBear:
"""
The bear takes a given PHP source code base and looks for several
potential problems within that source. These problems can be things like:
- Possible bugs
- Suboptimal code
- Overcomplicated expressions
- Unused parameters, methods, properties
"""

LANGUAGES = {'PHP'}
REQUIREMENTS = {DistributionRequirement(apt_get='phpmd')}
AUTHORS = {'The coala developers'}
AUTHORS_EMAILS = {'coala-devel@googlegroups.com'}
LICENSE = 'AGPL-3.0'
CAN_DETECT = {'Formatting', 'Complexity', 'Unused Code', 'Redundancy',
'Variable Misuse'}
SEE_MORE = 'https://phpmd.org/about.html'

@staticmethod
def create_arguments(filename, file, config_file,
phpmd_ruleset: typed_list(str)=''):
"""
:param phpmd_ruleset:
A ruleset filename or a comma-separated string of rulesetfilenames.
Available rulesets: cleancode, codesize, controversial, design,
naming, unusedcode.
"""
if phpmd_ruleset == '': # pragma: no cover
raise ValueError(
'The `phpmd_ruleset` is a mandatory argument.'
)
return filename, 'text', ','.join(phpmd_ruleset)
1 change: 1 addition & 0 deletions circle.yml
Expand Up @@ -29,6 +29,7 @@ dependencies:
- echo 'export PATH=$PATH:~/bakalint-0.4.0' >> ~/.circlerc
- echo 'export PATH=$PATH:~/.local/tailor/tailor-latest/bin' >> ~/.circlerc
- echo 'export PATH=$PATH:~/elm-format-0.18' >> ~/.circlerc
- echo 'export PATH=$PATH:~/phpmd' >> ~/.circlerc
- echo 'export R_LIB_USER=~/.RLibrary' >> ~/.circlerc
- sed -i '/source \/home\/ubuntu\/virtualenvs\//d' ~/.circlerc
- mkdir -p ~/.RLibrary
Expand Down
55 changes: 55 additions & 0 deletions tests/php/PHPMessDetectorBearTest.py
@@ -0,0 +1,55 @@
import os
from queue import Queue

from bears.php.PHPMessDetectorBear import PHPMessDetectorBear
from coalib.testing.LocalBearTestHelper import LocalBearTestHelper
from coalib.testing.BearTestHelper import generate_skip_decorator
from coalib.results.Result import Result
from coalib.settings.Section import Section


def get_testfile_path(name):
return os.path.join(os.path.dirname(__file__),
'phpmessdetector_test_files',
name)


def load_testfile(name):
return open(get_testfile_path(name)).readlines()


@generate_skip_decorator(PHPMessDetectorBear)
class PHPMessDetectorBearTest(LocalBearTestHelper):

def setUp(self):
self.uut = PHPMessDetectorBear(Section('name'), Queue())

def test_cleancode_violation(self):
file_contents = load_testfile('cleancode_violation.php')
self.check_results(
self.uut,
file_contents,
[Result.from_values('PHPMessDetectorBear',
'The method bar uses an else expression. Else '
'is never necessary and you can simplify the '
'code to work without else.',
file=get_testfile_path(
'cleancode_violation.php'),
line=8)],
filename=get_testfile_path('cleancode_violation.php'),
settings={'phpmd_ruleset': ['cleancode']})

def test_codesize_violation(self):
file_contents = load_testfile('codesize_violation.php')
self.check_results(
self.uut,
file_contents,
[Result.from_values('PHPMessDetectorBear',
'The method example() has a Cyclomatic '
'Complexity of 11. The configured cyclomatic '
'complexity threshold is 10.',
file=get_testfile_path(
'codesize_violation.php'),
line=4)],
filename=get_testfile_path('codesize_violation.php'),
settings={'phpmd_ruleset': ['codesize']})
Empty file.
13 changes: 13 additions & 0 deletions tests/php/phpmessdetector_test_files/cleancode_violation.php
@@ -0,0 +1,13 @@
<?
class Foo
{
public function bar($flag)
{
if ($flag) {
// one branch
} else {
// another branch
}
}
}
?>
39 changes: 39 additions & 0 deletions tests/php/phpmessdetector_test_files/codesize_violation.php
@@ -0,0 +1,39 @@
<?
// Cyclomatic Complexity = 11
class Foo {
public function example() {
if ($a == $b) {
if ($a1 == $b1) {
fiddle();
} elseif ($a2 == $b2) {
fiddle();
} else {
fiddle();
}
} elseif ($c == $d) {
while ($c == $d) {
fiddle();
}
} elseif ($e == $f) {
for ($n = 0; $n < $h; $n++) {
fiddle();
}
} else {
switch ($z) {
case 1:
fiddle();
break;
case 2:
fiddle();
break;
case 3:
fiddle();
break;
default:
fiddle();
break;
}
}
}
}
?>

0 comments on commit 95f0b60

Please sign in to comment.