Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SyntaxError::getNormalizedMessage(): improve tests + 2 bug fixes #118

Merged
merged 5 commits into from
Apr 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/Errors/SyntaxError.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

class SyntaxError extends ParallelLintError
{
const IN_ON_REGEX = '~ in %s on line [0-9]+$~';

/** @var Blame */
private $blame;

Expand All @@ -29,8 +31,22 @@ public function getLine()
*/
public function getNormalizedMessage($translateTokens = false)
{
$message = preg_replace('~^(Parse|Fatal) error: (syntax error, )?~', '', $this->message);
$message = preg_replace('~ in ' . preg_quote(basename($this->filePath)) . ' on line [0-9]+$~', '', $message);
$message = preg_replace('~^(?:Parse|Fatal) error: (?:syntax error, )?~', '', $this->message);
$baseName = basename($this->filePath);
$regex = sprintf(self::IN_ON_REGEX, preg_quote($baseName, '~'));
$message = preg_replace($regex, '', $message, -1, $count);

if ($count === 0 && strpos($baseName, '\\') !== false) {
$baseName = ltrim(strrchr($this->filePath, '\\'), '\\');
$regex = sprintf(self::IN_ON_REGEX, preg_quote($baseName, '~'));
$message = preg_replace($regex, '', $message, -1, $count);
}

if ($count === 0) {
$regex = sprintf(self::IN_ON_REGEX, preg_quote($this->filePath, '~'));
$message = preg_replace($regex, '', $message);
}

$message = ucfirst($message);

if ($translateTokens) {
Expand Down
116 changes: 109 additions & 7 deletions tests/Unit/Errors/SyntaxErrorGetNormalizeMessageTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,119 @@

class SyntaxErrorGetNormalizeMessageTest extends UnitTestCase
{
public function testInWordInErrorMessage()
const FILEPATH_MSG_TEMPLATE = "Parse error: unexpected 'Foo' (T_STRING) in %s on line 2";
const FILEPATH_MSG_EXPECTED = "Unexpected 'Foo' (T_STRING)";

/**
* Test retrieving a normalized error message.
*
* @dataProvider dataMessageNormalization
*
* @param string $message The message input to run the test with.
* @param string $expected The expected method return value.
*
* @return void
*/
public function testMessageNormalizationWithoutTokenTranslation($message, $expected)
{
$error = new SyntaxError('test.php', $message);
$this->assertSame($expected, $error->getNormalizedMessage());
}

/**
* Data provider.
*
* @return array
*/
public function dataMessageNormalization()
{
return array(
'Strip leading and trailing information - fatal error' => array(
'message' => "Fatal error: 'break' not in the 'loop' or 'switch' context in test.php on line 2",
'expected' => "'break' not in the 'loop' or 'switch' context",
),
'Strip leading and trailing information - parse error' => array(
'message' => "Parse error: unexpected 'Foo' (T_STRING) in test.php on line 2",
'expected' => "Unexpected 'Foo' (T_STRING)", // Also verifies ucfirst() call is being made.
),
'Strip trailing information, not leading - deprecation' => array(
'message' => "Deprecated: The (real) cast is deprecated, use (float) instead in test.php on line 2",
'expected' => "Deprecated: The (real) cast is deprecated, use (float) instead",
),
);
}

/**
* Test retrieving a normalized error message with token translation.
*
* @return void
*/
public function testMessageNormalizationWithTokenTranslation()
{
$message = 'Fatal error: \'break\' not in the \'loop\' or \'switch\' context in test.php on line 2';
$message = 'Parse error: unexpected T_FILE, expecting T_STRING in test.php on line 2';
$expected = 'Unexpected __FILE__ (T_FILE), expecting T_STRING';

$error = new SyntaxError('test.php', $message);
$this->assertSame('\'break\' not in the \'loop\' or \'switch\' context', $error->getNormalizedMessage());
$this->assertSame($expected, $error->getNormalizedMessage(true));
}

/**
* Test retrieving a normalized error message with variations for the file path.
*
* @dataProvider dataFilePathHandling
*
* @param string $filePath The file path input to run the test with.
* @param string $fileName The file name which is expected to be in the error message.
*
* @return void
*/
public function testFilePathHandling($filePath, $fileName)
{
$message = sprintf(self::FILEPATH_MSG_TEMPLATE, $fileName);
$error = new SyntaxError($filePath, $message);
$this->assertSame(self::FILEPATH_MSG_EXPECTED, $error->getNormalizedMessage());
}

public function testInWordInErrorMessageAndInFileName()
/**
* Data provider.
*
* @return array
*/
public function dataFilePathHandling()
{
$message = 'Fatal error: \'break\' not in the \'loop\' or \'switch\' context in test in file.php on line 2';
$error = new SyntaxError('test in file.php', $message);
$this->assertSame('\'break\' not in the \'loop\' or \'switch\' context', $error->getNormalizedMessage());
return array(
'Plain file name' => array(
'filePath' => 'test.php',
'fileName' => 'test.php',
),
'File name containing spaces' => array(
'filePath' => 'test in file.php',
'fileName' => 'test in file.php',
),
'File name containing regex delimiter' => array(
'filePath' => 'test~file.php',
'fileName' => 'test~file.php',
),
'Full file path, linux slashes' => array(
'filePath' => 'path/to/subdir/file.php',
'fileName' => 'file.php',
),
'File path, windows slashes' => array(
'filePath' => 'path\to\subdir\file.php',
'fileName' => 'file.php',
),
'Absolute file path, windows slashes' => array(
'filePath' => 'C:\path\to\subdir\file.php',
'fileName' => 'C:\path\to\subdir\file.php',
),
'Relative file path, windows slashes' => array(
'filePath' => '.\subdir\file.php',
'fileName' => '.\subdir\file.php',
),
'Phar file name' => array(
'filePath' => 'phar://031.phar.php/a.php',
'fileName' => 'phar://031.phar.php/a.php',
),
);
}
}