-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This class initially introduces four new utility methods for working with error/warning messages. The class currently contains the following methods: * `addMessage()` - simple method to add either an error or a warning to PHPCS based on an `$isError` parameter. Returns boolean (same as PHPCS natively). Supports all optional parameters supported by PHPCS. * `addFixableMessage()` - simple method to add either a fixable error or a fixable warning to PHPCS based on an `$isError` parameter. Returns boolean (same as PHPCS natively). Supports all optional parameters supported by PHPCS. * `stringToErrorcode()` - to convert an arbitrary text string to an alphanumeric string with underscores. Returns the adjusted text string. This method is intended to pre-empt issues in XML and PHP when arbitrary text strings are used as (part of) an error code. * `hasNewLineSupport()` - to check whether PHPCS can properly handle new lines in violation messages. Prior to PHPCS 3.3.1, new line support in error messages was buggy. Ref: squizlabs/PHP_CodeSniffer#2093 Includes dedicated unit tests for each method.
- Loading branch information
Showing
6 changed files
with
603 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
<?php | ||
/** | ||
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers. | ||
* | ||
* @package PHPCSUtils | ||
* @copyright 2019-2020 PHPCSUtils Contributors | ||
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3 | ||
* @link https://github.com/PHPCSStandards/PHPCSUtils | ||
*/ | ||
|
||
namespace PHPCSUtils\Utils; | ||
|
||
use PHP_CodeSniffer\Files\File; | ||
use PHPCSUtils\BackCompat\Helper; | ||
|
||
/** | ||
* Helper functions for creating PHPCS error/warning messages. | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class MessageHelper | ||
{ | ||
|
||
/** | ||
* Add a PHPCS message to the output stack as either a warning or an error. | ||
* | ||
* @since 1.0.0-alpha4 | ||
* | ||
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. | ||
* @param string $message The message. | ||
* @param int $stackPtr The position of the token | ||
* the message relates to. | ||
* @param bool $isError Whether to report the message as an | ||
* 'error' or 'warning'. | ||
* Defaults to true (error). | ||
* @param string $code The error code for the message. | ||
* Defaults to 'Found'. | ||
* @param array $data Optional input for the data replacements. | ||
* @param int $severity Optional. Severity level. Defaults to 0 which will | ||
* translate to the PHPCS default severity level. | ||
* | ||
* @return bool | ||
*/ | ||
public static function addMessage( | ||
File $phpcsFile, | ||
$message, | ||
$stackPtr, | ||
$isError = true, | ||
$code = 'Found', | ||
$data = [], | ||
$severity = 0 | ||
) { | ||
if ($isError === true) { | ||
return $phpcsFile->addError($message, $stackPtr, $code, $data, $severity); | ||
} | ||
|
||
return $phpcsFile->addWarning($message, $stackPtr, $code, $data, $severity); | ||
} | ||
|
||
/** | ||
* Add a PHPCS message to the output stack as either a fixable warning or a fixable error. | ||
* | ||
* @since 1.0.0-alpha4 | ||
* | ||
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found. | ||
* @param string $message The message. | ||
* @param int $stackPtr The position of the token | ||
* the message relates to. | ||
* @param bool $isError Whether to report the message as an | ||
* 'error' or 'warning'. | ||
* Defaults to true (error). | ||
* @param string $code The error code for the message. | ||
* Defaults to 'Found'. | ||
* @param array $data Optional input for the data replacements. | ||
* @param int $severity Optional. Severity level. Defaults to 0 which will | ||
* translate to the PHPCS default severity level. | ||
* | ||
* @return bool | ||
*/ | ||
public static function addFixableMessage( | ||
File $phpcsFile, | ||
$message, | ||
$stackPtr, | ||
$isError = true, | ||
$code = 'Found', | ||
$data = [], | ||
$severity = 0 | ||
) { | ||
if ($isError === true) { | ||
return $phpcsFile->addFixableError($message, $stackPtr, $code, $data, $severity); | ||
} | ||
|
||
return $phpcsFile->addFixableWarning($message, $stackPtr, $code, $data, $severity); | ||
} | ||
|
||
/** | ||
* Convert an arbitrary text string to an alphanumeric string with underscores. | ||
* | ||
* Pre-empt issues in XML and PHP when arbitrary strings are being used as error codes. | ||
* | ||
* @since 1.0.0-alpha4 | ||
* | ||
* @param string $text Arbitrary text string intended to be used in an error code. | ||
* | ||
* @return string | ||
*/ | ||
public static function stringToErrorcode($text) | ||
{ | ||
return \preg_replace('`[^a-z0-9_]`i', '_', $text); | ||
} | ||
|
||
/** | ||
* Check whether PHPCS can properly handle new lines in violation messages. | ||
* | ||
* @link https://github.com/squizlabs/PHP_CodeSniffer/pull/2093 | ||
* | ||
* @since 1.0.0-alpha4 | ||
* | ||
* @return bool | ||
*/ | ||
public static function hasNewLineSupport() | ||
{ | ||
static $supported; | ||
if (isset($supported) === false) { | ||
$supported = \version_compare(Helper::getVersion(), '3.3.1', '>='); | ||
} | ||
|
||
return $supported; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?php | ||
|
||
/* testAddErrorMessage */ | ||
echo 'test 1'; | ||
|
||
/* testAddWarningMessage */ | ||
echo 'test 2'; | ||
|
||
/* testAddFixableErrorMessage */ | ||
echo 'test 3'; | ||
|
||
/* testAddFixableWarningMessage */ | ||
echo 'test 4'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,243 @@ | ||
<?php | ||
/** | ||
* PHPCSUtils, utility functions and classes for PHP_CodeSniffer sniff developers. | ||
* | ||
* @package PHPCSUtils | ||
* @copyright 2019-2021 PHPCSUtils Contributors | ||
* @license https://opensource.org/licenses/LGPL-3.0 LGPL3 | ||
* @link https://github.com/PHPCSStandards/PHPCSUtils | ||
*/ | ||
|
||
namespace PHPCSUtils\Tests\Utils\MessageHelper; | ||
|
||
use PHPCSUtils\TestUtils\UtilityMethodTestCase; | ||
use PHPCSUtils\Utils\MessageHelper; | ||
|
||
/** | ||
* Tests for the \PHPCSUtils\Utils\MessageHelper::addMessage() and the | ||
* \PHPCSUtils\Utils\MessageHelper::addFixableMessage() methods. | ||
* | ||
* {@internal Note: this is largely testing PHPCS native functionality, but as PHPCS doesn't | ||
* have any unit tests in place for this functionality, that's not a bad thing.} | ||
* | ||
* @group messagehelper | ||
* | ||
* @since 1.0.0 | ||
*/ | ||
class AddMessageTest extends UtilityMethodTestCase | ||
{ | ||
|
||
/** | ||
* Dummy error code to use for the test. | ||
* | ||
* Using the dummy full error code to force it to record. | ||
* | ||
* @var string | ||
*/ | ||
const CODE = 'PHPCSUtils.MessageHelper.AddMessageTest.Found'; | ||
|
||
/** | ||
* Set the name of a sniff to pass to PHPCS to limit the run (and force it to record errors). | ||
* | ||
* @var array | ||
*/ | ||
protected static $selectedSniff = ['PHPCSUtils.MessageHelper.AddMessageTest']; | ||
|
||
/** | ||
* Test the addMessage wrapper. | ||
* | ||
* @dataProvider dataAddMessage | ||
* @covers \PHPCSUtils\Utils\MessageHelper::addMessage | ||
* | ||
* @param string $testMarker The comment which prefaces the target token in the test file. | ||
* @param bool $isError Whether to test adding an error or a warning. | ||
* @param array $expected Expected error details. | ||
* | ||
* @return void | ||
*/ | ||
public function testAddMessage($testMarker, $isError, $expected) | ||
{ | ||
$tokens = self::$phpcsFile->getTokens(); | ||
$stackPtr = $this->getTargetToken($testMarker, \T_CONSTANT_ENCAPSED_STRING); | ||
$severity = \mt_rand(5, 10); | ||
$expected['severity'] = $severity; | ||
|
||
$return = MessageHelper::addMessage( | ||
self::$phpcsFile, | ||
'Message added. Text: %s', | ||
$stackPtr, | ||
$isError, | ||
static::CODE, | ||
[$tokens[$stackPtr]['content']], | ||
$severity | ||
); | ||
|
||
$this->assertTrue($return); | ||
|
||
$this->verifyRecordedMessages($stackPtr, $isError, $expected); | ||
} | ||
|
||
/** | ||
* Data Provider. | ||
* | ||
* @see testAddMessage() For the array format. | ||
* | ||
* @return array | ||
*/ | ||
public function dataAddMessage() | ||
{ | ||
return [ | ||
'add-error' => [ | ||
'/* testAddErrorMessage */', | ||
true, | ||
[ | ||
'message' => "Message added. Text: 'test 1'", | ||
'source' => static::CODE, | ||
'fixable' => false, | ||
], | ||
], | ||
'add-warning' => [ | ||
'/* testAddWarningMessage */', | ||
false, | ||
[ | ||
'message' => "Message added. Text: 'test 2'", | ||
'source' => static::CODE, | ||
'fixable' => false, | ||
], | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* Test the addFixableMessage wrapper. | ||
* | ||
* @dataProvider dataAddFixableMessage | ||
* @covers \PHPCSUtils\Utils\MessageHelper::addFixableMessage | ||
* | ||
* @param string $testMarker The comment which prefaces the target token in the test file. | ||
* @param bool $isError Whether to test adding an error or a warning. | ||
* @param array $expected Expected error details. | ||
* | ||
* @return void | ||
*/ | ||
public function testAddFixableMessage($testMarker, $isError, $expected) | ||
{ | ||
$tokens = self::$phpcsFile->getTokens(); | ||
$stackPtr = $this->getTargetToken($testMarker, \T_CONSTANT_ENCAPSED_STRING); | ||
$severity = \mt_rand(5, 10); | ||
$expected['severity'] = $severity; | ||
|
||
$return = MessageHelper::addFixableMessage( | ||
self::$phpcsFile, | ||
'Message added. Text: %s', | ||
$stackPtr, | ||
$isError, | ||
static::CODE, | ||
[$tokens[$stackPtr]['content']], | ||
$severity | ||
); | ||
|
||
// Fixable message recording only returns true when the fixer is enabled (=phpcbf). | ||
$this->assertFalse($return); | ||
|
||
$this->verifyRecordedMessages($stackPtr, $isError, $expected); | ||
} | ||
|
||
/** | ||
* Data Provider. | ||
* | ||
* @see testAddFixableMessage() For the array format. | ||
* | ||
* @return array | ||
*/ | ||
public function dataAddFixableMessage() | ||
{ | ||
return [ | ||
'add-fixable-error' => [ | ||
'/* testAddFixableErrorMessage */', | ||
true, | ||
[ | ||
'message' => "Message added. Text: 'test 3'", | ||
'source' => static::CODE, | ||
'fixable' => true, | ||
], | ||
], | ||
'add-fixable-warning' => [ | ||
'/* testAddFixableWarningMessage */', | ||
false, | ||
[ | ||
'message' => "Message added. Text: 'test 4'", | ||
'source' => static::CODE, | ||
'fixable' => true, | ||
], | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* Helper method to verify the expected message details. | ||
* | ||
* @param int $stackPtr The stack pointer on which the error/warning is expected. | ||
* @param bool $isError Whether to test adding an error or a warning. | ||
* @param array $expected Expected error details. | ||
* | ||
* @return void | ||
*/ | ||
protected function verifyRecordedMessages($stackPtr, $isError, $expected) | ||
{ | ||
$tokens = self::$phpcsFile->getTokens(); | ||
$errors = self::$phpcsFile->getErrors(); | ||
$warnings = self::$phpcsFile->getWarnings(); | ||
$result = ($isError === true) ? $errors : $warnings; | ||
|
||
/* | ||
* Make sure that no errors/warnings were recorded when the other type is set to be expected. | ||
*/ | ||
if ($isError === true) { | ||
$this->assertArrayNotHasKey( | ||
$tokens[$stackPtr]['line'], | ||
$warnings, | ||
'Expected no warnings on line ' . $tokens[$stackPtr]['line'] . '. At least one found.' | ||
); | ||
} else { | ||
$this->assertArrayNotHasKey( | ||
$tokens[$stackPtr]['line'], | ||
$errors, | ||
'Expected no errors on line ' . $tokens[$stackPtr]['line'] . '. At least one found.' | ||
); | ||
} | ||
|
||
/* | ||
* Make sure the expected array keys for the the errors/warnings are available. | ||
*/ | ||
$this->assertArrayHasKey( | ||
$tokens[$stackPtr]['line'], | ||
$result, | ||
'Expected a violation on line ' . $tokens[$stackPtr]['line'] . '. None found.' | ||
); | ||
|
||
$this->assertArrayHasKey( | ||
$tokens[$stackPtr]['column'], | ||
$result[$tokens[$stackPtr]['line']], | ||
'Expected a violation on line ' . $tokens[$stackPtr]['line'] . ', column ' | ||
. $tokens[$stackPtr]['column'] . '. None found.' | ||
); | ||
|
||
$messages = $result[$tokens[$stackPtr]['line']][$tokens[$stackPtr]['column']]; | ||
|
||
// Expect one violation. | ||
$this->assertCount(1, $messages, 'Expected 1 violation, found: ' . \count($messages)); | ||
|
||
$violation = $messages[0]; | ||
|
||
// PHPCS 2.x places `unknownSniff.` before the actual error code for utility tests with a dummy error code. | ||
$violation['source'] = \str_replace('unknownSniff.', '', $violation['source']); | ||
|
||
/* | ||
* Test the violation details. | ||
*/ | ||
foreach ($expected as $key => $value) { | ||
$this->assertSame($value, $violation[$key], \ucfirst($key) . ' comparison failed'); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<?php | ||
|
||
/* testMessageWithNewLine */ | ||
echo 'test 1'; |
Oops, something went wrong.