diff --git a/.travis.yml b/.travis.yml index fd8b018b057..cc12086fd0e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: php matrix: include: - php: 7.1 - env: STATIC_ANALYSIS=true RUN_RECTOR=true MONOREPO_SPLIT=true + env: STATIC_ANALYSIS=true RUN_RECTOR=true #- php: 7.1 # env: COMPOSER_FLAGS="--prefer-lowest" - php: 7.2 @@ -30,14 +30,6 @@ script: bin/rector generate-rector-overview >> rector-overview.md fi -after_script: - # split monorepo to packages - only on merge to master + publish prefixed version - - | - if [[ $TRAVIS_EVENT_TYPE == "push" && $MONOREPO_SPLIT == true && $TRAVIS_BRANCH == "master" ]]; then - vendor/bin/monorepo-builder split -v - composer rector-prefixed - fi - cache: directories: - $HOME/.composer/cache diff --git a/monorepo-builder.yml b/monorepo-builder.yml deleted file mode 100644 index 8f3508bf722..00000000000 --- a/monorepo-builder.yml +++ /dev/null @@ -1,3 +0,0 @@ -parameters: - directories_to_repositories: - packages/NodeTypeResolver: 'git@github.com:rectorphp/node-type-resolver.git' diff --git a/packages/NodeTypeResolver/.travis.yml b/packages/NodeTypeResolver/.travis.yml deleted file mode 100644 index d0abb56bb2f..00000000000 --- a/packages/NodeTypeResolver/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: php - -matrix: - include: - - php: 7.1 - env: PHPUNIT_FLAGS="--coverage-clover coverage.xml" - - php: 7.1 - env: COMPOSER_FLAGS="--prefer-lowest" - - php: 7.2 - -install: - - composer update $COMPOSER_FLAGS - -script: - - vendor/bin/phpunit $PHPUNIT_FLAGS - -after_script: - # upload coverage.xml to Coveralls - - | - if [[ $PHPUNIT_FLAGS != "" ]]; then - wget https://github.com/php-coveralls/php-coveralls/releases/download/v2.1.0/php-coveralls.phar; - php php-coveralls.phar --verbose; - fi - -notifications: - email: false diff --git a/packages/NodeTypeResolver/README.md b/packages/NodeTypeResolver/README.md deleted file mode 100644 index cd31acc2409..00000000000 --- a/packages/NodeTypeResolver/README.md +++ /dev/null @@ -1,198 +0,0 @@ -# Node Type Resolver - -This package detects **class, interface and trait types** for classes, variables and properties. Those types are resolved by `NodeTypeResolver` service. It uses PHPStan for `PhpParser\Node\Expr` nodes and own type resolvers for other nodes like `PhpParser\Node\Stmt\Class_`, `PhpParser\Node\Stmt\Interface_` or `PhpParser\Node\Stmt\Trait_`. - - -## Install - -```bash -composer require rector/node-type-resolver -``` - -You first need to integrate `Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator` to you application. It will traverse nodes and decorate with attributes that you can use right away and also attributes that are required for `Rector\NodeTypeResolver\NodeTypeResolver`. - -This package works best in Symfony Kernel application, but is also available in standalone use thanks to decoupled container factory. - -### A. Symfony Application - -Import `services.yml` in your Symfony config: - -```yaml -# your-app/config.yml -imports: - - { resource: 'vendor/rector/node-type-resolver/config/config.yml' } -``` - -Require `Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator` in the constructor: - -```php -parser = $parser; - $this->nodeScopeAndMetadataDecorator = $nodeScopeAndMetadataDecorator; - } - - public function run(): void - { - $someFilePath = __DIR__ . '/SomeFile.php'; - $nodes = $this->parser->parse(file_get_contents($someFilePath)); - - $decoratedNodes = $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($nodes, $someFilePath); - - foreach ($decoratedNodes as $node) { - $className = $node->getAttribute(MetadataAttribute::CLASS_NAME); - // "string" with class name - var_dump($className); - } - - // do whatever you need :) - } -} -``` - -### B. Standalone PHP Code - -```php -create(ParserFactory::PREFER_PHP7); - -$someFilePath = __DIR__ . '/SomeFile.php'; -$nodes = $phpParser->parse(file_get_contents($someFilePath)); - -$nodeTypeResolverContainer = (new NodeTypeResolverContainerFactory())->create(); -/** @var NodeScopeAndMetadataDecorator $nodeScopeAndMetadataDecorator */ -$nodeScopeAndMetadataDecorator = $nodeTypeResolverContainer->get(NodeScopeAndMetadataDecorator::class); -$decoratedNodes = $nodeScopeAndMetadataDecorator->decorateNodesFromFile($nodes, $someFilePath); - -foreach ($decoratedNodes as $node) { - $className = $node->getAttribute(MetadataAttribute::CLASS_NAME); - // "string" with class name - var_dump($className); -} -``` - - ---- - -## Usage - -After this integration you have new attributes you can work with. - -### Attributes - -These attributes are always available anywhere inside the Node tree. That means that `CLASS_NAME` is available **in every node that is in the class**. That way you can easily get class name on `Property` node. - -#### Namespaces - -```php -setAttribute(MetadataAttribute::NAMESPACE_NAME, $this->namespaceName); - -// instance of "PhpParser\Node\Stmt\Namespace_" -$namespaceNode = $node->setAttribute(MetadataAttribute::NAMESPACE_NODE, $this->namespaceNode); - -// instances of "PhpParser\Node\Stmt\Use_" -$useNodes = $node->setAttribute(MetadataAttribute::USE_NODES, $this->useNodes); -``` - -#### Classes - -```php -getAttribute(MetadataAttribute::CLASS_NAME); - -// instance of "PhpParser\Node\Stmt\Class_" -$classNode = $node->getAttribute(MetadataAttribute::CLASS_NODE); - -// string name of current class -$parentClassName = $node->getAttribute(MetadataAttribute::PARENT_CLASS_NAME); -``` - -#### Methods - -```php -getAttribute(MetadataAttribute::METHOD_NAME); - -// instance of "PhpParser\Node\Stmt\ClassMethod" -$methodNode = $node->getAttribute(MetadataAttribute::METHOD_NODE); - -// string name of current method call ($this->get => "get") -$methodCallName = $node->getAttribute(MetadataAttribute::METHOD_NAME); -``` - -### Get Types of Node - -`Rector\NodeTypeResolver\NodeTypeResolver` helps you detect object types for any node that can have one. - -Get it via constructor or `$container->get(Rector\NodeTypeResolver\NodeTypeResolver::class)`; - -```php -resolve($node); - var_dump($classNodeTypes); // array of strings - } -} -``` - -### Inspiration - -Huge thanks for inspiration of this integration belongs to [PHPStanScopeVisitor](https://github.com/silverstripe/silverstripe-upgrader/blob/532182b23e854d02e0b27e68ebc394f436de0682/src/UpgradeRule/PHP/Visitor/PHPStanScopeVisitor.php) by [SilverStripe](https://github.com/silverstripe/) - Thank you ❤️️ ! - diff --git a/packages/NodeTypeResolver/composer.json b/packages/NodeTypeResolver/composer.json deleted file mode 100644 index 6e8997522c0..00000000000 --- a/packages/NodeTypeResolver/composer.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "name": "rector/node-type-resolver", - "description": "This package detects class, interface and trait types for classes, variables and properties.", - "license": "MIT", - "authors": [ - { "name": "Tomas Votruba", "email": "tomas.vot@gmail.com", "homepage": "https://tomasvotruba.com" } - ], - "require": { - "php": "^7.1", - "nikic/php-parser": "^4.0.3", - "phpstan/phpstan": "^0.10.3", - "symfony/dependency-injection": "^3.4|^4.1", - "symfony/finder": "^3.4|^4.1", - "symplify/better-phpdoc-parser": "^5.0", - "rector/utils": "dev-master", - "symplify/package-builder": "^5.0" - }, - "require-dev": { - "phpunit/phpunit": "^7.3" - }, - "autoload": { - "psr-4": { - "Rector\\NodeTypeResolver\\": "src" - } - }, - "autoload-dev": { - "psr-4": { - "Rector\\NodeTypeResolver\\Tests\\": "tests" - }, - "classmap": [ - "tests" - ] - }, - "config": { - "sort-packages": true - }, - "minimum-stability": "dev", - "prefer-stable": true -} diff --git a/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverContainerFactory.php b/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverContainerFactory.php deleted file mode 100644 index d024af14be5..00000000000 --- a/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverContainerFactory.php +++ /dev/null @@ -1,24 +0,0 @@ -boot(); - - return $kernel->getContainer(); - } - - public function createWithConfig(string $config): ContainerInterface - { - $kernel = new NodeTypeResolverKernel($config); - $kernel->boot(); - - return $kernel->getContainer(); - } -} diff --git a/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverKernel.php b/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverKernel.php deleted file mode 100644 index 48bcc590dad..00000000000 --- a/packages/NodeTypeResolver/src/DependencyInjection/NodeTypeResolverKernel.php +++ /dev/null @@ -1,56 +0,0 @@ -config = $config; - - parent::__construct('dev', true); - } - - public function registerContainerConfiguration(LoaderInterface $loader): void - { - $loader->load(__DIR__ . '/../../src/config/config.yml'); - - if ($this->config) { - $loader->load($this->config); - } - } - - /** - * @return BundleInterface[] - */ - public function registerBundles(): array - { - return []; - } - - public function getCacheDir(): string - { - return sys_get_temp_dir() . '/_rector_node_type_resolver_cache'; - } - - public function getLogDir(): string - { - return sys_get_temp_dir() . '/_rector_type_resolver_test_log'; - } - - protected function build(ContainerBuilder $containerBuilder): void - { - $containerBuilder->addCompilerPass(new AutoBindParametersCompilerPass()); - } -} diff --git a/packages/NodeTypeResolver/src/NodeTypeResolverFactory.php b/packages/NodeTypeResolver/src/NodeTypeResolverFactory.php deleted file mode 100644 index f17f23992f8..00000000000 --- a/packages/NodeTypeResolver/src/NodeTypeResolverFactory.php +++ /dev/null @@ -1,52 +0,0 @@ -container = $container; - } - - public function create(): NodeTypeResolver - { - /** @var TypeToStringResolver $typeToStringResolver */ - $typeToStringResolver = $this->container->get(TypeToStringResolver::class); - - /** @var Broker $broker */ - $broker = $this->container->get(Broker::class); - - /** @var ClassReflectionTypesResolver $classReflectionTypesResolver */ - $classReflectionTypesResolver = $this->container->get(ClassReflectionTypesResolver::class); - - $nodeTypeResolver = new NodeTypeResolver($typeToStringResolver, $broker, $classReflectionTypesResolver); - - foreach ($this->container->getServiceIds() as $serviceId) { - if (! is_a($serviceId, PerNodeTypeResolverInterface::class, true)) { - continue; - } - - /** @var PerNodeTypeResolverInterface $perNodeTypeResolver */ - $perNodeTypeResolver = $this->container->get($serviceId); - $nodeTypeResolver->addPerNodeTypeResolver($perNodeTypeResolver); - } - - return $nodeTypeResolver; - } -} diff --git a/packages/NodeTypeResolver/src/config/config.yml b/packages/NodeTypeResolver/src/config/config.yml index 0c6989cc62c..614998ef015 100644 --- a/packages/NodeTypeResolver/src/config/config.yml +++ b/packages/NodeTypeResolver/src/config/config.yml @@ -1,10 +1,12 @@ imports: - # to cover prefixed rector and projects autoload - monorepo - - { resource: '../../../../vendor/symplify/better-phpdoc-parser/src/config/config.yml' , ignore_errors: true } - # to cover installed as dependency - - { resource: '../../../../../../symplify/better-phpdoc-parser/src/config/config.yml' , ignore_errors: true } - - # rector/utils package - - { resource: '../../../Utils/src/config/services.yml' } - - { resource: 'services.yml' } + - { resource: '%vendor%/symplify/better-phpdoc-parser/src/config/config.yml' } + +parameters: + collectors: + - + main_type: 'Rector\NodeTypeResolver\NodeTypeResolver' + collected_type: 'Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface' + add_method: 'addPerNodeTypeResolver' + + diff --git a/packages/NodeTypeResolver/src/config/external-services.yml b/packages/NodeTypeResolver/src/config/external-services.yml index 9dbc9d66e94..109d232ecd5 100644 --- a/packages/NodeTypeResolver/src/config/external-services.yml +++ b/packages/NodeTypeResolver/src/config/external-services.yml @@ -1,13 +1,8 @@ services: _defaults: - # for "Rector\NodeTypeResolver\NodeTypeResolverFactory" standalone usage public: true autowire: true - Symplify\PackageBuilder\Parameter\ParameterProvider: ~ - PhpParser\NodeVisitor\CloningVisitor: ~ - PhpParser\NodeFinder: ~ - # PHPStan PHPStan\Broker\Broker: factory: ['@Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory', 'createBroker'] diff --git a/packages/NodeTypeResolver/src/config/services.yml b/packages/NodeTypeResolver/src/config/services.yml index 92e1bfa684a..9c01fe814d7 100644 --- a/packages/NodeTypeResolver/src/config/services.yml +++ b/packages/NodeTypeResolver/src/config/services.yml @@ -6,13 +6,12 @@ parameters: services: _defaults: - # for "Rector\NodeTypeResolver\NodeTypeResolverFactory" standalone usage public: true autowire: true Rector\NodeTypeResolver\: resource: '../' - exclude: '../{Contract,DependencyInjection/NodeTypeResolverKernel.php,DependencyInjection/NodeTypeResolverContainerFactory.php}' + exclude: '../{Contract}' Rector\PhpParser\CurrentNodeProvider: ~ @@ -21,7 +20,3 @@ services: Rector\Printer\BetterStandardPrinter: ~ Rector\FileSystem\FilesFinder: ~ Rector\Utils\BetterNodeFinder: ~ - - # factory to remove dependency on CompilerPass and make install DX smoother - Rector\NodeTypeResolver\NodeTypeResolver: - factory: ['@Rector\NodeTypeResolver\NodeTypeResolverFactory', 'create'] diff --git a/packages/NodeTypeResolver/tests/AbstractNodeTypeResolverContainerAwareTestCase.php b/packages/NodeTypeResolver/tests/AbstractNodeTypeResolverContainerAwareTestCase.php deleted file mode 100644 index 9326ac07475..00000000000 --- a/packages/NodeTypeResolver/tests/AbstractNodeTypeResolverContainerAwareTestCase.php +++ /dev/null @@ -1,38 +0,0 @@ -createWithConfig( - __DIR__ . '/config/config.tests.yml' - ); - } - - $this->container = self::$cachedContainer; - - parent::__construct($name, $data, $dataName); - } -} diff --git a/packages/NodeTypeResolver/tests/PerNodeTypeResolver/AbstractNodeTypeResolverTest.php b/packages/NodeTypeResolver/tests/PerNodeTypeResolver/AbstractNodeTypeResolverTest.php index e01fdd5f054..576b6dcf498 100644 --- a/packages/NodeTypeResolver/tests/PerNodeTypeResolver/AbstractNodeTypeResolverTest.php +++ b/packages/NodeTypeResolver/tests/PerNodeTypeResolver/AbstractNodeTypeResolverTest.php @@ -3,29 +3,35 @@ namespace Rector\NodeTypeResolver\Tests\PerNodeTypeResolver; use PhpParser\Node; +use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator; use Rector\NodeTypeResolver\NodeTypeResolver; -use Rector\NodeTypeResolver\Tests\AbstractNodeTypeResolverContainerAwareTestCase; -use Rector\NodeTypeResolver\Tests\StandaloneNodeTraverserQueue; +use Rector\Parser\Parser; +use Rector\Tests\AbstractContainerAwareTestCase; use Rector\Utils\BetterNodeFinder; -use Symfony\Component\Finder\SplFileInfo; +use Symplify\PackageBuilder\FileSystem\SmartFileInfo; use Symplify\PackageBuilder\Parameter\ParameterProvider; -abstract class AbstractNodeTypeResolverTest extends AbstractNodeTypeResolverContainerAwareTestCase +abstract class AbstractNodeTypeResolverTest extends AbstractContainerAwareTestCase { - /** - * @var BetterNodeFinder - */ - protected $betterNodeFinder; - /** * @var NodeTypeResolver */ protected $nodeTypeResolver; /** - * @var StandaloneNodeTraverserQueue + * @var BetterNodeFinder */ - private $standaloneNodeTraverserQueue; + private $betterNodeFinder; + + /** + * @var Parser + */ + private $parser; + + /** + * @var NodeScopeAndMetadataDecorator + */ + private $nodeScopeAndMetadataDecorator; /** * @var ParameterProvider @@ -35,9 +41,10 @@ abstract class AbstractNodeTypeResolverTest extends AbstractNodeTypeResolverCont protected function setUp(): void { $this->betterNodeFinder = $this->container->get(BetterNodeFinder::class); - $this->standaloneNodeTraverserQueue = $this->container->get(StandaloneNodeTraverserQueue::class); $this->parameterProvider = $this->container->get(ParameterProvider::class); $this->nodeTypeResolver = $this->container->get(NodeTypeResolver::class); + $this->parser = $this->container->get(Parser::class); + $this->nodeScopeAndMetadataDecorator = $this->container->get(NodeScopeAndMetadataDecorator::class); } /** @@ -53,12 +60,14 @@ abstract class AbstractNodeTypeResolverTest extends AbstractNodeTypeResolverCont /** * @return Node[] */ - protected function getNodesForFile(string $file): array + private function getNodesForFile(string $file): array { - $fileInfo = new SplFileInfo($file, '', ''); + $smartFileInfo = new SmartFileInfo($file); $this->parameterProvider->changeParameter('source', [$file]); - return $this->standaloneNodeTraverserQueue->processFileInfo($fileInfo); + $nodes = $this->parser->parseFile($smartFileInfo->getRealPath()); + + return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($nodes, $smartFileInfo->getRealPath()); } } diff --git a/packages/NodeTypeResolver/tests/PhpDoc/NodeAnalyzer/DocBlockAnalyzerTest.php b/packages/NodeTypeResolver/tests/PhpDoc/NodeAnalyzer/DocBlockAnalyzerTest.php index d3cceef8127..5291ce1d69d 100644 --- a/packages/NodeTypeResolver/tests/PhpDoc/NodeAnalyzer/DocBlockAnalyzerTest.php +++ b/packages/NodeTypeResolver/tests/PhpDoc/NodeAnalyzer/DocBlockAnalyzerTest.php @@ -5,10 +5,10 @@ namespace Rector\NodeTypeResolver\Tests\PhpDoc\NodeAnalyzer; use PhpParser\Comment\Doc; use PhpParser\Node\Scalar\String_; use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer; -use Rector\NodeTypeResolver\Tests\AbstractNodeTypeResolverContainerAwareTestCase; +use Rector\Tests\AbstractContainerAwareTestCase; use function Safe\sprintf; -final class DocBlockAnalyzerTest extends AbstractNodeTypeResolverContainerAwareTestCase +final class DocBlockAnalyzerTest extends AbstractContainerAwareTestCase { /** * @var DocBlockAnalyzer diff --git a/packages/NodeTypeResolver/tests/StandaloneNodeTraverserQueue.php b/packages/NodeTypeResolver/tests/StandaloneNodeTraverserQueue.php deleted file mode 100644 index 871e2acb58f..00000000000 --- a/packages/NodeTypeResolver/tests/StandaloneNodeTraverserQueue.php +++ /dev/null @@ -1,37 +0,0 @@ -parser = $parser; - $this->nodeScopeAndMetadataDecorator = $nodeScopeAndMetadataDecorator; - } - - /** - * @return Node[] - */ - public function processFileInfo(SplFileInfo $fileInfo): array - { - $nodes = $this->parser->parse($fileInfo->getContents()); - - return $this->nodeScopeAndMetadataDecorator->decorateNodesFromFile($nodes, $fileInfo->getRealPath()); - } -} diff --git a/packages/NodeTypeResolver/tests/config/config.tests.yml b/packages/NodeTypeResolver/tests/config/config.tests.yml deleted file mode 100644 index ef218e2b06c..00000000000 --- a/packages/NodeTypeResolver/tests/config/config.tests.yml +++ /dev/null @@ -1,12 +0,0 @@ -services: - _defaults: - autowire: true - public: true - - PhpParser\ParserFactory: ~ - PhpParser\Parser: - factory: ['@PhpParser\ParserFactory', 'create'] - arguments: - $kind: !php/const PhpParser\ParserFactory::PREFER_PHP7 - - Rector\NodeTypeResolver\Tests\StandaloneNodeTraverserQueue: ~ diff --git a/phpstan.neon b/phpstan.neon index b3ac418b06d..b53e52ca03d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -35,9 +35,6 @@ parameters: # already fixed, invalidated cache? - '#Access to an undefined property PhpParser\\Node\\Expr::\$args#' - # symfony container autowire interface falsy - - '#Call to an undefined method Symfony\\Component\\DependencyInjection\\ContainerInterface::getServiceIds\(\)#' - # nette container - '#Method Rector\\NodeTypeResolver\\DependencyInjection\\PHPStanServicesFactory::create(.*?)() should return (.*?) but returns object#' diff --git a/src/FileSystem/FilesFinder.php b/src/FileSystem/FilesFinder.php index d5abe39342e..8a69b3c3579 100644 --- a/src/FileSystem/FilesFinder.php +++ b/src/FileSystem/FilesFinder.php @@ -6,6 +6,7 @@ use Nette\Utils\Strings; use Rector\Utils\FilesystemTweaker; use Symfony\Component\Finder\Finder; use Symfony\Component\Finder\SplFileInfo; +use Symplify\PackageBuilder\FileSystem\SmartFileInfo; final class FilesFinder { @@ -49,7 +50,7 @@ final class FilesFinder $splFileInfos = []; foreach ($files as $file) { - $splFileInfos[] = new SplFileInfo($file, '', ''); + $splFileInfos[] = new SmartFileInfo($file); } $splFileInfos = array_merge($splFileInfos, $this->findInDirectories($directories, $suffixes));