Repository: phpactor/phpactor (php)

Issue:
Fill object code action on attribute
Fill object currently does not work on attributes

Pull request description:
Fill objects for attributes
Closes #2765

Patch:
diff --git a/lib/CodeTransform/Adapter/WorseReflection/Refactor/WorseFillObject.php b/lib/CodeTransform/Adapter/WorseReflection/Refactor/WorseFillObject.php
index 73415d02..e3fadec1 100644
--- a/lib/CodeTransform/Adapter/WorseReflection/Refactor/WorseFillObject.php
+++ b/lib/CodeTransform/Adapter/WorseReflection/Refactor/WorseFillObject.php
@@ -2,6 +2,7 @@
 
 namespace Phpactor\CodeTransform\Adapter\WorseReflection\Refactor;
 
+use Microsoft\PhpParser\Node\Attribute;
 use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
 use Microsoft\PhpParser\Parser;
 use Phpactor\CodeBuilder\Domain\Builder\SourceCodeBuilder;
@@ -37,11 +38,16 @@ class WorseFillObject implements ByteOffsetRefactor
 
     public function refactor(TextDocument $document, ByteOffset $offset): TextEdits
     {
-        $node = $this->parser->parseSourceFile($document->__toString())->getDescendantNodeAtPosition($offset->toInt());
-        $node = $node->getFirstAncestor(ObjectCreationExpression::class);
-        if (!$node instanceof ObjectCreationExpression) {
+        /** @var ObjectCreationExpression|Attribute|null $node */
+        $node = $this->parser
+            ->parseSourceFile($document->__toString())
+            ->getDescendantNodeAtPosition($offset->toInt())
+            ->getFirstAncestor(ObjectCreationExpression::class, Attribute::class)
+        ;
+        if ($node === null) {
             return TextEdits::none();
         }
+
         try {
             $offset = $this->reflector->reflectNode($document, $node->getStartPosition());
         } catch (NotFound $notFound) {
@@ -104,9 +110,11 @@ class WorseFillObject implements ByteOffsetRefactor
             $closedParen = ')';
         }
 
-        $textEdits = $textEdits->add(TextEdit::create($endPosition, 0, sprintf('%s%s%s', $openParen, implode(', ', $args), $closedParen)));
-
-        return $textEdits;
+        return $textEdits->add(TextEdit::create(
+            $endPosition,
+            0,
+            sprintf('%s%s%s', $openParen, implode(', ', $args), $closedParen),
+        ));
     }
 
     private function renderEmptyValue(Type $type): string


Test patch:
diff --git a/lib/CodeTransform/Tests/Adapter/WorseReflection/Refactor/fixtures/fillObject_attributes.test b/lib/CodeTransform/Tests/Adapter/WorseReflection/Refactor/fixtures/fillObject_attributes.test
new file mode 100644
index 00000000..b057b338
--- /dev/null
+++ b/lib/CodeTransform/Tests/Adapter/WorseReflection/Refactor/fixtures/fillObject_attributes.test
@@ -0,0 +1,47 @@
+// File: source
+<?php
+
+namespace Phpactor;
+
+#[Attribute()]
+class SomeAttribute
+{
+    public function __construct(string $barfoo) {
+    }
+}
+
+#[SomeAttrib<>ute()]
+class Foo {
+}
+
+// File: expected
+<?php
+
+namespace Phpactor;
+
+#[Attribute()]
+class SomeAttribute
+{
+    public function __construct(string $barfoo) {
+    }
+}
+
+#[SomeAttribute(barfoo: '')]
+class Foo {
+}
+
+// File: nonamed
+<?php
+
+namespace Phpactor;
+
+#[Attribute()]
+class SomeAttribute
+{
+    public function __construct(string $barfoo) {
+    }
+}
+
+#[SomeAttribute('' /** $barfoo string */)]
+class Foo {
+}