Repository: phpactor/phpactor (php)

Issue:
Generate @param refactoring not triggered for `iterable`
![image](https://user-images.githubusercontent.com/530801/218270747-b07486ea-4048-42fa-9477-53d9fcf8244f.png)


Pull request:
Generate @param for `iterable` type
Closes #2084

Patch:
diff --git a/doc/lsp/vim.rst b/doc/lsp/vim.rst
index aba6aabd..637e272e 100644
--- a/doc/lsp/vim.rst
+++ b/doc/lsp/vim.rst
@@ -22,7 +22,7 @@ Client Guides
 
             Plug 'neovim/nvim-lspconfig'
 
-        Then enable it in your ``.vimrc.`` (note that `on_attach` is a
+        Then enable it in your ``.vimrc``. (note that `on_attach` is a
         `callback
         <https://github.com/neovim/nvim-lspconfig#suggested-configuration>`_
         which can be used for key bindings):
diff --git a/lib/WorseReflection/Bridge/TolerantParser/Diagnostics/DocblockMissingReturnTypeProvider.php b/lib/WorseReflection/Bridge/TolerantParser/Diagnostics/DocblockMissingReturnTypeProvider.php
index bb8d1b1e..25dc672e 100644
--- a/lib/WorseReflection/Bridge/TolerantParser/Diagnostics/DocblockMissingReturnTypeProvider.php
+++ b/lib/WorseReflection/Bridge/TolerantParser/Diagnostics/DocblockMissingReturnTypeProvider.php
@@ -48,8 +48,7 @@ class DocblockMissingReturnTypeProvider implements DiagnosticProvider
             return;
         }
 
-        $docblock = $method->docblock();
-        $docblockType = $docblock->returnType();
+        $docblockType = $method->docblock()->returnType();
         $actualReturnType = $frame->returnType()->generalize();
         $claimedReturnType = $method->inferredType();
         $phpReturnType = $method->type();
@@ -74,12 +73,16 @@ class DocblockMissingReturnTypeProvider implements DiagnosticProvider
             return;
         }
 
-        if (
-            $claimedReturnType->isDefined() && !$claimedReturnType->isClass() && !$claimedReturnType->isArray() && !$claimedReturnType->isClosure()
+        if ($claimedReturnType->isDefined()
+            && !$claimedReturnType->isClass()
+            && !$claimedReturnType->isArray()
+            && !$claimedReturnType->isClosure()
+            && !$claimedReturnType->isIterable()
         ) {
             return;
         }
 
+
         if ($actualReturnType->isClosure()) {
             yield new DocblockMissingReturnTypeDiagnostic(
                 $method->nameRange(),
@@ -100,7 +103,7 @@ class DocblockMissingReturnTypeProvider implements DiagnosticProvider
             return;
         }
 
-        if ($claimedReturnType->isArray() && $actualReturnType->isMixed()) {
+        if ($actualReturnType->isMixed() && ($claimedReturnType->isArray() || $claimedReturnType->isIterable())) {
             return;
         }
 
diff --git a/lib/WorseReflection/Core/Reflector/CoreReflector.php b/lib/WorseReflection/Core/Reflector/CoreReflector.php
index d282a0e5..01ab2acc 100644
--- a/lib/WorseReflection/Core/Reflector/CoreReflector.php
+++ b/lib/WorseReflection/Core/Reflector/CoreReflector.php
@@ -242,7 +242,7 @@ class CoreReflector implements ClassReflector, SourceCodeReflector, FunctionRefl
         return $this->sourceLocator->locate(Name::fromUnknown($name));
     }
 
-    public function diagnostics($sourceCode): Promise
+    public function diagnostics(TextDocument $sourceCode): Promise
     {
         return $this->sourceReflector->diagnostics($sourceCode);
     }
diff --git a/lib/WorseReflection/Core/Type.php b/lib/WorseReflection/Core/Type.php
index 3a621d93..e4626202 100644
--- a/lib/WorseReflection/Core/Type.php
+++ b/lib/WorseReflection/Core/Type.php
@@ -16,6 +16,7 @@ use Phpactor\WorseReflection\Core\Type\MissingType;
 use Phpactor\WorseReflection\Core\Type\MixedType;
 use Phpactor\WorseReflection\Core\Type\NullableType;
 use Phpactor\WorseReflection\Core\Type\PrimitiveType;
+use Phpactor\WorseReflection\Core\Type\PseudoIterableType;
 use Phpactor\WorseReflection\Core\Type\UnionType;
 use Phpactor\WorseReflection\Core\Type\VoidType;
 
@@ -93,6 +94,11 @@ abstract class Type
         return $this instanceof ArrayType;
     }
 
+    public function isIterable(): bool
+    {
+        return $this instanceof PseudoIterableType;
+    }
+
     public function isNullable(): bool
     {
         return false;


Test patch:
diff --git a/lib/CodeTransform/Tests/Adapter/WorseReflection/Transformer/UpdateDocblockReturnTransformerTest.php b/lib/CodeTransform/Tests/Adapter/WorseReflection/Transformer/UpdateDocblockReturnTransformerTest.php
index da31548f..39ef2009 100644
--- a/lib/CodeTransform/Tests/Adapter/WorseReflection/Transformer/UpdateDocblockReturnTransformerTest.php
+++ b/lib/CodeTransform/Tests/Adapter/WorseReflection/Transformer/UpdateDocblockReturnTransformerTest.php
@@ -383,6 +383,49 @@ class UpdateDocblockReturnTransformerTest extends WorseTestCase
                 EOT
         ];
 
+        yield 'add docblock for iterables' => [
+            <<<'EOT'
+                <?php
+
+                class IFoo {
+                    public function bar(): iterable
+                    {
+                        return $this->baz();
+                    }
+
+                    /**
+                    * @return iterable<int>
+                    */
+                    public function baz(): iterable
+                    {
+                        yield 22;
+                    }
+                }
+                EOT
+            ,
+            <<<'EOT'
+                <?php
+
+                class IFoo {
+                    /**
+                     * @return iterable<array-key,int>
+                     */
+                    public function bar(): iterable
+                    {
+                        return $this->baz();
+                    }
+
+                    /**
+                    * @return iterable<int>
+                    */
+                    public function baz(): iterable
+                    {
+                        yield 22;
+                    }
+                }
+                EOT
+        ];
+
         yield 'does not add non-array return type when array return is given' => [
             <<<'EOT'
                 <?php