Skip to content

Commit

Permalink
feat: handle type importation from interface
Browse files Browse the repository at this point in the history
Allows usage of `@phpstan-import-type` and `@psalm-import-type` from
interfaces:

```php
/**
 * @phpstan-type SomeAlias = array{foo: string, bar: int}
 */
interface InterfaceWithPhpStanLocalAlias { }

/**
 * @phpstan-import-type SomeAlias from InterfaceWithPhpStanLocalAlias
 */
final class SomeClass
{
    /** @var SomeAlias */
    public $value;
}

(new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(SomeClass::class, [
        'foo' => 'bar',
        'bar' => 42,
    ]);
```
  • Loading branch information
romm committed Mar 27, 2024
1 parent 5020d62 commit 3af22d1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 5 deletions.
Expand Up @@ -23,6 +23,7 @@
use CuyZ\Valinor\Definition\Repository\ClassDefinitionRepository;
use CuyZ\Valinor\Type\ClassType;
use CuyZ\Valinor\Type\GenericType;
use CuyZ\Valinor\Type\ObjectType;
use CuyZ\Valinor\Type\Parser\Exception\InvalidType;
use CuyZ\Valinor\Type\Parser\Factory\Specifications\AliasSpecification;
use CuyZ\Valinor\Type\Parser\Factory\Specifications\ClassContextSpecification;
Expand Down Expand Up @@ -183,7 +184,7 @@ private function typeResolver(ClassType $type, ReflectionClass $target): Reflect
/**
* @return array<string, Type>
*/
private function localTypeAliases(ClassType $type): array
private function localTypeAliases(ObjectType $type): array
{
$reflection = Reflection::class($type->className());
$rawTypes = DocParser::localTypeAliases($reflection);
Expand Down Expand Up @@ -224,7 +225,7 @@ private function importedTypeAliases(ClassType $type): array
throw new InvalidTypeAliasImportClass($type, $class);
}

if (! $classType instanceof ClassType) {
if (! $classType instanceof ObjectType) {
throw new InvalidTypeAliasImportClassType($type, $classType);
}

Expand All @@ -242,7 +243,7 @@ private function importedTypeAliases(ClassType $type): array
return $importedTypes;
}

private function typeParser(ClassType $type): TypeParser
private function typeParser(ObjectType $type): TypeParser
{
$specs = [
new ClassContextSpecification($type->className()),
Expand Down
4 changes: 2 additions & 2 deletions src/Type/Types/UnresolvableType.php
Expand Up @@ -4,7 +4,7 @@

namespace CuyZ\Valinor\Type\Types;

use CuyZ\Valinor\Type\ClassType;
use CuyZ\Valinor\Type\ObjectType;
use CuyZ\Valinor\Type\Parser\Exception\InvalidType;
use CuyZ\Valinor\Type\Type;
use CuyZ\Valinor\Utility\Reflection\Reflection;
Expand Down Expand Up @@ -81,7 +81,7 @@ public static function forDocBlockTypeNotMatchingNative(ReflectionProperty|Refle
return new self($typeFromDocBlock->toString(), $message);
}

public static function forLocalAlias(string $raw, string $name, ClassType $type, InvalidType $exception): self
public static function forLocalAlias(string $raw, string $name, ObjectType $type, InvalidType $exception): self
{
return new self(
$raw,
Expand Down
20 changes: 20 additions & 0 deletions tests/Integration/Mapping/Object/LocalTypeAliasMappingTest.php
Expand Up @@ -51,10 +51,12 @@ public function test_type_aliases_are_imported_correctly(): void
->map($class, [
'firstImportedType' => 42,
'secondImportedType' => 1337,
'thirdImportedType' => 404,
]);

self::assertSame(42, $result->firstImportedType);
self::assertSame(1337, $result->secondImportedType);
self::assertSame(404, $result->thirdImportedType);
} catch (MappingError $error) {
$this->mappingFail($error);
}
Expand Down Expand Up @@ -112,12 +114,18 @@ class AnotherPhpStanLocalAlias
public int $aliasWithEqualsSign;
}

/**
* @phpstan-type AliasOfInteger = int
*/
interface InterfaceWithPhpStanLocalAlias {}

/**
* Comment:
* Some comment before import
*
* @phpstan-import-type AliasWithEqualsSign from PhpStanLocalAliases
* @phpstan-import-type AliasWithoutEqualsSign from AnotherPhpStanLocalAlias
* @phpstan-import-type AliasOfInteger from InterfaceWithPhpStanLocalAlias
*/
class PhpStanAliasImport
{
Expand All @@ -126,6 +134,9 @@ class PhpStanAliasImport

/** @var AliasWithoutEqualsSign */
public int $secondImportedType;

/** @var AliasOfInteger */
public int $thirdImportedType;
}

/**
Expand Down Expand Up @@ -178,12 +189,18 @@ class AnotherPsalmLocalAliases
public int $aliasWithEqualsSign;
}

/**
* @phpstan-type AliasOfInteger = int
*/
interface InterfaceWithPsalmLocalAlias {}

/**
* Comment:
* Some comment before import
*
* @psalm-import-type AliasWithEqualsSign from PsalmLocalAliases
* @psalm-import-type AliasWithoutEqualsSign from AnotherPsalmLocalAliases
* @psalm-import-type AliasOfInteger from InterfaceWithPsalmLocalAlias
*/
class PsalmAliasImport
{
Expand All @@ -192,4 +209,7 @@ class PsalmAliasImport

/** @var AliasWithoutEqualsSign */
public int $secondImportedType;

/** @var AliasOfInteger */
public int $thirdImportedType;
}

0 comments on commit 3af22d1

Please sign in to comment.