Skip to content

Commit

Permalink
Add and run reorder rector rule
Browse files Browse the repository at this point in the history
  • Loading branch information
sixlive committed Oct 20, 2024
1 parent a38dd2a commit 619c78d
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 45 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
"rector/rector": "^1.1",
"projektgopher/whisky": "^0.7.0",
"orchestra/testbench": "^9.4",
"mockery/mockery": "^1.6"
"mockery/mockery": "^1.6",
"symplify/rule-doc-generator-contracts": "^11.2"
},
"autoload-dev": {
"psr-4": {
Expand Down
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

declare(strict_types=1);

use EchoLabs\Prism\Rectors\ReorderMethodsRector;
use Rector\CodeQuality\Rector\Class_\InlineConstructorDefaultToPropertyRector;
use Rector\Config\RectorConfig;
use Rector\Set\ValueObject\LevelSetList;
Expand All @@ -15,6 +16,7 @@
])
->withRules([
InlineConstructorDefaultToPropertyRector::class,
ReorderMethodsRector::class,
])
->withSets([
LevelSetList::UP_TO_PHP_83,
Expand Down
32 changes: 16 additions & 16 deletions src/PrismManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ public function resolve(ProviderEnum|string $name): Provider
throw new InvalidArgumentException("Provider [{$name}] is not supported.");
}

/**
* @throws RuntimeException
*/
public function extend(string $provider, Closure $callback): self
{
if (($callback = $callback->bindTo($this, $this)) instanceof \Closure) {
$this->customCreators[$provider] = $callback;

return $this;
}

throw new RuntimeException(
sprintf('Couldn\'t bind %s', $provider)
);
}

protected function resolveName(ProviderEnum|string $name): string
{
if ($name instanceof ProviderEnum) {
Expand Down Expand Up @@ -108,22 +124,6 @@ protected function callCustomCreator(string $provider, array $config): Provider
return $this->customCreators[$provider]($this->app, $config);
}

/**
* @throws RuntimeException
*/
public function extend(string $provider, Closure $callback): self
{
if (($callback = $callback->bindTo($this, $this)) instanceof \Closure) {
$this->customCreators[$provider] = $callback;

return $this;
}

throw new RuntimeException(
sprintf('Couldn\'t bind %s', $provider)
);
}

/**
* @return null|array<string, mixed>
*/
Expand Down
18 changes: 9 additions & 9 deletions src/Providers/Anthropic/Anthropic.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,6 @@ public function __construct(
public readonly string $apiVersion,
) {}

protected function client(): Client
{
return new Client(
apiKey: $this->apiKey,
apiVersion: $this->apiVersion,
options: $this->clientOptions,
);
}

#[\Override]
public function text(TextRequest $request): ProviderResponse
{
Expand Down Expand Up @@ -94,6 +85,15 @@ public function text(TextRequest $request): ProviderResponse
);
}

protected function client(): Client
{
return new Client(
apiKey: $this->apiKey,
apiVersion: $this->apiVersion,
options: $this->clientOptions,
);
}

protected function mapFinishReason(string $stopReason): FinishReason
{
return match ($stopReason) {
Expand Down
18 changes: 9 additions & 9 deletions src/Providers/Ollama/Ollama.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,6 @@ public function __construct(
public readonly ?string $apiKey,
) {}

protected function client(): Client
{
return new Client(
url: $this->url,
apiKey: $this->apiKey,
options: $this->clientOptions,
);
}

#[\Override]
public function text(TextRequest $request): ProviderResponse
{
Expand Down Expand Up @@ -85,6 +76,15 @@ public function text(TextRequest $request): ProviderResponse
);
}

protected function client(): Client
{
return new Client(
url: $this->url,
apiKey: $this->apiKey,
options: $this->clientOptions,
);
}

protected function mapFinishReason(string $stopReason): FinishReason
{
return match ($stopReason) {
Expand Down
20 changes: 10 additions & 10 deletions src/Providers/OpenAI/OpenAI.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,6 @@ public function __construct(
public readonly ?string $organization,
) {}

protected function client(): Client
{
return new Client(
apiKey: $this->apiKey,
url: $this->url,
organization: $this->organization,
options: $this->clientOptions,
);
}

#[\Override]
public function text(TextRequest $request): ProviderResponse
{
Expand Down Expand Up @@ -89,6 +79,16 @@ public function text(TextRequest $request): ProviderResponse
);
}

protected function client(): Client
{
return new Client(
apiKey: $this->apiKey,
url: $this->url,
organization: $this->organization,
options: $this->clientOptions,
);
}

protected function mapFinishReason(string $stopReason): FinishReason
{
return match ($stopReason) {
Expand Down
127 changes: 127 additions & 0 deletions src/Rectors/ReorderMethodsRector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace EchoLabs\Prism\Rectors;

use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class ReorderMethodsRector extends AbstractRector
{
#[\Override]
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
#[\Override]
public function refactor(Node $node): ?Node
{
$methods = $node->getMethods();

if (count($methods) <= 1) {
return null;
}

$reorderedMethods = $this->reorderMethods($methods);

if ($methods === $reorderedMethods) {
return null;
}

$node->stmts = array_merge(
array_filter($node->stmts, fn ($stmt): bool => ! $stmt instanceof ClassMethod),
$reorderedMethods
);

return $node;
}

#[\Override]
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition(
'Reorders class methods: magic methods first, then public, protected, and private.',
[
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
private function privateMethod()
{
}
public function publicMethod()
{
}
protected function protectedMethod()
{
}
public function __construct()
{
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
public function __construct()
{
}
public function publicMethod()
{
}
protected function protectedMethod()
{
}
private function privateMethod()
{
}
}
CODE_SAMPLE
),
]
);
}

private function reorderMethods(array $methods): array

Check failure on line 99 in src/Rectors/ReorderMethodsRector.php

View workflow job for this annotation

GitHub Actions / phpstan

Method EchoLabs\Prism\Rectors\ReorderMethodsRector::reorderMethods() has parameter $methods with no value type specified in iterable type array.

Check failure on line 99 in src/Rectors/ReorderMethodsRector.php

View workflow job for this annotation

GitHub Actions / phpstan

Method EchoLabs\Prism\Rectors\ReorderMethodsRector::reorderMethods() return type has no value type specified in iterable type array.
{
usort($methods, fn (ClassMethod $a, ClassMethod $b): int => $this->getMethodWeight($a) <=> $this->getMethodWeight($b));

return $methods;
}

private function getMethodWeight(ClassMethod $method): int
{
if ($this->isMagicMethod($method)) {
return 0;
}

if ($method->isPublic()) {
return 1;
}

if ($method->isProtected()) {
return 2;
}

return 3; // private
}

private function isMagicMethod(ClassMethod $method): bool
{
return str_starts_with($method->name->toString(), '__');
}
}

0 comments on commit 619c78d

Please sign in to comment.