Skip to content

Commit

Permalink
Change ConstantScalarType to Type in DisallowedCallParam
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
ruudk committed Jan 5, 2023
1 parent f1f319b commit 84946da
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 84946da

Please sign in to comment.