commit
9476ced398
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'];
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue