Skip to content

Commit

Permalink
Adding support for extending anonymous classes
Browse files Browse the repository at this point in the history
  • Loading branch information
mamazu committed Mar 25, 2024
1 parent f32ad1b commit 681f9c8
Show file tree
Hide file tree
Showing 6 changed files with 520 additions and 461 deletions.
11 changes: 11 additions & 0 deletions lib/CodeBuilder/Adapter/TolerantParser/TolerantUpdater.php
@@ -1,6 +1,7 @@
<?php
namespace Phpactor\CodeBuilder\Adapter\TolerantParser;

use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
use Microsoft\PhpParser\Node\SourceFileNode;
use Microsoft\PhpParser\Node\Statement\ClassDeclaration;
use Microsoft\PhpParser\Node\Statement\TraitDeclaration;
Expand All @@ -22,6 +23,9 @@
use Phpactor\CodeBuilder\Adapter\TolerantParser\Updater\InterfaceUpdater;
use Phpactor\CodeBuilder\Adapter\TolerantParser\Updater\TraitUpdater;
use Phpactor\TextDocument\TextEdits;
use Phpactor\WorseReflection\Core\Util\NodeUtil;
use function Amp\Promise\wait;
use Microsoft\PhpParser\Token;

class TolerantUpdater implements Updater
{
Expand Down Expand Up @@ -122,6 +126,13 @@ private function updateClasses(Edits $edits, SourceCode $prototype, SourceFileNo
}
}

foreach($node->getDescendantNodes() as $classNode) {
if ($classNode instanceof ObjectCreationExpression && $classNode->classTypeDesignator instanceof Token) {
$name = NodeUtil::nameFromTokenOrNode($classNode, $classNode);
$classNodes[$name] = $classNode;
}
}

foreach ($prototype->classes()->in(array_keys($classNodes)) as $classPrototype) {
$this->classUpdater->updateClass($edits, $classPrototype, $classNodes[$classPrototype->name()]);
}
Expand Down
Expand Up @@ -6,6 +6,7 @@
use Microsoft\PhpParser\Node;
use Microsoft\PhpParser\Node\DelimitedList\ParameterDeclarationList;
use Microsoft\PhpParser\Node\EnumCaseDeclaration;
use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
use Microsoft\PhpParser\Node\MethodDeclaration;
use Microsoft\PhpParser\Node\Parameter;
use Microsoft\PhpParser\Node\PropertyDeclaration;
Expand All @@ -30,8 +31,11 @@ public function __construct(private Renderer $renderer)
{
}

public function updateMethods(Edits $edits, ClassLikePrototype $classPrototype, ClassLike $classNode): void
{
public function updateMethods(
Edits $edits,
ClassLikePrototype $classPrototype,
ClassLike|ObjectCreationExpression $classNode,
): void {
if (count($classPrototype->methods()) === 0) {
return;
}
Expand Down Expand Up @@ -137,7 +141,7 @@ public function updateMethods(Edits $edits, ClassLikePrototype $classPrototype,
/**
* @return array<Node>
*/
abstract protected function memberDeclarations(ClassLike $classNode): array;
abstract protected function memberDeclarations(ClassLike|ObjectCreationExpression $classNode): array;

/** @return TMembersNodeType */
abstract protected function memberDeclarationsNode(ClassLike $classNode);
Expand Down
Expand Up @@ -5,6 +5,7 @@
use Microsoft\PhpParser\Node\ClassMembersNode;
use Microsoft\PhpParser\ClassLike;
use Microsoft\PhpParser\Node\EnumMembers;
use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
use Microsoft\PhpParser\Node\Statement\ClassDeclaration;
use Microsoft\PhpParser\Node\Statement\EnumDeclaration;
use Microsoft\PhpParser\Node\Statement\TraitDeclaration;
Expand All @@ -22,9 +23,9 @@ class ClassMethodUpdater extends AbstractMethodUpdater
/**
* @return ClassMembersNode|TraitMembers|EnumMembers
*/
public function memberDeclarationsNode(ClassLike $classNode)
public function memberDeclarationsNode(ClassLike|ObjectCreationExpression $classNode): ClassMembersNode|TraitMembers|EnumMembers
{
if ($classNode instanceof ClassDeclaration) {
if ($classNode instanceof ClassDeclaration || $classNode instanceof ObjectCreationExpression) {
return $classNode->classMembers;

Check failure on line 29 in lib/CodeBuilder/Adapter/TolerantParser/Updater/ClassMethodUpdater.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Method Phpactor\CodeBuilder\Adapter\TolerantParser\Updater\ClassMethodUpdater::memberDeclarationsNode() should return Microsoft\PhpParser\Node\ClassMembersNode|Microsoft\PhpParser\Node\EnumMembers|Microsoft\PhpParser\Node\TraitMembers but returns Microsoft\PhpParser\Node\ClassMembersNode|null.
}
if ($classNode instanceof TraitDeclaration) {
Expand All @@ -48,9 +49,9 @@ public function renderMethod(Renderer $renderer, Method $method): string
}

/** @return array<Node> */
protected function memberDeclarations(ClassLike $classNode): array
protected function memberDeclarations(ClassLike|ObjectCreationExpression $classNode): array
{
if ($classNode instanceof ClassDeclaration) {
if ($classNode instanceof ClassDeclaration || $classNode instanceof ObjectCreationExpression) {
return $classNode->classMembers->classMemberDeclarations;

Check failure on line 55 in lib/CodeBuilder/Adapter/TolerantParser/Updater/ClassMethodUpdater.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Cannot access property $classMemberDeclarations on Microsoft\PhpParser\Node\ClassMembersNode|null.
}
if ($classNode instanceof TraitDeclaration) {
Expand Down
26 changes: 20 additions & 6 deletions lib/CodeBuilder/Adapter/TolerantParser/Updater/ClassUpdater.php
Expand Up @@ -4,6 +4,7 @@

use Microsoft\PhpParser\Node;
use Microsoft\PhpParser\Node\ClassConstDeclaration;
use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
use Microsoft\PhpParser\Node\MethodDeclaration;
use Microsoft\PhpParser\Node\PropertyDeclaration;
use Microsoft\PhpParser\Node\Statement\ClassDeclaration;
Expand All @@ -15,17 +16,22 @@

class ClassUpdater extends ClassLikeUpdater
{
public function updateClass(Edits $edits, ClassPrototype $classPrototype, ClassDeclaration $classNode): void
{
public function updateClass(
Edits $edits,
ClassPrototype $classPrototype,
ClassDeclaration|ObjectCreationExpression $classNode,
): void {
if (false === $classPrototype->applyUpdate()) {
return;
}

$this->updateDocblock($edits, $classPrototype, $classNode);

Check failure on line 28 in lib/CodeBuilder/Adapter/TolerantParser/Updater/ClassUpdater.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Parameter #3 $classLikeDeclaration of method Phpactor\CodeBuilder\Adapter\TolerantParser\Updater\ClassLikeUpdater::updateDocblock() expects Microsoft\PhpParser\Node\Statement\ClassDeclaration|Microsoft\PhpParser\Node\Statement\EnumDeclaration|Microsoft\PhpParser\Node\Statement\InterfaceDeclaration|Microsoft\PhpParser\Node\Statement\TraitDeclaration, Microsoft\PhpParser\Node\Expression\ObjectCreationExpression|Microsoft\PhpParser\Node\Statement\ClassDeclaration given.
$this->updateExtends($edits, $classPrototype, $classNode);
$this->updateImplements($edits, $classPrototype, $classNode);
$this->updateConstants($edits, $classPrototype, $classNode->classMembers);
$this->updateProperties($edits, $classPrototype, $classNode->classMembers);
if ($classNode->classMembers instanceof ClassMembersNode) {

Check failure on line 31 in lib/CodeBuilder/Adapter/TolerantParser/Updater/ClassUpdater.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Class Phpactor\CodeBuilder\Adapter\TolerantParser\Updater\ClassMembersNode not found.
$this->updateConstants($edits, $classPrototype, $classNode->classMembers);
$this->updateProperties($edits, $classPrototype, $classNode->classMembers);
}

$this->methodUpdater->updateMethods($edits, $classPrototype, $classNode);
}
Expand Down Expand Up @@ -79,7 +85,11 @@ protected function memberDeclarations(Node $node): array
return $node->classMemberDeclarations;
}

private function updateExtends(Edits $edits, ClassPrototype $classPrototype, ClassDeclaration $classNode): void
private function updateExtends(
Edits $edits,
ClassPrototype $classPrototype,
ClassDeclaration|ObjectCreationExpression $classNode,
): void
{
if (ExtendsClass::none() == $classPrototype->extendsClass()) {
return;
Expand All @@ -94,7 +104,11 @@ private function updateExtends(Edits $edits, ClassPrototype $classPrototype, Cla
$edits->replace($classNode->classBaseClause, ' extends ' . (string) $classPrototype->extendsClass());
}

private function updateImplements(Edits $edits, ClassPrototype $classPrototype, ClassDeclaration $classNode): void
private function updateImplements(
Edits $edits,
ClassPrototype $classPrototype,
ClassDeclaration|ObjectCreationExpression $classNode,
): void
{
if (ImplementsInterfaces::empty() == $classPrototype->implementsInterfaces()) {
return;
Expand Down
Expand Up @@ -3,6 +3,7 @@
namespace Phpactor\CodeBuilder\Adapter\TolerantParser\Updater;

use Microsoft\PhpParser\ClassLike;
use Microsoft\PhpParser\Node\Expression\ObjectCreationExpression;
use Microsoft\PhpParser\Node\InterfaceMembers;
use Phpactor\CodeBuilder\Domain\Renderer;
use Phpactor\CodeBuilder\Domain\Prototype\Method;
Expand All @@ -27,7 +28,7 @@ public function renderMethod(Renderer $renderer, Method $method): string
}

/** @return array<Node> */
protected function memberDeclarations(ClassLike $classNode): array
protected function memberDeclarations(ClassLike|ObjectCreationExpression $classNode): array
{
return $classNode->interfaceMembers->interfaceMemberDeclarations;

Check failure on line 33 in lib/CodeBuilder/Adapter/TolerantParser/Updater/InterfaceMethodUpdater.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.1)

Access to an undefined property Microsoft\PhpParser\ClassLike|Microsoft\PhpParser\Node\Expression\ObjectCreationExpression::$interfaceMembers.
}
Expand Down

0 comments on commit 681f9c8

Please sign in to comment.