diff --git a/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php b/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php index b62e88c7ceddde7e98e89b12708c78b790f0d632..9b4821caf7d05a7041f9c1e5046eee6a3bd446d4 100644 --- a/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php +++ b/dev/tests/static/framework/Magento/Sniffs/Translation/ConstantUsageSniff.php @@ -5,12 +5,10 @@ */ namespace Magento\Sniffs\Translation; -use PHP_CodeSniffer_File; - /** * Make sure that constants are not used as the first argument of translation function. */ -class ConstantUsageSniff extends \Generic_Sniffs_Files_LineLengthSniff +class ConstantUsageSniff implements \PHP_CodeSniffer_Sniff { /** * Having previous line content allows to process multi-line declaration. @@ -20,24 +18,76 @@ class ConstantUsageSniff extends \Generic_Sniffs_Files_LineLengthSniff protected $previousLineContent = ''; /** - * {@inheritdoc} + * {@inheritDoc} + */ + public function register() + { + return [T_OPEN_TAG]; + + } + + /** + * Copied from \Generic_Sniffs_Files_LineLengthSniff + * + * {@inheritDoc} */ - protected function checkLineLength(\PHP_CodeSniffer_File $phpcsFile, $stackPtr, $lineContent) + public function process(\PHP_CodeSniffer_File $phpcsFile, $stackPtr) { - $previousLineRegexp = '~__\($|Phrase\($~'; - $currentLineRegexp = '~__\(.+\)|Phrase\(.+\)~'; + $tokens = $phpcsFile->getTokens(); + + // Make sure this is the first open tag. + $previousOpenTag = $phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)); + if ($previousOpenTag !== false) { + return; + } + + $tokenCount = 0; + $currentLineContent = ''; + $currentLine = 1; + + $trim = (strlen($phpcsFile->eolChar) * -1); + for (; $tokenCount < $phpcsFile->numTokens; $tokenCount++) { + if ($tokens[$tokenCount]['line'] === $currentLine) { + $currentLineContent .= $tokens[$tokenCount]['content']; + } else { + $currentLineContent = substr($currentLineContent, 0, $trim); + $this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent); + $currentLineContent = $tokens[$tokenCount]['content']; + $currentLine++; + } + } + + $currentLineContent = substr($currentLineContent, 0, $trim); + $this->checkIfFirstArgumentConstant($phpcsFile, ($tokenCount - 1), $currentLineContent); + } + + /** + * Checks if first argument of \Magento\Framework\Phrase or translation function is a constant + * + * @param \PHP_CodeSniffer_File $phpcsFile + * @param int $stackPtr + * @param string $lineContent + * @return void + */ + private function checkIfFirstArgumentConstant( + \PHP_CodeSniffer_File $phpcsFile, + $stackPtr, + $lineContent + ) { + $previousLineRegexp = '/(__|Phrase)\($/im'; + $currentLineRegexp = '/(__|Phrase)\(.+\)/'; $currentLineMatch = preg_match($currentLineRegexp, $lineContent) !== 0; $previousLineMatch = preg_match($previousLineRegexp, $this->previousLineContent) !== 0; $this->previousLineContent = $lineContent; $error = 'Constants are not allowed as the first argument of translation function, use string literal instead'; $constantRegexp = '[^\$\'"]+::[A-Z_0-9]+.*'; if ($currentLineMatch) { - $variableRegexp = "~__\({$constantRegexp}\)|Phrase\({$constantRegexp}\)~"; + $variableRegexp = "/(__|Phrase)\({$constantRegexp}\)/"; if (preg_match($variableRegexp, $lineContent) !== 0) { $phpcsFile->addError($error, $stackPtr, 'VariableTranslation'); } } else if ($previousLineMatch) { - $variableRegexp = "~^\s+{$constantRegexp}~"; + $variableRegexp = "/^{$constantRegexp}/"; if (preg_match($variableRegexp, $lineContent) !== 0) { $phpcsFile->addError($error, $stackPtr, 'VariableTranslation'); } diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php index cf0e3092b25ead2432b3aef5998dc81546b4a673..addb30067529fcc7f12763f287a616e93de780bc 100644 --- a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/ConstantUsageSniffTest.php @@ -24,109 +24,74 @@ class ConstantUsageSniffTest extends \PHPUnit_Framework_TestCase } /** - * @param string $line - * @dataProvider checkLineLengthCorrectArguments + * @param string $file + * @param int $numIncorrectUsages + * @dataProvider processDataProvider */ - public function testCheckLineLengthCorrectArguments($line) + public function testProcessIncorrectArguments($file, $numIncorrectUsages) { - $this->fileMock->expects($this->never()) - ->method('addError'); - $this->checkLineLength(10, $line); - } - - /** - * @return array - */ - public function checkLineLengthCorrectArguments() - { - return [ - [ - '__($item)' - ], - [ - '__($item[ConfigConverter::KEY_TITLE])' - ], - [ - '__($item[\'value\'])' - ], - [ - '__($item->getValue())' - ], - [ - 'Phrase($item)' - ], - [ - 'Phrase($item[ConfigConverter::KEY_TITLE])' - ], - [ - 'Phrase($item[\'value\'])' - ], - [ - 'Phrase($item->getValue())' - ], - [ - '\Magento\Framework\Phrase($item)' - ] - ]; - } - - /** - * @param string $line - * @dataProvider checkLineLengthIncorrectArguments - */ - public function testCheckLineLengthIncorrectArguments($line) - { - $lineNumber = 10; + $stackPtr = 10; + $fileContent = file_get_contents(__DIR__ . '/_files/' . $file); + $tokens = $this->tokenizeString($fileContent); $this->fileMock->expects($this->once()) + ->method('findPrevious') + ->with( + T_OPEN_TAG, + $stackPtr - 1 + ) + ->willReturn(false); + $this->fileMock->expects($this->once()) + ->method('getTokens') + ->willReturn($tokens); + $this->fileMock->eolChar = 2; + $this->fileMock->numTokens = count($tokens); + $this->fileMock->expects($this->exactly($numIncorrectUsages)) ->method('addError') ->with( 'Constants are not allowed as the first argument of translation function, use string literal instead', - $lineNumber, + $this->anything(), 'VariableTranslation' ); - $this->checkLineLength($lineNumber, $line); + $this->constantUsageSniff->process($this->fileMock, $stackPtr); + } + + /** + * Get tokens for a string + * + * @param string $fileContent + * @return array + */ + private function tokenizeString($fileContent) + { + $lineNumber = 1; + $tokens = token_get_all($fileContent); + $snifferTokens = []; + for ($i = 0; $i < count($tokens); $i++) { + $content = is_array($tokens[$i]) ? $tokens[$i][1] : $tokens[$i]; + $snifferTokens[$i]['line'] = $lineNumber; + $snifferTokens[$i]['content'] = $content; + $trimmedContent = trim($content, ' '); + if ($trimmedContent == PHP_EOL || $trimmedContent == PHP_EOL . PHP_EOL) { + $lineNumber++; + } + } + return $snifferTokens; } /** * @return array */ - public function checkLineLengthIncorrectArguments() + public function processDataProvider() { return [ [ - '$item[ConfigConverter::KEY_TITLE] = __(Converter::KEY_TITLE)' - ], - [ - '$item[ConfigConverter::KEY_TITLE] = __(self::KEY_TITLE)' + 'incorrect_arguments.txt', + 9 ], [ - '$item[ConfigConverter::KEY_TITLE] = __(\Magento\Support\Model\Report\Config\Converter::KEY_TITLE)' - ], - [ - 'Phrase(Converter::KEY_TITLE)' - ], - [ - 'Phrase(self::KEY_TITLE)' - ], - [ - 'Phrase(\Magento\Support\Model\Report\Config\Converter::KEY_TITLE)' - ], - [ - '\Magento\Framework\Phrase(Converter::KEY_TITLE)' + 'correct_arguments.txt', + 0 ] ]; } - - /** - * Call checkLineLength method - * - * @param int $lineNumber - * @param string $line - */ - private function checkLineLength($lineNumber, $line) - { - $reflectionMethod = new \ReflectionMethod(ConstantUsageSniff::class, 'checkLineLength'); - $reflectionMethod->setAccessible(true); - $reflectionMethod->invoke($this->constantUsageSniff, $this->fileMock, $lineNumber, $line); - } } diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt new file mode 100644 index 0000000000000000000000000000000000000000..2ea7c6ed532c4334b031e93fd2b2eacdde222591 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/correct_arguments.txt @@ -0,0 +1,29 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +$item[ConfigConverter::KEY_TITLE] = __($item) + +$item[ConfigConverter::KEY_TITLE] = __($item[Converter::KEY_TITLE]) + +$item[ConfigConverter::KEY_TITLE] = __($item['\Magento\Support\Model\Report\Config\Converter::KEY_TITLE']) + +$item[ConfigConverter::KEY_TITLE] = __($item['value']) + +$item[ConfigConverter::KEY_TITLE] = __( + $item +) + +Phrase($item) + +Phrase($item[Converter::KEY_TITLE]) + +Phrase($item['\Magento\Support\Model\Report\Config\Converter::KEY_TITLE']) + +\Magento\Framework\Phrase($item['value']) + +\Magento\Framework\Phrase( + $item[Converter::KEY_TITLE] +) diff --git a/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt new file mode 100644 index 0000000000000000000000000000000000000000..d2e60b65c06ccda6751f52b8bc5db17c6c1585c3 --- /dev/null +++ b/dev/tests/static/framework/tests/unit/testsuite/Magento/Sniffs/Translation/_files/incorrect_arguments.txt @@ -0,0 +1,27 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +$item[ConfigConverter::KEY_TITLE] = __(Converter::KEY_TITLE) + +$item[ConfigConverter::KEY_TITLE] = __(self::KEY_TITLE) + +$item[ConfigConverter::KEY_TITLE] = __(\Magento\Support\Model\Report\Config\Converter::KEY_TITLE) + +$item[ConfigConverter::KEY_TITLE] = __( + Converter::KEY_TITLE +) + +Phrase(Converter::KEY_TITLE) + +Phrase(self::KEY_TITLE) + +Phrase(\Magento\Support\Model\Report\Config\Converter::KEY_TITLE) + +\Magento\Framework\Phrase(Converter::KEY_TITLE) + +\Magento\Framework\Phrase( + Converter::KEY_TITLE +)