Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,30 @@ parameters:
- '*/tests/**/Fixture/*'

ignoreErrors:
# partial enum
- '#Method Symplify\\CodingStandard\\TokenRunner\\Analyzer\\FixerAnalyzer\\BlockFinder\:\:(getBlockTypeByContent|getBlockTypeByToken)\(\) never returns \d+ so it can be removed from the return type#'

-
path: tests/bootstrap.php
message: '#Instantiated class PHP_CodeSniffer\\Util\\Tokens not found#'

- '#Constant T_OPEN_CURLY_BRACKET|T_START_NOWDOC not found#'
- '#Method Symplify\\CodingStandard\\TokenRunner\\Traverser\\ArrayBlockInfoFinder\:\:reverseTokens\(\) should return array<PhpCsFixer\\Tokenizer\\Token> but returns array<int, PhpCsFixer\\Tokenizer\\Token\|null>#'

# unused generics
- '#Class (.*?) implements generic interface PhpCsFixer\\Fixer\\ConfigurableFixerInterface but does not specify its types\: TFixerInputConfig, TFixerComputedConfig#'

# conditional check to allow various php versions
-
message: '#Comparison operation ">\=" between int<80200, 80499> and (.*?) is always true#'
message: '#Comparison operation ">\=" between int<80200, 80599> and (.*?) is always true#'
path: src/TokenAnalyzer/DocblockRelatedParamNamesResolver.php

# offset access issues
-
message: '#Offset int\|null might not exist on PhpCsFixer\\Tokenizer\\Tokens#'
path: src/Fixer/Naming/ClassNameResolver.php

-
message: '#Offset int\|null might not exist on PhpCsFixer\\Tokenizer\\Tokens#'
path: src/Fixer/Naming/MethodNameResolver.php

# array filter issue
-
message: '#Parameter \#1 \$array \(array<int, PhpCsFixer\\Tokenizer\\Token>\) to function array_filter does not contain falsy values, the array will always stay the same#'
path: src/TokenRunner/Traverser/TokenReverser.php
2 changes: 1 addition & 1 deletion rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
->withPaths([__DIR__ . '/config', __DIR__ . '/src', __DIR__ . '/tests'])
->withRootFiles()
->withPhpSets()
->withPreparedSets(codeQuality: true, codingStyle: true, naming: true, earlyReturn: true, privatization: true)
->withPreparedSets(codeQuality: true, codingStyle: true, privatization: true, naming: true, earlyReturn: true)
->withImportNames()
->withSkip([
'*/Source/*',
Expand Down
32 changes: 31 additions & 1 deletion src/TokenRunner/Analyzer/FixerAnalyzer/TokenSkipper.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,45 @@ public function skipBlocksReversed(Tokens $tokens, int $position): int
{
/** @var Token $token */
$token = $tokens[$position];
if (! $token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_CLOSE) && ! $token->equals(')')) {
if (! $token->isGivenKind(CT::T_ARRAY_SQUARE_BRACE_CLOSE) && ! $token->equals(')') && ! $token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
return $position;
}

// Check if this is an attribute closing bracket
if ($token->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
$attributeStartPosition = $this->findAttributeStart($tokens, $position);
if ($attributeStartPosition !== null) {
return $attributeStartPosition;
}
}

$blockInfo = $this->blockFinder->findInTokensByEdge($tokens, $position);
if (! $blockInfo instanceof BlockInfo) {
throw new ShouldNotHappenException();
}

return $blockInfo->getStart();
}

/**
* @param Tokens<Token> $tokens
*/
private function findAttributeStart(Tokens $tokens, int $closingBracketPosition): ?int
{
// Search backwards for T_ATTRIBUTE token (#[)
for ($i = $closingBracketPosition - 1; $i >= 0; --$i) {
$currentToken = $tokens[$i];

if ($currentToken->isGivenKind(T_ATTRIBUTE)) {
return $i;
}

// If we hit another ] or reach a statement boundary, stop searching
if ($currentToken->equals(']') || $currentToken->equals(';') || $currentToken->equals('{') || $currentToken->equals('}')) {
break;
}
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ public function breakItems(BlockInfo $blockInfo, Tokens $tokens, int $kind): voi

// again, from the bottom to the top
for ($i = $blockInfo->getEnd() - 1; $i >= $blockInfo->getStart(); --$i) {
$i = $this->tokenSkipper->skipBlocksReversed($tokens, $i);

/** @var Token $currentToken */
$currentToken = $tokens[$i];

$i = $this->tokenSkipper->skipBlocksReversed($tokens, $i);

// 2. new line after each comma ",", instead of just space
if ($currentToken->getContent() === ',') {
if ($this->isLastItem($tokens, $i)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

namespace Symplify\CodingStandard\Tests\Fixer\Spacing\StandaloneLinePromotedPropertyFixer\Fixture;

final class SkipAttributes
{
public function __construct(#[JMS\Expose, JMS\Type('integer')] private int $id, private string $name) {}
}

final class SkipAttributes2
{
public function __construct(
#[JMS\Expose, JMS\Type('integer')]
private int $id,
private string $name,
) {}
}

final class SkipAttributes3
{
public function __construct(
#[JMS\Expose, JMS\Type('integer')] private int $id,
private string $name,
) {}
}

final class SkipAttributes4
{
public function __construct(
#[JMS\Expose]
#[JMS\Type('integer')] private int $id,
private string $name,
) {}
}

final class SkipAttributes5
{
public function __construct(
#[JMS\Expose]
#[JMS\Type('integer')]
private int $id,
private string $name,
) {}
}

?>
-----
<?php

namespace Symplify\CodingStandard\Tests\Fixer\Spacing\StandaloneLinePromotedPropertyFixer\Fixture;

final class SkipAttributes
{
public function __construct(
#[JMS\Expose, JMS\Type('integer')] private int $id,
private string $name
) {}
}

final class SkipAttributes2
{
public function __construct(
#[JMS\Expose, JMS\Type('integer')]
private int $id,
private string $name,
) {}
}

final class SkipAttributes3
{
public function __construct(
#[JMS\Expose, JMS\Type('integer')] private int $id,
private string $name,
) {}
}

final class SkipAttributes4
{
public function __construct(
#[JMS\Expose]
#[JMS\Type('integer')] private int $id,
private string $name,
) {}
}

final class SkipAttributes5
{
public function __construct(
#[JMS\Expose]
#[JMS\Type('integer')]
private int $id,
private string $name,
) {}
}

?>