Skip to content

[feat] Adds support for ignoring a file on a specific sniff #182

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@ parameters:
- '#is not allowed to extend#'
- '#Language construct isset\(\) should not be used#'
- '#Access to an undefined property PHP_CodeSniffer\\Config::\$standards.#'
- '#Access to an undefined property PHP_CodeSniffer\\Sniffs\\Sniff::\$#'
autoload_files:
- %rootDir%/../../squizlabs/php_codesniffer/autoload.php
reportUnmatchedIgnoredErrors: false

excludes_analyse:
- %rootDir%/../../../tests/*/Fixtures/*
- %rootDir%/../../../tests/Fixtures/*
14 changes: 8 additions & 6 deletions src/Domain/EcsContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace NunoMaduro\PhpInsights\Domain;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Container;
use Symplify\EasyCodingStandard\HttpKernel\EasyCodingStandardKernel;
use Symplify\PackageBuilder\Console\Input\InputDetector;

Expand All @@ -14,14 +14,14 @@
final class EcsContainer
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
* @var \Symfony\Component\DependencyInjection\Container
*/
private static $container;

/**
* @return \Symfony\Component\DependencyInjection\ContainerInterface
* @return \Symfony\Component\DependencyInjection\Container
*/
public static function make(): ContainerInterface
public static function make(): Container
{
if (self::$container === null) {
$environment = str_replace('.', '_', sprintf(
Expand All @@ -31,11 +31,13 @@ public static function make(): ContainerInterface
$easyCodingStandardKernel = new EasyCodingStandardKernel($environment, InputDetector::isDebug());
$easyCodingStandardKernel->boot();

if ($easyCodingStandardKernel->getContainer() === null) {
$container = $easyCodingStandardKernel->getContainer();

if ($container === null || ! ($container instanceof Container)) {
throw new \RuntimeException('Unable to get EcsContainer.');
}

self::$container = $easyCodingStandardKernel->getContainer();
self::$container = $container;
}

return self::$container;
Expand Down
27 changes: 19 additions & 8 deletions src/Domain/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@

namespace NunoMaduro\PhpInsights\Domain;

use NunoMaduro\PhpInsights\Domain\Sniffs\SniffWrapper;
use PHP_CodeSniffer\Config;
use PHP_CodeSniffer\Files\File as BaseFile;
use PHP_CodeSniffer\Fixer;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Common;
use Symplify\EasyCodingStandard\Application\AppliedCheckersCollector;
use Symplify\EasyCodingStandard\Console\Style\EasyCodingStandardStyle;
use Symplify\EasyCodingStandard\Error\ErrorAndDiffCollector;
use Symplify\EasyCodingStandard\Skipper;
use Symplify\EasyCodingStandard\SniffRunner\Exception\File\NotImplementedException;
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;

final class File extends BaseFile
Expand All @@ -28,7 +29,7 @@ final class File extends BaseFile
private $previousActiveSniffClass;

/**
* @var array<array<\PHP_CodeSniffer\Sniffs\Sniff>>
* @var array<array<\NunoMaduro\PhpInsights\Domain\Sniffs\SniffWrapper>>
*/
private $tokenListeners = [];

Expand Down Expand Up @@ -120,15 +121,15 @@ public function process(): void

public function getErrorCount(): int
{
throw new \Symplify\EasyCodingStandard\SniffRunner\Exception\File\NotImplementedException();
throw new NotImplementedException();
}

/**
* {@inheritdoc}
*/
public function getErrors(): array
{
throw new \Symplify\EasyCodingStandard\SniffRunner\Exception\File\NotImplementedException();
throw new NotImplementedException();
}

/**
Expand All @@ -145,7 +146,7 @@ public function addFixableError($error, $stackPtr, $code, $data = [], $severity
}

/**
* @param array<array<Sniff>> $tokenListeners
* @param array<array<\NunoMaduro\PhpInsights\Domain\Sniffs\SniffWrapper>> $tokenListeners
*/
public function processWithTokenListenersAndFileInfo(array $tokenListeners, SmartFileInfo $fileInfo): void
{
Expand All @@ -154,6 +155,16 @@ public function processWithTokenListenersAndFileInfo(array $tokenListeners, Smar
$this->process();
}

/**
* Get's the file info from the file.
*
* @return SmartFileInfo
*/
public function getFileInfo(): SmartFileInfo
{
return $this->fileInfo;
}

/**
* {@inheritdoc}
*/
Expand Down Expand Up @@ -181,12 +192,12 @@ protected function addMessage(
}

/**
* @param Sniff $sniff
* @param SniffWrapper $sniff
*/
private function reportActiveSniffClass(Sniff $sniff): void
private function reportActiveSniffClass(SniffWrapper $sniff): void
{
// used in other places later
$this->activeSniffClass = get_class($sniff);
$this->activeSniffClass = get_class($sniff->getWrappedSniff());

if (! $this->easyCodingStandardStyle->isDebug()) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/Domain/FileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ final class FileProcessor implements FileProcessorInterface
private $sniffs = [];

/**
* @var array<array<\PHP_CodeSniffer\Sniffs\Sniff>>
* @var array<array<\NunoMaduro\PhpInsights\Domain\Sniffs\SniffWrapper>>
*/
private $tokenListeners = [];

Expand Down
11 changes: 9 additions & 2 deletions src/Domain/Insights/InsightCollectionFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,16 +92,23 @@ public function get(array $metrics, array $config, string $dir): InsightCollecti
*/
private function getInsights(string $metricClass, array $config): array
{
/** @var HasInsights $metric */
$metric = new $metricClass();

$insights = array_key_exists(HasInsights::class, class_implements($metricClass)) ? $metric->getInsights() : [];
$insights = array_key_exists(
HasInsights::class,
class_implements($metricClass)
) ? $metric->getInsights() : [];

$toAdd = array_key_exists('add', $config) &&
array_key_exists($metricClass, $config['add']) &&
is_array($config['add'][$metricClass]) ? $config['add'][$metricClass] : [];
is_array($config['add'][$metricClass])
? $config['add'][$metricClass]
: [];

$insights = array_merge($insights, $toAdd);

// Remove insights based on config.
return array_diff($insights, $config['remove'] ?? []);
}
}
7 changes: 6 additions & 1 deletion src/Domain/Insights/InsightFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use NunoMaduro\PhpInsights\Domain\EcsContainer;
use NunoMaduro\PhpInsights\Domain\FileProcessor;
use NunoMaduro\PhpInsights\Domain\Reflection;
use NunoMaduro\PhpInsights\Domain\Sniffs\SniffWrapper;
use PHP_CodeSniffer\Sniffs\Sniff as SniffContract;
use Symplify\EasyCodingStandard\Application\EasyCodingStandardApplication;
use Symplify\EasyCodingStandard\Configuration\Configuration;
Expand Down Expand Up @@ -173,7 +174,7 @@ private function getSniffCollector(array $config): ErrorAndDiffCollector

$sniffer = Container::make()->get(FileProcessor::class);
foreach ($this->sniffsFrom($this->insightsClasses, $config) as $sniff) {
$sniffer->addSniff($sniff);
$sniffer->addSniff(new SniffWrapper($sniff));
}

/** @var \Symplify\EasyCodingStandard\Application\EasyCodingStandardApplication $application */
Expand All @@ -192,6 +193,10 @@ private function getSniffCollector(array $config): ErrorAndDiffCollector
/** @var \Symplify\EasyCodingStandard\Error\ErrorAndDiffCollector $errorAndDiffCollector */
$errorAndDiffCollector = $ecsContainer->get(ErrorAndDiffCollector::class);

// Destroy the container, so we insights doesn't fail on consecutive
// runs. This is needed for tests also.
$ecsContainer->reset();

return $this->sniffCollector = $errorAndDiffCollector;
}
}
2 changes: 1 addition & 1 deletion src/Domain/Insights/Sniff.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function getDetails(): array
public function getInsightClass(): string
{
if (\count($this->errors) === 0) {
throw new SniffClassNotFound('Unable to found Sniff used.');
throw new SniffClassNotFound('Unable to find Sniff used.');
}

return explode('.', $this->errors[0]->getSourceClass())[0];
Expand Down
113 changes: 113 additions & 0 deletions src/Domain/Sniffs/SniffWrapper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

declare(strict_types=1);

namespace NunoMaduro\PhpInsights\Domain\Sniffs;

use NunoMaduro\PhpInsights\Domain\File as InsightFile;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;

/**
* This wrapper is meant for us to add custom logic which is applied to all
* sniffs.
*
* This logic could be for example to exclude the sniff if it's running on
* a specific class.
*/
final class SniffWrapper implements Sniff
{
/** @var Sniff */
private $sniff;

/**
* SniffWrapper constructor.
*
* @param Sniff $sniff
*/
public function __construct(Sniff $sniff)
{
$this->sniff = $sniff;
}

/**
* Registers the tokens that this sniff wants to listen for.
*
* @return mixed[]
*
* @see Tokens.php
*/
public function register(): array
{
return $this->sniff->register();
}

/**
* Called when one of the token types that this sniff is listening for
* is found.
*
* @param File|InsightFile $file The PHP_CodeSniffer file
* @param int $stackPtr The position in the PHP_CodeSniffer file's
* token stack
*
* @return void|int Optionally returns a stack pointer. The sniff will not be
* called again on the current file until the returned stack
* pointer is reached. Return (count($tokens) + 1) to skip
* the rest of the file.
*/
public function process(File $file, $stackPtr)
{
if ($file instanceof InsightFile) {
// skip files if they are part of ignore files array.
if ($this->skipFilesFromIgnoreFiles($file)) {
return;
}
}

return $this->sniff->process($file, $stackPtr);
}

private function skipFilesFromIgnoreFiles(InsightFile $file): bool
{
$path = $file->getFileInfo()->getRealPath();

if ($path === false) {
return false;
}

foreach ($this->getIgnoreFilesSetting() as $ignoreFile) {
if (self::pathsAreEqual(
$ignoreFile,
$path
)) {
return true;
}
}
return false;
}

/**
* Contains the setting for all files which the sniff should ignore.
*
* @return array<string>
*/
private function getIgnoreFilesSetting(): array
{
return $this->sniff->ignoreFiles ?? [];
}

private static function pathsAreEqual(string $pathA, string $pathB): bool
{
return realpath($pathA) === realpath($pathB);
}

/**
* Returns the sniff which we have wrapped.
*
* @return Sniff
*/
public function getWrappedSniff(): Sniff
{
return $this->sniff;
}
}
Loading