HeaderBag get default value return type (#49)

This commit is contained in:
Farhad Safarov 2020-06-26 14:58:43 +03:00 committed by GitHub
parent 3b5b7016fc
commit b9f4745e28
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 53 additions and 29 deletions

View File

@ -17,7 +17,7 @@ to use InputArgument and InputOption constants as a part of best practise.
- Detects correct Doctrine repository class if entities are configured with annotations.
- Fixes `PossiblyInvalidArgument` for `Symfony\Component\HttpFoundation\Request::getContent`.
The plugin calculates real return type by checking the given argument and marks return type as either string or resource.
- Detect return type of `Symfony\Component\HttpFoundation\HeaderBag::get` (by checking third argument for < Symfony 4.4)
- Detect return type of `Symfony\Component\HttpFoundation\HeaderBag::get` (by checking default value and third argument for < Symfony 4.4)
- Detects service [naming convention](https://symfony.com/doc/current/contributing/code/standards.html#naming-conventions) violations
- Complains when `Container` is injected to a service. Use dependency-injection.

View File

@ -2,42 +2,48 @@
namespace Psalm\SymfonyPsalmPlugin\Handler;
use PhpParser\Node\Expr;
use Psalm\Codebase;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Scalar\String_;
use Psalm\CodeLocation;
use Psalm\Context;
use Psalm\Plugin\Hook\AfterMethodCallAnalysisInterface;
use Psalm\Plugin\Hook\MethodReturnTypeProviderInterface;
use Psalm\StatementsSource;
use Psalm\Type\Atomic\TArray;
use Psalm\Type\Atomic\TInt;
use Psalm\Type\Atomic\TNull;
use Psalm\Type\Atomic\TString;
use Psalm\Type\Union;
use Symfony\Component\HttpFoundation\HeaderBag;
class HeaderBagHandler implements AfterMethodCallAnalysisInterface
class HeaderBagHandler implements MethodReturnTypeProviderInterface
{
/**
* {@inheritdoc}
*/
public static function afterMethodCallAnalysis(
Expr $expr,
string $method_id,
string $appearing_method_id,
string $declaring_method_id,
Context $context,
StatementsSource $statements_source,
Codebase $codebase,
array &$file_replacements = [],
Union &$return_type_candidate = null
) {
if ('Symfony\Component\HttpFoundation\HeaderBag::get' === $declaring_method_id) {
if ($return_type_candidate) {
/** @psalm-suppress MixedArrayAccess */
if (isset($expr->args[2]->value->name->parts[0]) && 'false' === $expr->args[2]->value->name->parts[0]) {
$return_type_candidate = new Union([new TArray([new Union([new TInt()]), new Union([new TString()])])]);
} else {
$return_type_candidate = new Union([new TString(), new TNull()]);
public static function getClassLikeNames(): array
{
return [
HeaderBag::class,
];
}
public static function getMethodReturnType(StatementsSource $source, string $fq_classlike_name, string $method_name_lowercase, array $call_args, Context $context, CodeLocation $code_location, array $template_type_parameters = null, string $called_fq_classlike_name = null, string $called_method_name_lowercase = null)
{
if (HeaderBag::class !== $fq_classlike_name) {
return null;
}
if ('get' === $method_name_lowercase) {
if (3 === count($call_args) && (($arg = $call_args[2]->value) instanceof ConstFetch) && 'false' === $arg->name->parts[0]) {
return new Union([new TArray([new Union([new TInt()]), new Union([new TString()])])]);
}
if (isset($call_args[1])) {
if ($call_args[1]->value instanceof String_) {
return new Union([new TString()]);
}
}
return new Union([new TString(), new TNull()]);
}
return null;
}
}

View File

@ -15,14 +15,16 @@ Feature: Header get
</plugins>
</psalm>
"""
Scenario: HeaderBag get method return type should return `?string` (unless third argument is provided for < Sf4.4)
Given I have the following code
And I have the following code preamble
"""
<?php
use Symfony\Component\HttpFoundation\Request;
"""
Scenario: HeaderBag get method return type should return `?string` (unless third argument is provided for < Sf4.4)
Given I have the following code
"""
class App
{
public function index(Request $request): void
@ -38,3 +40,19 @@ Feature: Header get
"""
When I run Psalm
Then I see no errors
Scenario: HeaderBag get method return type should return `string` if default value is provided with string
Given I have the following code
"""
class App
{
public function index(Request $request): void
{
$string = $request->headers->get('string', 'string');
trim($string);
}
}
"""
When I run Psalm
Then I see no errors