Missing dependancies
This commit is contained in:
Vendored
+175
@@ -0,0 +1,175 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\Analysis\NamespaceAnalysis;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\NamespaceUsesAnalyzer;
|
||||
use PhpCsFixer\Tokenizer\CT;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class ClassReferenceNameCasingFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'When referencing an internal class it must be written using the correct casing.',
|
||||
[
|
||||
new CodeSample("<?php\nthrow new \\exception();\n"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$namespacesAnalyzer = new NamespacesAnalyzer();
|
||||
$namespaceUsesAnalyzer = new NamespaceUsesAnalyzer();
|
||||
$classNames = $this->getClassNames();
|
||||
|
||||
foreach ($namespacesAnalyzer->getDeclarations($tokens) as $namespace) {
|
||||
$uses = [];
|
||||
|
||||
foreach ($namespaceUsesAnalyzer->getDeclarationsInNamespace($tokens, $namespace) as $use) {
|
||||
$uses[strtolower($use->getShortName())] = true;
|
||||
}
|
||||
|
||||
foreach ($this->getClassReference($tokens, $namespace) as $reference) {
|
||||
$currentContent = $tokens[$reference]->getContent();
|
||||
$lowerCurrentContent = strtolower($currentContent);
|
||||
|
||||
if (isset($classNames[$lowerCurrentContent]) && $currentContent !== $classNames[$lowerCurrentContent] && !isset($uses[$lowerCurrentContent])) {
|
||||
$tokens[$reference] = new Token([T_STRING, $classNames[$lowerCurrentContent]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getClassReference(Tokens $tokens, NamespaceAnalysis $namespace): \Generator
|
||||
{
|
||||
static $notBeforeKinds;
|
||||
static $blockKinds;
|
||||
|
||||
if (null === $notBeforeKinds) {
|
||||
$notBeforeKinds = [
|
||||
CT::T_USE_TRAIT,
|
||||
T_AS,
|
||||
T_CASE, // PHP 8.1 trait enum-case
|
||||
T_CLASS,
|
||||
T_CONST,
|
||||
T_DOUBLE_ARROW,
|
||||
T_DOUBLE_COLON,
|
||||
T_FUNCTION,
|
||||
T_INTERFACE,
|
||||
T_OBJECT_OPERATOR,
|
||||
T_TRAIT,
|
||||
];
|
||||
|
||||
if (\defined('T_ENUM')) { // @TODO: drop condition when PHP 8.1+ is required
|
||||
$notBeforeKinds[] = T_ENUM;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $blockKinds) {
|
||||
$blockKinds = ['before' => [','], 'after' => [',']];
|
||||
|
||||
foreach (Tokens::getBlockEdgeDefinitions() as $definition) {
|
||||
$blockKinds['before'][] = $definition['start'];
|
||||
$blockKinds['after'][] = $definition['end'];
|
||||
}
|
||||
}
|
||||
|
||||
$namespaceIsGlobal = $namespace->isGlobalNamespace();
|
||||
|
||||
for ($index = $namespace->getScopeStartIndex(); $index < $namespace->getScopeEndIndex(); ++$index) {
|
||||
if (!$tokens[$index]->isGivenKind(T_STRING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextIndex = $tokens->getNextMeaningfulToken($index);
|
||||
|
||||
if ($tokens[$nextIndex]->isGivenKind(T_NS_SEPARATOR)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
$nextIndex = $tokens->getNextMeaningfulToken($index);
|
||||
|
||||
$isNamespaceSeparator = $tokens[$prevIndex]->isGivenKind(T_NS_SEPARATOR);
|
||||
|
||||
if (!$isNamespaceSeparator && !$namespaceIsGlobal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($isNamespaceSeparator) {
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($prevIndex);
|
||||
|
||||
if ($tokens[$prevIndex]->isGivenKind(T_STRING)) {
|
||||
continue;
|
||||
}
|
||||
} elseif ($tokens[$prevIndex]->isGivenKind($notBeforeKinds)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tokens[$prevIndex]->equalsAny($blockKinds['before']) && $tokens[$nextIndex]->equalsAny($blockKinds['after'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$tokens[$prevIndex]->isGivenKind(T_NEW) && $tokens[$nextIndex]->equalsAny(['(', ';', [T_CLOSE_TAG]])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
yield $index;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function getClassNames(): array
|
||||
{
|
||||
static $classes = null;
|
||||
|
||||
if (null === $classes) {
|
||||
$classes = [];
|
||||
|
||||
foreach (get_declared_classes() as $class) {
|
||||
if ((new \ReflectionClass($class))->isInternal()) {
|
||||
$classes[strtolower($class)] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
}
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\ConfigurableFixerInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolver;
|
||||
use PhpCsFixer\FixerConfiguration\FixerConfigurationResolverInterface;
|
||||
use PhpCsFixer\FixerConfiguration\FixerOptionBuilder;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\CT;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* Fixer for constants case.
|
||||
*
|
||||
* @author Pol Dellaiera <pol.dellaiera@protonmail.com>
|
||||
*/
|
||||
final class ConstantCaseFixer extends AbstractFixer implements ConfigurableFixerInterface
|
||||
{
|
||||
/**
|
||||
* Hold the function that will be used to convert the constants.
|
||||
*
|
||||
* @var callable
|
||||
*/
|
||||
private $fixFunction;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
parent::configure($configuration);
|
||||
|
||||
if ('lower' === $this->configuration['case']) {
|
||||
$this->fixFunction = static function (string $content): string {
|
||||
return strtolower($content);
|
||||
};
|
||||
}
|
||||
|
||||
if ('upper' === $this->configuration['case']) {
|
||||
$this->fixFunction = static function (string $content): string {
|
||||
return strtoupper($content);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'The PHP constants `true`, `false`, and `null` MUST be written using the correct casing.',
|
||||
[
|
||||
new CodeSample("<?php\n\$a = FALSE;\n\$b = True;\n\$c = nuLL;\n"),
|
||||
new CodeSample("<?php\n\$a = FALSE;\n\$b = True;\n\$c = nuLL;\n", ['case' => 'upper']),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
|
||||
{
|
||||
return new FixerConfigurationResolver([
|
||||
(new FixerOptionBuilder('case', 'Whether to use the `upper` or `lower` case syntax.'))
|
||||
->setAllowedValues(['upper', 'lower'])
|
||||
->setDefault('lower')
|
||||
->getOption(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$fixFunction = $this->fixFunction;
|
||||
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isNativeConstant()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
$this->isNeighbourAccepted($tokens, $tokens->getPrevMeaningfulToken($index))
|
||||
&& $this->isNeighbourAccepted($tokens, $tokens->getNextMeaningfulToken($index))
|
||||
&& !$this->isEnumCaseName($tokens, $index)
|
||||
) {
|
||||
$tokens[$index] = new Token([$token->getId(), $fixFunction($token->getContent())]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isNeighbourAccepted(Tokens $tokens, int $index): bool
|
||||
{
|
||||
static $forbiddenTokens = null;
|
||||
|
||||
if (null === $forbiddenTokens) {
|
||||
$forbiddenTokens = array_merge(
|
||||
[
|
||||
T_AS,
|
||||
T_CLASS,
|
||||
T_CONST,
|
||||
T_EXTENDS,
|
||||
T_IMPLEMENTS,
|
||||
T_INSTANCEOF,
|
||||
T_INSTEADOF,
|
||||
T_INTERFACE,
|
||||
T_NEW,
|
||||
T_NS_SEPARATOR,
|
||||
T_PAAMAYIM_NEKUDOTAYIM,
|
||||
T_TRAIT,
|
||||
T_USE,
|
||||
CT::T_USE_TRAIT,
|
||||
CT::T_USE_LAMBDA,
|
||||
],
|
||||
Token::getObjectOperatorKinds()
|
||||
);
|
||||
}
|
||||
|
||||
$token = $tokens[$index];
|
||||
|
||||
if ($token->equalsAny(['{', '}'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !$token->isGivenKind($forbiddenTokens);
|
||||
}
|
||||
|
||||
private function isEnumCaseName(Tokens $tokens, int $index): bool
|
||||
{
|
||||
if (!\defined('T_ENUM') || !$tokens->isTokenKindFound(T_ENUM)) { // @TODO: drop condition when PHP 8.1+ is required
|
||||
return false;
|
||||
}
|
||||
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
|
||||
if (null === $prevIndex || !$tokens[$prevIndex]->isGivenKind(T_CASE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!$tokens->isTokenKindFound(T_SWITCH)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$prevIndex = $tokens->getPrevTokenOfKind($prevIndex, [[T_ENUM], [T_SWITCH]]);
|
||||
|
||||
return null !== $prevIndex && $tokens[$prevIndex]->isGivenKind(T_ENUM);
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class IntegerLiteralCaseFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Integer literals must be in correct case.',
|
||||
[
|
||||
new CodeSample(
|
||||
"<?php\n\$foo = 0Xff;\n\$bar = 0B11111111;\n"
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_LNUMBER);
|
||||
}
|
||||
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isGivenKind(T_LNUMBER)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = $token->getContent();
|
||||
|
||||
if (1 !== Preg::match('#^0[bxoBXO][0-9a-fA-F]+$#', $content)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newContent = '0'.strtolower($content[1]).strtoupper(substr($content, 2));
|
||||
|
||||
if ($content === $newContent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([T_LNUMBER, $newContent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* Fixer for rules defined in PSR2 ¶2.5.
|
||||
*
|
||||
* @author Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*/
|
||||
final class LowercaseKeywordsFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private static array $excludedTokens = [T_HALT_COMPILER];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'PHP keywords MUST be in lower case.',
|
||||
[
|
||||
new CodeSample(
|
||||
'<?php
|
||||
FOREACH($a AS $B) {
|
||||
TRY {
|
||||
NEW $C($a, ISSET($B));
|
||||
WHILE($B) {
|
||||
INCLUDE "test.php";
|
||||
}
|
||||
} CATCH(\Exception $e) {
|
||||
EXIT(1);
|
||||
}
|
||||
}
|
||||
'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound(Token::getKeywords());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if ($token->isKeyword() && !$token->isGivenKind(self::$excludedTokens)) {
|
||||
$tokens[$index] = new Token([$token->getId(), strtolower($token->getContent())]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+106
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\CT;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* @author Kuba Werłos <werlos@gmail.com>
|
||||
*/
|
||||
final class LowercaseStaticReferenceFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Class static references `self`, `static` and `parent` MUST be in lower case.',
|
||||
[
|
||||
new CodeSample('<?php
|
||||
class Foo extends Bar
|
||||
{
|
||||
public function baz1()
|
||||
{
|
||||
return STATIC::baz2();
|
||||
}
|
||||
|
||||
public function baz2($x)
|
||||
{
|
||||
return $x instanceof Self;
|
||||
}
|
||||
|
||||
public function baz3(PaRent $x)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
'),
|
||||
new CodeSample(
|
||||
'<?php
|
||||
class Foo extends Bar
|
||||
{
|
||||
public function baz(?self $x) : SELF
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound([T_STATIC, T_STRING]);
|
||||
}
|
||||
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->equalsAny([[T_STRING, 'self'], [T_STATIC, 'static'], [T_STRING, 'parent']], false)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$newContent = strtolower($token->getContent());
|
||||
if ($token->getContent() === $newContent) {
|
||||
continue; // case is already correct
|
||||
}
|
||||
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
if ($tokens[$prevIndex]->isGivenKind([T_CONST, T_DOUBLE_COLON, T_FUNCTION, T_NAMESPACE, T_NS_SEPARATOR]) || $tokens[$prevIndex]->isObjectOperator()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$nextIndex = $tokens->getNextMeaningfulToken($index);
|
||||
if ($tokens[$nextIndex]->isGivenKind([T_FUNCTION, T_NS_SEPARATOR, T_PRIVATE, T_PROTECTED, T_PUBLIC, T_STRING, CT::T_NULLABLE_TYPE])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ('static' === $newContent && $tokens[$nextIndex]->isGivenKind(T_VARIABLE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([$token->getId(), $newContent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\CT;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* @author ntzm
|
||||
*/
|
||||
final class MagicConstantCasingFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Magic constants should be referred to using the correct casing.',
|
||||
[new CodeSample("<?php\necho __dir__;\n")]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound($this->getMagicConstantTokens());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$magicConstants = $this->getMagicConstants();
|
||||
$magicConstantTokens = $this->getMagicConstantTokens();
|
||||
|
||||
foreach ($tokens as $index => $token) {
|
||||
if ($token->isGivenKind($magicConstantTokens)) {
|
||||
$tokens[$index] = new Token([$token->getId(), $magicConstants[$token->getId()]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function getMagicConstants(): array
|
||||
{
|
||||
static $magicConstants = null;
|
||||
|
||||
if (null === $magicConstants) {
|
||||
$magicConstants = [
|
||||
T_LINE => '__LINE__',
|
||||
T_FILE => '__FILE__',
|
||||
T_DIR => '__DIR__',
|
||||
T_FUNC_C => '__FUNCTION__',
|
||||
T_CLASS_C => '__CLASS__',
|
||||
T_METHOD_C => '__METHOD__',
|
||||
T_NS_C => '__NAMESPACE__',
|
||||
CT::T_CLASS_CONSTANT => 'class',
|
||||
T_TRAIT_C => '__TRAIT__',
|
||||
];
|
||||
}
|
||||
|
||||
return $magicConstants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int>
|
||||
*/
|
||||
private function getMagicConstantTokens(): array
|
||||
{
|
||||
static $magicConstantTokens = null;
|
||||
|
||||
if (null === $magicConstantTokens) {
|
||||
$magicConstantTokens = array_keys($this->getMagicConstants());
|
||||
}
|
||||
|
||||
return $magicConstantTokens;
|
||||
}
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class MagicMethodCasingFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* @var array<string,string>
|
||||
*/
|
||||
private static array $magicNames = [
|
||||
'__call' => '__call',
|
||||
'__callstatic' => '__callStatic',
|
||||
'__clone' => '__clone',
|
||||
'__construct' => '__construct',
|
||||
'__debuginfo' => '__debugInfo',
|
||||
'__destruct' => '__destruct',
|
||||
'__get' => '__get',
|
||||
'__invoke' => '__invoke',
|
||||
'__isset' => '__isset',
|
||||
'__serialize' => '__serialize',
|
||||
'__set' => '__set',
|
||||
'__set_state' => '__set_state',
|
||||
'__sleep' => '__sleep',
|
||||
'__tostring' => '__toString',
|
||||
'__unserialize' => '__unserialize',
|
||||
'__unset' => '__unset',
|
||||
'__wakeup' => '__wakeup',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Magic method definitions and calls must be using the correct casing.',
|
||||
[
|
||||
new CodeSample(
|
||||
'<?php
|
||||
class Foo
|
||||
{
|
||||
public function __Sleep()
|
||||
{
|
||||
}
|
||||
}
|
||||
'
|
||||
),
|
||||
new CodeSample(
|
||||
'<?php
|
||||
$foo->__INVOKE(1);
|
||||
'
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_STRING) && $tokens->isAnyTokenKindsFound(array_merge([T_FUNCTION, T_DOUBLE_COLON], Token::getObjectOperatorKinds()));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$inClass = 0;
|
||||
$tokenCount = \count($tokens);
|
||||
|
||||
for ($index = 1; $index < $tokenCount - 2; ++$index) {
|
||||
if (0 === $inClass && $tokens[$index]->isClassy()) {
|
||||
$inClass = 1;
|
||||
$index = $tokens->getNextTokenOfKind($index, ['{']);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 !== $inClass) {
|
||||
if ($tokens[$index]->equals('{')) {
|
||||
++$inClass;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tokens[$index]->equals('}')) {
|
||||
--$inClass;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$tokens[$index]->isGivenKind(T_STRING)) {
|
||||
continue; // wrong type
|
||||
}
|
||||
|
||||
$content = $tokens[$index]->getContent();
|
||||
|
||||
if (!str_starts_with($content, '__')) {
|
||||
continue; // cheap look ahead
|
||||
}
|
||||
|
||||
$name = strtolower($content);
|
||||
|
||||
if (!$this->isMagicMethodName($name)) {
|
||||
continue; // method name is not one of the magic ones we can fix
|
||||
}
|
||||
|
||||
$nameInCorrectCasing = $this->getMagicMethodNameInCorrectCasing($name);
|
||||
if ($nameInCorrectCasing === $content) {
|
||||
continue; // method name is already in the correct casing, no fix needed
|
||||
}
|
||||
|
||||
if ($this->isFunctionSignature($tokens, $index)) {
|
||||
if (0 !== $inClass) {
|
||||
// this is a method definition we want to fix
|
||||
$this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isMethodCall($tokens, $index)) {
|
||||
$this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
('__callstatic' === $name || '__set_state' === $name)
|
||||
&& $this->isStaticMethodCall($tokens, $index)
|
||||
) {
|
||||
$this->setTokenToCorrectCasing($tokens, $index, $nameInCorrectCasing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function isFunctionSignature(Tokens $tokens, int $index): bool
|
||||
{
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
if (!$tokens[$prevIndex]->isGivenKind(T_FUNCTION)) {
|
||||
return false; // not a method signature
|
||||
}
|
||||
|
||||
return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('(');
|
||||
}
|
||||
|
||||
private function isMethodCall(Tokens $tokens, int $index): bool
|
||||
{
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
if (!$tokens[$prevIndex]->isObjectOperator()) {
|
||||
return false; // not a "simple" method call
|
||||
}
|
||||
|
||||
return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('(');
|
||||
}
|
||||
|
||||
private function isStaticMethodCall(Tokens $tokens, int $index): bool
|
||||
{
|
||||
$prevIndex = $tokens->getPrevMeaningfulToken($index);
|
||||
if (!$tokens[$prevIndex]->isGivenKind(T_DOUBLE_COLON)) {
|
||||
return false; // not a "simple" static method call
|
||||
}
|
||||
|
||||
return $tokens[$tokens->getNextMeaningfulToken($index)]->equals('(');
|
||||
}
|
||||
|
||||
private function isMagicMethodName(string $name): bool
|
||||
{
|
||||
return isset(self::$magicNames[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name name of a magic method
|
||||
*/
|
||||
private function getMagicMethodNameInCorrectCasing(string $name): string
|
||||
{
|
||||
return self::$magicNames[$name];
|
||||
}
|
||||
|
||||
private function setTokenToCorrectCasing(Tokens $tokens, int $index, string $nameInCorrectCasing): void
|
||||
{
|
||||
$tokens[$index] = new Token([T_STRING, $nameInCorrectCasing]);
|
||||
}
|
||||
}
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class NativeFunctionCasingFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Function defined by PHP should be called using the correct casing.',
|
||||
[new CodeSample("<?php\nSTRLEN(\$str);\n")]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run after FunctionToConstantFixer, NoUselessSprintfFixer, PowToExponentiationFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$functionsAnalyzer = new FunctionsAnalyzer();
|
||||
|
||||
static $nativeFunctionNames = null;
|
||||
|
||||
if (null === $nativeFunctionNames) {
|
||||
$nativeFunctionNames = $this->getNativeFunctionNames();
|
||||
}
|
||||
|
||||
for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
|
||||
// test if we are at a function all
|
||||
if (!$functionsAnalyzer->isGlobalFunctionCall($tokens, $index)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// test if the function call is to a native PHP function
|
||||
$lower = strtolower($tokens[$index]->getContent());
|
||||
if (!\array_key_exists($lower, $nativeFunctionNames)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([T_STRING, $nativeFunctionNames[$lower]]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function getNativeFunctionNames(): array
|
||||
{
|
||||
$allFunctions = get_defined_functions();
|
||||
$functions = [];
|
||||
foreach ($allFunctions['internal'] as $function) {
|
||||
$functions[strtolower($function)] = $function;
|
||||
}
|
||||
|
||||
return $functions;
|
||||
}
|
||||
}
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of PHP CS Fixer.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
namespace PhpCsFixer\Fixer\Casing;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\FixerDefinition\VersionSpecification;
|
||||
use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\Analysis\TypeAnalysis;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\FunctionsAnalyzer;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* https://secure.php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration.
|
||||
*
|
||||
* self PHP 5.0
|
||||
* array PHP 5.1
|
||||
* callable PHP 5.4
|
||||
* bool PHP 7.0
|
||||
* float PHP 7.0
|
||||
* int PHP 7.0
|
||||
* string PHP 7.0
|
||||
* iterable PHP 7.1
|
||||
* void PHP 7.1
|
||||
* object PHP 7.2
|
||||
* static PHP 8.0 (return type only)
|
||||
* mixed PHP 8.0
|
||||
* false PHP 8.0 (union return type only)
|
||||
* null PHP 8.0 (union return type only)
|
||||
* never PHP 8.1 (return type only)
|
||||
* true PHP 8.2 (standalone type: https://wiki.php.net/rfc/true-type)
|
||||
* false PHP 8.2 (standalone type: https://wiki.php.net/rfc/null-false-standalone-types)
|
||||
* null PHP 8.2 (standalone type: https://wiki.php.net/rfc/null-false-standalone-types)
|
||||
*
|
||||
* @var array<string, true>
|
||||
*/
|
||||
private array $hints;
|
||||
|
||||
private FunctionsAnalyzer $functionsAnalyzer;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$this->hints = [
|
||||
'array' => true,
|
||||
'bool' => true,
|
||||
'callable' => true,
|
||||
'float' => true,
|
||||
'int' => true,
|
||||
'iterable' => true,
|
||||
'object' => true,
|
||||
'self' => true,
|
||||
'string' => true,
|
||||
'void' => true,
|
||||
];
|
||||
|
||||
if (\PHP_VERSION_ID >= 80000) {
|
||||
$this->hints['false'] = true;
|
||||
$this->hints['mixed'] = true;
|
||||
$this->hints['null'] = true;
|
||||
$this->hints['static'] = true;
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID >= 80100) {
|
||||
$this->hints['never'] = true;
|
||||
}
|
||||
|
||||
if (\PHP_VERSION_ID >= 80200) {
|
||||
$this->hints['true'] = true;
|
||||
}
|
||||
|
||||
$this->functionsAnalyzer = new FunctionsAnalyzer();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Native type hints for functions should use the correct case.',
|
||||
[
|
||||
new CodeSample("<?php\nclass Bar {\n public function Foo(CALLABLE \$bar)\n {\n return 1;\n }\n}\n"),
|
||||
new CodeSample(
|
||||
"<?php\nfunction Foo(INT \$a): Bool\n{\n return true;\n}\n"
|
||||
),
|
||||
new CodeSample(
|
||||
"<?php\nfunction Foo(Iterable \$a): VOID\n{\n echo 'Hello world';\n}\n"
|
||||
),
|
||||
new VersionSpecificCodeSample(
|
||||
"<?php\nfunction Foo(Object \$a)\n{\n return 'hi!';\n}\n",
|
||||
new VersionSpecification(70200)
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAllTokenKindsFound([T_FUNCTION, T_STRING]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
for ($index = $tokens->count() - 1; $index >= 0; --$index) {
|
||||
if ($tokens[$index]->isGivenKind(T_FUNCTION)) {
|
||||
$this->fixFunctionReturnType($tokens, $index);
|
||||
$this->fixFunctionArgumentTypes($tokens, $index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function fixFunctionArgumentTypes(Tokens $tokens, int $index): void
|
||||
{
|
||||
foreach ($this->functionsAnalyzer->getFunctionArguments($tokens, $index) as $argument) {
|
||||
$this->fixArgumentType($tokens, $argument->getTypeAnalysis());
|
||||
}
|
||||
}
|
||||
|
||||
private function fixFunctionReturnType(Tokens $tokens, int $index): void
|
||||
{
|
||||
$this->fixArgumentType($tokens, $this->functionsAnalyzer->getFunctionReturnType($tokens, $index));
|
||||
}
|
||||
|
||||
private function fixArgumentType(Tokens $tokens, ?TypeAnalysis $type = null): void
|
||||
{
|
||||
if (null === $type) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ($index = $type->getStartIndex(); $index <= $type->getEndIndex(); ++$index) {
|
||||
if ($tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_NS_SEPARATOR)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$lowerCasedName = strtolower($tokens[$index]->getContent());
|
||||
|
||||
if (!isset($this->hints[$lowerCasedName])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([$tokens[$index]->getId(), $lowerCasedName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user