Skip to content

Commit

Permalink
Change ConstantScalarType to Type in DisallowedCallParam (#159)
Browse files Browse the repository at this point in the history
This allows for more types to be matched, like a CallbackType.

In my use case, I wanted to disallow `array_filter` without specifying a
callback.

But because the current `DisallowedCallParam` interface only works with
`ConstantScalarType` this was not possible.
  • Loading branch information
spaze committed Jan 6, 2023
2 parents f1f319b + 84946da commit 800f5f8
Show file tree
Hide file tree
Showing 12 changed files with 53 additions and 15 deletions.
3 changes: 1 addition & 2 deletions src/DisallowedHelper.php
Expand Up @@ -15,7 +15,6 @@
use PHPStan\Reflection\MethodReflection;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
Expand Down Expand Up @@ -109,7 +108,7 @@ private function hasAllowedParams(Scope $scope, ?CallLike $node, array $allowCon

foreach ($allowConfig as $param) {
$type = $this->getArgType($node, $scope, $param);
if (!$type instanceof ConstantScalarType) {
if ($type === null) {
return !$paramsRequired;
}
if (!$param->matches($type)) {
Expand Down
4 changes: 2 additions & 2 deletions src/Params/DisallowedCallParam.php
Expand Up @@ -3,12 +3,12 @@

namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

interface DisallowedCallParam
{

public function matches(ConstantScalarType $type): bool;
public function matches(Type $type): bool;


public function getPosition(): ?int;
Expand Down
4 changes: 2 additions & 2 deletions src/Params/DisallowedCallParamValue.php
Expand Up @@ -3,7 +3,7 @@

namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @template T of int|bool|string|null
Expand All @@ -21,7 +21,7 @@ abstract class DisallowedCallParamValue implements DisallowedCallParam
private $value;


abstract public function matches(ConstantScalarType $type): bool;
abstract public function matches(Type $type): bool;


/**
Expand Down
4 changes: 2 additions & 2 deletions src/Params/DisallowedCallParamValueAny.php
Expand Up @@ -3,15 +3,15 @@

namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int|bool|string|null>
*/
final class DisallowedCallParamValueAny extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
return true;
}
Expand Down
6 changes: 5 additions & 1 deletion src/Params/DisallowedCallParamValueCaseInsensitiveExcept.php
Expand Up @@ -5,15 +5,19 @@

use PHPStan\Type\Constant\ConstantStringType;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int|bool|string|null>
*/
class DisallowedCallParamValueCaseInsensitiveExcept extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
if (!$type instanceof ConstantScalarType) {
return false;
}
$a = is_string($this->getValue()) ? strtolower($this->getValue()) : $this->getValue();
$b = $type instanceof ConstantStringType ? strtolower($type->getValue()) : $type->getValue();
return $a !== $b;
Expand Down
6 changes: 5 additions & 1 deletion src/Params/DisallowedCallParamValueExcept.php
Expand Up @@ -4,15 +4,19 @@
namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int|bool|string|null>
*/
class DisallowedCallParamValueExcept extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
if (!$type instanceof ConstantScalarType) {
return false;
}
return $this->getValue() !== $type->getValue();
}

Expand Down
4 changes: 2 additions & 2 deletions src/Params/DisallowedCallParamValueFlagExcept.php
Expand Up @@ -4,15 +4,15 @@
namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int>
*/
class DisallowedCallParamValueFlagExcept extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
if (!$type instanceof ConstantIntegerType) {
return false;
Expand Down
4 changes: 2 additions & 2 deletions src/Params/DisallowedCallParamValueFlagSpecific.php
Expand Up @@ -4,15 +4,15 @@
namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\Constant\ConstantIntegerType;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int>
*/
class DisallowedCallParamValueFlagSpecific extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
if (!$type instanceof ConstantIntegerType) {
return false;
Expand Down
6 changes: 5 additions & 1 deletion src/Params/DisallowedCallParamValueSpecific.php
Expand Up @@ -4,15 +4,19 @@
namespace Spaze\PHPStan\Rules\Disallowed\Params;

use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\Type;

/**
* @extends DisallowedCallParamValue<int|bool|string|null>
*/
class DisallowedCallParamValueSpecific extends DisallowedCallParamValue
{

public function matches(ConstantScalarType $type): bool
public function matches(Type $type): bool
{
if (!$type instanceof ConstantScalarType) {
return false;
}
return $this->getValue() === $type->getValue();
}

Expand Down
15 changes: 15 additions & 0 deletions tests/Calls/FunctionCallsTest.php
Expand Up @@ -160,6 +160,17 @@ protected function getRule(): Rule
],
],
],
[
'function' => 'array_filter()',
'message' => 'callback parameter must be given.',
'allowIn' => [
'../src/disallowed-allowed/*.php',
'../src/*-allow/*.*',
],
'allowParamsAnywhereAnyValue' => [
2,
],
],
]
);
}
Expand Down Expand Up @@ -252,6 +263,10 @@ public function testRule(): void
'Calling htmlspecialchars() is forbidden, because reasons',
71,
],
[
'Calling array_filter() is forbidden, callback parameter must be given.',
74,
],
]);
// Based on the configuration above, no errors in this file:
$this->analyse([__DIR__ . '/../src/disallowed-allow/functionCalls.php'], [
Expand Down
6 changes: 6 additions & 0 deletions tests/src/disallowed-allow/functionCalls.php
Expand Up @@ -69,3 +69,9 @@
htmlspecialchars('foo', ENT_QUOTES);
htmlspecialchars('foo', ENT_DISALLOWED | ENT_QUOTES);
htmlspecialchars('foo', ENT_DISALLOWED | ENT_QUOTES | ENT_HTML5);

// allowed only with callback
array_filter(['1', '2']);
array_filter(['1', '2'], function () {
return true;
});
6 changes: 6 additions & 0 deletions tests/src/disallowed/functionCalls.php
Expand Up @@ -69,3 +69,9 @@
htmlspecialchars('foo', ENT_QUOTES);
htmlspecialchars('foo', ENT_DISALLOWED | ENT_QUOTES);
htmlspecialchars('foo', ENT_DISALLOWED | ENT_QUOTES | ENT_HTML5);

// allowed only with callback
array_filter(['1', '2']);
array_filter(['1', '2'], function () {
return true;
});

0 comments on commit 800f5f8

Please sign in to comment.