Skip to content

Commit 20cf3c9

Browse files
committed
Add PsalmApi::$methods->getStorage and PsalmApi::$properties->getStorage
1 parent 12806b2 commit 20cf3c9

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

src/Toolkit/Methods.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Fp\PsalmToolkit\Toolkit;
6+
7+
use Fp\Functional\Option\Option;
8+
use Psalm\Internal\MethodIdentifier;
9+
use Psalm\Storage\ClassLikeStorage;
10+
use Psalm\Storage\MethodStorage;
11+
use Psalm\Type\Atomic\TNamedObject;
12+
13+
use function Fp\Collection\at;
14+
15+
final class Methods
16+
{
17+
/**
18+
* @return Option<MethodStorage>
19+
*/
20+
public function getStorage(string|TNamedObject|ClassLikeStorage $object, string $method): Option
21+
{
22+
$storage = !($object instanceof ClassLikeStorage)
23+
? PsalmApi::$classlikes->getStorage($object)
24+
: Option::some($object);
25+
26+
return $storage->flatMap(fn(ClassLikeStorage $s) => at($s->methods, strtolower($method))->orElse(
27+
fn() => self::getDeclaringStorage($s, strtolower($method)),
28+
));
29+
}
30+
31+
/**
32+
* @return Option<MethodStorage>
33+
*/
34+
private function getDeclaringStorage(ClassLikeStorage $storage, string $method): Option
35+
{
36+
return at($storage->declaring_method_ids, strtolower($method))->flatMap(
37+
fn(MethodIdentifier $id) => Option::try(fn() => PsalmApi::$codebase->methods->getStorage($id)),
38+
);
39+
}
40+
}

src/Toolkit/Plugin.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ public function __invoke(RegistrationInterface $registration, ?SimpleXMLElement
2424
PsalmApi::$classlikes = new Classlikes();
2525
PsalmApi::$codebase = ProjectAnalyzer::getInstance()->getCodebase();
2626
PsalmApi::$issue = new Issue();
27+
PsalmApi::$methods = new Methods();
28+
PsalmApi::$properties = new Properties();
2729

2830
$register = function(string $hook) use ($registration): void {
2931
if (class_exists($hook)) {

src/Toolkit/Properties.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Fp\PsalmToolkit\Toolkit;
6+
7+
use Fp\Functional\Option\Option;
8+
use Psalm\Storage\ClassLikeStorage;
9+
use Psalm\Storage\PropertyStorage;
10+
use Psalm\Type\Atomic\TNamedObject;
11+
12+
use function Fp\Collection\at;
13+
14+
final class Properties
15+
{
16+
/**
17+
* @return Option<PropertyStorage>
18+
*/
19+
public function getStorage(string|TNamedObject|ClassLikeStorage $object, string $property): Option
20+
{
21+
$storage = !($object instanceof ClassLikeStorage)
22+
? PsalmApi::$classlikes->getStorage($object)
23+
: Option::some($object);
24+
25+
return $storage->flatMap(fn(ClassLikeStorage $s) => at($s->properties, $property)->orElse(
26+
fn() => self::getAppearingStorage($s, $property),
27+
));
28+
}
29+
30+
/**
31+
* @return Option<PropertyStorage>
32+
*/
33+
private function getAppearingStorage(ClassLikeStorage $storage, string $property): Option
34+
{
35+
return at($storage->appearing_property_ids, $property)->flatMap(
36+
fn(string $propertyId) => Option::try(fn() => PsalmApi::$codebase->properties->getStorage($propertyId)),
37+
);
38+
}
39+
}

src/Toolkit/PsalmApi.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ final class PsalmApi
1313
public static Codebase $codebase;
1414
public static Classlikes $classlikes;
1515
public static Issue $issue;
16+
public static Methods $methods;
17+
public static Properties $properties;
1618
}

0 commit comments

Comments
 (0)