Skip to content

Commit

Permalink
add dynamic class constant fetch support (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
llaville committed Dec 31, 2023
1 parent d136f7e commit 46f03fa
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/components/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ They are grouped by categories to solve PHP features (from 4.0 to 8.2)
- Arrays (3)
- Attributes (4)
- Classes (11)
- Constants (5)
- Constants (6)
- ControlStructures (4)
- Enumerations (1)
- Expressions (4)
Expand Down
14 changes: 8 additions & 6 deletions docs/components/sniffs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,14 @@ Here is the list of features supported and their corresponding sniffs :

## [PHP 8.3](https://www.php.net/manual/en/migration83.php)

| Sniff category | Sniff class name | PHP Feature |
|----------------|---------------------------|------------------------------------------------------|
| Attributes | OverrideAttributeSniff | [Override attribute][OverrideAttribute] |
| Constants | TypedClassConstantSniff | [Typed Class Constants][TypedClassConstant] |
| Expressions | StaticVarInitializerSniff | [Static Variable initializers][StaticVarInitializer] |

| Sniff category | Sniff class name | PHP Feature |
|----------------|--------------------------------|------------------------------------------------------------------|
| Attributes | OverrideAttributeSniff | [Override attribute][OverrideAttribute] |
| Constants | DynamicClassConstantFetchSniff | [Dynamic Class Constant fetch syntax][DynamicClassConstantFetch] |
| Constants | TypedClassConstantSniff | [Typed Class Constants][TypedClassConstant] |
| Expressions | StaticVarInitializerSniff | [Static Variable initializers][StaticVarInitializer] |

[DynamicClassConstantFetch]: https://www.php.net/releases/8.3/en.php#dynamic_class_constant_fetch
[OverrideAttribute]: https://www.php.net/releases/8.3/en.php#override_attribute
[StaticVarInitializer]: https://www.php.net/manual/en/migration83.new-features.php#migration83.new-features.core.static-variable-initializers
[TypedClassConstant]: https://www.php.net/releases/8.3/en.php#typed_class_constants
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php declare(strict_types=1);
/**
* This file is part of the PHP_CompatInfo package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Bartlett\CompatInfo\Application\Sniffs\Constants;

use Bartlett\CompatInfo\Application\Sniffs\SniffAbstract;

use PhpParser\Node;

use Generator;

/**
* Dynamic class constant fetch syntax is available since PHP 8.3.0 alpha1
*
* @author Laurent Laville
* @since Class available since Release 7.1.0
*
* @link https://wiki.php.net/rfc/dynamic_class_constant_fetch
* @link https://stitcher.io/blog/new-in-php-83#dynamic-class-constant-fetch-rfc
* @see tests/Sniffs/DynamicClassConstantFetchSniffTest
*/
final class DynamicClassConstantFetchSniff extends SniffAbstract
{
// Rules identifiers for SARIF report
private const CA83 = 'CA8304';

/**
* @inheritDoc
*/
public function getRules(): Generator
{
yield self::CA83 => [
'name' => $this->getShortClass(),
'fullDescription' => "Dynamic class constant fetch syntax is available since PHP 8.3.0",
'helpUri' => '%baseHelpUri%/01_Components/03_Sniffs/Features/#php-83',
];
}

/**
* @inheritDoc
*/
public function enterNode(Node $node)
{
if (!$node instanceof Node\Expr\ClassConstFetch) {
return null;
}

if ($node->name instanceof Node\Expr\Variable) {
if (!$parent = $node->getAttribute($this->attributeParentKeyStore)) {
return null;
}
$this->updateNodeElementVersion($parent, $this->attributeKeyStore, ['php.min' => '8.3.0alpha1']);
$this->updateNodeElementRule($parent, $this->attributeKeyStore, self::CA83);
}
return null;
}
}
57 changes: 57 additions & 0 deletions tests/Sniffs/DynamicClassConstantFetchSniffTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php declare(strict_types=1);
/**
* This file is part of the PHP_CompatInfo package.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Bartlett\CompatInfo\Tests\Sniffs;

use Exception;

/**
* Unit test for dynamic class constant fetch syntax
*
* @author Laurent Laville
* @since Class available since Release 7.1.0
*
* @link https://www.php.net/releases/8.3/en.php#dynamic_class_constant_fetch
* @link https://wiki.php.net/rfc/dynamic_class_constant_fetch
* @link https://stitcher.io/blog/new-in-php-83#dynamic-class-constant-fetch-rfc
*/
final class DynamicClassConstantFetchSniffTest extends SniffTestCase
{
/**
* @inheritDoc
*/
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();

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

/**
* Feature test for dynamic class constant fetch syntax
*
* @group features
* @return void
* @throws Exception
*/
public function testDynamicClassConstantFetch()
{
$dataSource = 'dynamic_class_const_fetch.php';
$metrics = $this->executeAnalysis($dataSource);
$versions = $metrics[self::$analyserId]['versions'];

$this->assertEquals(
'8.3.0alpha1',
$versions['php.min']
);

$this->assertEquals(
'',
$versions['php.max']
);
}
}
14 changes: 14 additions & 0 deletions tests/fixtures/sniffs/constants/dynamic_class_const_fetch.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
class Foo
{
const BAR = 'bar';
}

$name = 'BAR';

// Instead of this:
constant(Foo::class . '::' . $name);

// Since PHP 8.3, you can now do this:
Foo::{$name};

0 comments on commit 46f03fa

Please sign in to comment.