From fe4ab4666cce889c1e9ee0973acf25e423003ac2 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 27 Dec 2021 12:17:43 +0100 Subject: [PATCH 1/4] Tests: introduce base `HighlighterTestCase` ... from which all test classes should extend and which contains the `getConsoleColorMock()` method to prevent having to duplicate it in multiple places. The method has been adjusted to be slightly more flexible for re-use, in that the `$withTheme` parameter can be used to determine whether the ConsoleColor class should behave as if themes have been registered or not. --- tests/HighlighterTestCase.php | 39 +++++++++++++++++++++++++++++++++++ tests/TokenizeTest.php | 27 +----------------------- 2 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 tests/HighlighterTestCase.php diff --git a/tests/HighlighterTestCase.php b/tests/HighlighterTestCase.php new file mode 100644 index 0000000..ebedff5 --- /dev/null +++ b/tests/HighlighterTestCase.php @@ -0,0 +1,39 @@ +createMock('\PHP_Parallel_Lint\PhpConsoleColor\ConsoleColor') + : $this->getMock('\PHP_Parallel_Lint\PhpConsoleColor\ConsoleColor'); + + $mock->expects($this->any()) + ->method('apply') + ->will($this->returnCallback(function ($style, $text) use ($withTheme) { + if ($withTheme) { + return "<$style>$text"; + } else { + return $text; + } + })); + + $mock->expects($this->any()) + ->method('hasTheme') + ->will($this->returnValue($withTheme)); + + return $mock; + } +} diff --git a/tests/TokenizeTest.php b/tests/TokenizeTest.php index 0170bc8..11e36f7 100644 --- a/tests/TokenizeTest.php +++ b/tests/TokenizeTest.php @@ -3,7 +3,6 @@ namespace PHP_Parallel_Lint\PhpConsoleHighlighter\Test; use PHP_Parallel_Lint\PhpConsoleHighlighter\Highlighter; -use PHPUnit\Framework\TestCase; /** * Test support for all token types. @@ -11,7 +10,7 @@ * @covers PHP_Parallel_Lint\PhpConsoleHighlighter\Highlighter::tokenize * @covers PHP_Parallel_Lint\PhpConsoleHighlighter\Highlighter::getTokenType */ -class TokenizeTest extends TestCase +class TokenizeTest extends HighlighterTestCase { /** @var Highlighter */ private $uut; @@ -24,30 +23,6 @@ protected function setUpHighlighter() $this->uut = new Highlighter($this->getConsoleColorMock()); } - /** - * Helper method mocking the Console Color Class. - * - * @return \PHP_Parallel_Lint\PhpConsoleColor\ConsoleColor - */ - protected function getConsoleColorMock() - { - $mock = method_exists($this, 'createMock') - ? $this->createMock('\PHP_Parallel_Lint\PhpConsoleColor\ConsoleColor') - : $this->getMock('\PHP_Parallel_Lint\PhpConsoleColor\ConsoleColor'); - - $mock->expects($this->any()) - ->method('apply') - ->will($this->returnCallback(function ($style, $text) { - return "<$style>$text"; - })); - - $mock->expects($this->any()) - ->method('hasTheme') - ->will($this->returnValue(true)); - - return $mock; - } - /** * Helper method executing the actual tests. * From fd1d8dce621ae8e3b542257e7fbe64a3d1e0b573 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 27 Dec 2021 09:52:02 +0100 Subject: [PATCH 2/4] Tests: add dedicated tests for the `getCodeSnippet()` method These tests also test the `private` `getHighlightedLines()`, `splitToLines()` and `lineNumbers()` methods and the data sets in the data provider have been set up to ensure those methods are tested thoroughly. --- tests/GetCodeSnippetTest.php | 138 +++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 tests/GetCodeSnippetTest.php diff --git a/tests/GetCodeSnippetTest.php b/tests/GetCodeSnippetTest.php new file mode 100644 index 0000000..989a6ed --- /dev/null +++ b/tests/GetCodeSnippetTest.php @@ -0,0 +1,138 @@ + +EOL; + + /** + * Test retrieving a code snippet from a larger context. + * + * @dataProvider dataGetCodeSnippet + * + * @param string $expected Expected function output. + * @param int $lineNo Line number to get the code snippet for. + * @param int $linesBeforeAfter Number of lines of code context to retrieve. + */ + public function testGetCodeSnippet($expected, $lineNo, $linesBeforeAfter = 2) + { + $highlighter = new Highlighter($this->getConsoleColorMock()); + $output = $highlighter->getCodeSnippet($this->input, $lineNo, $linesBeforeAfter, $linesBeforeAfter); + + // Allow unit tests to succeed on non-*nix systems. + $output = str_replace(array("\r\n", "\r"), "\n", $output); + + $this->assertSame($expected, $output); + } + + /** + * Data provider. + * + * Includes test cases to verify that the line number padding is handled correctly + * depending on the "widest" line number. + * + * @return array + */ + public function dataGetCodeSnippet() + { + return array( + 'Snippet at start of code - line 1' => array( + 'expected' => <<<'EOL' + > 1| + 2| + 3| namespace FooBar; +EOL + , + 'lineNo' => 1, + ), + 'Snippet at start of code - line 2' => array( + 'expected' => <<<'EOL' + 1| + > 2| + 3| namespace FooBar; + 4| +EOL + , + 'lineNo' => 2, + ), + 'Snippet middle of code' => array( + 'expected' => <<<'EOL' + 7| * @param type $param Description. + 8| */ + > 9| public function bar($param) { + 10| // Do something. + 11| } +EOL + , + 'lineNo' => 9, + ), + 'Snippet at end of code - line before last' => array( + 'expected' => <<<'EOL' + 10| // Do something. + 11| } + > 12| } + 13| ?> +EOL + , + 'lineNo' => 12, + ), + 'Snippet at end of code - last line' => array( + 'expected' => <<<'EOL' + 11| } + 12| } + > 13| ?> +EOL + , + 'lineNo' => 13, + ), + 'Snippet middle of code, 1 line context' => array( + 'expected' => <<<'EOL' + 8| */ + > 9| public function bar($param) { + 10| // Do something. +EOL + , + 'lineNo' => 9, + 'linesBeforeAfter' => 1, + ), + 'Snippet middle of code, 3 line context' => array( + 'expected' => <<<'EOL' + 6| /** + 7| * @param type $param Description. + 8| */ + > 9| public function bar($param) { + 10| // Do something. + 11| } + 12| } +EOL + , + 'lineNo' => 9, + 'linesBeforeAfter' => 3, + ), + ); + } +} From 4dc2d151b3aaf15f1a7a9e0d92de4475c347557a Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 27 Dec 2021 11:21:55 +0100 Subject: [PATCH 3/4] Highlighter::getCodeSnippet(): bug fix - too many lines retrieved at start of file When a code snippet in the middle of code is retrieved, the target snippet length calculation `$length = $linesAfter + $linesBefore + 1;` functions correctly, displaying the target line in the middle, padded by x number of lines before and after. Given `$linesBefore` and `$linesAfter` both being set to two, this would display as: ``` before before target after after ``` Similarly, when a code snippet at the end of the code is retrieved, it will work correctly as well, the target line is displayed with x number of lines before. The number of lines _after_ is limited automatically by the length of the `$tokenLines` array. Given `$linesBefore` and `$linesAfter` both being set to two, this would display as: ``` before before target ``` However, when a code snippet at the _start_ of the code is retrieved, the number of lines retrieved was incorrect. The target line would display with `($linesBefore + $linesAfter)` lines _after_ the target line. Given `$linesBefore` and `$linesAfter` both being set to two, this currently displays as: ``` target after after after after ``` ... while it should be: ``` target after after ``` The change in this commit fixes this bug. --- src/Highlighter.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Highlighter.php b/src/Highlighter.php index f284bbb..a65a1b8 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -103,7 +103,13 @@ public function getCodeSnippet($source, $lineNumber, $linesBefore = 2, $linesAft $offset = $lineNumber - $linesBefore - 1; $offset = max($offset, 0); - $length = $linesAfter + $linesBefore + 1; + + if ($lineNumber <= $linesBefore) { + $length = $lineNumber + $linesAfter; + } else { + $length = $linesAfter + $linesBefore + 1; + } + $tokenLines = array_slice($tokenLines, $offset, $length, $preserveKeys = true); $lines = $this->colorLines($tokenLines); From 08f8b2f064c275c9713c1e82c0dfee53f3e86658 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Mon, 27 Dec 2021 12:37:31 +0100 Subject: [PATCH 4/4] Highlighter::lineNumbers(): bug fix - remove stray blank line at end of output The `lineNumbers()` functionality adds a new line marker at the end of each line, including the last line, meaning that any code snippets being passed through this function will have a stray blank line at the end of the output. Fixed now. --- src/Highlighter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Highlighter.php b/src/Highlighter.php index a65a1b8..5b6e527 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -315,6 +315,6 @@ private function lineNumbers(array $lines, $markLine = null) $snippet .= $line . PHP_EOL; } - return $snippet; + return rtrim($snippet, PHP_EOL); } }