From 032b10214679b020de7a41dbeb18c3ffdc3c169d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sun, 11 Sep 2022 22:05:47 +0200 Subject: [PATCH] Remove deprecated Error constructor And use this chance to provide accurate position information for namespace errors. --- lib/PhpParser/Error.php | 13 ++++--------- lib/PhpParser/ParserAbstract.php | 19 +++++++++++++++++-- test/PhpParser/ErrorTest.php | 2 +- test/code/parser/stmt/namespace/mix.test | 6 +++--- .../stmt/namespace/outsideStmtInvalid.test | 2 +- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/lib/PhpParser/Error.php b/lib/PhpParser/Error.php index 443d615288..e033caee44 100644 --- a/lib/PhpParser/Error.php +++ b/lib/PhpParser/Error.php @@ -11,17 +11,12 @@ class Error extends \RuntimeException { /** * Creates an Exception signifying a parse error. * - * @param string $message Error message - * @param array|int $attributes Attributes of node/token where error occurred - * (or start line of error -- deprecated) + * @param string $message Error message + * @param array $attributes Attributes of node/token where error occurred */ - public function __construct(string $message, $attributes = []) { + public function __construct(string $message, array $attributes = []) { $this->rawMessage = $message; - if (is_array($attributes)) { - $this->attributes = $attributes; - } else { - $this->attributes = ['startLine' => $attributes]; - } + $this->attributes = $attributes; $this->updateMessage(); } diff --git a/lib/PhpParser/ParserAbstract.php b/lib/PhpParser/ParserAbstract.php index e7a383a399..bc4c432cc5 100644 --- a/lib/PhpParser/ParserAbstract.php +++ b/lib/PhpParser/ParserAbstract.php @@ -579,6 +579,21 @@ private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt): void { } } + private function getNamespaceErrorAttributes(Namespace_ $node): array { + $attrs = $node->getAttributes(); + // Adjust end attributes to only cover the "namespace" keyword, not the whole namespace. + if (isset($attrs['startLine'])) { + $attrs['endLine'] = $attrs['startLine']; + } + if (isset($attrs['startTokenPos'])) { + $attrs['endTokenPos'] = $attrs['startTokenPos']; + } + if (isset($attrs['startFilePos'])) { + $attrs['endFilePos'] = $attrs['startFilePos'] + \strlen('namespace') - 1; + } + return $attrs; + } + /** * Determine namespacing style (semicolon or brace) * @@ -597,13 +612,13 @@ private function getNamespacingStyle(array $stmts): ?string { if ($hasNotAllowedStmts) { $this->emitError(new Error( 'Namespace declaration statement has to be the very first statement in the script', - $stmt->getLine() // Avoid marking the entire namespace as an error + $this->getNamespaceErrorAttributes($stmt) )); } } elseif ($style !== $currentStyle) { $this->emitError(new Error( 'Cannot mix bracketed namespace declarations with unbracketed namespace declarations', - $stmt->getLine() // Avoid marking the entire namespace as an error + $this->getNamespaceErrorAttributes($stmt) )); // Treat like semicolon style for namespace normalization return 'semicolon'; diff --git a/test/PhpParser/ErrorTest.php b/test/PhpParser/ErrorTest.php index 03e825441e..f378ab234d 100644 --- a/test/PhpParser/ErrorTest.php +++ b/test/PhpParser/ErrorTest.php @@ -73,7 +73,7 @@ public function provideTestColumnInfo() { } public function testNoColumnInfo() { - $error = new Error('Some error', 3); + $error = new Error('Some error', ['startLine' => 3]); $this->assertFalse($error->hasColumnInfo()); try { diff --git a/test/code/parser/stmt/namespace/mix.test b/test/code/parser/stmt/namespace/mix.test index f11b8a1e1f..4c557d4538 100644 --- a/test/code/parser/stmt/namespace/mix.test +++ b/test/code/parser/stmt/namespace/mix.test @@ -8,7 +8,7 @@ namespace B { } echo 3; ----- -Cannot mix bracketed namespace declarations with unbracketed namespace declarations on line 4 +Cannot mix bracketed namespace declarations with unbracketed namespace declarations from 4:1 to 4:9 array( 0: Stmt_Namespace( name: Name( @@ -59,7 +59,7 @@ echo 2; namespace B; echo 3; ----- -Cannot mix bracketed namespace declarations with unbracketed namespace declarations on line 6 +Cannot mix bracketed namespace declarations with unbracketed namespace declarations from 6:1 to 6:9 array( 0: Stmt_Namespace( name: Name( @@ -100,4 +100,4 @@ array( ) ) ) -) \ No newline at end of file +) diff --git a/test/code/parser/stmt/namespace/outsideStmtInvalid.test b/test/code/parser/stmt/namespace/outsideStmtInvalid.test index 8d8c75ab47..79a9c21efe 100644 --- a/test/code/parser/stmt/namespace/outsideStmtInvalid.test +++ b/test/code/parser/stmt/namespace/outsideStmtInvalid.test @@ -5,7 +5,7 @@ echo 1; echo 2; namespace A; ----- -Namespace declaration statement has to be the very first statement in the script on line 4 +Namespace declaration statement has to be the very first statement in the script from 4:1 to 4:9 array( 0: Stmt_Echo( exprs: array(