Skip to content

Commit

Permalink
Including a path to a sniff in a ruleset works again.
Browse files Browse the repository at this point in the history
To achieve this, the autoloader keeps track of loaded file paths and the resulting namespace/class it loads. Unit tests have been changed to make use of this by caching the config and ruleset objects, so testing happens a bit faster now as well.
  • Loading branch information
gsherwood committed Apr 10, 2015
1 parent 46c0a58 commit a3856b7
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 36 deletions.
53 changes: 49 additions & 4 deletions autoload.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
<?php
spl_autoload_register(
function ($class) {
namespace PHP_CodeSniffer;

class Autoload {

private static $declaredClasses = array();
private static $declaredInterfaces = array();
private static $loadedClasses = array();

public static function load($class)
{
if (empty(self::$declaredClasses) === true) {
self::$declaredClasses = get_declared_classes();
self::$declaredInterfaces = get_declared_interfaces();
}

$ds = DIRECTORY_SEPARATOR;
$path = null;

Expand All @@ -13,10 +26,42 @@ function ($class) {
}

if ($path !== null && is_file($path) === true) {
include $path;
self::loadFile($path);
return true;
}

return false;
}
);

public static function loadFile($path)
{
if (isset(self::$loadedClasses[$path]) === true) {
return self::$loadedClasses[$path];
}

$classes = get_declared_classes();
$interfaces = get_declared_interfaces();

include $path;

$className = array_pop(array_diff(get_declared_classes(), $classes));
if ($className === null) {
$className = array_pop(array_diff(get_declared_interfaces(), $interfaces));
}

self::$loadedClasses[$path] = $className;
return self::$loadedClasses[$path];
}

public static function getLoadedClassName($file)
{
if (isset(self::$loadedClasses[$file]) === false) {
throw new \Exception("Cannot get class name for $file; file has not been included");
}

return self::$loadedClasses[$file];
}

}

spl_autoload_register(__NAMESPACE__.'\Autoload::load', true, true);
31 changes: 13 additions & 18 deletions src/Ruleset.php
Original file line number Diff line number Diff line change
Expand Up @@ -824,10 +824,13 @@ public function registerSniffs($files, $restrictions)
continue;
}

$className = substr($file, ($slashPos + 1));
$className = substr($className, 0, -4);
$className = str_replace(DIRECTORY_SEPARATOR, '\\', $className);
$className = 'PHP_CodeSniffer\Standards\\'.$className;
#$className = substr($file, ($slashPos + 1));
#$className = substr($className, 0, -4);
#$className = str_replace(DIRECTORY_SEPARATOR, '\\', $className);
#$className = 'PHP_CodeSniffer\Standards\\'.$className;
#echo "OLD: $className\n";

$className = Autoload::loadFile($file);

// If they have specified a list of sniffs to restrict to, check
// to see if this sniff is allowed.
Expand All @@ -837,8 +840,6 @@ public function registerSniffs($files, $restrictions)
continue;
}

include_once $file;

// Skip abstract classes.
$reflection = new \ReflectionClass($className);
if ($reflection->isAbstract() === true) {
Expand Down Expand Up @@ -870,17 +871,13 @@ public function populateTokenListeners()

foreach ($this->sniffs as $sniffClass => $sniffObject) {
$this->sniffs[$sniffClass] = null;

// Work out the internal code for this sniff.
$parts = explode('\\', $sniffClass);
$code = $parts[2].'.'.$parts[4].'.'.$parts[5];
$code = substr($code, 0, -5);

$this->sniffs[$sniffClass] = new $sniffClass();

$sniffCode = Util\Common::getSniffCode($sniffClass);

// Set custom properties.
if (isset($this->ruleset[$code]['properties']) === true) {
foreach ($this->ruleset[$code]['properties'] as $name => $value) {
if (isset($this->ruleset[$sniffCode]['properties']) === true) {
foreach ($this->ruleset[$sniffCode]['properties'] as $name => $value) {
$this->setSniffProperty($sniffClass, $name, $value);
}
}
Expand All @@ -901,10 +898,8 @@ public function populateTokenListeners()
throw new RuntimeException($msg);
}

$parts = explode('\\', $sniffClass);
$listenerSource = $parts[2].'.'.$parts[4].'.'.substr($parts[5], 0, -5);
$ignorePatterns = array();
$patterns = $this->getIgnorePatterns($listenerSource);
$patterns = $this->getIgnorePatterns($sniffCode);
foreach ($patterns as $pattern => $type) {
// While there is support for a type of each pattern
// (absolute or relative) we don't actually support it here.
Expand All @@ -924,7 +919,7 @@ public function populateTokenListeners()
if (isset($this->tokenListeners[$token][$sniffClass]) === false) {
$this->tokenListeners[$token][$sniffClass] = array(
'class' => $sniffClass,
'source' => $listenerSource,
'source' => $sniffCode,
'tokenizers' => $tokenizers,
'ignore' => $ignorePatterns,
);
Expand Down
11 changes: 11 additions & 0 deletions src/Util/Common.php
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,15 @@ public static function suggestType($varType)

}//end suggestType()

public static function getSniffCode($sniffClass)
{
$parts = explode('\\', $sniffClass);
$sniff = substr(array_pop($parts), 0, -5);
$category = array_pop($parts);
$sniffDir = array_pop($parts);
$standard = array_pop($parts);
$code = $standard.'.'.$category.'.'.$sniff;
return $code;
}

}
29 changes: 20 additions & 9 deletions tests/Standards/AbstractSniffUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ abstract class AbstractSniffUnitTest extends \PHPUnit_Framework_TestCase
*/
protected $backupGlobals = false;

/**
* The PHP_CodeSniffer object used for testing.
*
* @var PHP_CodeSniffer
*/
protected static $phpcs = null;

/**
* The path to the directory under which the sniff's standard lives.
*
Expand Down Expand Up @@ -131,12 +124,30 @@ public final function testSniff()
// Get them in order.
sort($testFiles);

$config = new Config();
if (isset($GLOBALS['PHP_CODESNIFFER_CONFIG']) === true) {
$config = $GLOBALS['PHP_CODESNIFFER_CONFIG'];
} else {
$config = new Config();
$GLOBALS['PHP_CODESNIFFER_CONFIG'] = $config;
}

$config->standards = array($standardName);
$config->sniffs = array($sniffCode);
$config->ignored = array();

$ruleset = new Ruleset($config);
if (isset($GLOBALS['PHP_CODESNIFFER_RULESET']) === true) {
$ruleset = $GLOBALS['PHP_CODESNIFFER_RULESET'];

$sniffBasename = str_replace('\Tests\\', '\Sniffs\\', $basename).'Sniff';
$testFile = $this->standardsDir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $sniffBasename).'.php';

$restrictions = array('php_codesniffer\standards\\'.strtolower($sniffBasename) => true);
$ruleset->registerSniffs(array($testFile), $restrictions);
$ruleset->populateTokenListeners();
} else {
$ruleset = new Ruleset($config);
$GLOBALS['PHP_CODESNIFFER_RULESET'] = $ruleset;
}

$failureMessages = array();
foreach ($testFiles as $testFile) {
Expand Down
26 changes: 23 additions & 3 deletions tests/Standards/AllSniffs.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

namespace PHP_CodeSniffer\Tests\Standards;

use PHP_CodeSniffer\Util;
use PHP_CodeSniffer\Util\Tokens;
use PHP_CodeSniffer\Util\Standards;

/**
* A test class for testing all sniffs for installed standards.
Expand All @@ -18,6 +19,22 @@
* @link http://pear.php.net/package/PHP_CodeSniffer
*/

if (defined('PHP_CODESNIFFER_IN_TESTS') === false) {
define('PHP_CODESNIFFER_IN_TESTS', true);
}

if (defined('PHP_CODESNIFFER_CBF') === false) {
define('PHP_CODESNIFFER_CBF', false);
}

if (defined('PHP_CODESNIFFER_VERBOSITY') === false) {
define('PHP_CODESNIFFER_VERBOSITY', 0);
}

require_once __DIR__.'/../../autoload.php';

$tokens = new Tokens();

/**
* A test class for testing all sniffs for installed standards.
*
Expand Down Expand Up @@ -61,14 +78,17 @@ public static function main()
*/
public static function suite()
{
$GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = array();
$GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = array();

$suite = new \PHPUnit_Framework_TestSuite('PHP CodeSniffer Standards');

#$isInstalled = !is_file(dirname(__FILE__).'/../../CodeSniffer.php');

$installedPaths = Util\Standards::getInstalledStandardPaths();
$installedPaths = Standards::getInstalledStandardPaths();
foreach ($installedPaths as $path) {
$origPath = $path;
$standards = Util\Standards::getInstalledStandards(true, $path);
$standards = Standards::getInstalledStandards(true, $path);

// If the test is running PEAR installed, the built-in standards
// are split into different directories; one for the sniffs and
Expand Down
4 changes: 2 additions & 2 deletions tests/TestSuite.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ class TestSuite extends \PHPUnit_Framework_TestSuite
*/
public function run(\PHPUnit_Framework_TestResult $result=null, $filter=false)
{
$GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = array();
$GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = array();
#$GLOBALS['PHP_CODESNIFFER_SNIFF_CODES'] = array();
#$GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES'] = array();

#spl_autoload_register(array('PHP_CodeSniffer', 'autoload'));
$result = parent::run($result, $filter);
Expand Down

0 comments on commit a3856b7

Please sign in to comment.