Missing dependancies
This commit is contained in:
www-api/vendor/friendsofphp/php-cs-fixer/src/Fixer/StringNotation/EscapeImplicitBackslashesFixer.php
Vendored
+171
@@ -0,0 +1,171 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
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\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* @author Filippo Tessarotto <zoeslam@gmail.com>
|
||||
*/
|
||||
final class EscapeImplicitBackslashesFixer extends AbstractFixer implements ConfigurableFixerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
$codeSample = <<<'EOF'
|
||||
<?php
|
||||
|
||||
$singleQuoted = 'String with \" and My\Prefix\\';
|
||||
|
||||
$doubleQuoted = "Interpret my \n but not my \a";
|
||||
|
||||
$hereDoc = <<<HEREDOC
|
||||
Interpret my \100 but not my \999
|
||||
HEREDOC;
|
||||
|
||||
EOF;
|
||||
|
||||
return new FixerDefinition(
|
||||
'Escape implicit backslashes in strings and heredocs to ease the understanding of which are special chars interpreted by PHP and which not.',
|
||||
[
|
||||
new CodeSample($codeSample),
|
||||
new CodeSample(
|
||||
$codeSample,
|
||||
['single_quoted' => true]
|
||||
),
|
||||
new CodeSample(
|
||||
$codeSample,
|
||||
['double_quoted' => false]
|
||||
),
|
||||
new CodeSample(
|
||||
$codeSample,
|
||||
['heredoc_syntax' => false]
|
||||
),
|
||||
],
|
||||
'In PHP double-quoted strings and heredocs some chars like `n`, `$` or `u` have special meanings if preceded by a backslash '
|
||||
.'(and some are special only if followed by other special chars), while a backslash preceding other chars are interpreted like a plain '
|
||||
.'backslash. The precise list of those special chars is hard to remember and to identify quickly: this fixer escapes backslashes '
|
||||
."that do not start a special interpretation with the char after them.\n"
|
||||
.'It is possible to fix also single-quoted strings: in this case there is no special chars apart from single-quote and backslash '
|
||||
.'itself, so the fixer simply ensure that all backslashes are escaped. Both single and double backslashes are allowed in single-quoted '
|
||||
.'strings, so the purpose in this context is mainly to have a uniformed way to have them written all over the codebase.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run before HeredocToNowdocFixer, SingleQuoteFixer.
|
||||
* Must run after BacktickToShellExecFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
static $singleQuotedRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![\\\'\\\\])/';
|
||||
static $doubleQuotedRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![efnrtv$"\\\\0-7]|x[0-9A-Fa-f]|u{)/';
|
||||
static $heredocSyntaxRegex = '/(?<!\\\\)\\\\((?:\\\\\\\\)*)(?![efnrtv$\\\\0-7]|x[0-9A-Fa-f]|u{)/';
|
||||
|
||||
$doubleQuoteOpened = false;
|
||||
foreach ($tokens as $index => $token) {
|
||||
$content = $token->getContent();
|
||||
if ($token->equalsAny(['"', 'b"', 'B"'])) {
|
||||
$doubleQuoteOpened = !$doubleQuoteOpened;
|
||||
}
|
||||
if (!$token->isGivenKind([T_ENCAPSED_AND_WHITESPACE, T_CONSTANT_ENCAPSED_STRING]) || !str_contains($content, '\\')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Nowdoc syntax
|
||||
if ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE) && '\'' === substr(rtrim($tokens[$index - 1]->getContent()), -1)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$firstTwoCharacters = strtolower(substr($content, 0, 2));
|
||||
$isSingleQuotedString = $token->isGivenKind(T_CONSTANT_ENCAPSED_STRING) && ('\'' === $content[0] || 'b\'' === $firstTwoCharacters);
|
||||
$isDoubleQuotedString =
|
||||
($token->isGivenKind(T_CONSTANT_ENCAPSED_STRING) && ('"' === $content[0] || 'b"' === $firstTwoCharacters))
|
||||
|| ($token->isGivenKind(T_ENCAPSED_AND_WHITESPACE) && $doubleQuoteOpened)
|
||||
;
|
||||
$isHeredocSyntax = !$isSingleQuotedString && !$isDoubleQuotedString;
|
||||
if (
|
||||
(false === $this->configuration['single_quoted'] && $isSingleQuotedString)
|
||||
|| (false === $this->configuration['double_quoted'] && $isDoubleQuotedString)
|
||||
|| (false === $this->configuration['heredoc_syntax'] && $isHeredocSyntax)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$regex = $heredocSyntaxRegex;
|
||||
if ($isSingleQuotedString) {
|
||||
$regex = $singleQuotedRegex;
|
||||
} elseif ($isDoubleQuotedString) {
|
||||
$regex = $doubleQuotedRegex;
|
||||
}
|
||||
|
||||
$newContent = Preg::replace($regex, '\\\\\\\\$1', $content);
|
||||
if ($newContent !== $content) {
|
||||
$tokens[$index] = new Token([$token->getId(), $newContent]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
|
||||
{
|
||||
return new FixerConfigurationResolver([
|
||||
(new FixerOptionBuilder('single_quoted', 'Whether to fix single-quoted strings.'))
|
||||
->setAllowedTypes(['bool'])
|
||||
->setDefault(false)
|
||||
->getOption(),
|
||||
(new FixerOptionBuilder('double_quoted', 'Whether to fix double-quoted strings.'))
|
||||
->setAllowedTypes(['bool'])
|
||||
->setDefault(true)
|
||||
->getOption(),
|
||||
(new FixerOptionBuilder('heredoc_syntax', 'Whether to fix heredoc syntax.'))
|
||||
->setAllowedTypes(['bool'])
|
||||
->setDefault(true)
|
||||
->getOption(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
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\StringNotation;
|
||||
|
||||
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 Filippo Tessarotto <zoeslam@gmail.com>
|
||||
*/
|
||||
final class ExplicitStringVariableFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Converts implicit variables into explicit ones in double-quoted strings or heredoc syntax.',
|
||||
[new CodeSample(
|
||||
<<<'EOT'
|
||||
<?php
|
||||
$a = "My name is $name !";
|
||||
$b = "I live in $state->country !";
|
||||
$c = "I have $farm[0] chickens !";
|
||||
|
||||
EOT
|
||||
)],
|
||||
'The reasoning behind this rule is the following:'
|
||||
."\n".'- When there are two valid ways of doing the same thing, using both is confusing, there should be a coding standard to follow'
|
||||
."\n".'- PHP manual marks `"$var"` syntax as implicit and `"${var}"` syntax as explicit: explicit code should always be preferred'
|
||||
."\n".'- Explicit syntax allows word concatenation inside strings, e.g. `"${var}IsAVar"`, implicit doesn\'t'
|
||||
."\n".'- Explicit syntax is easier to detect for IDE/editors and therefore has colors/highlight with higher contrast, which is easier to read'
|
||||
."\n".'Backtick operator is skipped because it is harder to handle; you can use `backtick_to_shell_exec` fixer to normalize backticks to strings'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run after BacktickToShellExecFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_VARIABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$backtickStarted = false;
|
||||
for ($index = \count($tokens) - 1; $index > 0; --$index) {
|
||||
$token = $tokens[$index];
|
||||
|
||||
if ($token->equals('`')) {
|
||||
$backtickStarted = !$backtickStarted;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($backtickStarted || !$token->isGivenKind(T_VARIABLE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$prevToken = $tokens[$index - 1];
|
||||
|
||||
if (!$this->isStringPartToken($prevToken)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$distinctVariableIndex = $index;
|
||||
$variableTokens = [
|
||||
$distinctVariableIndex => [
|
||||
'tokens' => [$index => $token],
|
||||
'firstVariableTokenIndex' => $index,
|
||||
'lastVariableTokenIndex' => $index,
|
||||
],
|
||||
];
|
||||
|
||||
$nextIndex = $index + 1;
|
||||
$squareBracketCount = 0;
|
||||
|
||||
while (!$this->isStringPartToken($tokens[$nextIndex])) {
|
||||
if ($tokens[$nextIndex]->isGivenKind(T_CURLY_OPEN)) {
|
||||
$nextIndex = $tokens->getNextTokenOfKind($nextIndex, [[CT::T_CURLY_CLOSE]]);
|
||||
} elseif ($tokens[$nextIndex]->isGivenKind(T_VARIABLE) && 1 !== $squareBracketCount) {
|
||||
$distinctVariableIndex = $nextIndex;
|
||||
$variableTokens[$distinctVariableIndex] = [
|
||||
'tokens' => [$nextIndex => $tokens[$nextIndex]],
|
||||
'firstVariableTokenIndex' => $nextIndex,
|
||||
'lastVariableTokenIndex' => $nextIndex,
|
||||
];
|
||||
} else {
|
||||
$variableTokens[$distinctVariableIndex]['tokens'][$nextIndex] = $tokens[$nextIndex];
|
||||
$variableTokens[$distinctVariableIndex]['lastVariableTokenIndex'] = $nextIndex;
|
||||
|
||||
if ($tokens[$nextIndex]->equalsAny(['[', ']'])) {
|
||||
++$squareBracketCount;
|
||||
}
|
||||
}
|
||||
|
||||
++$nextIndex;
|
||||
}
|
||||
krsort($variableTokens, SORT_NUMERIC);
|
||||
|
||||
foreach ($variableTokens as $distinctVariableSet) {
|
||||
if (1 === \count($distinctVariableSet['tokens'])) {
|
||||
$singleVariableIndex = key($distinctVariableSet['tokens']);
|
||||
$singleVariableToken = current($distinctVariableSet['tokens']);
|
||||
$tokens->overrideRange($singleVariableIndex, $singleVariableIndex, [
|
||||
new Token([T_CURLY_OPEN, '{']),
|
||||
new Token([T_VARIABLE, $singleVariableToken->getContent()]),
|
||||
new Token([CT::T_CURLY_CLOSE, '}']),
|
||||
]);
|
||||
} else {
|
||||
foreach ($distinctVariableSet['tokens'] as $variablePartIndex => $variablePartToken) {
|
||||
if ($variablePartToken->isGivenKind(T_NUM_STRING)) {
|
||||
$tokens[$variablePartIndex] = new Token([T_LNUMBER, $variablePartToken->getContent()]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($variablePartToken->isGivenKind(T_STRING) && $tokens[$variablePartIndex + 1]->equals(']')) {
|
||||
$tokens[$variablePartIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, "'".$variablePartToken->getContent()."'"]);
|
||||
}
|
||||
}
|
||||
|
||||
$tokens->insertAt($distinctVariableSet['lastVariableTokenIndex'] + 1, new Token([CT::T_CURLY_CLOSE, '}']));
|
||||
$tokens->insertAt($distinctVariableSet['firstVariableTokenIndex'], new Token([T_CURLY_OPEN, '{']));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if token is a part of a string.
|
||||
*
|
||||
* @param Token $token The token to check
|
||||
*/
|
||||
private function isStringPartToken(Token $token): bool
|
||||
{
|
||||
return $token->isGivenKind(T_ENCAPSED_AND_WHITESPACE)
|
||||
|| $token->isGivenKind(T_START_HEREDOC)
|
||||
|| '"' === $token->getContent()
|
||||
|| 'b"' === strtolower($token->getContent())
|
||||
;
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Gregor Harlan <gharlan@web.de>
|
||||
*/
|
||||
final class HeredocToNowdocFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Convert `heredoc` to `nowdoc` where possible.',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'EOF'
|
||||
<?php $a = <<<"TEST"
|
||||
Foo
|
||||
TEST;
|
||||
|
||||
EOF
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run after EscapeImplicitBackslashesFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_START_HEREDOC);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isGivenKind(T_START_HEREDOC) || str_contains($token->getContent(), "'")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($tokens[$index + 1]->isGivenKind(T_END_HEREDOC)) {
|
||||
$tokens[$index] = $this->convertToNowdoc($token);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!$tokens[$index + 1]->isGivenKind(T_ENCAPSED_AND_WHITESPACE)
|
||||
|| !$tokens[$index + 2]->isGivenKind(T_END_HEREDOC)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = $tokens[$index + 1]->getContent();
|
||||
// regex: odd number of backslashes, not followed by dollar
|
||||
if (Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?![$\\\\])/', $content)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$index] = $this->convertToNowdoc($token);
|
||||
$content = str_replace(['\\\\', '\\$'], ['\\', '$'], $content);
|
||||
$tokens[$index + 1] = new Token([
|
||||
$tokens[$index + 1]->getId(),
|
||||
$content,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the heredoc start token to nowdoc notation.
|
||||
*/
|
||||
private function convertToNowdoc(Token $token): Token
|
||||
{
|
||||
return new Token([
|
||||
$token->getId(),
|
||||
Preg::replace('/^([Bb]?<<<)(\h*)"?([^\s"]+)"?/', '$1$2\'$3\'', $token->getContent()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* @author ntzm
|
||||
*/
|
||||
final class NoBinaryStringFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound(
|
||||
[
|
||||
T_CONSTANT_ENCAPSED_STRING,
|
||||
T_START_HEREDOC,
|
||||
'b"',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'There should not be a binary flag before strings.',
|
||||
[
|
||||
new CodeSample("<?php \$a = b'foo';\n"),
|
||||
new CodeSample("<?php \$a = b<<<EOT\nfoo\nEOT;\n"),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run before NoUselessConcatOperatorFixer, PhpUnitDedicateAssertInternalTypeFixer, RegularCallableCallFixer, SetTypeToCastFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if ($token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_START_HEREDOC])) {
|
||||
$content = $token->getContent();
|
||||
|
||||
if ('b' === strtolower($content[0])) {
|
||||
$tokens[$index] = new Token([$token->getId(), substr($content, 1)]);
|
||||
}
|
||||
} elseif ($token->equals('b"')) {
|
||||
$tokens[$index] = new Token('"');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author Gregor Harlan
|
||||
*/
|
||||
final class NoTrailingWhitespaceInStringFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRisky(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'There must be no trailing whitespace in strings.',
|
||||
[
|
||||
new CodeSample(
|
||||
"<?php \$a = ' \n foo \n';\n"
|
||||
),
|
||||
],
|
||||
null,
|
||||
'Changing the whitespaces in strings might affect string comparisons and outputs.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
for ($index = $tokens->count() - 1, $last = true; $index >= 0; --$index, $last = false) {
|
||||
/** @var Token $token */
|
||||
$token = $tokens[$index];
|
||||
|
||||
if (!$token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$isInlineHtml = $token->isGivenKind(T_INLINE_HTML);
|
||||
$regex = $isInlineHtml && $last ? '/\h+(?=\R|$)/' : '/\h+(?=\R)/';
|
||||
$content = Preg::replace($regex, '', $token->getContent());
|
||||
|
||||
if ($token->getContent() === $content) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$isInlineHtml || 0 === $index) {
|
||||
$this->updateContent($tokens, $index, $content);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$prev = $index - 1;
|
||||
|
||||
if ($tokens[$prev]->equals([T_CLOSE_TAG, '?>']) && Preg::match('/^\R/', $content, $match)) {
|
||||
$tokens[$prev] = new Token([T_CLOSE_TAG, $tokens[$prev]->getContent().$match[0]]);
|
||||
$content = substr($content, \strlen($match[0]));
|
||||
$content = false === $content ? '' : $content; // @phpstan-ignore-line due to https://github.com/phpstan/phpstan/issues/1215 , awaiting PHP8 as min requirement of Fixer
|
||||
}
|
||||
|
||||
$this->updateContent($tokens, $index, $content);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateContent(Tokens $tokens, int $index, string $content): void
|
||||
{
|
||||
if ('' === $content) {
|
||||
$tokens->clearAt($index);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$tokens[$index] = new Token([$tokens[$index]->getId(), $content]);
|
||||
}
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
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 Dave van der Brugge <dmvdbrugge@gmail.com>
|
||||
*/
|
||||
final class SimpleToComplexStringVariableFixer extends AbstractFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'Converts explicit variables in double-quoted strings and heredoc syntax from simple to complex format (`${` to `{$`).',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'EOT'
|
||||
<?php
|
||||
$name = 'World';
|
||||
echo "Hello ${name}!";
|
||||
|
||||
EOT
|
||||
),
|
||||
new CodeSample(
|
||||
<<<'EOT'
|
||||
<?php
|
||||
$name = 'World';
|
||||
echo <<<TEST
|
||||
Hello ${name}!
|
||||
TEST;
|
||||
|
||||
EOT
|
||||
),
|
||||
],
|
||||
"Doesn't touch implicit variables. Works together nicely with `explicit_string_variable`."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run after ExplicitStringVariableFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return -10;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_DOLLAR_OPEN_CURLY_BRACES);
|
||||
}
|
||||
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
for ($index = \count($tokens) - 3; $index > 0; --$index) {
|
||||
$token = $tokens[$index];
|
||||
|
||||
if (!$token->isGivenKind(T_DOLLAR_OPEN_CURLY_BRACES)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$varnameToken = $tokens[$index + 1];
|
||||
|
||||
if (!$varnameToken->isGivenKind(T_STRING_VARNAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$dollarCloseToken = $tokens[$index + 2];
|
||||
|
||||
if (!$dollarCloseToken->isGivenKind(CT::T_DOLLAR_CLOSE_CURLY_BRACES)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokenOfStringBeforeToken = $tokens[$index - 1];
|
||||
$stringContent = $tokenOfStringBeforeToken->getContent();
|
||||
|
||||
if (str_ends_with($stringContent, '$') && !str_ends_with($stringContent, '\\$')) {
|
||||
$newContent = substr($stringContent, 0, -1).'\\$';
|
||||
$tokenOfStringBeforeToken = new Token([T_ENCAPSED_AND_WHITESPACE, $newContent]);
|
||||
}
|
||||
|
||||
$tokens->overrideRange($index - 1, $index + 2, [
|
||||
$tokenOfStringBeforeToken,
|
||||
new Token([T_CURLY_OPEN, '{']),
|
||||
new Token([T_VARIABLE, '$'.$varnameToken->getContent()]),
|
||||
new Token([CT::T_CURLY_CLOSE, '}']),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
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\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* @author Gregor Harlan <gharlan@web.de>
|
||||
*/
|
||||
final class SingleQuoteFixer extends AbstractFixer implements ConfigurableFixerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
$codeSample = <<<'EOF'
|
||||
<?php
|
||||
|
||||
$a = "sample";
|
||||
$b = "sample with 'single-quotes'";
|
||||
|
||||
EOF;
|
||||
|
||||
return new FixerDefinition(
|
||||
'Convert double quotes to single quotes for simple strings.',
|
||||
[
|
||||
new CodeSample($codeSample),
|
||||
new CodeSample(
|
||||
$codeSample,
|
||||
['strings_containing_single_quote_chars' => true]
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run before NoUselessConcatOperatorFixer.
|
||||
* Must run after BacktickToShellExecFixer, EscapeImplicitBackslashesFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isTokenKindFound(T_CONSTANT_ENCAPSED_STRING);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
foreach ($tokens as $index => $token) {
|
||||
if (!$token->isGivenKind(T_CONSTANT_ENCAPSED_STRING)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$content = $token->getContent();
|
||||
$prefix = '';
|
||||
|
||||
if ('b' === strtolower($content[0])) {
|
||||
$prefix = $content[0];
|
||||
$content = substr($content, 1);
|
||||
}
|
||||
|
||||
if (
|
||||
'"' === $content[0]
|
||||
&& (true === $this->configuration['strings_containing_single_quote_chars'] || !str_contains($content, "'"))
|
||||
// regex: odd number of backslashes, not followed by double quote or dollar
|
||||
&& !Preg::match('/(?<!\\\\)(?:\\\\{2})*\\\\(?!["$\\\\])/', $content)
|
||||
) {
|
||||
$content = substr($content, 1, -1);
|
||||
$content = str_replace(['\\"', '\\$', '\''], ['"', '$', '\\\''], $content);
|
||||
$tokens[$index] = new Token([T_CONSTANT_ENCAPSED_STRING, $prefix.'\''.$content.'\'']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function createConfigurationDefinition(): FixerConfigurationResolverInterface
|
||||
{
|
||||
return new FixerConfigurationResolver([
|
||||
(new FixerOptionBuilder('strings_containing_single_quote_chars', 'Whether to fix double-quoted strings that contains single-quotes.'))
|
||||
->setAllowedTypes(['bool'])
|
||||
->setDefault(false)
|
||||
->getOption(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Vendored
+329
@@ -0,0 +1,329 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
use PhpCsFixer\AbstractFunctionReferenceFixer;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Tokenizer\Analyzer\ArgumentsAnalyzer;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
final class StringLengthToEmptyFixer extends AbstractFunctionReferenceFixer
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'String tests for empty must be done against `\'\'`, not with `strlen`.',
|
||||
[new CodeSample("<?php \$a = 0 === strlen(\$b) || \\STRLEN(\$c) < 1;\n")],
|
||||
null,
|
||||
'Risky when `strlen` is overridden, when called using a `stringable` object, also no longer triggers warning when called using non-string(able).'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* Must run before NoExtraBlankLinesFixer, NoTrailingWhitespaceFixer.
|
||||
* Must run after NoSpacesInsideParenthesisFixer.
|
||||
*/
|
||||
public function getPriority(): int
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$argumentsAnalyzer = new ArgumentsAnalyzer();
|
||||
|
||||
foreach ($this->findStrLengthCalls($tokens) as $candidate) {
|
||||
[$functionNameIndex, $openParenthesisIndex, $closeParenthesisIndex] = $candidate;
|
||||
$arguments = $argumentsAnalyzer->getArguments($tokens, $openParenthesisIndex, $closeParenthesisIndex);
|
||||
|
||||
if (1 !== \count($arguments)) {
|
||||
continue; // must be one argument
|
||||
}
|
||||
|
||||
// test for leading `\` before `strlen` call
|
||||
|
||||
$nextIndex = $tokens->getNextMeaningfulToken($closeParenthesisIndex);
|
||||
$previousIndex = $tokens->getPrevMeaningfulToken($functionNameIndex);
|
||||
|
||||
if ($tokens[$previousIndex]->isGivenKind(T_NS_SEPARATOR)) {
|
||||
$namespaceSeparatorIndex = $previousIndex;
|
||||
$previousIndex = $tokens->getPrevMeaningfulToken($previousIndex);
|
||||
} else {
|
||||
$namespaceSeparatorIndex = null;
|
||||
}
|
||||
|
||||
// test for yoda vs non-yoda fix case
|
||||
|
||||
if ($this->isOperatorOfInterest($tokens[$previousIndex])) { // test if valid yoda case to fix
|
||||
$operatorIndex = $previousIndex;
|
||||
$operandIndex = $tokens->getPrevMeaningfulToken($previousIndex);
|
||||
|
||||
if (!$this->isOperandOfInterest($tokens[$operandIndex])) { // test if operand is `0` or `1`
|
||||
continue;
|
||||
}
|
||||
|
||||
$replacement = $this->getReplacementYoda($tokens[$operatorIndex], $tokens[$operandIndex]);
|
||||
|
||||
if (null === $replacement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isOfHigherPrecedence($tokens[$nextIndex])) { // is of higher precedence right; continue
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isOfHigherPrecedence($tokens[$tokens->getPrevMeaningfulToken($operandIndex)])) { // is of higher precedence left; continue
|
||||
continue;
|
||||
}
|
||||
} elseif ($this->isOperatorOfInterest($tokens[$nextIndex])) { // test if valid !yoda case to fix
|
||||
$operatorIndex = $nextIndex;
|
||||
$operandIndex = $tokens->getNextMeaningfulToken($nextIndex);
|
||||
|
||||
if (!$this->isOperandOfInterest($tokens[$operandIndex])) { // test if operand is `0` or `1`
|
||||
continue;
|
||||
}
|
||||
|
||||
$replacement = $this->getReplacementNotYoda($tokens[$operatorIndex], $tokens[$operandIndex]);
|
||||
|
||||
if (null === $replacement) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isOfHigherPrecedence($tokens[$tokens->getNextMeaningfulToken($operandIndex)])) { // is of higher precedence right; continue
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->isOfHigherPrecedence($tokens[$previousIndex])) { // is of higher precedence left; continue
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// prepare for fixing
|
||||
|
||||
$keepParentheses = $this->keepParentheses($tokens, $openParenthesisIndex, $closeParenthesisIndex);
|
||||
|
||||
if (T_IS_IDENTICAL === $replacement) {
|
||||
$operandContent = '===';
|
||||
} else { // T_IS_NOT_IDENTICAL === $replacement
|
||||
$operandContent = '!==';
|
||||
}
|
||||
|
||||
// apply fixing
|
||||
|
||||
$tokens[$operandIndex] = new Token([T_CONSTANT_ENCAPSED_STRING, "''"]);
|
||||
$tokens[$operatorIndex] = new Token([$replacement, $operandContent]);
|
||||
|
||||
if (!$keepParentheses) {
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($closeParenthesisIndex);
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($openParenthesisIndex);
|
||||
}
|
||||
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($functionNameIndex);
|
||||
|
||||
if (null !== $namespaceSeparatorIndex) {
|
||||
$tokens->clearTokenAndMergeSurroundingWhitespace($namespaceSeparatorIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getReplacementYoda(Token $operator, Token $operand): ?int
|
||||
{
|
||||
/* Yoda 0
|
||||
|
||||
0 === strlen($b) | '' === $b
|
||||
0 !== strlen($b) | '' !== $b
|
||||
0 <= strlen($b) | X makes no sense, assume overridden
|
||||
0 >= strlen($b) | '' === $b
|
||||
0 < strlen($b) | '' !== $b
|
||||
0 > strlen($b) | X makes no sense, assume overridden
|
||||
*/
|
||||
|
||||
if ('0' === $operand->getContent()) {
|
||||
if ($operator->isGivenKind([T_IS_IDENTICAL, T_IS_GREATER_OR_EQUAL])) {
|
||||
return T_IS_IDENTICAL;
|
||||
}
|
||||
|
||||
if ($operator->isGivenKind(T_IS_NOT_IDENTICAL) || $operator->equals('<')) {
|
||||
return T_IS_NOT_IDENTICAL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Yoda 1
|
||||
|
||||
1 === strlen($b) | X cannot simplify
|
||||
1 !== strlen($b) | X cannot simplify
|
||||
1 <= strlen($b) | '' !== $b
|
||||
1 >= strlen($b) | cannot simplify
|
||||
1 < strlen($b) | cannot simplify
|
||||
1 > strlen($b) | '' === $b
|
||||
*/
|
||||
|
||||
if ($operator->isGivenKind(T_IS_SMALLER_OR_EQUAL)) {
|
||||
return T_IS_NOT_IDENTICAL;
|
||||
}
|
||||
|
||||
if ($operator->equals('>')) {
|
||||
return T_IS_IDENTICAL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function getReplacementNotYoda(Token $operator, Token $operand): ?int
|
||||
{
|
||||
/* Not Yoda 0
|
||||
|
||||
strlen($b) === 0 | $b === ''
|
||||
strlen($b) !== 0 | $b !== ''
|
||||
strlen($b) <= 0 | $b === ''
|
||||
strlen($b) >= 0 | X makes no sense, assume overridden
|
||||
strlen($b) < 0 | X makes no sense, assume overridden
|
||||
strlen($b) > 0 | $b !== ''
|
||||
*/
|
||||
|
||||
if ('0' === $operand->getContent()) {
|
||||
if ($operator->isGivenKind([T_IS_IDENTICAL, T_IS_SMALLER_OR_EQUAL])) {
|
||||
return T_IS_IDENTICAL;
|
||||
}
|
||||
|
||||
if ($operator->isGivenKind(T_IS_NOT_IDENTICAL) || $operator->equals('>')) {
|
||||
return T_IS_NOT_IDENTICAL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/* Not Yoda 1
|
||||
|
||||
strlen($b) === 1 | X cannot simplify
|
||||
strlen($b) !== 1 | X cannot simplify
|
||||
strlen($b) <= 1 | X cannot simplify
|
||||
strlen($b) >= 1 | $b !== ''
|
||||
strlen($b) < 1 | $b === ''
|
||||
strlen($b) > 1 | X cannot simplify
|
||||
*/
|
||||
|
||||
if ($operator->isGivenKind(T_IS_GREATER_OR_EQUAL)) {
|
||||
return T_IS_NOT_IDENTICAL;
|
||||
}
|
||||
|
||||
if ($operator->equals('<')) {
|
||||
return T_IS_IDENTICAL;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function isOperandOfInterest(Token $token): bool
|
||||
{
|
||||
if (!$token->isGivenKind(T_LNUMBER)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$content = $token->getContent();
|
||||
|
||||
return '0' === $content || '1' === $content;
|
||||
}
|
||||
|
||||
private function isOperatorOfInterest(Token $token): bool
|
||||
{
|
||||
return
|
||||
$token->isGivenKind([T_IS_IDENTICAL, T_IS_NOT_IDENTICAL, T_IS_SMALLER_OR_EQUAL, T_IS_GREATER_OR_EQUAL])
|
||||
|| $token->equals('<') || $token->equals('>')
|
||||
;
|
||||
}
|
||||
|
||||
private function isOfHigherPrecedence(Token $token): bool
|
||||
{
|
||||
static $operatorsPerContent = [
|
||||
'!',
|
||||
'%',
|
||||
'*',
|
||||
'+',
|
||||
'-',
|
||||
'.',
|
||||
'/',
|
||||
'~',
|
||||
'?',
|
||||
];
|
||||
|
||||
return $token->isGivenKind([T_INSTANCEOF, T_POW, T_SL, T_SR]) || $token->equalsAny($operatorsPerContent);
|
||||
}
|
||||
|
||||
private function keepParentheses(Tokens $tokens, int $openParenthesisIndex, int $closeParenthesisIndex): bool
|
||||
{
|
||||
$i = $tokens->getNextMeaningfulToken($openParenthesisIndex);
|
||||
|
||||
if ($tokens[$i]->isCast()) {
|
||||
$i = $tokens->getNextMeaningfulToken($i);
|
||||
}
|
||||
|
||||
for (; $i < $closeParenthesisIndex; ++$i) {
|
||||
$token = $tokens[$i];
|
||||
|
||||
if ($token->isGivenKind([T_VARIABLE, T_STRING]) || $token->isObjectOperator() || $token->isWhitespace() || $token->isComment()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$blockType = Tokens::detectBlockType($token);
|
||||
|
||||
if (null !== $blockType && $blockType['isStart']) {
|
||||
$i = $tokens->findBlockEnd($blockType['type'], $i);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function findStrLengthCalls(Tokens $tokens): \Generator
|
||||
{
|
||||
$candidates = [];
|
||||
$count = \count($tokens);
|
||||
|
||||
for ($i = 0; $i < $count; ++$i) {
|
||||
$candidate = $this->find('strlen', $tokens, $i, $count);
|
||||
|
||||
if (null === $candidate) {
|
||||
break;
|
||||
}
|
||||
|
||||
$i = $candidate[1]; // proceed to openParenthesisIndex
|
||||
$candidates[] = $candidate;
|
||||
}
|
||||
|
||||
foreach (array_reverse($candidates) as $candidate) {
|
||||
yield $candidate;
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+88
@@ -0,0 +1,88 @@
|
||||
<?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\StringNotation;
|
||||
|
||||
use PhpCsFixer\AbstractFixer;
|
||||
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
|
||||
use PhpCsFixer\FixerDefinition\CodeSample;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinition;
|
||||
use PhpCsFixer\FixerDefinition\FixerDefinitionInterface;
|
||||
use PhpCsFixer\Preg;
|
||||
use PhpCsFixer\Tokenizer\Token;
|
||||
use PhpCsFixer\Tokenizer\Tokens;
|
||||
|
||||
/**
|
||||
* Fixes the line endings in multi-line strings.
|
||||
*
|
||||
* @author Ilija Tovilo <ilija.tovilo@me.com>
|
||||
*/
|
||||
final class StringLineEndingFixer extends AbstractFixer implements WhitespacesAwareFixerInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isCandidate(Tokens $tokens): bool
|
||||
{
|
||||
return $tokens->isAnyTokenKindsFound([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isRisky(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDefinition(): FixerDefinitionInterface
|
||||
{
|
||||
return new FixerDefinition(
|
||||
'All multi-line strings must use correct line ending.',
|
||||
[
|
||||
new CodeSample(
|
||||
"<?php \$a = 'my\r\nmulti\nline\r\nstring';\r\n"
|
||||
),
|
||||
],
|
||||
null,
|
||||
'Changing the line endings of multi-line strings might affect string comparisons and outputs.'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function applyFix(\SplFileInfo $file, Tokens $tokens): void
|
||||
{
|
||||
$ending = $this->whitespacesConfig->getLineEnding();
|
||||
|
||||
foreach ($tokens as $tokenIndex => $token) {
|
||||
if (!$token->isGivenKind([T_CONSTANT_ENCAPSED_STRING, T_ENCAPSED_AND_WHITESPACE, T_INLINE_HTML])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tokens[$tokenIndex] = new Token([
|
||||
$token->getId(),
|
||||
Preg::replace(
|
||||
'#\R#u',
|
||||
$ending,
|
||||
$token->getContent()
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user