Skip to content

Commit

Permalink
Add PHPStan extension for dynamic properties on Dictionary and Parame…
Browse files Browse the repository at this point in the history
…ters
  • Loading branch information
gapple committed Feb 14, 2024
1 parent 3925c08 commit 5b308a4
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 4 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"autoload": {
"psr-4": {
"gapple\\StructuredFields\\": "src/",
"gapple\\StructuredFields\\PHPStan\\": "phpstan-extension/src/",
"gapple\\Tests\\StructuredFields\\": "tests/"
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace gapple\StructuredFields\PHPStan;

use gapple\StructuredFields\Dictionary;
use gapple\StructuredFields\Parameters;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertiesClassReflectionExtension;
use PHPStan\Reflection\PropertyReflection;

class DynamicPropertiesClassReflectionExtension implements PropertiesClassReflectionExtension
{
public function hasProperty(ClassReflection $classReflection, string $propertyName): bool
{
return (
$classReflection->is(Dictionary::class)
|| $classReflection->is(Parameters::class)
)
&& preg_match('/^[a-z*][a-z0-9.*_-]*$/', $propertyName);
}

/**
* {@inheritdoc}
*/
public function getProperty(ClassReflection $classReflection, string $propertyName): PropertyReflection
{
return new DynamicPropertyReflection($classReflection);
}
}
87 changes: 87 additions & 0 deletions phpstan-extension/src/DynamicPropertyReflection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?php

namespace gapple\StructuredFields\PHPStan;

use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\PropertyReflection;
use PHPStan\TrinaryLogic;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;

class DynamicPropertyReflection implements PropertyReflection
{
/**
* @var ClassReflection
*/
private $classReflection;

public function __construct(ClassReflection $classReflection)
{
$this->classReflection = $classReflection;
}

public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
{
return $this->classReflection;
}

public function isStatic(): bool
{
return false;
}

public function isPrivate(): bool
{
return false;
}

public function isPublic(): bool
{
return true;
}

public function getDocComment(): ?string
{
return null;
}

public function getReadableType(): Type
{
return new MixedType();
}

public function getWritableType(): Type
{
return new MixedType();
}

public function canChangeTypeAfterAssignment(): bool
{
return true;
}

public function isReadable(): bool
{
return true;
}

public function isWritable(): bool
{
return true;
}

public function isDeprecated(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getDeprecatedDescription(): ?string
{
return null;
}

public function isInternal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}
}
9 changes: 5 additions & 4 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ parameters:
- src
- tests

universalObjectCratesClasses:
- gapple\StructuredFields\Dictionary
- gapple\StructuredFields\Parameters

featureToggles:
readOnlyByPhpDoc: true

ignoreErrors:
-
message: '#Unreachable statement - code above always terminates.#'
path: src/TupleTrait.php

services:
- class: gapple\StructuredFields\PHPStan\DynamicPropertiesClassReflectionExtension
tags:
- phpstan.broker.propertiesClassReflectionExtension

0 comments on commit 5b308a4

Please sign in to comment.