Skip to content
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

Add debug information to cache results #1015

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ Command line options

- The command line interface also accepts the following optional arguments:

- ``-v, -vv, -vvv`` - The output verbosity level. Will print more information
what is being processed or cached. Will be send to ``STDERR`` to not interfere
with report output.

- ``--minimumpriority`` - The rule priority threshold; rules with lower
priority than they will not be used.

Expand Down
31 changes: 27 additions & 4 deletions src/main/php/PHPMD/Cache/ResultCacheEngineFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,25 @@

namespace PHPMD\Cache;

use PHPMD\Console\OutputInterface;
use PHPMD\RuleSet;
use PHPMD\TextUI\CommandLineOptions;

class ResultCacheEngineFactory
{
/** @var OutputInterface */
private $output;
/** @var ResultCacheKeyFactory */
private $cacheKeyFactory;
/** @var ResultCacheStateFactory */
private $cacheStateFactory;

public function __construct(ResultCacheKeyFactory $cacheKeyFactory, ResultCacheStateFactory $cacheStateFactory)
{
public function __construct(
OutputInterface $output,
ResultCacheKeyFactory $cacheKeyFactory,
ResultCacheStateFactory $cacheStateFactory
) {
$this->output = $output;
$this->cacheKeyFactory = $cacheKeyFactory;
$this->cacheStateFactory = $cacheStateFactory;
}
Expand All @@ -26,6 +33,7 @@ public function __construct(ResultCacheKeyFactory $cacheKeyFactory, ResultCacheS
public function create($basePath, CommandLineOptions $options, array $ruleSetList)
{
if ($options->isCacheEnabled() === false) {
$this->output->writeln('ResultCache is not enabled.', OutputInterface::VERBOSITY_VERY_VERBOSE);
return null;
}

Expand All @@ -34,15 +42,30 @@ public function create($basePath, CommandLineOptions $options, array $ruleSetLis

// load result cache from file
$state = $this->cacheStateFactory->fromFile($options->cacheFile());
if ($state === null) {
$this->output->writeln(
'ResultCache is enabled, but no prior cache-result file exists.',
OutputInterface::VERBOSITY_VERY_VERBOSE
);
}

// the cache key doesn't match the stored cache key. Invalidate cache
if ($state !== null && $state->getCacheKey()->isEqualTo($cacheKey) === false) {
$this->output->writeln(
'ResultCache is enabled, but the cache metadata doesn\'t match.',
OutputInterface::VERBOSITY_VERY_VERBOSE
);
$state = null;
} else {
$this->output->writeln(
'ResultCache is enabled, and read from ' . $options->cacheFile(),
OutputInterface::VERBOSITY_VERY_VERBOSE
);
}

return new ResultCacheEngine(
new ResultCacheFileFilter($basePath, $options->cacheStrategy(), $cacheKey, $state),
new ResultCacheUpdater($basePath),
new ResultCacheFileFilter($this->output, $basePath, $options->cacheStrategy(), $cacheKey, $state),
new ResultCacheUpdater($this->output, $basePath),
new ResultCacheWriter($options->cacheFile())
);
}
Expand Down
19 changes: 18 additions & 1 deletion src/main/php/PHPMD/Cache/ResultCacheFileFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PDepend\Input\Filter;
use PHPMD\Cache\Model\ResultCacheKey;
use PHPMD\Cache\Model\ResultCacheState;
use PHPMD\Console\OutputInterface;
use PHPMD\Utility\Paths;

class ResultCacheFileFilter implements Filter
Expand All @@ -24,14 +25,18 @@ class ResultCacheFileFilter implements Filter
/** @var array<string, bool> */
private $fileIsModified = array();

/** @var OutputInterface */
private $output;


/**
* @param string $basePath
* @param string $strategy
* @param ResultCacheState|null $state
*/
public function __construct($basePath, $strategy, ResultCacheKey $cacheKey, $state)
public function __construct(OutputInterface $output, $basePath, $strategy, ResultCacheKey $cacheKey, $state)
{
$this->output = $output;
$this->basePath = $basePath;
$this->strategy = $strategy;
$this->state = $state;
Expand Down Expand Up @@ -72,6 +77,18 @@ public function accept($relative, $absolute)
$this->newState->setViolations($filePath, $this->state->getViolations($filePath));
}

if ($isModified) {
$this->output->writeln(
'Cache: MISS for file ' . $filePath . '.',
OutputInterface::VERBOSITY_DEBUG
);
} else {
$this->output->writeln(
'Cache: HIT for file ' . $filePath . '.',
OutputInterface::VERBOSITY_DEBUG
);
}

return $this->fileIsModified[$filePath] = $isModified;
}

Expand Down
18 changes: 17 additions & 1 deletion src/main/php/PHPMD/Cache/ResultCacheUpdater.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,24 @@
namespace PHPMD\Cache;

use PHPMD\Cache\Model\ResultCacheState;
use PHPMD\Console\OutputInterface;
use PHPMD\Report;
use PHPMD\RuleSet;
use PHPMD\Utility\Paths;

class ResultCacheUpdater
{
/** @var OutputInterface */
private $output;
/** @var string */
private $basePath;

/**
* @param string $basePath
*/
public function __construct($basePath)
public function __construct(OutputInterface $output, $basePath)
{
$this->output = $output;
$this->basePath = $basePath;
}

Expand All @@ -30,8 +34,11 @@ public function update(array $ruleSetList, ResultCacheState $state, Report $repo
$newViolations = $report->getRuleViolations();

// add RuleViolations from the result cache to the report
$violationsFromCache = 0;

foreach ($state->getRuleViolations($this->basePath, $ruleSetList) as $ruleViolation) {
$report->addRuleViolation($ruleViolation);
++$violationsFromCache;
}

// add violations from the report to the result cache
Expand All @@ -40,6 +47,15 @@ public function update(array $ruleSetList, ResultCacheState $state, Report $repo
$state->addRuleViolation($filePath, $violation);
}

$this->output->writeln(
'Cache: added ' . count($newViolations) . ' violations to the result cache.',
OutputInterface::VERBOSITY_VERY_VERBOSE
);
$this->output->writeln(
'Cache: added ' . $violationsFromCache . ' violations from the result cache to the report.',
OutputInterface::VERBOSITY_VERY_VERBOSE
);

return $state;
}
}
14 changes: 14 additions & 0 deletions src/main/php/PHPMD/Console/NullOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php

namespace PHPMD\Console;

class NullOutput extends Output
{
/**
* @inheritDoc
*/
protected function doWrite($message)
{
// do nothing
}
}
80 changes: 80 additions & 0 deletions src/main/php/PHPMD/Console/Output.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace PHPMD\Console;

abstract class Output implements OutputInterface
{
/** @var int */
private $verbosity;

/**
* @param int $verbosity
*/
public function __construct($verbosity = self::VERBOSITY_NORMAL)
{
$this->verbosity = $verbosity;
}

/**
* @param string|string[] $messages
* @param bool $newline
* @param int $options A bitmask of options (one of the VERBOSITY constants),
* 0 is considered the same as self::VERBOSITY_NORMAL
* @return void
*/
public function write($messages, $newline = false, $options = self::VERBOSITY_NORMAL)
{
if (is_array($messages) === false) {
$messages = array($messages);
}

$verbosities = self::VERBOSITY_QUIET
| self::VERBOSITY_NORMAL
| self::VERBOSITY_VERBOSE
| self::VERBOSITY_VERY_VERBOSE
| self::VERBOSITY_DEBUG;
$verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;

if ($verbosity > $this->getVerbosity()) {
return;
}

foreach ($messages as $message) {
$this->doWrite($message . ($newline ? "\n" : ""));
}
}

/**
* @param string|string[] $messages
* @param int $options A bitmask of options (one of the VERBOSITY constants),
* 0 is considered the same as self::VERBOSITY_NORMAL
* @return void
*/
public function writeln($messages, $options = self::VERBOSITY_NORMAL)
{
$this->write($messages, true, $options);
}

/**
* @param int $level
* @return void
*/
public function setVerbosity($level)
{
$this->verbosity = $level;
}

/**
* @return int
*/
public function getVerbosity()
{
return $this->verbosity;
}

/**
* @param string $message
* @return void
*/
abstract protected function doWrite($message);
}
44 changes: 44 additions & 0 deletions src/main/php/PHPMD/Console/OutputInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace PHPMD\Console;

/**
* A basic OutputInterface that follows a partial implementation of Symfony's OutputInterface to allow future drop-in
* replacement by the Console package.
*/
interface OutputInterface
{
const VERBOSITY_QUIET = 16;
const VERBOSITY_NORMAL = 32;
const VERBOSITY_VERBOSE = 64;
const VERBOSITY_VERY_VERBOSE = 128;
const VERBOSITY_DEBUG = 256;

/**
* @param string|string[] $messages
* @param bool $newline
* @param int $options A bitmask of options (one of the VERBOSITY constants),
* 0 is considered the same as self::VERBOSITY_NORMAL
* @return void
*/
public function write($messages, $newline = false, $options = self::VERBOSITY_NORMAL);

/**
* @param string|string[] $messages
* @param int $options A bitmask of options (one of the VERBOSITY constants),
* 0 is considered the same as self::VERBOSITY_NORMAL
* @return void
*/
public function writeln($messages, $options = self::VERBOSITY_NORMAL);

/**
* @param int $level
* @return void
*/
public function setVerbosity($level);

/**
* @return int
*/
public function getVerbosity();
}
26 changes: 26 additions & 0 deletions src/main/php/PHPMD/Console/StreamOutput.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace PHPMD\Console;

class StreamOutput extends Output
{
/** @var resource */
private $stream;

/**
* @param resource $stream
*/
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL)
{
parent::__construct($verbosity);
$this->stream = $stream;
}

/**
* @inheritDoc
*/
protected function doWrite($message)
{
fwrite($this->stream, $message);
}
}
14 changes: 13 additions & 1 deletion src/main/php/PHPMD/TextUI/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
use PHPMD\Cache\ResultCacheEngineFactory;
use PHPMD\Cache\ResultCacheKeyFactory;
use PHPMD\Cache\ResultCacheStateFactory;
use PHPMD\Console\Output;
use PHPMD\Console\StreamOutput;
use PHPMD\PHPMD;
use PHPMD\Renderer\RendererFactory;
use PHPMD\Report;
Expand All @@ -44,6 +46,14 @@ class Command
EXIT_VIOLATION = 2,
EXIT_ERROR = 3;

/** @var Output */
private $output;

public function __construct(Output $output)
{
$this->output = $output;
}

/**
* This method creates a PHPMD instance and configures this object based
* on the user's input, then it starts the source analysis.
Expand Down Expand Up @@ -138,6 +148,7 @@ public function run(CommandLineOptions $opts, RuleSetFactory $ruleSetFactory)
// Configure Result Cache Engine
if ($opts->generateBaseline() === BaselineMode::NONE) {
$cacheEngineFactory = new ResultCacheEngineFactory(
$this->output,
new ResultCacheKeyFactory(getcwd(), $baselineFile),
new ResultCacheStateFactory()
);
Expand Down Expand Up @@ -195,7 +206,8 @@ public static function main(array $args)
try {
$ruleSetFactory = new RuleSetFactory();
$options = new CommandLineOptions($args, $ruleSetFactory->listAvailableRuleSets());
$command = new Command();
$output = new StreamOutput(STDERR, $options->getVerbosity());
$command = new Command($output);

$exitCode = $command->run($options, $ruleSetFactory);
} catch (\Exception $e) {
Expand Down