Skip to content

Commit

Permalink
PHP 8 supports %h and %H in printf/sprintf
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Mar 18, 2021
1 parent 82596f5 commit 0cbbfba
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 2 deletions.
5 changes: 5 additions & 0 deletions src/Php/PhpVersion.php
Expand Up @@ -96,4 +96,9 @@ public function throwsTypeErrorForInternalFunctions(): bool
return $this->versionId >= 80000;
}

public function supportsHhPrintfSpecifier(): bool
{
return $this->versionId >= 80000;
}

}
17 changes: 16 additions & 1 deletion src/Rules/Functions/PrintfParametersRule.php
Expand Up @@ -5,6 +5,7 @@
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Php\PhpVersion;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\TypeUtils;

Expand All @@ -14,6 +15,13 @@
class PrintfParametersRule implements \PHPStan\Rules\Rule
{

private PhpVersion $phpVersion;

public function __construct(PhpVersion $phpVersion)
{
$this->phpVersion = $phpVersion;
}

public function getNodeType(): string
{
return FuncCall::class;
Expand Down Expand Up @@ -94,7 +102,14 @@ public function processNode(Node $node, Scope $scope): array

private function getPlaceholdersCount(string $functionName, string $format): int
{
$specifiers = in_array($functionName, ['sprintf', 'printf'], true) ? '[bcdeEfFgGosuxX]' : '(?:[cdDeEfinosuxX]|\[[^\]]+\])';
$specifiers = in_array($functionName, ['sprintf', 'printf'], true) ? '[bcdeEfFgGosuxX%s]' : '(?:[cdDeEfinosuxX%s]|\[[^\]]+\])';
$addSpecifier = '';
if ($this->phpVersion->supportsHhPrintfSpecifier()) {
$addSpecifier .= 'hH';
}

$specifiers = sprintf($specifiers, $addSpecifier);

$pattern = '~(?<before>%*)%(?:(?<position>\d+)\$)?[-+]?(?:[ 0]|(?:\'[^%]))?-?\d*(?:\.\d*)?' . $specifiers . '~';

$matches = \Nette\Utils\Strings::matchAll($format, $pattern, PREG_SET_ORDER);
Expand Down
19 changes: 18 additions & 1 deletion tests/PHPStan/Rules/Functions/PrintfParametersRuleTest.php
Expand Up @@ -2,6 +2,9 @@

namespace PHPStan\Rules\Functions;

use PHPStan\Php\PhpVersion;
use const PHP_VERSION_ID;

/**
* @extends \PHPStan\Testing\RuleTestCase<PrintfParametersRule>
*/
Expand All @@ -10,7 +13,7 @@ class PrintfParametersRuleTest extends \PHPStan\Testing\RuleTestCase

protected function getRule(): \PHPStan\Rules\Rule
{
return new PrintfParametersRule();
return new PrintfParametersRule(new PhpVersion(PHP_VERSION_ID));
}

public function testFile(): void
Expand Down Expand Up @@ -91,4 +94,18 @@ public function testFile(): void
]);
}

public function testBug4717(): void
{
$errors = [
[
'Call to sprintf contains 1 placeholder, 2 values given.',
5,
],
];
if (PHP_VERSION_ID >= 80000) {
$errors = [];
}
$this->analyse([__DIR__ . '/data/bug-4717.php'], $errors);
}

}
5 changes: 5 additions & 0 deletions tests/PHPStan/Rules/Functions/data/bug-4717.php
@@ -0,0 +1,5 @@
<?php

$f = 4.0/3;
$s = 'Bug';
echo sprintf('%s qty = %h', $s, $f);

0 comments on commit 0cbbfba

Please sign in to comment.