diff --git a/.dev-tools/composer.json b/.dev-tools/composer.json
index b44a5699..3dfc4267 100644
--- a/.dev-tools/composer.json
+++ b/.dev-tools/composer.json
@@ -16,7 +16,7 @@
"shipmonk/phpstan-rules": "^4.1.4",
"squizlabs/php_codesniffer": "^3.13.2",
"tomasvotruba/type-coverage": "^2.0.2",
- "vimeo/psalm": "^6.12.1"
+ "vimeo/psalm": "^6.13.0"
},
"autoload": {
"psr-4": {
diff --git a/.dev-tools/composer.lock b/.dev-tools/composer.lock
index 2bbc2bb5..f3bb138b 100644
--- a/.dev-tools/composer.lock
+++ b/.dev-tools/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "cc29da6bc114fd14f8df10b0cfcbe6c9",
+ "content-hash": "ab0b2efbd9f8b7f3444da6ac50cd0e93",
"packages": [
{
"name": "amphp/amp",
@@ -2994,16 +2994,16 @@
},
{
"name": "vimeo/psalm",
- "version": "6.12.1",
+ "version": "6.13.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
- "reference": "e71404b0465be25cf7f8a631b298c01c5ddd864f"
+ "reference": "70cdf647255a1362b426bb0f522a85817b8c791c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vimeo/psalm/zipball/e71404b0465be25cf7f8a631b298c01c5ddd864f",
- "reference": "e71404b0465be25cf7f8a631b298c01c5ddd864f"
+ "url": "https://api.github.com/repos/vimeo/psalm/zipball/70cdf647255a1362b426bb0f522a85817b8c791c",
+ "reference": "70cdf647255a1362b426bb0f522a85817b8c791c"
},
"require": {
"amphp/amp": "^3",
diff --git a/.dev-tools/psalm.xml b/.dev-tools/psalm.xml
index 4fc196dd..e92d3fbb 100644
--- a/.dev-tools/psalm.xml
+++ b/.dev-tools/psalm.xml
@@ -15,6 +15,10 @@
+
+
+
+
diff --git a/.dev-tools/psalm_stub.php b/.dev-tools/psalm_stub.php
new file mode 100644
index 00000000..3c21f86a
--- /dev/null
+++ b/.dev-tools/psalm_stub.php
@@ -0,0 +1,22 @@
+> */
- private array $predecessorKindMap;
-
- public function __construct()
- {
- if (\defined('T_PUBLIC_SET')) {
- $this->predecessorKindMap = [
- \T_PUBLIC_SET => [\T_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC],
- \T_PROTECTED_SET => [\T_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED],
- \T_PRIVATE_SET => [\T_PRIVATE, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE],
- ];
- }
- }
+ private const PREDECESSOR_KIND_MAP = [
+ FCT::T_PUBLIC_SET => [\T_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC],
+ FCT::T_PROTECTED_SET => [\T_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED],
+ FCT::T_PRIVATE_SET => [\T_PRIVATE, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE],
+ ];
public function getDefinition(): FixerDefinitionInterface
{
@@ -61,7 +54,7 @@ public function getPriority(): int
public function isCandidate(Tokens $tokens): bool
{
- return \defined('T_PUBLIC_SET') && $tokens->isAnyTokenKindsFound(\array_keys($this->predecessorKindMap));
+ return $tokens->isAnyTokenKindsFound([FCT::T_PUBLIC_SET, FCT::T_PROTECTED_SET, FCT::T_PRIVATE_SET]);
}
public function isRisky(): bool
@@ -71,14 +64,14 @@ public function isRisky(): bool
public function fix(\SplFileInfo $file, Tokens $tokens): void
{
- foreach ($tokens->findGivenKind(\array_keys($this->predecessorKindMap)) as $kind => $elements) {
+ foreach ($tokens->findGivenKind([FCT::T_PUBLIC_SET, FCT::T_PROTECTED_SET, FCT::T_PRIVATE_SET]) as $kind => $elements) {
foreach (\array_keys($elements) as $index) {
- $this->fixVisibility($tokens, $index, $kind, $kind === \T_PUBLIC_SET);
+ self::fixVisibility($tokens, $index, $kind, $kind === \T_PUBLIC_SET);
}
}
}
- private function fixVisibility(Tokens $tokens, int $index, int $kind, bool $makePublicIfNone): void
+ private static function fixVisibility(Tokens $tokens, int $index, int $kind, bool $makePublicIfNone): void
{
$prevIndex = $tokens->getPrevMeaningfulToken($index);
\assert(\is_int($prevIndex));
@@ -87,7 +80,7 @@ private function fixVisibility(Tokens $tokens, int $index, int $kind, bool $make
\assert(\is_int($prevIndex));
}
- if (!$tokens[$prevIndex]->isGivenKind($this->predecessorKindMap[$kind])) {
+ if (!$tokens[$prevIndex]->isGivenKind(self::PREDECESSOR_KIND_MAP[$kind])) {
if ($makePublicIfNone) {
$prevDeciderIndex = $tokens->getPrevTokenOfKind($index, ['(', ';', '{']);
\assert(\is_int($prevDeciderIndex));
diff --git a/src/Fixer/PhpdocNoIncorrectVarAnnotationFixer.php b/src/Fixer/PhpdocNoIncorrectVarAnnotationFixer.php
index 2899ca1b..13c92f56 100644
--- a/src/Fixer/PhpdocNoIncorrectVarAnnotationFixer.php
+++ b/src/Fixer/PhpdocNoIncorrectVarAnnotationFixer.php
@@ -17,6 +17,7 @@
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\CT;
+use PhpCsFixer\Tokenizer\FCT;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixerCustomFixers\TokenRemover;
@@ -96,7 +97,7 @@ private static function getIndexAfterPhpDoc(Tokens $tokens, int $index): ?int
{
$nextIndex = $tokens->getNextMeaningfulToken($index);
- while ($nextIndex !== null && \defined('T_ATTRIBUTE') && $tokens[$nextIndex]->isGivenKind(\T_ATTRIBUTE)) {
+ while ($nextIndex !== null && $tokens[$nextIndex]->isGivenKind(FCT::T_ATTRIBUTE)) {
$nextIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $nextIndex);
$nextIndex = $tokens->getNextMeaningfulToken($nextIndex);
}
@@ -106,14 +107,7 @@ private static function getIndexAfterPhpDoc(Tokens $tokens, int $index): ?int
private static function removeForClassElement(Tokens $tokens, int $index, int $propertyStartIndex): void
{
- $tokenKinds = [\T_NS_SEPARATOR, \T_STATIC, \T_STRING, \T_WHITESPACE, CT::T_ARRAY_TYPEHINT, CT::T_NULLABLE_TYPE, CT::T_TYPE_ALTERNATION];
-
- if (\defined('T_READONLY')) {
- $tokenKinds[] = CT::T_TYPE_INTERSECTION;
- $tokenKinds[] = \T_READONLY;
- }
-
- $variableIndex = $tokens->getTokenNotOfKindsSibling($propertyStartIndex, 1, $tokenKinds);
+ $variableIndex = $tokens->getTokenNotOfKindsSibling($propertyStartIndex, 1, [\T_NS_SEPARATOR, \T_STATIC, \T_STRING, \T_WHITESPACE, CT::T_ARRAY_TYPEHINT, CT::T_NULLABLE_TYPE, CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION, FCT::T_READONLY]);
\assert(\is_int($variableIndex));
if (!$tokens[$variableIndex]->isGivenKind(\T_VARIABLE)) {
diff --git a/src/Fixer/ReadonlyPromotedPropertiesFixer.php b/src/Fixer/ReadonlyPromotedPropertiesFixer.php
index 50c322d6..a3a6ca47 100644
--- a/src/Fixer/ReadonlyPromotedPropertiesFixer.php
+++ b/src/Fixer/ReadonlyPromotedPropertiesFixer.php
@@ -16,6 +16,7 @@
use PhpCsFixer\FixerDefinition\VersionSpecification;
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
use PhpCsFixer\Tokenizer\CT;
+use PhpCsFixer\Tokenizer\FCT;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixerCustomFixers\Analyzer\ConstructorAnalyzer;
@@ -43,23 +44,14 @@ final class ReadonlyPromotedPropertiesFixer extends AbstractFixer
[\T_COALESCE_EQUAL, '??='],
[\T_CONCAT_EQUAL, '.='],
];
-
- /** @var list */
- private array $promotedPropertyVisibilityKinds;
-
- public function __construct()
- {
- $this->promotedPropertyVisibilityKinds = [
- CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE,
- CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED,
- CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC,
- ];
- if (\defined('T_PUBLIC_SET')) {
- $this->promotedPropertyVisibilityKinds[] = \T_PUBLIC_SET;
- $this->promotedPropertyVisibilityKinds[] = \T_PROTECTED_SET;
- $this->promotedPropertyVisibilityKinds[] = \T_PRIVATE_SET;
- }
- }
+ private const PROMOTED_PROPERTY_VISIBILITY_KINDS = [
+ CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE,
+ CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED,
+ CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC,
+ FCT::T_PUBLIC_SET,
+ FCT::T_PROTECTED_SET,
+ FCT::T_PRIVATE_SET,
+ ];
public function getDefinition(): FixerDefinitionInterface
{
@@ -92,7 +84,7 @@ public function getPriority(): int
public function isCandidate(Tokens $tokens): bool
{
- return \defined('T_READONLY') && $tokens->isAnyTokenKindsFound($this->promotedPropertyVisibilityKinds);
+ return $tokens->isAnyTokenKindsFound(self::PROMOTED_PROPERTY_VISIBILITY_KINDS);
}
public function isRisky(): bool
@@ -126,7 +118,7 @@ public function fix(\SplFileInfo $file, Tokens $tokens): void
\assert(\is_int($constructorOpenParenthesisIndex));
$constructorCloseParenthesisIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $constructorOpenParenthesisIndex);
- $this->fixParameters(
+ self::fixParameters(
$tokens,
$classOpenBraceIndex,
$classCloseBraceIndex,
@@ -146,7 +138,7 @@ private static function isClassReadonly(Tokens $tokens, int $index): bool
return $tokens[$index]->isGivenKind(\T_READONLY);
}
- private function fixParameters(
+ private static function fixParameters(
Tokens $tokens,
int $classOpenBraceIndex,
int $classCloseBraceIndex,
@@ -158,7 +150,7 @@ private function fixParameters(
continue;
}
- $insertIndex = $this->getInsertIndex($tokens, $index);
+ $insertIndex = self::getInsertIndex($tokens, $index);
if ($insertIndex === null) {
continue;
}
@@ -177,7 +169,7 @@ private function fixParameters(
}
}
- private function getInsertIndex(Tokens $tokens, int $index): ?int
+ private static function getInsertIndex(Tokens $tokens, int $index): ?int
{
$insertIndex = null;
@@ -189,7 +181,7 @@ private function getInsertIndex(Tokens $tokens, int $index): ?int
if ($tokens[$index]->isGivenKind(\T_READONLY)) {
return null;
}
- if ($insertIndex === null && $tokens[$index]->isGivenKind($this->promotedPropertyVisibilityKinds)) {
+ if ($insertIndex === null && $tokens[$index]->isGivenKind(self::PROMOTED_PROPERTY_VISIBILITY_KINDS)) {
$insertIndex = $index;
}
}
diff --git a/tests/AutoReview/SrcCodeTest.php b/tests/AutoReview/SrcCodeTest.php
index b691050e..a151d29f 100644
--- a/tests/AutoReview/SrcCodeTest.php
+++ b/tests/AutoReview/SrcCodeTest.php
@@ -89,9 +89,9 @@ public function testFixerSupportsAllFilesByDefault(): void
/**
* @param class-string $className
*
- * @dataProvider provideThereIsNoPregFunctionUsedDirectlyCases
+ * @dataProvider provideThereIsNoDisallowedFunctionUsedDirectlyCases
*/
- public function testThereIsNoPregFunctionUsedDirectly(string $className): void
+ public function testThereIsNoDisallowedFunctionUsedDirectly(string $className): void
{
$reflectionClass = new \ReflectionClass($className);
@@ -113,8 +113,8 @@ public function testThereIsNoPregFunctionUsedDirectly(string $className): void
$stringTokens,
);
$strings = \array_unique($strings);
- $message = \sprintf('Class %s must not use preg_*, it shall use Preg::* instead.', $className);
+ $message = \sprintf('Class %s must not use preg_*, it shall use Preg::* instead.', $className);
self::assertNotContains('preg_filter', $strings, $message);
self::assertNotContains('preg_grep', $strings, $message);
self::assertNotContains('preg_match', $strings, $message);
@@ -122,18 +122,18 @@ public function testThereIsNoPregFunctionUsedDirectly(string $className): void
self::assertNotContains('preg_replace', $strings, $message);
self::assertNotContains('preg_replace_callback', $strings, $message);
self::assertNotContains('preg_split', $strings, $message);
+
+ self::assertNotContains('defined', $strings);
}
/**
* @return iterable
*/
- public static function provideThereIsNoPregFunctionUsedDirectlyCases(): iterable
+ public static function provideThereIsNoDisallowedFunctionUsedDirectlyCases(): iterable
{
$finder = Finder::create()
->files()
->in(__DIR__ . '/../../src')
- ->notName('php-cs-fixer.config.*.php')
- ->notName('run')
->sortByName();
/** @var SplFileInfo $file */