From 8f68e0c9e3fd29f392373dc87b3b147776957fa7 Mon Sep 17 00:00:00 2001 From: Kaloyan Raev Date: Mon, 10 Oct 2016 18:00:38 +0300 Subject: [PATCH] Fixes #59: Handle correctly negative endLine in PHP Parser errors --- src/PhpDocument.php | 9 +-- tests/Server/TextDocument/ParseErrorsTest.php | 56 +++++++++++++------ 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/src/PhpDocument.php b/src/PhpDocument.php index 963e0c9..ef11328 100644 --- a/src/PhpDocument.php +++ b/src/PhpDocument.php @@ -176,10 +176,11 @@ class PhpDocument $diagnostics = []; foreach ($errors as $error) { $diagnostic = new Diagnostic(); - $diagnostic->range = new Range( - new Position($error->getStartLine() - 1, $error->hasColumnInfo() ? $error->getStartColumn($this->content) - 1 : 0), - new Position($error->getEndLine() - 1, $error->hasColumnInfo() ? $error->getEndColumn($this->content) : 0) - ); + $startLine = $error->getStartLine() === -1 ? 0 : $error->getStartLine() - 1; + $startColumn = $error->hasColumnInfo() ? $error->getStartColumn($this->content) - 1 : 0; + $endLine = $error->getEndLine() === -1 ? $startLine : $error->getEndLine() - 1; + $endColumn = $error->hasColumnInfo() ? $error->getEndColumn($this->content) : 0; + $diagnostic->range = new Range(new Position($startLine, $startColumn), new Position($endLine, $endColumn)); $diagnostic->severity = DiagnosticSeverity::ERROR; $diagnostic->source = 'php'; // Do not include "on line ..." in the error message diff --git a/tests/Server/TextDocument/ParseErrorsTest.php b/tests/Server/TextDocument/ParseErrorsTest.php index 24d155c..53dcacc 100644 --- a/tests/Server/TextDocument/ParseErrorsTest.php +++ b/tests/Server/TextDocument/ParseErrorsTest.php @@ -14,19 +14,13 @@ class ParseErrorsTest extends TestCase * @var Server\TextDocument */ private $textDocument; + + private $args; public function setUp() { $client = new LanguageClient(new MockProtocolStream()); - $project = new Project($client); - $this->textDocument = new Server\TextDocument($project, $client); - } - - public function testParseErrorsArePublishedAsDiagnostics() - { - $args = null; - $client = new LanguageClient(new MockProtocolStream()); - $client->textDocument = new class($args) extends Client\TextDocument { + $client->textDocument = new class($this->args) extends Client\TextDocument { private $args; public function __construct(&$args) { @@ -38,18 +32,22 @@ class ParseErrorsTest extends TestCase $this->args = func_get_args(); } }; - $project = new Project($client); - - $textDocument = new Server\TextDocument($project, $client); - - // Trigger parsing of source + $this->textDocument = new Server\TextDocument($project, $client); + } + + private function openFile($file) { $textDocumentItem = new TextDocumentItem(); $textDocumentItem->uri = 'whatever'; $textDocumentItem->languageId = 'php'; $textDocumentItem->version = 1; - $textDocumentItem->text = file_get_contents(__DIR__ . '/../../../fixtures/invalid_file.php'); - $textDocument->didOpen($textDocumentItem); + $textDocumentItem->text = file_get_contents($file); + $this->textDocument->didOpen($textDocumentItem); + } + + public function testParseErrorsArePublishedAsDiagnostics() + { + $this->openFile(__DIR__ . '/../../../fixtures/invalid_file.php'); $this->assertEquals([ 'whatever', [[ @@ -68,6 +66,30 @@ class ParseErrorsTest extends TestCase 'source' => 'php', 'message' => "Syntax error, unexpected T_CLASS, expecting T_STRING" ]] - ], json_decode(json_encode($args), true)); + ], json_decode(json_encode($this->args), true)); + } + + public function testParseErrorsWithOnlyStartLine() + { + $this->openFile(__DIR__ . '/../../../fixtures/namespace_not_first.php'); + $this->assertEquals([ + 'whatever', + [[ + 'range' => [ + 'start' => [ + 'line' => 4, + 'character' => 0 + ], + 'end' => [ + 'line' => 4, + 'character' => 0 + ] + ], + 'severity' => DiagnosticSeverity::ERROR, + 'code' => null, + 'source' => 'php', + 'message' => "Namespace declaration statement has to be the very first statement in the script" + ]] + ], json_decode(json_encode($this->args), true)); } }