diff --git a/src/Highlighter.php b/src/Highlighter.php index f284bbb..5b6e527 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); @@ -309,6 +315,6 @@ private function lineNumbers(array $lines, $markLine = null) $snippet .= $line . PHP_EOL; } - return $snippet; + return rtrim($snippet, PHP_EOL); } } 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, + ), + ); + } +} 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. *