Skip to content

Commit 4ffb9fb

Browse files
authored
Merge pull request #74 from mzeis/6-LineLength-UnitTest
#6: Fix line length sniff when using translations
2 parents 8673f24 + 8f758dd commit 4ffb9fb

File tree

3 files changed

+113
-11
lines changed

3 files changed

+113
-11
lines changed

Magento2/Sniffs/Files/LineLengthSniff.php

+96-10
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento2\Sniffs\Files;
77

8+
use PHP_CodeSniffer\Files\File;
89
use PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff as FilesLineLengthSniff;
910

1011
/**
@@ -13,11 +14,32 @@
1314
class LineLengthSniff extends FilesLineLengthSniff
1415
{
1516
/**
16-
* Having previous line content allows to ignore long lines in case of multi-line declaration.
17+
* Having previous line content allows to ignore long lines in case of translations.
1718
*
1819
* @var string
1920
*/
20-
protected $previousLineContent = '';
21+
protected $lastLineContent = '';
22+
23+
/**
24+
* Regular expression for finding a translation in the last line.
25+
*
26+
* @var string
27+
*/
28+
protected $lastLineRegExp = '~__\(.+\)|\bPhrase\(.+\)~';
29+
30+
/**
31+
* Having the next-to-last line content allows to ignore long lines in case of translations.
32+
*
33+
* @var string
34+
*/
35+
protected $nextToLastLineContent = '';
36+
37+
/**
38+
* Regular expression for finding a translation in the next-to-last line.
39+
*
40+
* @var string
41+
*/
42+
protected $nextToLastLineRegexp = '~__\($|\bPhrase\($~';
2143

2244
/**
2345
* @inheritdoc
@@ -32,15 +54,79 @@ class LineLengthSniff extends FilesLineLengthSniff
3254
/**
3355
* @inheritdoc
3456
*/
35-
protected function checkLineLength($phpcsFile, $stackPtr, $lineContent)
57+
protected function checkLineLength($phpcsFile, $tokens, $stackPtr)
58+
{
59+
/*
60+
* The parent sniff checks the length of the previous line, so we have to inspect the previous line instead of
61+
* the current one.
62+
*/
63+
if (!$this->doesPreviousLineContainTranslationString()) {
64+
parent::checkLineLength($phpcsFile, $tokens, $stackPtr);
65+
}
66+
67+
$this->updateLineBuffer($phpcsFile, $tokens, $stackPtr);
68+
}
69+
70+
/**
71+
* Checks whether the previous line is part of a translation.
72+
*
73+
* The generic line sniff (which we are falling back to if there is no translation) always checks the length of the
74+
* last line, so we have to check the last and next-to-last line for translations.
75+
*
76+
* @return bool
77+
*/
78+
protected function doesPreviousLineContainTranslationString()
3679
{
37-
$previousLineRegexp = '~__\($|\bPhrase\($~';
38-
$currentLineRegexp = '~__\(.+\)|\bPhrase\(.+\)~';
39-
$currentLineMatch = preg_match($currentLineRegexp, $lineContent) !== 0;
40-
$previousLineMatch = preg_match($previousLineRegexp, $this->previousLineContent) !== 0;
41-
$this->previousLineContent = $lineContent;
42-
if (! $currentLineMatch && !$previousLineMatch) {
43-
parent::checkLineLength($phpcsFile, $stackPtr, $lineContent);
80+
$lastLineMatch = preg_match($this->lastLineRegExp, $this->lastLineContent) !== 0;
81+
$nextToLastLineMatch = preg_match($this->nextToLastLineRegexp, $this->nextToLastLineContent) !== 0;
82+
83+
return $lastLineMatch || $nextToLastLineMatch;
84+
}
85+
86+
/**
87+
* Assembles and returns the content for the code line of the provided stack pointer.
88+
*
89+
* @param File $phpcsFile
90+
* @param array $tokens
91+
* @param int $stackPtr
92+
* @return string
93+
*/
94+
protected function getLineContent(File $phpcsFile, array $tokens, $stackPtr)
95+
{
96+
$lineContent = '';
97+
98+
/*
99+
* Avoid out of range error at the end of the file
100+
*/
101+
if (!array_key_exists($stackPtr, $tokens)) {
102+
return $lineContent;
44103
}
104+
105+
$codeLine = $tokens[$stackPtr]['line'];
106+
107+
/*
108+
* Concatenate the string until we jump to the next line or reach the end of line character.
109+
*/
110+
while (array_key_exists($stackPtr, $tokens) &&
111+
$tokens[$stackPtr]['line'] === $codeLine &&
112+
$tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) {
113+
$lineContent .= $tokens[$stackPtr]['content'];
114+
$stackPtr++;
115+
}
116+
117+
return $lineContent;
118+
}
119+
120+
/**
121+
* Pre-fills the line buffer for the next iteration.
122+
*
123+
* @param File $phpcsFile
124+
* @param array $tokens
125+
* @param int $stackPtr
126+
*/
127+
protected function updateLineBuffer(File $phpcsFile, array $tokens, $stackPtr)
128+
{
129+
$this->nextToLastLineContent = $this->lastLineContent;
130+
$this->lastLineContent = $this->getLineContent($phpcsFile, $tokens, $stackPtr);
45131
}
46132
}

Magento2/Tests/Files/LineLengthUnitTest.inc

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<?php
22

3+
use Magento\Framework\Phrase;
4+
35
// allowed
46
$shortString = 'This is a short line';
57

@@ -10,6 +12,19 @@ $tooLongString = 'This is a pretty long line. The code sniffer will report an er
1012
$longStringBrokenUp = 'This is a pretty long line. The code sniffer would report an error if this was written as a ' .
1113
'single line. You have to insert a line break to avoid this error.';
1214

15+
// allowed: long lines for translations
16+
$phraseObjects = [
17+
Phrase('This is a short line'),
18+
Phrase('Lines which include translations are excluded from this check. You can exceed the maximum character count without receiving a warning or an error.'),
19+
'This is no translation string, so let us make sure this throws an error even when we use the word Phrase inside the string',
20+
__(
21+
'Also if we use this syntax and we put the actual translation string into a new line, there should be no error if this is used in a translation.'
22+
),
23+
Phrase(
24+
'The same goes for the Phrase class when we put the actual translation string into a new line, also here we should not receive an error.'
25+
)
26+
];
27+
1328
// allowed by Magento Standard (Generic ruleset would trigger warning / error)
1429
$test = '012344567890123445678901234456789012344567890123445678901234456789';
1530
$test1 = '01234456789012344567890123445678901234456789012344567890123445678901234456789';

Magento2/Tests/Files/LineLengthUnitTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ class LineLengthUnitTest extends AbstractSniffUnitTest
1818
public function getErrorList()
1919
{
2020
return [
21-
7 => 1
21+
9 => 1,
22+
19 => 1,
2223
];
2324
}
2425

0 commit comments

Comments
 (0)