1
0
Fork 0

Merge pull request #8471 from adaamz/phpstan-0.12

updated phpstan to 0.12
pull/8528/head
Jordi Boggiano 2019-12-17 08:04:00 +01:00 committed by GitHub
commit 9476ced398
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 143 additions and 36 deletions

1
.gitattributes vendored
View File

@ -15,3 +15,4 @@
.travis.yml export-ignore .travis.yml export-ignore
appveyor.yml export-ignore appveyor.yml export-ignore
phpunit.xml.dist export-ignore phpunit.xml.dist export-ignore
/phpstan/ export-ignore

View File

@ -25,7 +25,9 @@ matrix:
- php: 7.1 - php: 7.1
- php: 7.2 - php: 7.2
- php: 7.3 - php: 7.3
env: PHPSTAN=1 env:
- deps=high
- PHPSTAN=1
- php: 7.3 - php: 7.3
env: env:
- deps=high - deps=high
@ -64,8 +66,8 @@ script:
- ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);' - ls -d tests/Composer/Test/* | grep -v TestCase.php | parallel --gnu --keep-order 'echo "Running {} tests"; ./vendor/bin/phpunit -c tests/complete.phpunit.xml --colors=always {} || (echo -e "\e[41mFAILED\e[0m {}" && exit 1);'
# Run PHPStan # Run PHPStan
- if [[ $PHPSTAN == "1" ]]; then - if [[ $PHPSTAN == "1" ]]; then
bin/composer require --dev phpstan/phpstan-shim:^0.11 --ignore-platform-reqs && bin/composer require --dev phpstan/phpstan:^0.12 &&
vendor/bin/phpstan.phar analyse --configuration=phpstan/config.neon; vendor/bin/phpstan analyse --configuration=phpstan/config.neon;
fi fi
before_deploy: before_deploy:

View File

@ -66,8 +66,13 @@
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {
"Composer\\Test\\": "tests/Composer/Test" "Composer\\Test\\": "tests/Composer/Test",
} "Composer\\PHPStanRules\\": "phpstan/Rules/src",
"Composer\\PHPStanRulesTests\\": "phpstan/Rules/tests"
},
"classmap": [
"phpstan/Rules/tests/data"
]
}, },
"bin": [ "bin": [
"bin/composer" "bin/composer"

View File

@ -0,0 +1,46 @@
<?php declare(strict_types = 1);
namespace Composer\PHPStanRules;
use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
/**
* @phpstan-implements Rule<\PhpParser\Node\Expr\Variable>
*/
final class AnonymousFunctionWithThisRule implements Rule
{
/**
* @inheritDoc
*/
public function getNodeType(): string
{
return \PhpParser\Node\Expr\Variable::class;
}
/**
* @inheritDoc
*/
public function processNode(Node $node, Scope $scope): array
{
if (!\is_string($node->name) || $node->name !== 'this') {
return [];
}
if ($scope->isInClosureBind()) {
return [];
}
if (!$scope->isInClass()) {
// reported in other standard rule on level 0
return [];
}
if ($scope->isInAnonymousFunction()) {
return ['Using $this inside anonymous function is prohibited because of PHP 5.3 support.'];
}
return [];
}
}

View File

@ -0,0 +1,28 @@
<?php declare(strict_types = 1);
namespace Composer\PHPStanRulesTests;
use Composer\PHPStanRules\AnonymousFunctionWithThisRule;
use PHPStan\Testing\RuleTestCase;
/**
* @phpstan-extends RuleTestCase<AnonymousFunctionWithThisRule>
*/
final class AnonymousFunctionWithThisRuleTest extends RuleTestCase
{
/**
* @inheritDoc
*/
protected function getRule(): \PHPStan\Rules\Rule
{
return new AnonymousFunctionWithThisRule();
}
public function testWithThis(): void
{
$this->analyse([__DIR__ . '/data/method-with-this.php'], [
['Using $this inside anonymous function is prohibited because of PHP 5.3 support.', 13],
['Using $this inside anonymous function is prohibited because of PHP 5.3 support.', 17],
]);
}
}

View File

@ -0,0 +1,34 @@
<?php
class FirstClass
{
/**
* @var int
*/
private $firstProp = 9;
public function funMethod()
{
function() {
$this->firstProp;
};
call_user_func(function() {
$this->funMethod();
}, $this);
$bind = 'bind';
function() use($bind) {
};
}
}
function global_ok() {
$_SERVER['REMOTE_ADDR'];
}
function global_this() {
// not checked by our rule, it is checked with standard phpstan rule on level 0
$this['REMOTE_ADDR'];
}

View File

@ -1,24 +1,12 @@
parameters: parameters:
autoload_files: autoload_files:
- phpstan/autoload.php - autoload.php
level: 0 level: 0
excludes_analyse: excludes_analyse:
- 'tests/Composer/Test/Fixtures' - '../tests/Composer/Test/Fixtures/*'
- 'tests/Composer/Test/Autoload/Fixtures' - '../tests/Composer/Test/Autoload/Fixtures/*'
- 'tests/Composer/Test/Plugin/Fixtures' - '../tests/Composer/Test/Plugin/Fixtures/*'
ignoreErrors: ignoreErrors:
# unused parameters
- '~^Constructor of class Composer\\Repository\\VcsRepository has an unused parameter \$dispatcher\.$~'
- '~^Constructor of class Composer\\Repository\\PearRepository has an unused parameter \$dispatcher\.$~'
- '~^Constructor of class Composer\\Util\\Http\\CurlDownloader has an unused parameter \$disableTls\.$~'
- '~^Constructor of class Composer\\Util\\Http\\CurlDownloader has an unused parameter \$options\.$~'
- '~^Constructor of class Composer\\Repository\\PearRepository has an unused parameter \$config\.$~'
# unused uses
- '~^Anonymous function has an unused use \$io\.$~'
- '~^Anonymous function has an unused use \$cache\.$~'
- '~^Anonymous function has an unused use \$path\.$~'
# ion cube is not installed # ion cube is not installed
- '~^Function ioncube_loader_\w+ not found\.$~' - '~^Function ioncube_loader_\w+ not found\.$~'
# rar is not installed # rar is not installed
@ -33,14 +21,17 @@ parameters:
# variable defined in eval # variable defined in eval
- '~^Undefined variable: \$res$~' - '~^Undefined variable: \$res$~'
# always checked whether the class exists # we don't have different constructors for parent/child
- '~^Instantiated class Symfony\\Component\\Console\\Terminal not found\.$~' - '~^Unsafe usage of new static\(\)\.$~'
- '~^Class Symfony\\Component\\Console\\Input\\StreamableInputInterface not found\.$~'
- '~^Call to an undefined static method Symfony\\Component\\Process\\Process::fromShellCommandline\(\).$~'
# parent call in test mocks # hhvm should have support for $this in closures
- '~^Composer\\Test\\Mock\\HttpDownloaderMock::__construct\(\) does not call parent constructor from Composer\\Util\\HttpDownloader\.$~' -
- '~^Composer\\Test\\Mock\\InstallationManagerMock::__construct\(\) does not call parent constructor from Composer\\Installer\\InstallationManager\.$~' count: 1
message: '~^Using \$this inside anonymous function is prohibited because of PHP 5\.3 support\.$~'
path: '../tests/Composer/Test/Repository/PlatformRepositoryTest.php'
paths: paths:
- src - ../src
- tests - ../tests
rules:
- Composer\PHPStanRules\AnonymousFunctionWithThisRule

View File

@ -113,7 +113,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
$accept = null; $accept = null;
$reject = null; $reject = null;
$download = function () use ($io, $output, $httpDownloader, $cache, $eventDispatcher, $package, $fileName, $path, &$urls, &$accept, &$reject) { $download = function () use ($io, $output, $httpDownloader, $cache, $eventDispatcher, $package, $fileName, &$urls, &$accept, &$reject) {
$url = reset($urls); $url = reset($urls);
if ($eventDispatcher) { if ($eventDispatcher) {
@ -160,7 +160,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
}); });
}; };
$accept = function ($response) use ($io, $cache, $package, $fileName, $path, $self, &$urls) { $accept = function ($response) use ($cache, $package, $fileName, $self, &$urls) {
$url = reset($urls); $url = reset($urls);
$cacheKey = $url['cacheKey']; $cacheKey = $url['cacheKey'];
@ -174,7 +174,7 @@ class FileDownloader implements DownloaderInterface, ChangeReportInterface
return $fileName; return $fileName;
}; };
$reject = function ($e) use ($io, &$urls, $download, $fileName, $path, $package, &$retries, $filesystem, $self) { $reject = function ($e) use ($io, &$urls, $download, $fileName, $package, &$retries, $filesystem, $self) {
// clean up // clean up
if (file_exists($fileName)) { if (file_exists($fileName)) {
$filesystem->unlink($fileName); $filesystem->unlink($fileName);

View File

@ -246,7 +246,7 @@ class InstallationManager
$dispatcher->dispatchPackageEvent(constant($event), $devMode, $repo, $operations, $operation); $dispatcher->dispatchPackageEvent(constant($event), $devMode, $repo, $operations, $operation);
} }
}, function ($e) use ($jobType, $installer, $package, $initialPackage, $loop, $io) { }, function ($e) use ($jobType, $installer, $package, $initialPackage, $loop, $io) {
$this->io->writeError(' <error>' . ucfirst($jobType) .' of '.$package->getPrettyName().' failed</error>'); $io->writeError(' <error>' . ucfirst($jobType) .' of '.$package->getPrettyName().' failed</error>');
$promise = $installer->cleanup($jobType, $package, $initialPackage); $promise = $installer->cleanup($jobType, $package, $initialPackage);
if ($promise) { if ($promise) {

View File

@ -1119,7 +1119,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito
return $data; return $data;
}; };
$reject = function ($e) use (&$retries, $httpDownloader, $filename, $options, &$reject, $accept, $io, $url, $cache, &$degradedMode) { $reject = function ($e) use (&$retries, $httpDownloader, $filename, $options, &$reject, $accept, $io, $url, &$degradedMode) {
if ($e instanceof TransportException && $e->getStatusCode() === 404) { if ($e instanceof TransportException && $e->getStatusCode() === 404) {
return false; return false;
} }

View File

@ -190,7 +190,7 @@ class HttpDownloader
$downloader->scheduleNextJob(); $downloader->scheduleNextJob();
return $response; return $response;
}, function ($e) use ($io, &$job, $downloader) { }, function ($e) use (&$job, $downloader) {
$job['status'] = HttpDownloader::STATUS_FAILED; $job['status'] = HttpDownloader::STATUS_FAILED;
$job['exception'] = $e; $job['exception'] = $e;