Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying errorIdentifier to RuleError #97

Merged
merged 1 commit into from
Dec 30, 2021
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ parameters:
-
method: 'Redis::connect()'
message: 'use our own Redis instead'
errorIdentifier: 'redis.connect'

disallowedStaticCalls:
-
Expand Down Expand Up @@ -136,6 +137,8 @@ parameters:

The `message` key is optional. Functions and methods can be specified with or without `()`. Omitting `()` is not recommended though to avoid confusing method calls with class constants.

The `errorIdentifier` key is optional. It can be used to provide a unique identifier to the PHPStan error.

Use wildcard (`*`) to ignore all functions, methods, namespaces starting with a prefix, for example:
```neon
parameters:
Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ parameters:
- src
level: max
typeAliases:
ForbiddenCallsConfig: 'array<array{function?:string, method?:string, message?:string, allowIn?:string[], allowInFunctions?:string[], allowInMethods?:string[], allowParamsInAllowed?:array<integer, integer|boolean|string>, allowParamsInAllowedAnyValue?:array<integer, integer>, allowParamsAnywhere?:array<integer, integer|boolean|string>, allowParamsAnywhereAnyValue?:array<integer, integer>, allowExceptParamsInAllowed?:array<integer, integer|boolean|string>, allowExceptParams?:array<integer, integer|boolean|string>, allowExceptCaseInsensitiveParams?:array<integer, integer|boolean|string>}>'
ForbiddenCallsConfig: 'array<array{function?:string, method?:string, message?:string, allowIn?:string[], allowInFunctions?:string[], allowInMethods?:string[], allowParamsInAllowed?:array<integer, integer|boolean|string>, allowParamsInAllowedAnyValue?:array<integer, integer>, allowParamsAnywhere?:array<integer, integer|boolean|string>, allowParamsAnywhereAnyValue?:array<integer, integer>, allowExceptParamsInAllowed?:array<integer, integer|boolean|string>, allowExceptParams?:array<integer, integer|boolean|string>, allowExceptCaseInsensitiveParams?:array<integer, integer|boolean|string>, errorIdentifier?:string}>'

includes:
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/EchoCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Stmt\Echo_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getNodeType(): string
/**
* @param Echo_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/EmptyCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\Empty_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getNodeType(): string
/**
* @param Empty_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/EvalCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\Eval_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getNodeType(): string
/**
* @param Eval_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/ExitDieCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\Exit_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getNodeType(): string
/**
* @param Exit_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/FunctionCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -53,7 +54,7 @@ public function getNodeType(): string
/**
* @param FuncCall $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/MethodCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -55,7 +56,7 @@ public function getNodeType(): string
/**
* @param MethodCall $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
* @throws ClassNotFoundException
*/
public function processNode(Node $node, Scope $scope): array
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/NewCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use PHPStan\Type\ConstantScalarType;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
Expand Down Expand Up @@ -55,7 +56,7 @@ public function getNodeType(): string
/**
* @param New_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/PrintCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\Print_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -52,7 +53,7 @@ public function getNodeType(): string
/**
* @param Print_ $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/ShellExecCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PhpParser\Node\Expr\ShellExec;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -56,7 +57,7 @@ public function getNodeType(): string
/**
* @param ShellExec $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
Expand Down
3 changes: 2 additions & 1 deletion src/Calls/StaticCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\ShouldNotHappenException;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCall;
use Spaze\PHPStan\Rules\Disallowed\DisallowedCallFactory;
Expand Down Expand Up @@ -55,7 +56,7 @@ public function getNodeType(): string
/**
* @param StaticCall $node
* @param Scope $scope
* @return string[]
* @return RuleError[]
* @throws ClassNotFoundException
*/
public function processNode(Node $node, Scope $scope): array
Expand Down
13 changes: 12 additions & 1 deletion src/DisallowedCall.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class DisallowedCall
/** @var array<int, DisallowedCallParam> */
private $allowExceptParams;

/** @var string */
private $errorIdentifier;


/**
* DisallowedCall constructor.
Expand All @@ -44,8 +47,9 @@ class DisallowedCall
* @param array<int, DisallowedCallParam> $allowParamsAnywhere
* @param array<int, DisallowedCallParam> $allowExceptParamsInAllowed
* @param array<int, DisallowedCallParam> $allowExceptParams
* @param string $errorIdentifier
*/
public function __construct(string $call, ?string $message, array $allowIn, array $allowInCalls, array $allowParamsInAllowed, array $allowParamsAnywhere, array $allowExceptParamsInAllowed, array $allowExceptParams)
public function __construct(string $call, ?string $message, array $allowIn, array $allowInCalls, array $allowParamsInAllowed, array $allowParamsAnywhere, array $allowExceptParamsInAllowed, array $allowExceptParams, string $errorIdentifier)
{
$this->call = $call;
$this->message = $message;
Expand All @@ -55,6 +59,7 @@ public function __construct(string $call, ?string $message, array $allowIn, arra
$this->allowParamsAnywhere = $allowParamsAnywhere;
$this->allowExceptParamsInAllowed = $allowExceptParamsInAllowed;
$this->allowExceptParams = $allowExceptParams;
$this->errorIdentifier = $errorIdentifier;
}


Expand Down Expand Up @@ -124,6 +129,12 @@ public function getAllowExceptParams(): array
}


public function getErrorIdentifier(): string
{
return $this->errorIdentifier;
}


public function getKey(): string
{
// The key consists of "initial" config values that would be overwritten with more specific details in a custom config.
Expand Down
3 changes: 2 additions & 1 deletion src/DisallowedCallFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ public function createFromConfig(array $config): array
$allowParamsInAllowed,
$allowParamsAnywhere,
$allowExceptParamsInAllowed,
$allowExceptParams
$allowExceptParams,
$disallowedCall['errorIdentifier'] ?? ''
);
$calls[$disallowedCall->getKey()] = $disallowedCall;
}
Expand Down
13 changes: 12 additions & 1 deletion src/DisallowedConstant.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,24 @@ class DisallowedConstant
/** @var string[] */
private $allowIn;

/** @var string */
private $errorIdentifier;


/**
* DisallowedCall constructor.
*
* @param string $constant
* @param string|null $message
* @param string[] $allowIn
* @param string $errorIdentifier
*/
public function __construct(string $constant, ?string $message, array $allowIn)
public function __construct(string $constant, ?string $message, array $allowIn, string $errorIdentifier)
{
$this->constant = ltrim($constant, '\\');
$this->message = $message;
$this->allowIn = $allowIn;
$this->errorIdentifier = $errorIdentifier;
}


Expand All @@ -51,4 +56,10 @@ public function getAllowIn(): array
return $this->allowIn;
}


public function getErrorIdentifier(): string
{
return $this->errorIdentifier;
}

}
5 changes: 3 additions & 2 deletions src/DisallowedConstantFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class DisallowedConstantFactory
{

/**
* @param array<array{class?:string, constant?:string, message?:string, allowIn?:string[]}> $config
* @param array<array{class?:string, constant?:string, message?:string, allowIn?:string[], errorIdentifier?:string}> $config
* @return DisallowedConstant[]
* @throws ShouldNotHappenException
*/
Expand All @@ -25,7 +25,8 @@ public function createFromConfig(array $config): array
$disallowedConstant = new DisallowedConstant(
$class ? "{$class}::{$constant}" : $constant,
$disallowedConstant['message'] ?? null,
$disallowedConstant['allowIn'] ?? []
$disallowedConstant['allowIn'] ?? [],
$disallowedConstant['errorIdentifier'] ?? ''
);
$constants[$disallowedConstant->getConstant()] = $disallowedConstant;
}
Expand Down
20 changes: 13 additions & 7 deletions src/DisallowedHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
use PHPStan\Broker\ClassNotFoundException;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ConstantScalarType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -111,19 +113,21 @@ private function getArgType(CallLike $node, Scope $scope, int $param): ?Type
* @param string|null $displayName
* @param DisallowedCall[] $disallowedCalls
* @param string|null $message
* @return string[]
* @return RuleError[]
*/
public function getDisallowedMessage(?CallLike $node, Scope $scope, string $name, ?string $displayName, array $disallowedCalls, ?string $message = null): array
{
foreach ($disallowedCalls as $disallowedCall) {
if ($this->callMatches($disallowedCall, $name) && !$this->isAllowed($scope, $node, $disallowedCall)) {
return [
sprintf(
RuleErrorBuilder::message(sprintf(
$message ?? 'Calling %s is forbidden, %s%s',
($displayName && $displayName !== $name) ? "{$name}() (as {$displayName}())" : "{$name}()",
$disallowedCall->getMessage(),
$disallowedCall->getCall() !== $name ? " [{$name}() matches {$disallowedCall->getCall()}()]" : ''
),
))
->identifier($disallowedCall->getErrorIdentifier())
->build(),
];
}
}
Expand All @@ -145,7 +149,7 @@ private function callMatches(DisallowedCall $disallowedCall, string $name): bool
* @param CallLike $node
* @param Scope $scope
* @param DisallowedCall[] $disallowedCalls
* @return string[]
* @return RuleError[]
* @throws ClassNotFoundException
*/
public function getDisallowedMethodMessage($class, CallLike $node, Scope $scope, array $disallowedCalls): array
Expand Down Expand Up @@ -215,19 +219,21 @@ private function isAllowedPath(Scope $scope, DisallowedConstant $disallowedConst
* @param Scope $scope
* @param string|null $displayName
* @param DisallowedConstant[] $disallowedConstants
* @return string[]
* @return RuleError[]
*/
public function getDisallowedConstantMessage(string $constant, Scope $scope, ?string $displayName, array $disallowedConstants): array
{
foreach ($disallowedConstants as $disallowedConstant) {
if ($disallowedConstant->getConstant() === $constant && !$this->isAllowedPath($scope, $disallowedConstant)) {
return [
sprintf(
RuleErrorBuilder::message(sprintf(
'Using %s%s is forbidden, %s',
$disallowedConstant->getConstant(),
$displayName && $displayName !== $disallowedConstant->getConstant() ? ' (as ' . $displayName . ')' : '',
$disallowedConstant->getMessage()
),
))
->identifier($disallowedConstant->getErrorIdentifier())
->build(),
];
}
}
Expand Down
Loading