Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-phpunit": "^2.0.8",
"phpstan/phpstan-phpunit": "^2.0.13",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.6",
"psr/container": "1.1.2",
Expand Down
15 changes: 10 additions & 5 deletions extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,14 @@ services:
tags: [phpstan.broker.dynamicMethodReturnTypeExtension]

-
class: PHPStan\Symfony\SymfonyContainerResultCacheMetaExtension
arguments:
tmpDir: %tmpDir%
containerXmlPath: %symfony.containerXmlPath%
class: PHPStan\Symfony\ServiceResultCacheValueExtension
tags:
- phpstan.resultCacheValueExtension
-
class: PHPStan\Symfony\ParameterResultCacheValueExtension
tags:
- phpstan.resultCacheValueExtension
-
class: PHPStan\Symfony\MessageResultCacheValueExtension
tags:
- phpstan.resultCacheMetaExtension
- phpstan.resultCacheValueExtension
6 changes: 6 additions & 0 deletions src/Rules/Symfony/ContainerInterfacePrivateServiceRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\DependencyEmitter;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Symfony\ServiceMap;
use PHPStan\Symfony\ServiceResultCacheValueExtension;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
Expand All @@ -31,6 +33,9 @@ public function getNodeType(): string
return MethodCall::class;
}

/**
* @param Scope&DependencyEmitter $scope
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->name instanceof Node\Identifier) {
Expand Down Expand Up @@ -66,6 +71,7 @@ public function processNode(Node $node, Scope $scope): array

$serviceId = $this->serviceMap::getServiceIdFromNode($node->getArgs()[0]->value, $scope);
if ($serviceId !== null) {
$scope->valueDependency(ServiceResultCacheValueExtension::class, $serviceId);
$service = $this->serviceMap->getService($serviceId);
if ($service !== null && !$service->isPublic()) {
return [
Expand Down
6 changes: 6 additions & 0 deletions src/Rules/Symfony/ContainerInterfaceUnknownServiceRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\DependencyEmitter;
use PHPStan\Analyser\Scope;
use PHPStan\Node\Printer\Printer;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Symfony\ServiceMap;
use PHPStan\Symfony\ServiceResultCacheValueExtension;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Symfony\Helper;
use function sprintf;
Expand All @@ -34,6 +36,9 @@ public function getNodeType(): string
return MethodCall::class;
}

/**
* @param Scope&DependencyEmitter $scope
*/
public function processNode(Node $node, Scope $scope): array
{
if (!$node->name instanceof Node\Identifier) {
Expand Down Expand Up @@ -65,6 +70,7 @@ public function processNode(Node $node, Scope $scope): array

$serviceId = $this->serviceMap::getServiceIdFromNode($node->getArgs()[0]->value, $scope);
if ($serviceId !== null) {
$scope->valueDependency(ServiceResultCacheValueExtension::class, $serviceId);
$service = $this->serviceMap->getService($serviceId);
$serviceIdType = $scope->getType($node->getArgs()[0]->value);
if ($service === null && !$scope->getType(Helper::createMarkerNode($node->var, $serviceIdType, $this->printer))->equals($serviceIdType)) {
Expand Down
48 changes: 48 additions & 0 deletions src/Symfony/MessageResultCacheValueExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php declare(strict_types = 1);

namespace PHPStan\Symfony;

use PHPStan\Analyser\ResultCache\ResultCacheValueExtension;
use PHPStan\Type\VerbosityLevel;

/**
* What handling a message returns, for the files handling it through HandleTrait. It comes from
* the handlers in the container, and from their code.
*/
final class MessageResultCacheValueExtension implements ResultCacheValueExtension
{

private MessageMapFactory $messageMapFactory;

private ?MessageMap $messageMap = null;

public function __construct(MessageMapFactory $symfonyMessageMapFactory)
{
$this->messageMapFactory = $symfonyMessageMapFactory;
}

public function getValue(string $key): string
{
if ($this->messageMap === null) {
$this->messageMap = $this->messageMapFactory->create();
}

$type = $this->messageMap->getTypeForClass($key);
if ($type === null) {
return 'none';
}

return $type->describe(VerbosityLevel::precise());
}

public function keyToResultCache(string $key): string
{
return $key;
}

public function keyFromResultCache(string $storedKey): string
{
return $storedKey;
}

}
42 changes: 42 additions & 0 deletions src/Symfony/ParameterResultCacheValueExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php declare(strict_types = 1);

namespace PHPStan\Symfony;

use PHPStan\Analyser\ResultCache\ResultCacheValueExtension;
use function hash;
use function var_export;

/**
* A parameter in the container, for the files asking about it.
*/
final class ParameterResultCacheValueExtension implements ResultCacheValueExtension
{

private ParameterMap $parameterMap;

public function __construct(ParameterMap $symfonyParameterMap)
{
$this->parameterMap = $symfonyParameterMap;
}

public function getValue(string $key): string
{
$parameter = $this->parameterMap->getParameter($key);
if ($parameter === null) {
return 'missing';
}

return hash('sha256', var_export($parameter->getValue(), true));
}

public function keyToResultCache(string $key): string
{
return $key;
}

public function keyFromResultCache(string $storedKey): string
{
return $storedKey;
}

}
73 changes: 73 additions & 0 deletions src/Symfony/ServiceResultCacheValueExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php declare(strict_types = 1);

namespace PHPStan\Symfony;

use PHPStan\Analyser\ResultCache\ResultCacheValueExtension;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use function class_exists;
use function hash;
use function strpos;
use function var_export;

/**
* A service in the container, for the files asking about it: its class, whether it's public
* and whether it's synthetic. When the class is a parameter, the parameters are part of it too.
*/
final class ServiceResultCacheValueExtension implements ResultCacheValueExtension
{

private ServiceMap $serviceMap;

private ParameterMap $parameterMap;

public function __construct(ServiceMap $symfonyServiceMap, ParameterMap $symfonyParameterMap)
{
$this->serviceMap = $symfonyServiceMap;
$this->parameterMap = $symfonyParameterMap;
}

public function getValue(string $key): string
{
$service = $this->serviceMap->getService($key);
if ($service === null) {
return 'missing';
}

$class = $service->getClass();

return hash('sha256', var_export([
'class' => $class,
'resolvedClass' => $class !== null && strpos($class, '%') !== false ? $this->resolveClass($class) : null,
'public' => $service->isPublic(),
'synthetic' => $service->isSynthetic(),
], true));
}

public function keyToResultCache(string $key): string
{
return $key;
}

public function keyFromResultCache(string $storedKey): string
{
return $storedKey;
}

/**
* @return mixed
*/
private function resolveClass(string $class)
{
if (!class_exists(ParameterBag::class)) {
return null;
}

$parameters = [];
foreach ($this->parameterMap->getParameters() as $parameter) {
$parameters[$parameter->getKey()] = $parameter->getValue();
}

return (new ParameterBag($parameters))->resolveValue($class);
}

}
100 changes: 0 additions & 100 deletions src/Symfony/SymfonyContainerResultCacheMetaExtension.php

This file was deleted.

6 changes: 6 additions & 0 deletions src/Type/Symfony/MessengerHandleTraitReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Identifier;
use PHPStan\Analyser\DependencyEmitter;
use PHPStan\Analyser\Scope;
use PHPStan\Symfony\MessageMap;
use PHPStan\Symfony\MessageMapFactory;
use PHPStan\Symfony\MessageResultCacheValueExtension;
use PHPStan\Type\ExpressionTypeResolverExtension;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
Expand All @@ -29,6 +31,9 @@ public function __construct(MessageMapFactory $symfonyMessageMapFactory)
$this->messageMapFactory = $symfonyMessageMapFactory;
}

/**
* @param Scope&DependencyEmitter $scope
*/
public function getType(Expr $expr, Scope $scope): ?Type
{
if (!$this->isSupported($expr, $scope)) {
Expand All @@ -51,6 +56,7 @@ public function getType(Expr $expr, Scope $scope): ?Type

$returnTypes = [];
foreach ($argClassNames as $argClassName) {
$scope->valueDependency(MessageResultCacheValueExtension::class, $argClassName);
$returnType = $messageMap->getTypeForClass($argClassName);

if (is_null($returnType)) {
Expand Down
Loading
Loading