forked from symplify/coding-standard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTokenSkipper.php
More file actions
101 lines (82 loc) · 3.01 KB
/
TokenSkipper.php
File metadata and controls
101 lines (82 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
<?php
declare(strict_types=1);
namespace Symplify\CodingStandard\TokenRunner\Analyzer\FixerAnalyzer;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use Symplify\CodingStandard\Exception\ShouldNotHappenException;
use Symplify\CodingStandard\TokenRunner\Exception\TokenNotFoundException;
use Symplify\CodingStandard\TokenRunner\ValueObject\BlockInfo;
final readonly class TokenSkipper
{
public function __construct(
private BlockFinder $blockFinder
) {
}
/**
* @param Tokens<Token> $tokens
*/
public function skipBlocks(Tokens $tokens, int $position): int
{
if (! isset($tokens[$position])) {
throw new TokenNotFoundException($position);
}
$token = $tokens[$position];
if ($token->getContent() === '{') {
$blockInfo = $this->blockFinder->findInTokensByEdge($tokens, $position);
if (! $blockInfo instanceof BlockInfo) {
return $position;
}
return $blockInfo->getEnd();
}
if ($token->isGivenKind([CT::T_ARRAY_SQUARE_BRACE_OPEN, T_ARRAY])) {
$blockInfo = $this->blockFinder->findInTokensByEdge($tokens, $position);
if (! $blockInfo instanceof BlockInfo) {
return $position;
}
return $blockInfo->getEnd();
}
return $position;
}
/**
* @param Tokens<Token> $tokens
*/
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(')') && ! $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;
}
}