Repository: spaze/phpstan-disallowed-calls (php)

Issue:
`disallowedSuperglobals` with `allowIn` doesn't seem to work when referencing a trait
I'm trying out the new [disallowedSuperglobals rule](https://github.com/spaze/phpstan-disallowed-calls/pull/105) while allowing a use inside trait:
```neon
parameters:
    disallowedSuperglobals:
        -
            superglobal: '$_SERVER'
            message: 'use <fg=yellow>Symfony\Component\HttpFoundation\Request</> object instead'
            allowIn:
                - **/src/Infrastructure/Persistence/Doctrine/DBAL/QueryBuffering.php
                - **/src/Kernel.php
```

It seems that [the fix for traits](https://github.com/spaze/phpstan-disallowed-calls/pull/103) doesn't work for super globals. 

I get this error:

```
Using $_SERVER is forbidden, use Symfony\Component\HttpFoundation\Request object instead
↳ src/Core/SearchBundle/CliCommand/IndexUsersCommand.php:24
↳ src/Infrastructure/Persistence/.../DBAL/QueryBuffering.php:24
```

/cc @ekisu @spaze 

Pull request:
Allow superglobal when allowed in a trait
`IsAllowedFileHelper` now does the matching, it doesn't just concatenate some strings anymore.

First I wanted to also iterate say `DisallowedCalls::allowedIn` in the method but there are some other conditions that will influence the return value sometimes too, like exactly in `DisallowedCalls`:
https://github.com/spaze/phpstan-disallowed-calls/blob/a16e9219f02c3b70099fe640abbb39b0452aa8d4/src/DisallowedHelper.php#L49-L54

Plus now the trait-related code is actually tested.

Fix #106

Patch:
diff --git a/src/DisallowedHelper.php b/src/DisallowedHelper.php
index 3277138..0fb0f33 100644
--- a/src/DisallowedHelper.php
+++ b/src/DisallowedHelper.php
@@ -47,8 +47,7 @@ class DisallowedHelper
 			}
 		}
 		foreach ($disallowedCall->getAllowIn() as $allowedPath) {
-			$file = $scope->getTraitReflection() ? $scope->getTraitReflection()->getFileName() : $scope->getFile();
-			if ($file !== null && fnmatch($this->isAllowedFileHelper->absolutizePath($allowedPath), $file)) {
+			if ($this->isAllowedFileHelper->matches($scope, $allowedPath)) {
 				return $this->hasAllowedParamsInAllowed($scope, $node, $disallowedCall);
 			}
 		}
@@ -207,7 +206,7 @@ class DisallowedHelper
 	private function isAllowedPath(Scope $scope, DisallowedConstant $disallowedConstant): bool
 	{
 		foreach ($disallowedConstant->getAllowIn() as $allowedPath) {
-			if (fnmatch($this->isAllowedFileHelper->absolutizePath($allowedPath), $scope->getFile())) {
+			if ($this->isAllowedFileHelper->matches($scope, $allowedPath)) {
 				return true;
 			}
 		}
diff --git a/src/DisallowedNamespaceHelper.php b/src/DisallowedNamespaceHelper.php
index 8b464e5..db97643 100644
--- a/src/DisallowedNamespaceHelper.php
+++ b/src/DisallowedNamespaceHelper.php
@@ -28,8 +28,7 @@ class DisallowedNamespaceHelper
 	private function isAllowed(Scope $scope, DisallowedNamespace $disallowedNamespace): bool
 	{
 		foreach ($disallowedNamespace->getAllowIn() as $allowedPath) {
-			$match = fnmatch($this->isAllowedFileHelper->absolutizePath($allowedPath), $scope->getFile());
-			if ($match) {
+			if ($this->isAllowedFileHelper->matches($scope, $allowedPath)) {
 				return true;
 			}
 		}
diff --git a/src/DisallowedSuperglobalHelper.php b/src/DisallowedSuperglobalHelper.php
index aff711b..02e64a2 100644
--- a/src/DisallowedSuperglobalHelper.php
+++ b/src/DisallowedSuperglobalHelper.php
@@ -23,7 +23,7 @@ class DisallowedSuperglobalHelper
 	private function isAllowedPath(Scope $scope, DisallowedSuperglobal $disallowedSuperglobal): bool
 	{
 		foreach ($disallowedSuperglobal->getAllowIn() as $allowedPath) {
-			if (fnmatch($this->isAllowedFileHelper->absolutizePath($allowedPath), $scope->getFile())) {
+			if ($this->isAllowedFileHelper->matches($scope, $allowedPath)) {
 				return true;
 			}
 		}
diff --git a/src/IsAllowedFileHelper.php b/src/IsAllowedFileHelper.php
index cc8ebc0..9308529 100644
--- a/src/IsAllowedFileHelper.php
+++ b/src/IsAllowedFileHelper.php
@@ -3,6 +3,7 @@ declare(strict_types = 1);
 
 namespace Spaze\PHPStan\Rules\Disallowed;
 
+use PHPStan\Analyser\Scope;
 use PHPStan\File\FileHelper;
 
 class IsAllowedFileHelper
@@ -28,7 +29,7 @@ class IsAllowedFileHelper
 	 * @param string $path
 	 * @return string
 	 */
-	public function absolutizePath(string $path): string
+	private function absolutizePath(string $path): string
 	{
 		if (strpos($path, '*') === 0) {
 			return $path;
@@ -40,4 +41,11 @@ class IsAllowedFileHelper
 		return $this->fileHelper->normalizePath($this->fileHelper->absolutizePath($path));
 	}
 
+
+	public function matches(Scope $scope, string $allowedPath): bool
+	{
+		$file = $scope->getTraitReflection() ? $scope->getTraitReflection()->getFileName() : $scope->getFile();
+		return $file !== null && fnmatch($this->absolutizePath($allowedPath), $file);
+	}
+
 }


Test patch:
diff --git a/tests/IsAllowedFileHelperTest.php b/tests/IsAllowedFileHelperTest.php
index 56e2491..36dc27d 100644
--- a/tests/IsAllowedFileHelperTest.php
+++ b/tests/IsAllowedFileHelperTest.php
@@ -4,10 +4,15 @@ declare(strict_types = 1);
 namespace Spaze\PHPStan\Rules\Disallowed;
 
 use Generator;
+use PHPStan\Analyser\ScopeContext;
+use PHPStan\Analyser\ScopeFactory;
 use PHPStan\File\FileHelper;
-use PHPUnit\Framework\TestCase;
+use PHPStan\Reflection\ReflectionProvider;
+use PHPStan\Testing\PHPStanTestCase;
+use Traits\TestClass;
+use Traits\TestTrait;
 
-class IsAllowedFileHelperTest extends TestCase
+class IsAllowedFileHelperTest extends PHPStanTestCase
 {
 
 	/** @var IsAllowedFileHelper */
@@ -16,23 +21,31 @@ class IsAllowedFileHelperTest extends TestCase
 	/** @var IsAllowedFileHelper */
 	private $isAllowedHelperWithRootDir;
 
+	/** @var ScopeFactory */
+	private $scopeFactory;
+
+	/** @var ReflectionProvider */
+	private $reflectionProvider;
+
 
 	protected function setUp(): void
 	{
 		$this->isAllowedHelper = new IsAllowedFileHelper(new FileHelper(__DIR__));
 		$this->isAllowedHelperWithRootDir = new IsAllowedFileHelper(new FileHelper(__DIR__), '/foo/bar');
+		$this->reflectionProvider = $this->createReflectionProvider();
+		$this->scopeFactory = $this->createScopeFactory($this->reflectionProvider, self::getContainer()->getService('typeSpecifier'));
 	}
 
 
 	/**
-	 * @param string $input
-	 * @param string $output
 	 * @dataProvider pathProvider
 	 */
-	public function testAbsolutizePath(string $input, string $output, string $outputWithDir): void
+	public function testMatches(string $allowedPath, string $file, string $fileWithRootDir): void
 	{
-		$this->assertSame($output, $this->isAllowedHelper->absolutizePath($input));
-		$this->assertSame($outputWithDir, $this->isAllowedHelperWithRootDir->absolutizePath($input));
+		$context = ScopeContext::create($file);
+		$this->assertTrue($this->isAllowedHelper->matches($this->scopeFactory->create($context), $allowedPath));
+		$context = ScopeContext::create($fileWithRootDir);
+		$this->assertTrue($this->isAllowedHelperWithRootDir->matches($this->scopeFactory->create($context), $allowedPath));
 	}
 
 
@@ -45,18 +58,18 @@ class IsAllowedFileHelperTest extends TestCase
 		];
 		yield [
 			'src/*',
-			__DIR__ . '/src/*',
-			'/foo/bar/src/*',
+			__DIR__ . '/src/waldo.php',
+			'/foo/bar/src/waldo.php',
 		];
 		yield [
 			'../src/*',
-			str_replace(basename(__DIR__) . '/../', '', __DIR__ . '/../src/*'),
-			'/foo/src/*',
+			str_replace(basename(__DIR__) . '/../', '', __DIR__ . '/../src/waldo.php'),
+			'/foo/src/waldo.php',
 		];
 		yield [
 			'src/foo/../*',
-			__DIR__ . '/src/*',
-			'/foo/bar/src/*',
+			__DIR__ . '/src/waldo.php',
+			'/foo/bar/src/waldo.php',
 		];
 		yield [
 			'*/src',
@@ -75,4 +88,13 @@ class IsAllowedFileHelperTest extends TestCase
 		];
 	}
 
+
+	public function testMatchesInTraits(): void
+	{
+		$classReflection = $this->reflectionProvider->getClass(TestClass::class);
+		$traitReflection = $this->reflectionProvider->getClass(TestTrait::class);
+		$context = ScopeContext::create($classReflection->getFileName())->enterClass($classReflection)->enterTrait($traitReflection);
+		$this->assertTrue($this->isAllowedHelper->matches($this->scopeFactory->create($context), $traitReflection->getFileName()));
+	}
+
 }
diff --git a/tests/bootstrap.php b/tests/bootstrap.php
index db5fde2..4127a75 100644
--- a/tests/bootstrap.php
+++ b/tests/bootstrap.php
@@ -9,4 +9,5 @@ require_once __DIR__ . '/libs/Inheritance.php';
 require_once __DIR__ . '/libs/Royale.php';
 require_once __DIR__ . '/libs/SomeInterface.php';
 require_once __DIR__ . '/libs/Option.php';
+require_once __DIR__ . '/libs/TestTrait.php';
 require_once __DIR__ . '/libs/Traits.php';
diff --git a/tests/libs/TestTrait.php b/tests/libs/TestTrait.php
new file mode 100644
index 0000000..336a528
--- /dev/null
+++ b/tests/libs/TestTrait.php
@@ -0,0 +1,23 @@
+<?php
+declare(strict_types = 1);
+
+namespace Traits;
+
+trait TestTrait
+{
+
+	public function x(): void
+	{
+	}
+
+
+	public function y(): void
+	{
+	}
+
+
+	public static function z(): void
+	{
+	}
+
+}
diff --git a/tests/libs/Traits.php b/tests/libs/Traits.php
index 57ce92a..ee868f0 100644
--- a/tests/libs/Traits.php
+++ b/tests/libs/Traits.php
@@ -3,25 +3,6 @@ declare(strict_types = 1);
 
 namespace Traits;
 
-trait TestTrait
-{
-
-	public function x(): void
-	{
-	}
-
-
-	public function y(): void
-	{
-	}
-
-
-	public static function z(): void
-	{
-	}
-
-}
-
 
 trait AnotherTrait
 {