From db9c015965da269b7dfaddefd43760cc099e8c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20=C5=A0pa=C4=8Dek?= Date: Sun, 26 Jan 2025 23:37:57 +0100 Subject: [PATCH] Can re-allow namespace if in a class with given attributes And can add `allowInUse` which is handy when using the `allowExceptIn...` (or `disallowIn...`) config option. --- docs/allow-in-class-with-attributes.md | 59 ++++++++++++++- extension.neon | 21 ++++++ src/Allowed/Allowed.php | 14 ++-- src/DisallowedNamespace.php | 41 +++++----- src/DisallowedNamespaceFactory.php | 41 ++++++---- .../DisallowedNamespaceRuleErrors.php | 27 +++---- src/Usages/NamespaceUsage.php | 32 ++++++++ src/Usages/NamespaceUsageFactory.php | 25 +++++++ src/Usages/NamespaceUsages.php | 38 +++++----- ...ionCallsAllowInClassWithAttributesTest.php | 4 +- ...teUsagesAllowInClassWithAttributesTest.php | 4 +- ...ceUsagesAllowInClassWithAttributesTest.php | 74 +++++++++++++++++++ tests/Usages/NamespaceUsagesTest.php | 3 +- tests/Usages/NamespaceUsagesTypesTest.php | 3 +- tests/src/AttributeClass.php | 11 +++ 15 files changed, 315 insertions(+), 82 deletions(-) create mode 100644 src/Usages/NamespaceUsage.php create mode 100644 src/Usages/NamespaceUsageFactory.php create mode 100644 tests/Usages/NamespaceUsagesAllowInClassWithAttributesTest.php diff --git a/docs/allow-in-class-with-attributes.md b/docs/allow-in-class-with-attributes.md index d7be2ec..7e19130 100644 --- a/docs/allow-in-class-with-attributes.md +++ b/docs/allow-in-class-with-attributes.md @@ -1,8 +1,15 @@ ## Allow in class with given attributes -It is possible to allow a previously disallowed function, method call or an attribute usage when done in a class with specified attributes. +It is possible to allow a previously disallowed item when done in a class with specified attributes. You can use the `allowInClassWithAttributes` configuration option. +This is supported for the following items: +- function calls +- method calls +- attribute usages +- namespace usages +- classname usages + For example, if you'd have a configuration like this: ```neon @@ -27,7 +34,7 @@ class Foo } ``` -On the other hand, if you need to disallow a method call, a function call, or an attribute usage only when present in a method from a class with a given attribute, +On the other hand, if you need to disallow an item only when present in a method from a class with a given attribute, use `allowExceptInClassWithAttributes` (or the `disallowInClassWithAttributes` alias): ```neon @@ -65,3 +72,51 @@ class Foo ``` The attribute names in the _allow_ directives support [fnmatch()](https://www.php.net/function.fnmatch) patterns. + +### Allow namespace or classname use in `use` imports + +You can allow a namespace or a classname to be used in `use` imports with `allowInUse: true`. +This can be useful when you want to disallow a namespace usage in a class with an attribute (with `allowExceptInClassWithAttributes` or `disallowInClassWithAttributes`), +but don't want the error to be reported on line with the `use` statement. + +Let's have a class like this: + +```php +use Foo\Bar\DisallowedClass; // line 1 + +#[MyAttribute] +class Waldo +{ + + public function fred(DisallowedClass $param) // line 7 + { + } + +} +``` + +Then with a configuration like this: + +```neon +parameters: + disallowedNamespace: + - + namespace: 'Foo\Bar\DisallowedClass' + allowExceptInClassWithAttributes: + - MyAttribute +``` + +the error would be reported both on line 1, because `use Foo\Bar\DisallowedClass;` uses a disallowed namespace, and on line 7 because `$param` has the disallowed type. +But maybe you'd expect the error to be reported only on line 7, because _that_ is a disallowed class used in a class with the `MyAttribute` attribute. + +To omit the `use` finding, you can add the `allowInUse` line, like this: + +```neon +parameters: + disallowedNamespace: + - + namespace: 'Foo\Bar\DisallowedClass' + allowExceptInClassWithAttributes: + - MyAttribute + allowInUse: true +``` diff --git a/extension.neon b/extension.neon index dc22c23..f76fca0 100644 --- a/extension.neon +++ b/extension.neon @@ -24,6 +24,16 @@ parametersSchema: ?allowIn: listOf(string()), ?allowExceptIn: listOf(string()), ?disallowIn: listOf(string()), + ?allowInClassWithAttributes: listOf(string()), + ?allowExceptInClassWithAttributes: listOf(string()), + ?disallowInClassWithAttributes: listOf(string()), + ?allowInCallWithAttributes: listOf(string()), + ?allowExceptInCallWithAttributes: listOf(string()), + ?disallowInCallWithAttributes: listOf(string()), + ?allowInClassWithMethodAttributes: listOf(string()), + ?allowExceptInClassWithMethodAttributes: listOf(string()), + ?disallowInClassWithMethodAttributes: listOf(string()), + ?allowInUse: bool(), ?errorIdentifier: string(), ?errorTip: string(), ]) @@ -37,6 +47,16 @@ parametersSchema: ?allowIn: listOf(string()), ?allowExceptIn: listOf(string()), ?disallowIn: listOf(string()), + ?allowInClassWithAttributes: listOf(string()), + ?allowExceptInClassWithAttributes: listOf(string()), + ?disallowInClassWithAttributes: listOf(string()), + ?allowInCallWithAttributes: listOf(string()), + ?allowExceptInCallWithAttributes: listOf(string()), + ?disallowInCallWithAttributes: listOf(string()), + ?allowInClassWithMethodAttributes: listOf(string()), + ?allowExceptInClassWithMethodAttributes: listOf(string()), + ?disallowInClassWithMethodAttributes: listOf(string()), + ?allowInUse: bool(), ?errorIdentifier: string(), ?errorTip: string(), ]) @@ -298,6 +318,7 @@ services: - Spaze\PHPStan\Rules\Disallowed\RuleErrors\DisallowedCallsRuleErrors - Spaze\PHPStan\Rules\Disallowed\RuleErrors\DisallowedVariableRuleErrors - Spaze\PHPStan\Rules\Disallowed\Type\TypeResolver + - Spaze\PHPStan\Rules\Disallowed\Usages\NamespaceUsageFactory - factory: Spaze\PHPStan\Rules\Disallowed\Usages\NamespaceUsages(forbiddenNamespaces: %disallowedNamespaces%) tags: diff --git a/src/Allowed/Allowed.php b/src/Allowed/Allowed.php index 2228888..e8ddb93 100644 --- a/src/Allowed/Allowed.php +++ b/src/Allowed/Allowed.php @@ -11,6 +11,7 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Type\Type; use PHPStan\Type\UnionType; +use Spaze\PHPStan\Rules\Disallowed\Disallowed; use Spaze\PHPStan\Rules\Disallowed\DisallowedWithParams; use Spaze\PHPStan\Rules\Disallowed\Exceptions\UnsupportedParamTypeException; use Spaze\PHPStan\Rules\Disallowed\Formatter\Formatter; @@ -36,14 +37,15 @@ public function __construct( /** * @param Scope $scope * @param array|null $args - * @param DisallowedWithParams $disallowed + * @param Disallowed|DisallowedWithParams $disallowed * @return bool */ - public function isAllowed(Scope $scope, ?array $args, DisallowedWithParams $disallowed): bool + public function isAllowed(Scope $scope, ?array $args, Disallowed $disallowed): bool { + $hasParams = $disallowed instanceof DisallowedWithParams; foreach ($disallowed->getAllowInCalls() as $call) { if ($this->callMatches($scope, $call)) { - return $this->hasAllowedParamsInAllowed($scope, $args, $disallowed); + return !$hasParams || $this->hasAllowedParamsInAllowed($scope, $args, $disallowed); } } foreach ($disallowed->getAllowExceptInCalls() as $call) { @@ -53,7 +55,7 @@ public function isAllowed(Scope $scope, ?array $args, DisallowedWithParams $disa } foreach ($disallowed->getAllowIn() as $allowedPath) { if ($this->allowedPath->matches($scope, $allowedPath)) { - return $this->hasAllowedParamsInAllowed($scope, $args, $disallowed); + return !$hasParams || $this->hasAllowedParamsInAllowed($scope, $args, $disallowed); } } if ($disallowed->getAllowExceptIn()) { @@ -64,10 +66,10 @@ public function isAllowed(Scope $scope, ?array $args, DisallowedWithParams $disa } return true; } - if ($disallowed->getAllowExceptParams()) { + if ($hasParams && $disallowed->getAllowExceptParams()) { return $this->hasAllowedParams($scope, $args, $disallowed->getAllowExceptParams(), false); } - if ($disallowed->getAllowParamsAnywhere()) { + if ($hasParams && $disallowed->getAllowParamsAnywhere()) { return $this->hasAllowedParams($scope, $args, $disallowed->getAllowParamsAnywhere(), true); } if ($disallowed->getAllowInClassWithAttributes() && $scope->isInClass()) { diff --git a/src/DisallowedNamespace.php b/src/DisallowedNamespace.php index 03f8533..442ad50 100644 --- a/src/DisallowedNamespace.php +++ b/src/DisallowedNamespace.php @@ -3,7 +3,7 @@ namespace Spaze\PHPStan\Rules\Disallowed; -use Spaze\PHPStan\Rules\Disallowed\Exceptions\NotImplementedYetException; +use Spaze\PHPStan\Rules\Disallowed\Allowed\AllowedConfig; class DisallowedNamespace implements Disallowed { @@ -15,23 +15,20 @@ class DisallowedNamespace implements Disallowed private ?string $message; - /** @var list */ - private array $allowIn; - - /** @var list */ - private array $allowExceptIn; - private ?string $errorIdentifier; private ?string $errorTip; + private AllowedConfig $allowedConfig; + + private bool $allowInUse; + /** * @param string $namespace * @param list $excludes * @param string|null $message - * @param list $allowIn - * @param list $allowExceptIn + * @param AllowedConfig $allowedConfig * @param string|null $errorIdentifier * @param string|null $errorTip */ @@ -39,16 +36,16 @@ public function __construct( string $namespace, array $excludes, ?string $message, - array $allowIn, - array $allowExceptIn, + AllowedConfig $allowedConfig, + bool $allowInUse, ?string $errorIdentifier, ?string $errorTip ) { $this->namespace = $namespace; $this->excludes = $excludes; $this->message = $message; - $this->allowIn = $allowIn; - $this->allowExceptIn = $allowExceptIn; + $this->allowedConfig = $allowedConfig; + $this->allowInUse = $allowInUse; $this->errorIdentifier = $errorIdentifier; $this->errorTip = $errorTip; } @@ -78,38 +75,44 @@ public function getMessage(): ?string /** @inheritDoc */ public function getAllowIn(): array { - return $this->allowIn; + return $this->allowedConfig->getAllowIn(); } /** @inheritDoc */ public function getAllowExceptIn(): array { - return $this->allowExceptIn; + return $this->allowedConfig->getAllowExceptIn(); } public function getAllowInCalls(): array { - throw new NotImplementedYetException(); + return $this->allowedConfig->getAllowInCalls(); } public function getAllowExceptInCalls(): array { - throw new NotImplementedYetException(); + return $this->allowedConfig->getAllowExceptInCalls(); } public function getAllowInClassWithAttributes(): array { - throw new NotImplementedYetException(); + return $this->allowedConfig->getAllowInClassWithAttributes(); } public function getAllowExceptInClassWithAttributes(): array { - throw new NotImplementedYetException(); + return $this->allowedConfig->getAllowExceptInClassWithAttributes(); + } + + + public function isAllowInUse(): bool + { + return $this->allowInUse; } diff --git a/src/DisallowedNamespaceFactory.php b/src/DisallowedNamespaceFactory.php index 4ae3223..9c5cea3 100644 --- a/src/DisallowedNamespaceFactory.php +++ b/src/DisallowedNamespaceFactory.php @@ -4,23 +4,33 @@ namespace Spaze\PHPStan\Rules\Disallowed; use PHPStan\ShouldNotHappenException; +use Spaze\PHPStan\Rules\Disallowed\Allowed\AllowedConfigFactory; +use Spaze\PHPStan\Rules\Disallowed\Exceptions\UnsupportedParamTypeInConfigException; +use Spaze\PHPStan\Rules\Disallowed\Formatter\Formatter; use Spaze\PHPStan\Rules\Disallowed\Normalizer\Normalizer; class DisallowedNamespaceFactory { + private Formatter $formatter; + private Normalizer $normalizer; + private AllowedConfigFactory $allowedConfigFactory; + - public function __construct(Normalizer $normalizer) + public function __construct(Formatter $formatter, Normalizer $normalizer, AllowedConfigFactory $allowedConfigFactory) { + $this->formatter = $formatter; $this->normalizer = $normalizer; + $this->allowedConfigFactory = $allowedConfigFactory; } /** - * @param array, class?:string|list, exclude?:string|list, message?:string, allowIn?:list, allowExceptIn?:list, disallowIn?:list, errorIdentifier?:string, errorTip?:string}> $config + * @param array, class?:string|list, exclude?:string|list, message?:string, allowIn?:list, allowExceptIn?:list, disallowIn?:list, allowInUse?:bool, errorIdentifier?:string, errorTip?:string}> $config * @return list + * @throws ShouldNotHappenException */ public function createFromConfig(array $config): array { @@ -35,17 +45,22 @@ public function createFromConfig(array $config): array foreach ((array)($disallowed['exclude'] ?? []) as $exclude) { $excludes[] = $this->normalizer->normalizeNamespace($exclude); } - foreach ((array)$namespaces as $namespace) { - $disallowedNamespace = new DisallowedNamespace( - $this->normalizer->normalizeNamespace($namespace), - $excludes, - $disallowed['message'] ?? null, - $disallowed['allowIn'] ?? [], - $disallowed['allowExceptIn'] ?? $disallowed['disallowIn'] ?? [], - $disallowed['errorIdentifier'] ?? null, - $disallowed['errorTip'] ?? null - ); - $disallowedNamespaces[$disallowedNamespace->getNamespace()] = $disallowedNamespace; + $namespaces = (array)$namespaces; + try { + foreach ($namespaces as $namespace) { + $disallowedNamespace = new DisallowedNamespace( + $this->normalizer->normalizeNamespace($namespace), + $excludes, + $disallowed['message'] ?? null, + $this->allowedConfigFactory->getConfig($disallowed), + $disallowed['allowInUse'] ?? false, + $disallowed['errorIdentifier'] ?? null, + $disallowed['errorTip'] ?? null + ); + $disallowedNamespaces[$disallowedNamespace->getNamespace()] = $disallowedNamespace; + } + } catch (UnsupportedParamTypeInConfigException $e) { + throw new ShouldNotHappenException(sprintf('%s: %s', $this->formatter->formatIdentifier($namespaces), $e->getMessage())); } } return array_values($disallowedNamespaces); diff --git a/src/RuleErrors/DisallowedNamespaceRuleErrors.php b/src/RuleErrors/DisallowedNamespaceRuleErrors.php index 30daa71..901ae68 100644 --- a/src/RuleErrors/DisallowedNamespaceRuleErrors.php +++ b/src/RuleErrors/DisallowedNamespaceRuleErrors.php @@ -6,54 +6,55 @@ use PHPStan\Analyser\Scope; use PHPStan\Rules\IdentifierRuleError; use PHPStan\Rules\RuleErrorBuilder; -use Spaze\PHPStan\Rules\Disallowed\Allowed\AllowedPath; +use Spaze\PHPStan\Rules\Disallowed\Allowed\Allowed; use Spaze\PHPStan\Rules\Disallowed\DisallowedNamespace; use Spaze\PHPStan\Rules\Disallowed\Formatter\Formatter; use Spaze\PHPStan\Rules\Disallowed\Identifier\Identifier; +use Spaze\PHPStan\Rules\Disallowed\Usages\NamespaceUsage; class DisallowedNamespaceRuleErrors { - private AllowedPath $allowedPath; + private Allowed $allowed; private Identifier $identifier; private Formatter $formatter; - public function __construct(AllowedPath $allowedPath, Identifier $identifier, Formatter $formatter) + public function __construct(Allowed $allowed, Identifier $identifier, Formatter $formatter) { - $this->allowedPath = $allowedPath; + $this->allowed = $allowed; $this->identifier = $identifier; $this->formatter = $formatter; } /** - * @param string $namespace + * @param NamespaceUsage $namespaceUsage * @param string $description * @param Scope $scope * @param list $disallowedNamespaces * @param string $identifier * @return list */ - public function getDisallowedMessage(string $namespace, string $description, Scope $scope, array $disallowedNamespaces, string $identifier): array + public function getDisallowedMessage(NamespaceUsage $namespaceUsage, string $description, Scope $scope, array $disallowedNamespaces, string $identifier): array { foreach ($disallowedNamespaces as $disallowedNamespace) { - if ($this->allowedPath->isAllowedPath($scope, $disallowedNamespace)) { - continue; - } - - if (!$this->identifier->matches($disallowedNamespace->getNamespace(), $namespace, $disallowedNamespace->getExcludes())) { + if ( + !$this->identifier->matches($disallowedNamespace->getNamespace(), $namespaceUsage->getNamespace(), $disallowedNamespace->getExcludes()) + || $this->allowed->isAllowed($scope, null, $disallowedNamespace) + || ($disallowedNamespace->isAllowInUse() && $namespaceUsage->isUseItem()) + ) { continue; } $errorBuilder = RuleErrorBuilder::message(sprintf( '%s %s is forbidden%s%s', $description, - $namespace, + $namespaceUsage->getNamespace(), $this->formatter->formatDisallowedMessage($disallowedNamespace->getMessage()), - $disallowedNamespace->getNamespace() !== $namespace ? " [{$namespace} matches {$disallowedNamespace->getNamespace()}]" : '' + $disallowedNamespace->getNamespace() !== $namespaceUsage->getNamespace() ? " [{$namespaceUsage->getNamespace()} matches {$disallowedNamespace->getNamespace()}]" : '' )); $errorBuilder->identifier($disallowedNamespace->getErrorIdentifier() ?? $identifier); if ($disallowedNamespace->getErrorTip()) { diff --git a/src/Usages/NamespaceUsage.php b/src/Usages/NamespaceUsage.php new file mode 100644 index 0000000..4d2959f --- /dev/null +++ b/src/Usages/NamespaceUsage.php @@ -0,0 +1,32 @@ +namespace = $namespace; + $this->isUseItem = $isUseItem; + } + + + public function getNamespace(): string + { + return $this->namespace; + } + + + public function isUseItem(): bool + { + return $this->isUseItem; + } + +} diff --git a/src/Usages/NamespaceUsageFactory.php b/src/Usages/NamespaceUsageFactory.php new file mode 100644 index 0000000..69e138d --- /dev/null +++ b/src/Usages/NamespaceUsageFactory.php @@ -0,0 +1,25 @@ +normalizer = $normalizer; + } + + + public function create(string $namespace, bool $isUseItem = false): NamespaceUsage + { + return new NamespaceUsage($this->normalizer->normalizeNamespace($namespace), $isUseItem); + } + +} diff --git a/src/Usages/NamespaceUsages.php b/src/Usages/NamespaceUsages.php index 396aabe..eed14bd 100644 --- a/src/Usages/NamespaceUsages.php +++ b/src/Usages/NamespaceUsages.php @@ -20,7 +20,6 @@ use PHPStan\Rules\RuleError; use Spaze\PHPStan\Rules\Disallowed\DisallowedNamespace; use Spaze\PHPStan\Rules\Disallowed\DisallowedNamespaceFactory; -use Spaze\PHPStan\Rules\Disallowed\Normalizer\Normalizer; use Spaze\PHPStan\Rules\Disallowed\RuleErrors\DisallowedNamespaceRuleErrors; use Spaze\PHPStan\Rules\Disallowed\RuleErrors\ErrorIdentifiers; @@ -32,27 +31,26 @@ class NamespaceUsages implements Rule private DisallowedNamespaceRuleErrors $disallowedNamespaceRuleErrors; + private NamespaceUsageFactory $namespaceUsageFactory; + /** @var list */ private array $disallowedNamespace; - private Normalizer $normalizer; - /** * @param DisallowedNamespaceRuleErrors $disallowedNamespaceRuleErrors * @param DisallowedNamespaceFactory $disallowNamespaceFactory - * @param Normalizer $normalizer - * @param array, class?:string|list, exclude?:string|list, message?:string, allowIn?:list, allowExceptIn?:list, disallowIn?:list, errorIdentifier?:string, errorTip?:string}> $forbiddenNamespaces + * @param array, class?:string|list, exclude?:string|list, message?:string, allowIn?:list, allowExceptIn?:list, disallowIn?:list, allowInUse?:bool, errorIdentifier?:string, errorTip?:string}> $forbiddenNamespaces */ public function __construct( DisallowedNamespaceRuleErrors $disallowedNamespaceRuleErrors, DisallowedNamespaceFactory $disallowNamespaceFactory, - Normalizer $normalizer, + NamespaceUsageFactory $namespaceUsageFactory, array $forbiddenNamespaces ) { $this->disallowedNamespaceRuleErrors = $disallowedNamespaceRuleErrors; $this->disallowedNamespace = $disallowNamespaceFactory->createFromConfig($forbiddenNamespaces); - $this->normalizer = $normalizer; + $this->namespaceUsageFactory = $namespaceUsageFactory; } @@ -72,61 +70,59 @@ public function processNode(Node $node, Scope $scope): array if ($node instanceof FullyQualified) { $description = 'Class'; $identifier = ErrorIdentifiers::DISALLOWED_CLASS; - $namespaces = [$node->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->toString())]; } elseif ($node instanceof NullableType && $node->type instanceof FullyQualified) { $description = 'Class'; $identifier = ErrorIdentifiers::DISALLOWED_CLASS; - $namespaces = [$node->type->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->type->toString())]; } elseif ($node instanceof UnionType || $node instanceof IntersectionType) { $description = 'Class'; $identifier = ErrorIdentifiers::DISALLOWED_CLASS; $namespaces = []; foreach ($node->types as $type) { if ($type instanceof FullyQualified) { - $namespaces[] = $type->toString(); + $namespaces[] = $this->namespaceUsageFactory->create($type->toString()); } } } elseif ($node instanceof UseUse) { - $namespaces = [$node->name->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->name->toString(), true)]; } elseif ($node instanceof StaticCall && $node->class instanceof Name) { - $namespaces = [$node->class->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->class->toString())]; } elseif ($node instanceof ClassConstFetch && $node->class instanceof Name) { $namespaces = []; $classReflection = $scope->resolveTypeByName($node->class)->getClassReflection(); if ($classReflection && $classReflection->isEnum()) { $description = 'Enum'; $identifier = ErrorIdentifiers::DISALLOWED_ENUM; - $namespaces = [$node->class->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->class->toString())]; } } elseif ($node instanceof Class_ && ($node->extends !== null || count($node->implements) > 0)) { $namespaces = []; - if ($node->extends !== null) { - $namespaces[] = $node->extends->toString(); + $namespaces[] = $this->namespaceUsageFactory->create($node->extends->toString()); } - foreach ($node->implements as $implement) { - $namespaces[] = $implement->toString(); + $namespaces[] = $this->namespaceUsageFactory->create($implement->toString()); } } elseif ($node instanceof New_ && $node->class instanceof Name) { $description = 'Class'; $identifier = ErrorIdentifiers::DISALLOWED_CLASS; - $namespaces = [$node->class->toString()]; + $namespaces = [$this->namespaceUsageFactory->create($node->class->toString())]; } elseif ($node instanceof TraitUse) { $description = 'Trait'; $identifier = ErrorIdentifiers::DISALLOWED_TRAIT; $namespaces = []; foreach ($node->traits as $trait) { - $namespaces[] = $trait->toString(); + $namespaces[] = $this->namespaceUsageFactory->create($trait->toString()); } } else { return []; } $errors = []; - foreach ($namespaces as $namespace) { + foreach ($namespaces as $namespaceUsage) { $ruleErrors = $this->disallowedNamespaceRuleErrors->getDisallowedMessage( - $this->normalizer->normalizeNamespace($namespace), + $namespaceUsage, $description ?? 'Namespace', $scope, $this->disallowedNamespace, diff --git a/tests/Calls/FunctionCallsAllowInClassWithAttributesTest.php b/tests/Calls/FunctionCallsAllowInClassWithAttributesTest.php index d701336..e090256 100644 --- a/tests/Calls/FunctionCallsAllowInClassWithAttributesTest.php +++ b/tests/Calls/FunctionCallsAllowInClassWithAttributesTest.php @@ -53,11 +53,11 @@ public function testRule(): void $this->analyse([__DIR__ . '/../src/AttributeClass.php'], [ [ 'Calling strlen() is forbidden.', - 30, + 35, ], [ 'Calling md5() is forbidden.', - 41, + 48, ], ]); } diff --git a/tests/Usages/AttributeUsagesAllowInClassWithAttributesTest.php b/tests/Usages/AttributeUsagesAllowInClassWithAttributesTest.php index 4ddb897..f67a604 100644 --- a/tests/Usages/AttributeUsagesAllowInClassWithAttributesTest.php +++ b/tests/Usages/AttributeUsagesAllowInClassWithAttributesTest.php @@ -40,11 +40,11 @@ public function testRule(): void $this->analyse([__DIR__ . '/../src/AttributeClass.php'], [ [ 'Attribute Attributes\Attribute5 is forbidden.', - 27, + 32, ], [ 'Attribute Attributes\Attribute4 is forbidden.', - 38, + 45, ], ]); } diff --git a/tests/Usages/NamespaceUsagesAllowInClassWithAttributesTest.php b/tests/Usages/NamespaceUsagesAllowInClassWithAttributesTest.php new file mode 100644 index 0000000..61980e4 --- /dev/null +++ b/tests/Usages/NamespaceUsagesAllowInClassWithAttributesTest.php @@ -0,0 +1,74 @@ +getByType(DisallowedNamespaceRuleErrors::class), + $container->getByType(DisallowedNamespaceFactory::class), + $container->getByType(NamespaceUsageFactory::class), + [ + [ + 'namespace' => 'Waldo\Foo\Bar', + 'allowInClassWithAttributes' => [ + '\Attributes\Attribute2', + ], + ], + [ + 'class' => 'Waldo\Quux\Blade', + 'disallowInClassWithAttributes' => [ + '\Attributes\Attribute3', + ], + 'allowInUse' => true, + ], + ] + ); + } + + + public function testRule(): void + { + $this->analyse([__DIR__ . '/../src/AttributeClass.php'], [ + [ + 'Namespace Waldo\Foo\Bar is forbidden.', + 7, + ], + [ + 'Class Waldo\Foo\Bar is forbidden.', + 36, + ], + [ + 'Class Waldo\Quux\Blade is forbidden.', + 37, + ], + [ + 'Class Waldo\Foo\Bar is forbidden.', + 50, + ], + [ + 'Class Waldo\Foo\Bar is forbidden.', + 63, + ], + ]); + } + + + public static function getAdditionalConfigFiles(): array + { + return [ + __DIR__ . '/../../extension.neon', + ]; + } + +} diff --git a/tests/Usages/NamespaceUsagesTest.php b/tests/Usages/NamespaceUsagesTest.php index a2f5aea..4aa28b8 100644 --- a/tests/Usages/NamespaceUsagesTest.php +++ b/tests/Usages/NamespaceUsagesTest.php @@ -6,7 +6,6 @@ use PHPStan\Rules\Rule; use PHPStan\Testing\RuleTestCase; use Spaze\PHPStan\Rules\Disallowed\DisallowedNamespaceFactory; -use Spaze\PHPStan\Rules\Disallowed\Normalizer\Normalizer; use Spaze\PHPStan\Rules\Disallowed\RuleErrors\DisallowedNamespaceRuleErrors; class NamespaceUsagesTest extends RuleTestCase @@ -18,7 +17,7 @@ protected function getRule(): Rule return new NamespaceUsages( $container->getByType(DisallowedNamespaceRuleErrors::class), $container->getByType(DisallowedNamespaceFactory::class), - $container->getByType(Normalizer::class), + $container->getByType(NamespaceUsageFactory::class), [ [ 'namespace' => 'Framew*rk\Some*', diff --git a/tests/Usages/NamespaceUsagesTypesTest.php b/tests/Usages/NamespaceUsagesTypesTest.php index 827ee56..de35432 100644 --- a/tests/Usages/NamespaceUsagesTypesTest.php +++ b/tests/Usages/NamespaceUsagesTypesTest.php @@ -7,7 +7,6 @@ use PHPStan\Testing\RuleTestCase; use PHPUnit\Framework\Attributes\RequiresPhp; use Spaze\PHPStan\Rules\Disallowed\DisallowedNamespaceFactory; -use Spaze\PHPStan\Rules\Disallowed\Normalizer\Normalizer; use Spaze\PHPStan\Rules\Disallowed\RuleErrors\DisallowedNamespaceRuleErrors; /** @@ -23,7 +22,7 @@ protected function getRule(): Rule return new NamespaceUsages( $container->getByType(DisallowedNamespaceRuleErrors::class), $container->getByType(DisallowedNamespaceFactory::class), - $container->getByType(Normalizer::class), + $container->getByType(NamespaceUsageFactory::class), [ [ 'class' => 'Waldo\Quux\Blade', diff --git a/tests/src/AttributeClass.php b/tests/src/AttributeClass.php index db155ba..8dadf31 100644 --- a/tests/src/AttributeClass.php +++ b/tests/src/AttributeClass.php @@ -4,6 +4,8 @@ namespace Attributes; use Attribute; +use Waldo\Foo\Bar; +use Waldo\Quux\Blade; #[Attribute] #[Attribute2] @@ -16,6 +18,9 @@ public function method(): void md5('QNKCDZO'); sha1('aaroZmOk'); strlen('anazgoh'); + Bar::NAME; + (new Bar())->bar(); + Blade::RUNNER; } } @@ -28,6 +33,8 @@ class AttributeClass2 public function method(): void { strlen('anazgoh'); + (new Bar())->foo(); + Blade::RUNNER; } } @@ -40,6 +47,8 @@ public function method(): void { md5('QNKCDZO'); strlen('anazgoh'); + (new Bar())->foo(); + Blade::RUNNER; } } @@ -51,6 +60,8 @@ class ChildAttributeClass2 public function method(): void { strlen('anazgoh'); + (new Bar())->foo(); + Blade::RUNNER; } }