Skip to content

Commit

Permalink
extract Parameters Type Declaration handler from VersionResolverVisit…
Browse files Browse the repository at this point in the history
…or to a new Sniff
  • Loading branch information
llaville committed Aug 6, 2020
1 parent df3f001 commit 58660ad
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 26 deletions.
2 changes: 2 additions & 0 deletions src/Bartlett/CompatInfo/Analyser/CompatibilityAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use Bartlett\CompatInfo\Sniffs\Arrays\ShortArraySyntaxSniff;
use Bartlett\CompatInfo\Sniffs\Classes\AnonymousClassSniff;
use Bartlett\CompatInfo\Sniffs\ControlStructures\DeclareSniff;
use Bartlett\CompatInfo\Sniffs\FunctionDeclarations\ParamTypeDeclarationSniff;
use Bartlett\CompatInfo\Sniffs\FunctionDeclarations\ReturnTypeDeclarationSniff;
use Bartlett\CompatInfo\Sniffs\FunctionDeclarations\VariadicFunctionSniff;
use Bartlett\CompatInfo\Sniffs\Keywords\ReservedSniff;
Expand Down Expand Up @@ -72,6 +73,7 @@ public function __construct()
$this->sniffs = [
new DeclareSniff(),
new AnonymousClassSniff(),
new ParamTypeDeclarationSniff(),
new ReturnTypeDeclarationSniff(),
new ReservedSniff(),
new VariadicFunctionSniff(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,32 +157,7 @@ private function resolveTypeVersions(Node $node): array
return $versions;
} else {
$groups = ['interfaces', 'classes'];
if ($node instanceof Node\Param) {
if ($node->type === null) {
// no type hinting
return self::$php4;
}

if ($this->isNullableType($node->type)) {
$versions = self::$php4;
$versions['php.min'] = '7.1.0';
return $versions;
}

// @link https://www.php.net/manual/fr/functions.arguments.php#functions.arguments.type-declaration
$name = (string) $node->type;
if ($node->variadic) {
// Variadic functions
$min = '5.6.0';
} elseif ($node->type instanceof Node\Identifier && strcasecmp($name, 'array')) {
$min = '5.1.0';
} elseif ($node->type instanceof Node\Name && $node->type->isFullyQualified()) {
// type hint object required at least PHP 5.0
$min = '5.0.0';
} else {
$min = '4.0.0';
}
} elseif ($node instanceof Node\FunctionLike) {
if ($node instanceof Node\FunctionLike) {
$returnType = $node->getReturnType();

if ($this->isNullableType($returnType)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php declare(strict_types=1);

namespace Bartlett\CompatInfo\Sniffs\FunctionDeclarations;

use Bartlett\CompatInfo\Sniffs\KeywordBag;
use Bartlett\CompatInfo\Sniffs\SniffAbstract;

use PhpParser\Node;

/**
* Parameters Type Declaration
* @link https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
*
* - Nullable Type Declarations since PHP 7.1
* @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types
*/
final class ParamTypeDeclarationSniff extends SniffAbstract
{
/** @var array */
private $paramTypeDeclarations;

/**
* {@inheritDoc}
*/
public function enterSniff(): void
{
parent::enterSniff();

// Type declarations were not present in PHP 4.4 or earlier.
$this->paramTypeDeclarations = new KeywordBag([
'array' => '5.1',
'self' => '5.2',
'parent' => '5.2',
'callable' => '5.4',
'bool' => '7.0',
'float' => '7.0',
'int' => '7.0',
'string' => '7.0',
'iterable' => '7.1',
'object' => '7.2',
]);
}

/**
* Process this sniff only on this scope.
*
* {@inheritDoc}
*/
public function enterNode(Node $node)
{
if ($node instanceof Node\FunctionLike) {
$this->process($node);
}
}

private function process(Node\FunctionLike $node)
{
foreach ($node->getParams() as $param) {
if (null === $param->type) {
// no type hint
$min = '4.0.0';
} elseif ($param->type instanceof Node\NullableType) {
// @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types
$min = '7.1.0';
} elseif (true === $param->variadic) {
// Variadic functions
$min = '5.6.0';
} elseif ($param->type instanceof Node\Name\FullyQualified) {
// type hint object required at least PHP 5.0
$min = '5.0.0';
} else {
$min = '4.0.0';
}

$this->updateNodeElementVersion($node, $this->attributeKeyStore, ['php.min' => $min]);
}
}
}
56 changes: 56 additions & 0 deletions tests/Sniffs/ParamTypeDeclarationSniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
/**
* Unit tests for PHP_CompatInfo package, parameter type declaration sniff
*
* PHP version 7
*
* @category PHP
* @package PHP_CompatInfo
* @subpackage Tests
* @author Laurent Laville <[email protected]>
* @license https://opensource.org/licenses/BSD-3-Clause The 3-Clause BSD License
* @since Class available since Release 5.4.0
*/

namespace Bartlett\Tests\CompatInfo\Sniffs;

/**
* Parameters Type Declaration
*
* @link https://www.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
* @link https://www.php.net/manual/en/migration71.new-features.php#migration71.new-features.nullable-types
*/
final class ParamTypeDeclarationSniffTest extends SniffTestCase
{
/**
* {@inheritDoc}
*/
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();

self::$fixtures .= 'functions' . DIRECTORY_SEPARATOR;
}

/**
* Regression test for nullable type hint declaration detection GH#273
*
* @link https://github.com/llaville/php-compat-info/issues/273
* PHP 7.1 Nullable types not being detected
* @group features
* @group regression
* @return void
*/
public function testNullableTypeHint()
{
$dataSource = self::$fixtures . 'gh273.php';
$analysers = ['compatibility'];
$metrics = self::$api->run($dataSource, $analysers);
$functions = $metrics[self::$analyserId]['functions'];

$this->assertEquals(
'7.1.0',
$functions['test']['php.min']
);
}
}

0 comments on commit 58660ad

Please sign in to comment.