forked from symplify/coding-standard
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTokensNewliner.php
More file actions
116 lines (97 loc) · 3.77 KB
/
TokensNewliner.php
File metadata and controls
116 lines (97 loc) · 3.77 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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<?php
declare(strict_types=1);
namespace Symplify\CodingStandard\TokenRunner\Transformer\FixerTransformer;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;
use PhpCsFixer\WhitespacesFixerConfig;
use Symplify\CodingStandard\TokenRunner\Analyzer\FixerAnalyzer\TokenSkipper;
use Symplify\CodingStandard\TokenRunner\Exception\TokenNotFoundException;
use Symplify\CodingStandard\TokenRunner\ValueObject\BlockInfo;
use Symplify\CodingStandard\TokenRunner\Whitespace\IndentResolver;
final readonly class TokensNewliner
{
public function __construct(
private LineLengthCloserTransformer $lineLengthCloserTransformer,
private TokenSkipper $tokenSkipper,
private LineLengthOpenerTransformer $lineLengthOpenerTransformer,
private WhitespacesFixerConfig $whitespacesFixerConfig,
private IndentResolver $indentResolver
) {
}
/**
* @param Tokens<Token> $tokens
*/
public function breakItems(BlockInfo $blockInfo, Tokens $tokens, int $kind): void
{
// from bottom top, to prevent skipping ids
// e.g when token is added in the middle, the end index does now point to earlier element!
$currentNewlineIndentWhitespace = $this->indentResolver->resolveCurrentNewlineIndentWhitespace(
$tokens,
$blockInfo->getStart()
);
$newlineIndentWhitespace = $this->indentResolver->resolveNewlineIndentWhitespace(
$tokens,
$blockInfo->getStart()
);
// 1. break before arguments closing
$this->lineLengthCloserTransformer->insertNewlineBeforeClosingIfNeeded(
$tokens,
$blockInfo,
$kind,
$currentNewlineIndentWhitespace,
$this->indentResolver->resolveClosingBracketNewlineWhitespace($tokens, $blockInfo->getStart()),
);
// 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];
// 2. new line after each comma ",", instead of just space
if ($currentToken->getContent() === ',') {
if ($this->isLastItem($tokens, $i)) {
continue;
}
if ($this->isFollowedByComment($tokens, $i)) {
continue;
}
$tokens->ensureWhitespaceAtIndex($i + 1, 0, $newlineIndentWhitespace);
}
}
// 3. break after arguments opening
$this->lineLengthOpenerTransformer->insertNewlineAfterOpeningIfNeeded(
$tokens,
$blockInfo->getStart(),
$newlineIndentWhitespace
);
}
/**
* Has already newline? usually the last line => skip to prevent double spacing
*
* @param Tokens<Token> $tokens
*/
private function isLastItem(Tokens $tokens, int $position): bool
{
$nextPosition = $position + 1;
if (! isset($tokens[$nextPosition])) {
throw new TokenNotFoundException($nextPosition);
}
$tokenContent = $tokens[$nextPosition]->getContent();
return \str_contains($tokenContent, $this->whitespacesFixerConfig->getLineEnding());
}
/**
* @param Tokens<Token> $tokens
*/
private function isFollowedByComment(Tokens $tokens, int $i): bool
{
$nextToken = $tokens[$i + 1];
$nextNextToken = $tokens[$i + 2];
if ($nextNextToken->isComment()) {
return true;
}
// if next token is just space, turn it to newline
if (! $nextToken->isWhitespace(' ')) {
return false;
}
return $nextNextToken->isComment();
}
}