From bf84ba8e9d486419ec825875014d4773a03f9b14 Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Tue, 12 May 2026 22:49:05 +0200 Subject: [PATCH 1/2] fix: detect PHPUnit #[Test] attribute with fully-qualified name Extends the phpunit-test runnable query to also match methods annotated with a fully-qualified attribute such as: #[\PHPUnit\Framework\Attributes\Test] Previously only the short form `#[Test]` was matched, because the query only handled `(attribute (name))`. For a FQDN attribute the tree-sitter node is a `qualified_name` whose direct `name` child is the class name ("Test"); the namespace segments live inside the nested `prefix` field and are not matched. The fix adds an alternative branch `(qualified_name (name) @_attribute)` alongside the existing `(name) @_attribute` inside the attribute match, so both forms produce the gutter play button. --- languages/php/runnables.scm | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/languages/php/runnables.scm b/languages/php/runnables.scm index 183cf88..170c6c2 100644 --- a/languages/php/runnables.scm +++ b/languages/php/runnables.scm @@ -49,7 +49,7 @@ ; Class that follow the naming convention of PHPUnit test classes ; and that doesn't have the abstract modifier -; and have a method that has the #[Test] attribute +; and have a method that has the #[Test] attribute (short or fully-qualified form) ; and the method is public ( (class_declaration @@ -62,7 +62,12 @@ (method_declaration (attribute_list (attribute_group - (attribute (name) @_attribute) + (attribute + [ + (name) @_attribute + (qualified_name (name) @_attribute) + ] + ) ) ) (#eq? @_attribute "Test") From 12669d087ba5c34568cddfcf8f0f19372ab3714f Mon Sep 17 00:00:00 2001 From: Zois Pagoulatos Date: Mon, 6 Jul 2026 21:31:37 +0300 Subject: [PATCH 2/2] fix: scope PHPUnit qualified #[Test] attribute match to full FQN Matching only the last segment of the qualified name against "Test" would false-positive on any framework's Test-named attribute (e.g. #[\Testo\Test] or #[\App\Test]). Split the qualified-name case into its own pattern that matches the whole PHPUnit\Framework\Attributes\Test path instead. Suggested by @roxblnfk in review of #121. --- languages/php/runnables.scm | 40 ++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/languages/php/runnables.scm b/languages/php/runnables.scm index 170c6c2..472dd73 100644 --- a/languages/php/runnables.scm +++ b/languages/php/runnables.scm @@ -49,7 +49,7 @@ ; Class that follow the naming convention of PHPUnit test classes ; and that doesn't have the abstract modifier -; and have a method that has the #[Test] attribute (short or fully-qualified form) +; and have a method that has the #[Test] attribute (short imported form) ; and the method is public ( (class_declaration @@ -62,12 +62,7 @@ (method_declaration (attribute_list (attribute_group - (attribute - [ - (name) @_attribute - (qualified_name (name) @_attribute) - ] - ) + (attribute (name) @_attribute) ) ) (#eq? @_attribute "Test") @@ -81,6 +76,37 @@ (#set! tag phpunit-test) ) +; Class that follow the naming convention of PHPUnit test classes +; and that doesn't have the abstract modifier +; and have a method that has the #[Test] attribute (relative- or +; fully-qualified form), matched against the whole PHPUnit\Framework\Attributes\Test +; path so it doesn't false-positive on other frameworks' `Test`-named attributes +; and the method is public +( + (class_declaration + (_)* @_modifier + (#not-any-eq? @_modifier "abstract") + . + name: (_) @_name + (#match? @_name ".*Test$") + body: (declaration_list + (method_declaration + (attribute_list + (attribute_group + (attribute (qualified_name) @_attribute) + ) + ) + (#match? @_attribute "^\\\\?PHPUnit\\\\Framework\\\\Attributes\\\\Test$") + (visibility_modifier)? @_visibility + (#eq? @_visibility "public") + name: (_) @run + (#not-match? @run "^test.*") + ) + ) + ) @_phpunit-test + (#set! tag phpunit-test) +) + ; Class that follow the naming convention of PHPUnit test classes ; and that doesn't have the abstract modifier (