diff --git a/composer.json b/composer.json index 070cd9d..049bc80 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "squizlabs/php_codesniffer": "^3.5", "symfony/css-selector": "^4.4|^5.0", "symfony/dom-crawler": "^4.4|^5.0", - "vimeo/psalm": "^3.12|^4.0" + "vimeo/psalm": "^4.30|^5.22" }, "autoload": { "psr-4": { diff --git a/psalm.xml b/psalm.xml index 832ed33..c687ab6 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,6 +5,8 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + findUnusedBaselineEntry="true" + findUnusedCode="false" > diff --git a/src/analyzer/Model/TombstoneIndex.php b/src/analyzer/Model/TombstoneIndex.php index c80e7d1..a878dbe 100644 --- a/src/analyzer/Model/TombstoneIndex.php +++ b/src/analyzer/Model/TombstoneIndex.php @@ -7,6 +7,9 @@ use Scheb\Tombstone\Core\Model\FilePathInterface; use Scheb\Tombstone\Core\Model\Tombstone; +/** + * @template-implements \IteratorAggregate + */ class TombstoneIndex implements \Countable, \IteratorAggregate { /** diff --git a/src/analyzer/Model/VampireIndex.php b/src/analyzer/Model/VampireIndex.php index c0c8041..0542a89 100644 --- a/src/analyzer/Model/VampireIndex.php +++ b/src/analyzer/Model/VampireIndex.php @@ -6,6 +6,9 @@ use Scheb\Tombstone\Core\Model\Vampire; +/** + * @template-implements \IteratorAggregate + */ class VampireIndex implements \Countable, \IteratorAggregate { /** diff --git a/src/analyzer/Report/Checkstyle/CheckstyleReportGenerator.php b/src/analyzer/Report/Checkstyle/CheckstyleReportGenerator.php index 6334aea..37ad3c7 100644 --- a/src/analyzer/Report/Checkstyle/CheckstyleReportGenerator.php +++ b/src/analyzer/Report/Checkstyle/CheckstyleReportGenerator.php @@ -82,7 +82,7 @@ private function getCalledBy(Tombstone $tombstone): string } $invoker = array_shift($vampires)->getInvoker(); - $calledBy = sprintf(' by "%s"', $invoker ?: 'global scope'); + $calledBy = sprintf(' by "%s"', null !== $invoker ? $invoker : 'global scope'); $numAdditionalVampires = $numVampires - 1; if ($numAdditionalVampires > 0) { diff --git a/src/analyzer/Report/Console/ConsoleReportGenerator.php b/src/analyzer/Report/Console/ConsoleReportGenerator.php index 2947eae..796603a 100644 --- a/src/analyzer/Report/Console/ConsoleReportGenerator.php +++ b/src/analyzer/Report/Console/ConsoleReportGenerator.php @@ -94,8 +94,9 @@ private function displayTombstones(array $result): void $this->newLine(); $this->printTombstone($tombstone, 'RIP'); $date = $tombstone->getTombstoneDate(); - if ($date) { - if ($age = TimePeriodFormatter::formatAge($date)) { + if (null !== $date) { + $age = TimePeriodFormatter::formatAge($date); + if (null !== $age) { $this->output->writeln(sprintf(' was not called for %s', $age)); } else { $this->output->writeln(sprintf(' was not called since %s', $date)); @@ -109,10 +110,10 @@ private function printTombstone(Tombstone $tombstone, string $prefix): void $this->output->writeln(sprintf(' [%s] %s', $prefix, (string) $tombstone)); $this->output->writeln(sprintf(' in line %s', $tombstone->getLine())); $method = $tombstone->getMethod(); - if ($method) { + if (null !== $method) { $this->output->writeln(sprintf(' in method %s', $method)); } else { - $this->output->writeln(sprintf(' in global scope')); + $this->output->writeln(' in global scope'); } } diff --git a/src/analyzer/Report/Html/Renderer/DashboardRenderer.php b/src/analyzer/Report/Html/Renderer/DashboardRenderer.php index f7568db..e47f8c7 100644 --- a/src/analyzer/Report/Html/Renderer/DashboardRenderer.php +++ b/src/analyzer/Report/Html/Renderer/DashboardRenderer.php @@ -131,7 +131,8 @@ private function getDeadSince(Tombstone $tombstone): string return 'since unknown'; } - if ($age = TimePeriodFormatter::formatAge($date)) { + $age = TimePeriodFormatter::formatAge($date); + if (null !== $age) { return 'for '.$age; } @@ -167,7 +168,7 @@ private function renderInvokers(Tombstone $tombstone): string $invokersString = ''; foreach ($invokers as $invoker) { $this->invokerTemplate->setVar([ - 'invoker' => $invoker ? htmlspecialchars($invoker) : 'global scope', + 'invoker' => null !== $invoker ? htmlspecialchars($invoker) : 'global scope', ]); $invokersString .= $this->invokerTemplate->render(); } @@ -218,7 +219,8 @@ private function renderDeletedTombstones(AnalyzerFileResult $fileResult): string private function getLastCalled(Vampire $vampire): string { $invocationDate = $vampire->getInvocationDate(); - if ($age = TimePeriodFormatter::formatAge($invocationDate)) { + $age = TimePeriodFormatter::formatAge($invocationDate); + if (null !== $age) { return $age; } @@ -228,7 +230,7 @@ private function getLastCalled(Vampire $vampire): string private function getTombstoneScope(Tombstone $tombstone): string { $method = $tombstone->getMethod(); - if ($method) { + if (null !== $method) { return sprintf('method %s', htmlspecialchars($method)); } diff --git a/src/analyzer/Report/Html/Renderer/PhpFileFormatter.php b/src/analyzer/Report/Html/Renderer/PhpFileFormatter.php index dd93fd7..a51d38e 100644 --- a/src/analyzer/Report/Html/Renderer/PhpFileFormatter.php +++ b/src/analyzer/Report/Html/Renderer/PhpFileFormatter.php @@ -49,8 +49,9 @@ private function formatTokens(array $tokens): \Traversable $stringFlag = false; $result = ''; foreach ($tokens as $j => $token) { + $previousToken = $j > 0 ? $tokens[$j - 1] : null; if (\is_string($token)) { - if ('"' === $token && '\\' !== $tokens[$j - 1]) { + if ('"' === $token && '\\' !== $previousToken) { $result .= $this->highlighter->formatString($token); $stringFlag = !$stringFlag; } else { diff --git a/src/analyzer/Report/TimePeriodFormatter.php b/src/analyzer/Report/TimePeriodFormatter.php index ef8a8a2..144fe9c 100644 --- a/src/analyzer/Report/TimePeriodFormatter.php +++ b/src/analyzer/Report/TimePeriodFormatter.php @@ -11,7 +11,7 @@ class TimePeriodFormatter public static function formatAge(string $date): ?string { $tombstoneDate = strtotime($date); - if (!$tombstoneDate) { + if (false === $tombstoneDate) { return null; } diff --git a/src/analyzer/Stock/TombstoneNodeVisitor.php b/src/analyzer/Stock/TombstoneNodeVisitor.php index d99725c..9151ea9 100644 --- a/src/analyzer/Stock/TombstoneNodeVisitor.php +++ b/src/analyzer/Stock/TombstoneNodeVisitor.php @@ -42,7 +42,7 @@ public function __construct(TombstoneExtractor $tombstoneCallback, array $tombst $this->tombstoneFunctionNames = $tombstoneFunctionNames; } - public function enterNode(Node $node) + public function enterNode(Node $node): void { parent::enterNode($node); if ($node instanceof Class_) { @@ -114,7 +114,7 @@ private function visitStaticCallNode(StaticCall $node): void } } - public function leaveNode(Node $node) + public function leaveNode(Node $node): void { parent::leaveNode($node); if ($node instanceof ClassMethod || $node instanceof Function_) { diff --git a/src/core/Model/RootPath.php b/src/core/Model/RootPath.php index 671c447..a9b970b 100644 --- a/src/core/Model/RootPath.php +++ b/src/core/Model/RootPath.php @@ -69,11 +69,11 @@ private function createRelativePath(string $path): RelativeFilePath { if ('' !== $path && '.' === $path[0]) { if ('.' === $path) { - $path = ''; // Path is equal root path - } elseif ('.' === $path[0]) { - // Remove leading "./" - $path = preg_replace('#^(\\./)+#', '', $path); + // Path is equal root path + return new RelativeFilePath('', $this); } + // Remove leading "./" + $path = preg_replace('#^(\\./)+#', '', $path); } return new RelativeFilePath($path, $this); diff --git a/src/core/Model/StackTrace.php b/src/core/Model/StackTrace.php index 1fccafe..0033c8c 100644 --- a/src/core/Model/StackTrace.php +++ b/src/core/Model/StackTrace.php @@ -4,7 +4,7 @@ namespace Scheb\Tombstone\Core\Model; -class StackTrace implements \Countable, \IteratorAggregate, \ArrayAccess +class StackTrace implements \Countable, StackTraceInterface { /** * @var StackTraceFrame[] @@ -32,7 +32,7 @@ public function count(): int } /** - * @return \Traversable + * @return \Traversable */ public function getIterator(): \Traversable { diff --git a/src/core/Model/StackTraceInterface.php b/src/core/Model/StackTraceInterface.php new file mode 100644 index 0000000..2eee7c4 --- /dev/null +++ b/src/core/Model/StackTraceInterface.php @@ -0,0 +1,14 @@ + + * @extends \ArrayAccess + */ +interface StackTraceInterface extends \IteratorAggregate, \ArrayAccess +{ + public function getHash(): int; +} diff --git a/src/logger/Handler/PsrLoggerHandler.php b/src/logger/Handler/PsrLoggerHandler.php index fedf610..b0ec904 100644 --- a/src/logger/Handler/PsrLoggerHandler.php +++ b/src/logger/Handler/PsrLoggerHandler.php @@ -14,8 +14,14 @@ class PsrLoggerHandler extends AbstractHandler */ private $logger; + /** + * @var string|int|mixed + */ private $level; + /** + * @param string|int|mixed $level + */ public function __construct(LoggerInterface $logger, $level) { $this->logger = $logger; diff --git a/src/logger/Handler/StreamHandler.php b/src/logger/Handler/StreamHandler.php index 9a34cac..14c3fbf 100644 --- a/src/logger/Handler/StreamHandler.php +++ b/src/logger/Handler/StreamHandler.php @@ -71,7 +71,7 @@ public function __construct($stream, ?int $filePermission = null, $useLocking = public function close(): void { - if ($this->url && \is_resource($this->stream)) { + if (null !== $this->url && \is_resource($this->stream)) { fclose($this->stream); } $this->stream = null;