Skip to content

Commit 4a94eb7

Browse files
kubawerloskeradus
authored andcommitted
Add SingleLineThrowFixer
1 parent 9f68642 commit 4a94eb7

File tree

5 files changed

+414
-0
lines changed

5 files changed

+414
-0
lines changed

README.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,10 @@ Choose from the list of available rules:
18411841
- ``comment_types`` (a subset of ``['asterisk', 'hash']``): list of comment types
18421842
to fix; defaults to ``['asterisk', 'hash']``
18431843

1844+
* **single_line_throw**
1845+
1846+
Throwing exception must be done in single line.
1847+
18441848
* **single_quote** [@Symfony, @PhpCsFixer]
18451849

18461850
Convert double quotes to single quotes for simple strings.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PHP CS Fixer.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
namespace PhpCsFixer\Fixer\FunctionNotation;
14+
15+
use PhpCsFixer\AbstractFixer;
16+
use PhpCsFixer\FixerDefinition\CodeSample;
17+
use PhpCsFixer\FixerDefinition\FixerDefinition;
18+
use PhpCsFixer\Preg;
19+
use PhpCsFixer\Tokenizer\Token;
20+
use PhpCsFixer\Tokenizer\Tokens;
21+
22+
/**
23+
* @author Kuba Werłos <werlos@gmail.com>
24+
*/
25+
final class SingleLineThrowFixer extends AbstractFixer
26+
{
27+
/**
28+
* @internal
29+
*/
30+
const REMOVE_WHITESPACE_AFTER_TOKENS = ['['];
31+
32+
/**
33+
* @internal
34+
*/
35+
const REMOVE_WHITESPACE_AROUND_TOKENS = ['(', [T_OBJECT_OPERATOR], [T_DOUBLE_COLON]];
36+
37+
/**
38+
* @internal
39+
*/
40+
const REMOVE_WHITESPACE_BEFORE_TOKENS = [')', ']', ',', ';'];
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function getDefinition()
46+
{
47+
return new FixerDefinition(
48+
'Throwing exception must be done in single line.',
49+
[
50+
new CodeSample("<?php\nthrow new Exception(\n 'Error',\n 500\n);\n"),
51+
]
52+
);
53+
}
54+
55+
/**
56+
* {@inheritdoc}
57+
*/
58+
public function isCandidate(Tokens $tokens)
59+
{
60+
return $tokens->isTokenKindFound(T_THROW);
61+
}
62+
63+
/**
64+
* {@inheritdoc}
65+
*/
66+
public function getPriority()
67+
{
68+
// must be fun before ConcatSpaceFixer
69+
return 1;
70+
}
71+
72+
/**
73+
* {@inheritdoc}
74+
*/
75+
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
76+
{
77+
for ($index = 0, $count = $tokens->count(); $index < $count; ++$index) {
78+
if (!$tokens[$index]->isGivenKind(T_THROW)) {
79+
continue;
80+
}
81+
82+
/** @var int $openingBraceCandidateIndex */
83+
$openingBraceCandidateIndex = $tokens->getNextTokenOfKind($index, [';', '(']);
84+
85+
while ($tokens[$openingBraceCandidateIndex]->equals('(')) {
86+
/** @var int $closingBraceIndex */
87+
$closingBraceIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $openingBraceCandidateIndex);
88+
/** @var int $openingBraceCandidateIndex */
89+
$openingBraceCandidateIndex = $tokens->getNextTokenOfKind($closingBraceIndex, [';', '(']);
90+
}
91+
92+
$this->trimNewLines($tokens, $index, $openingBraceCandidateIndex);
93+
}
94+
}
95+
96+
/**
97+
* @param int $startIndex
98+
* @param int $endIndex
99+
*/
100+
private function trimNewLines(Tokens $tokens, $startIndex, $endIndex)
101+
{
102+
for ($index = $startIndex; $index < $endIndex; ++$index) {
103+
$content = $tokens[$index]->getContent();
104+
105+
if ($tokens[$index]->isGivenKind(T_COMMENT)) {
106+
if (0 === strpos($content, '//')) {
107+
$content = '/*'.substr($content, 2).' */';
108+
$tokens->clearAt($index + 1);
109+
} elseif (0 === strpos($content, '#')) {
110+
$content = '/*'.substr($content, 1).' */';
111+
$tokens->clearAt($index + 1);
112+
} elseif (false !== Preg::match('/\R/', $content)) {
113+
$content = Preg::replace('/\R/', ' ', $content);
114+
}
115+
$tokens[$index] = new Token([T_COMMENT, $content]);
116+
117+
continue;
118+
}
119+
120+
if (!$tokens[$index]->isGivenKind(T_WHITESPACE)) {
121+
continue;
122+
}
123+
124+
if (0 === Preg::match('/\R/', $content)) {
125+
continue;
126+
}
127+
128+
$prevIndex = $tokens->getNonEmptySibling($index, -1);
129+
if ($tokens[$prevIndex]->equalsAny(array_merge(self::REMOVE_WHITESPACE_AFTER_TOKENS, self::REMOVE_WHITESPACE_AROUND_TOKENS))) {
130+
$tokens->clearAt($index);
131+
132+
continue;
133+
}
134+
135+
$nextIndex = $tokens->getNonEmptySibling($index, 1);
136+
if ($tokens[$nextIndex]->equalsAny(array_merge(self::REMOVE_WHITESPACE_AROUND_TOKENS, self::REMOVE_WHITESPACE_BEFORE_TOKENS))) {
137+
if (!$tokens[$prevIndex]->isGivenKind(T_FUNCTION)) {
138+
$tokens->clearAt($index);
139+
140+
continue;
141+
}
142+
}
143+
144+
$tokens[$index] = new Token([T_WHITESPACE, ' ']);
145+
}
146+
}
147+
}

tests/AutoReview/FixerFactoryTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ public function provideFixersPriorityCases()
221221
[$fixers['single_import_per_statement'], $fixers['no_singleline_whitespace_before_semicolons']],
222222
[$fixers['single_import_per_statement'], $fixers['no_unused_imports']],
223223
[$fixers['single_import_per_statement'], $fixers['space_after_semicolon']],
224+
[$fixers['single_line_throw'], $fixers['concat_space']],
224225
[$fixers['single_trait_insert_per_statement'], $fixers['braces']],
225226
[$fixers['single_trait_insert_per_statement'], $fixers['space_after_semicolon']],
226227
[$fixers['standardize_increment'], $fixers['increment_style']],

0 commit comments

Comments
 (0)