Skip to content

Commit ae56751

Browse files
Merge pull request #80 from VincentLanglet/feature/operatorSpacing
✨ Add operatorSpacing sniff
2 parents acd4b23 + 94812a2 commit ae56751

22 files changed

+450
-194
lines changed

TwigCS/Report/Report.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ class Report
1010
const MESSAGE_TYPE_NOTICE = 0;
1111
const MESSAGE_TYPE_WARNING = 1;
1212
const MESSAGE_TYPE_ERROR = 2;
13+
const MESSAGE_TYPE_FATAL = 3;
1314

1415
/**
1516
* @var SniffViolation[]
@@ -61,6 +62,7 @@ public function addMessage(SniffViolation $sniffViolation)
6162
++$this->totalWarnings;
6263
break;
6364
case self::MESSAGE_TYPE_ERROR:
65+
case self::MESSAGE_TYPE_FATAL:
6466
++$this->totalErrors;
6567
break;
6668
}
@@ -77,7 +79,7 @@ public function addMessage(SniffViolation $sniffViolation)
7779
*/
7880
public function getMessages(array $filters = [])
7981
{
80-
if (empty($filters)) {
82+
if (0 === count($filters)) {
8183
// Return all messages, without filtering.
8284
return $this->messages;
8385
}

TwigCS/Report/SniffViolation.php

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
namespace TwigCS\Report;
44

5+
use \LogicException;
56
use TwigCS\Sniff\SniffInterface;
67

78
/**
89
* Wrapper class that represents a violation to a sniff with context.
910
*/
1011
class SniffViolation
1112
{
13+
const LEVEL_NOTICE = 'NOTICE';
14+
const LEVEL_WARNING = 'WARNING';
15+
const LEVEL_ERROR = 'ERROR';
16+
const LEVEL_FATAL = 'FATAL';
17+
1218
/**
1319
* Level of the message among `notice`, `warning`, `error`
1420
*
@@ -86,13 +92,16 @@ public function getLevel()
8692
public function getLevelAsString()
8793
{
8894
switch ($this->level) {
89-
case SniffInterface::MESSAGE_TYPE_NOTICE:
90-
return 'NOTICE';
91-
case SniffInterface::MESSAGE_TYPE_WARNING:
92-
return 'WARNING';
93-
case SniffInterface::MESSAGE_TYPE_ERROR:
95+
case Report::MESSAGE_TYPE_NOTICE:
96+
return self::LEVEL_NOTICE;
97+
case Report::MESSAGE_TYPE_WARNING:
98+
return self::LEVEL_WARNING;
99+
case Report::MESSAGE_TYPE_ERROR:
100+
return self::LEVEL_ERROR;
101+
case Report::MESSAGE_TYPE_FATAL:
102+
return self::LEVEL_FATAL;
94103
default:
95-
return 'ERROR';
104+
throw new LogicException();
96105
}
97106
}
98107

@@ -106,13 +115,16 @@ public function getLevelAsString()
106115
public static function getLevelAsInt(string $level)
107116
{
108117
switch (strtoupper($level)) {
109-
case 'NOTICE':
110-
return SniffInterface::MESSAGE_TYPE_NOTICE;
111-
case 'WARNING':
112-
return SniffInterface::MESSAGE_TYPE_WARNING;
113-
case 'ERROR':
118+
case self::LEVEL_NOTICE:
119+
return Report::MESSAGE_TYPE_NOTICE;
120+
case self::LEVEL_WARNING:
121+
return Report::MESSAGE_TYPE_WARNING;
122+
case self::LEVEL_ERROR:
123+
return Report::MESSAGE_TYPE_ERROR;
124+
case self::LEVEL_FATAL:
125+
return Report::MESSAGE_TYPE_FATAL;
114126
default:
115-
return SniffInterface::MESSAGE_TYPE_ERROR;
127+
throw new LogicException();
116128
}
117129
}
118130

TwigCS/Ruleset/Generic/BlankEOFSniff.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ public function process(int $tokenPosition, array $tokens)
3333

3434
if (1 !== $i) {
3535
// Either 0 or 2+ blank lines.
36-
$fix = $this->addFixableMessage(
37-
$this::MESSAGE_TYPE_ERROR,
36+
$fix = $this->addFixableError(
3837
sprintf('A file must end with 1 blank line; found %d', $i),
3938
$token
4039
);

TwigCS/Ruleset/Generic/DelimiterSpacingSniff.php

Lines changed: 14 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -2,119 +2,35 @@
22

33
namespace TwigCS\Ruleset\Generic;
44

5-
use \Exception;
6-
use TwigCS\Sniff\AbstractSniff;
5+
use TwigCS\Sniff\AbstractSpacingSniff;
76
use TwigCS\Token\Token;
87

98
/**
10-
* Ensure there is one space before and after a delimiter {{, {%, {#, }}, %} and #}
9+
* Ensure there is one space before {{, {%, {#, and after }}, %} and #}
1110
*/
12-
class DelimiterSpacingSniff extends AbstractSniff
11+
class DelimiterSpacingSniff extends AbstractSpacingSniff
1312
{
1413
/**
15-
* @param int $tokenPosition
16-
* @param Token[] $tokens
14+
* @param Token $token
1715
*
18-
* @return Token
19-
*
20-
* @throws Exception
16+
* @return bool
2117
*/
22-
public function process(int $tokenPosition, array $tokens)
18+
protected function shouldHaveSpaceBefore(Token $token)
2319
{
24-
$token = $tokens[$tokenPosition];
25-
26-
if ($this->isTokenMatching($token, Token::VAR_START_TYPE)
27-
|| $this->isTokenMatching($token, Token::BLOCK_START_TYPE)
28-
|| $this->isTokenMatching($token, Token::COMMENT_START_TYPE)
29-
) {
30-
$this->processStart($tokenPosition, $tokens);
31-
}
32-
33-
if ($this->isTokenMatching($token, Token::VAR_END_TYPE)
20+
return $this->isTokenMatching($token, Token::VAR_END_TYPE)
3421
|| $this->isTokenMatching($token, Token::BLOCK_END_TYPE)
35-
|| $this->isTokenMatching($token, Token::COMMENT_END_TYPE)
36-
) {
37-
$this->processEnd($tokenPosition, $tokens);
38-
}
39-
40-
return $token;
41-
}
42-
43-
/**
44-
* @param int $tokenPosition
45-
* @param Token[] $tokens
46-
*
47-
* @throws Exception
48-
*/
49-
public function processStart(int $tokenPosition, array $tokens)
50-
{
51-
$token = $tokens[$tokenPosition];
52-
53-
// Ignore new line
54-
$next = $this->findNext(Token::WHITESPACE_TYPE, $tokens, $tokenPosition + 1, true);
55-
if ($this->isTokenMatching($tokens[$next], Token::EOL_TYPE)) {
56-
return;
57-
}
58-
59-
if ($this->isTokenMatching($tokens[$tokenPosition + 1], Token::WHITESPACE_TYPE)) {
60-
$count = strlen($tokens[$tokenPosition + 1]->getValue());
61-
} else {
62-
$count = 0;
63-
}
64-
65-
if (1 !== $count) {
66-
$fix = $this->addFixableMessage(
67-
$this::MESSAGE_TYPE_ERROR,
68-
sprintf('Expecting 1 whitespace after "%s"; found %d', $token->getValue(), $count),
69-
$token
70-
);
71-
72-
if ($fix) {
73-
if (0 === $count) {
74-
$this->fixer->addContent($tokenPosition, ' ');
75-
} else {
76-
$this->fixer->replaceToken($tokenPosition + 1, ' ');
77-
}
78-
}
79-
}
22+
|| $this->isTokenMatching($token, Token::COMMENT_END_TYPE);
8023
}
8124

8225
/**
83-
* @param int $tokenPosition
84-
* @param Token[] $tokens
26+
* @param Token $token
8527
*
86-
* @throws Exception
28+
* @return bool
8729
*/
88-
public function processEnd(int $tokenPosition, array $tokens)
30+
protected function shouldHaveSpaceAfter(Token $token)
8931
{
90-
$token = $tokens[$tokenPosition];
91-
92-
// Ignore new line
93-
$previous = $this->findPrevious(Token::WHITESPACE_TYPE, $tokens, $tokenPosition - 1, true);
94-
if ($this->isTokenMatching($tokens[$previous], Token::EOL_TYPE)) {
95-
return;
96-
}
97-
98-
if ($this->isTokenMatching($tokens[$tokenPosition - 1], Token::WHITESPACE_TYPE)) {
99-
$count = strlen($tokens[$tokenPosition - 1]->getValue());
100-
} else {
101-
$count = 0;
102-
}
103-
104-
if (1 !== $count) {
105-
$fix = $this->addFixableMessage(
106-
$this::MESSAGE_TYPE_ERROR,
107-
sprintf('Expecting 1 whitespace before "%s"; found %d', $token->getValue(), $count),
108-
$token
109-
);
110-
111-
if ($fix) {
112-
if (0 === $count) {
113-
$this->fixer->addContentBefore($tokenPosition, ' ');
114-
} else {
115-
$this->fixer->replaceToken($tokenPosition - 1, ' ');
116-
}
117-
}
118-
}
32+
return $this->isTokenMatching($token, Token::VAR_START_TYPE)
33+
|| $this->isTokenMatching($token, Token::BLOCK_START_TYPE)
34+
|| $this->isTokenMatching($token, Token::COMMENT_START_TYPE);
11935
}
12036
}

TwigCS/Ruleset/Generic/DisallowCommentedCodeSniff.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ public function process(int $tokenPosition, array $tokens)
4343
}
4444

4545
if ($found) {
46-
$this->addMessage(
47-
$this::MESSAGE_TYPE_WARNING,
46+
$this->addWarning(
4847
'Probable commented code found; keeping commented code is not advised',
4948
$token
5049
);

TwigCS/Ruleset/Generic/EmptyLinesSniff.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ public function process(int $tokenPosition, array $tokens)
3232
}
3333

3434
if (1 < $i) {
35-
$fix = $this->addFixableMessage(
36-
$this::MESSAGE_TYPE_ERROR,
35+
$fix = $this->addFixableError(
3736
sprintf('More than 1 empty lines are not allowed, found %d', $i),
3837
$token
3938
);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace TwigCS\Ruleset\Generic;
4+
5+
use TwigCS\Sniff\AbstractSpacingSniff;
6+
use TwigCS\Token\Token;
7+
8+
/**
9+
* Ensure there is one space before and after an operator
10+
*/
11+
class OperatorSpacingSniff extends AbstractSpacingSniff
12+
{
13+
/**
14+
* @param Token $token
15+
*
16+
* @return bool
17+
*/
18+
protected function shouldHaveSpaceBefore(Token $token)
19+
{
20+
return $this->isTokenMatching($token, Token::OPERATOR_TYPE);
21+
}
22+
23+
/**
24+
* @param Token $token
25+
*
26+
* @return bool
27+
*/
28+
protected function shouldHaveSpaceAfter(Token $token)
29+
{
30+
return $this->isTokenMatching($token, Token::OPERATOR_TYPE);
31+
}
32+
}

TwigCS/Runner/Fixer.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ public function rollbackChangeset()
327327
$this->inChangeset = false;
328328
$this->inConflict = false;
329329

330-
if (empty($this->changeset) === false) {
330+
if (count($this->changeset) > 0) {
331331
$this->changeset = [];
332332
}
333333
}

TwigCS/Runner/Linter.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ public function processTemplate(string $file, Ruleset $ruleset, Report $report)
126126
$this->env->parse($this->env->tokenize($twigSource));
127127
} catch (Error $e) {
128128
$sniffViolation = new SniffViolation(
129-
SniffInterface::MESSAGE_TYPE_ERROR,
129+
Report::MESSAGE_TYPE_FATAL,
130130
$e->getRawMessage(),
131131
$e->getSourceContext()->getName(),
132132
$e->getTemplateLine()
@@ -142,8 +142,8 @@ public function processTemplate(string $file, Ruleset $ruleset, Report $report)
142142
$stream = $this->tokenizer->tokenize($twigSource);
143143
} catch (Exception $e) {
144144
$sniffViolation = new SniffViolation(
145-
SniffInterface::MESSAGE_TYPE_ERROR,
146-
sprintf('Unable to tokenize file'),
145+
Report::MESSAGE_TYPE_FATAL,
146+
sprintf('Unable to tokenize file: %s', $e->getMessage()),
147147
$file
148148
);
149149

@@ -170,7 +170,7 @@ protected function setErrorHandler(Report $report, string $file = null)
170170
set_error_handler(function ($type, $message) use ($report, $file) {
171171
if (E_USER_DEPRECATED === $type) {
172172
$sniffViolation = new SniffViolation(
173-
SniffInterface::MESSAGE_TYPE_NOTICE,
173+
Report::MESSAGE_TYPE_NOTICE,
174174
$message,
175175
$file
176176
);

0 commit comments

Comments
 (0)