Skip to content

Commit 995d2e6

Browse files
✨ Add Whitespace check for delimiter
1 parent 93fe82a commit 995d2e6

File tree

4 files changed

+137
-1
lines changed

4 files changed

+137
-1
lines changed
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
namespace TwigCS\Sniff\Standard;
4+
5+
use \Exception;
6+
use TwigCS\Sniff\AbstractPreParserSniff;
7+
use TwigCS\Token\Token;
8+
9+
/**
10+
* Ensure there is one space before and after a delimiter {{, {%, {#, }}, %} and #}
11+
*/
12+
class EnsureWhitespaceDelimiterSniff extends AbstractPreParserSniff
13+
{
14+
/**
15+
* @param Token $token
16+
* @param int $tokenPosition
17+
* @param Token[] $tokens
18+
*
19+
* @return Token
20+
*
21+
* @throws Exception
22+
*/
23+
public function process(Token $token, $tokenPosition, $tokens)
24+
{
25+
if ($this->isTokenMatching($token, Token::VAR_START_TYPE)
26+
|| $this->isTokenMatching($token, Token::BLOCK_START_TYPE)
27+
|| $this->isTokenMatching($token, Token::COMMENT_START_TYPE)
28+
) {
29+
$this->processStart($token, $tokenPosition, $tokens);
30+
}
31+
32+
if ($this->isTokenMatching($token, Token::VAR_END_TYPE)
33+
|| $this->isTokenMatching($token, Token::BLOCK_END_TYPE)
34+
|| $this->isTokenMatching($token, Token::COMMENT_END_TYPE)
35+
) {
36+
$this->processEnd($token, $tokenPosition, $tokens);
37+
}
38+
39+
return $token;
40+
}
41+
42+
/**
43+
* @param Token $token
44+
* @param int $tokenPosition
45+
* @param Token[] $tokens
46+
*
47+
* @throws Exception
48+
*/
49+
public function processStart(Token $token, $tokenPosition, $tokens)
50+
{
51+
$offset = 1;
52+
while ($this->isTokenMatching($tokens[$tokenPosition + $offset], Token::WHITESPACE_TYPE)) {
53+
++$offset;
54+
}
55+
56+
// Ignore new line
57+
if ($this->isTokenMatching($tokens[$tokenPosition + $offset], Token::EOL_TYPE)) {
58+
return;
59+
}
60+
61+
$count = $offset - 1;
62+
if (1 !== $count) {
63+
$this->addMessage(
64+
$this::MESSAGE_TYPE_ERROR,
65+
sprintf('Expecting 1 whitespace AFTER start of expression eg. "{{" or "{%%"; found %d', $count),
66+
$token
67+
);
68+
}
69+
}
70+
71+
/**
72+
* @param Token $token
73+
* @param int $tokenPosition
74+
* @param Token[] $tokens
75+
*
76+
* @throws Exception
77+
*/
78+
public function processEnd(Token $token, $tokenPosition, $tokens)
79+
{
80+
$offset = 1;
81+
while ($this->isTokenMatching($tokens[$tokenPosition - $offset], Token::WHITESPACE_TYPE)) {
82+
++$offset;
83+
}
84+
85+
// Ignore new line
86+
if ($this->isTokenMatching($tokens[$tokenPosition - $offset], Token::EOL_TYPE)) {
87+
return;
88+
}
89+
90+
$count = $offset - 1;
91+
if (1 !== $count) {
92+
$this->addMessage(
93+
$this::MESSAGE_TYPE_ERROR,
94+
sprintf('Expecting 1 whitespace BEFORE end of expression eg. "}}" or "%%}"; found %d', $count),
95+
$token
96+
);
97+
}
98+
}
99+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{{ foo }}
2+
{# comment #}
3+
{% if foo %}{% endif %}
4+
5+
{{- foo -}}
6+
{#- comment -#}
7+
{%- if foo -%}{%- endif -%}
8+
9+
{{
10+
shouldNotCareAboutNewLine
11+
}}
12+
{%-if foo -%}{%- endif-%}
13+
14+
{{ foo({'bar': {'baz': 'shouldNotCareAboutDoubleHashes'}}) }}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace TwigCS\Tests\Sniff;
4+
5+
use TwigCS\Sniff\Standard\EnsureWhitespaceDelimiterSniff;
6+
use TwigCS\Tests\AbstractSniffTest;
7+
8+
/**
9+
* Class EnsureWhitespaceDelimiterTest
10+
*/
11+
class EnsureWhitespaceDelimiterTest extends AbstractSniffTest
12+
{
13+
public function testSniff1()
14+
{
15+
$this->checkGenericSniff('ensureWhitespaceDelimiter.twig', new EnsureWhitespaceDelimiterSniff(), [
16+
[12, 1],
17+
[12, 12],
18+
[12, 15],
19+
[12, 25],
20+
]);
21+
}
22+
}

TwigCS/Token/Tokenizer.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ protected function lex($endType, $endRegex)
279279
{
280280
preg_match($endRegex, $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor);
281281

282-
if (!isset($match[0])) {
282+
if (!empty($this->brackets) || !isset($match[0])) {
283283
$this->lexExpression();
284284
} elseif ($match[0][1] === $this->cursor) {
285285
$this->pushToken($endType, $match[0][0]);
@@ -290,6 +290,7 @@ protected function lex($endType, $endRegex)
290290
// Parse as text until the end position.
291291
$this->lexData($match[0][1]);
292292
} else {
293+
// Should not happen
293294
while ($this->cursor < $match[0][1]) {
294295
$this->lexExpression();
295296
}

0 commit comments

Comments
 (0)