Skip to content

Commit

Permalink
Merge pull request #470 from kukulich/php-internal
Browse files Browse the repository at this point in the history
PhpInternalSourceLocator is not based on internal reflection anymore
  • Loading branch information
Ocramius authored May 14, 2019
2 parents a86a811 + 8e125f1 commit 89795a1
Show file tree
Hide file tree
Showing 20 changed files with 5,264 additions and 351 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
/.gitignore export-ignore
/.scrutinizer.yml export-ignore
/.travis.yml export-ignore
/bin/ export-ignore
/composer.lock export-ignore
/demo/ export-ignore
/docs/ export-ignore
Expand Down
24 changes: 16 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,24 @@ jobs:
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.2.17 DEPENDENCIES=""
env: PHP_VERSION=7.2.18 DEPENDENCIES=""
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit

- stage: Test
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.2.17 DEPENDENCIES="--prefer-lowest --prefer-stable"
env: PHP_VERSION=7.2.18 DEPENDENCIES="--prefer-lowest --prefer-stable"
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit

- stage: Test
Expand All @@ -54,22 +56,24 @@ jobs:
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.3.4 DEPENDENCIES=""
env: PHP_VERSION=7.3.5 DEPENDENCIES=""
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit

- stage: Test
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.3.4 DEPENDENCIES="--prefer-lowest --prefer-stable"
env: PHP_VERSION=7.3.5 DEPENDENCIES="--prefer-lowest --prefer-stable"
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit

- stage: Test Compatibility
Expand All @@ -86,22 +90,24 @@ jobs:
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.2.17 DEPENDENCIES=""
env: PHP_VERSION=7.2.18 DEPENDENCIES=""
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit test/compat

- stage: Test Compatibility
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.2.17 DEPENDENCIES="--prefer-lowest --prefer-stable"
env: PHP_VERSION=7.2.18 DEPENDENCIES="--prefer-lowest --prefer-stable"
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit test/compat

- stage: Test Compatibility
Expand All @@ -118,22 +124,24 @@ jobs:
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.3.4 DEPENDENCIES=""
env: PHP_VERSION=7.3.5 DEPENDENCIES=""
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit test/compat

- stage: Test Compatibility
os: windows
dist: 1803-containers
language: sh # No PHP currently
env: PHP_VERSION=7.3.4 DEPENDENCIES="--prefer-lowest --prefer-stable"
env: PHP_VERSION=7.3.5 DEPENDENCIES="--prefer-lowest --prefer-stable"
install:
- choco install php --version=${PHP_VERSION} --package-parameters="/InstallDir:c:\tools\php"
- choco install composer --ia "/DEV=C:\tools\php"
- export PATH=/c/tools/php:$PATH
- echo "memory_limit=1G" >> /c/tools/php/php.ini
script: vendor/bin/phpunit test/compat

- stage: Check Demo Scripts
Expand Down
175 changes: 175 additions & 0 deletions bin/generate-phpstorm-stubs-map.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

declare(strict_types=1);

namespace Roave\BetterReflection;

use DirectoryIterator;
use Exception;
use PhpParser\Node;
use PhpParser\NodeTraverser;
use PhpParser\NodeVisitor\NameResolver;
use PhpParser\NodeVisitorAbstract;
use PhpParser\ParserFactory;
use function array_map;
use function file_get_contents;
use function file_put_contents;
use function in_array;
use function is_file;
use function is_readable;
use function ksort;
use function preg_match;
use function sprintf;
use function str_replace;
use function strlen;
use function substr;
use function var_export;

(function () : void {
require __DIR__ . '/../vendor/autoload.php';

$phpStormStubsDirectory = __DIR__ . '/../vendor/jetbrains/phpstorm-stubs';

$phpParser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);

$fileVisitor = new class() extends NodeVisitorAbstract
{
/** @var string[] */
private $classNames = [];

/** @var string[] */
private $functionNames = [];

public function enterNode(Node $node) : ?int
{
if ($node instanceof Node\Stmt\ClassLike) {
$this->classNames[] = $node->namespacedName->toString();

return NodeTraverser::DONT_TRAVERSE_CHILDREN;
}

if ($node instanceof Node\Stmt\Function_) {
/** @psalm-suppress UndefinedPropertyFetch */
$this->functionNames[] = $node->namespacedName->toString();

return NodeTraverser::DONT_TRAVERSE_CHILDREN;
}

return null;
}

/**
* @return string[]
*/
public function getClassNames() : array
{
return $this->classNames;
}

/**
* @return string[]
*/
public function getFunctionNames() : array
{
return $this->functionNames;
}

public function clear() : void
{
$this->classNames = [];
$this->functionNames = [];
}
};

$nodeTraverser = new NodeTraverser();
$nodeTraverser->addVisitor(new NameResolver());
$nodeTraverser->addVisitor($fileVisitor);

$map = ['classes' => [], 'functions' => []];

foreach (new DirectoryIterator($phpStormStubsDirectory) as $directoryInfo) {
if ($directoryInfo->isDot()) {
continue;
}

if (! $directoryInfo->isDir()) {
continue;
}

if (in_array($directoryInfo->getBasename(), ['tests', 'meta'], true)) {
continue;
}

foreach (new DirectoryIterator($directoryInfo->getPathName()) as $fileInfo) {
if ($fileInfo->isDot()) {
continue;
}

if (! preg_match('/\.php$/', $fileInfo->getBasename())) {
continue;
}

if (! is_file($fileInfo->getPathname())) {
throw new Exception(sprintf('"%s" is not a file', $fileInfo->getPathname()));
}

if (! is_readable($fileInfo->getPathname())) {
throw new Exception(sprintf('File "%s" is not readable', $fileInfo->getPathname()));
}

$ast = $phpParser->parse(file_get_contents($fileInfo->getPathname()));

$nodeTraverser->traverse($ast);

/** @psalm-suppress UndefinedMethod */
foreach ($fileVisitor->getClassNames() as $className) {
$map['classes'][$className] = $fileInfo->getPathname();
}

/** @psalm-suppress UndefinedMethod */
foreach ($fileVisitor->getFunctionNames() as $functionName) {
$map['functions'][$functionName] = $fileInfo->getPathname();
}

$fileVisitor->clear();
}
}

$mapWithRelativeFilePaths = array_map(static function (array $files) use ($phpStormStubsDirectory) : array {
ksort($files);

return array_map(static function (string $filePath) use ($phpStormStubsDirectory) : string {
return str_replace('\\', '/', substr($filePath, strlen($phpStormStubsDirectory) + 1));
}, $files);
}, $map);

$exportedClasses = var_export($mapWithRelativeFilePaths['classes'], true);
$exportedFunctions = var_export($mapWithRelativeFilePaths['functions'], true);

$output = <<<"PHP"
<?php
declare(strict_types=1);
namespace Roave\BetterReflection\SourceLocator\SourceStubber;
/**
* @internal
*/
final class PhpStormStubsMap
{
const CLASSES = {$exportedClasses};
const FUNCTIONS = {$exportedFunctions};
}
PHP;

$mapFile = __DIR__ . '/../src/SourceLocator/SourceStubber/PhpStormStubsMap.php';

$bytesWritten = @file_put_contents($mapFile, $output);
if ($bytesWritten === false) {
throw new Exception(sprintf('File "%s" is not writeable.', $mapFile));
}

exit('Done');
})();
1 change: 1 addition & 0 deletions phpcs.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<arg name="colors"/>
<arg name="cache" value=".phpcs-cache"/>

<file>bin</file>
<file>src</file>
<file>test/unit</file>
<exclude-pattern>test/unit/Assets/*</exclude-pattern>
Expand Down
3 changes: 2 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ parameters:
level: 5

paths:
- bin
- src

ignoreErrors:
# Some parent constructors are explicitly to be ignored
- '#does not call parent constructor#'
- '#Access to an undefined property PhpParser\\Node\\Param::\$isOptional#'
# Impossible to define type hint for anonymous class
- '#Call to an undefined method PhpParser\\NodeVisitorAbstract::getNode\(\)#'
- '#Call to an undefined method PhpParser\\NodeVisitorAbstract::(clearNodes|getClassNodes|getFunctionNodes)\(\)#'
1 change: 1 addition & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
allowPhpStormGenerics="true"
>
<projectFiles>
<directory name="bin" />
<directory name="src" />
</projectFiles>

Expand Down
18 changes: 8 additions & 10 deletions src/SourceLocator/SourceStubber/AggregateSourceStubber.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

namespace Roave\BetterReflection\SourceLocator\SourceStubber;

use ReflectionClass as CoreReflectionClass;
use ReflectionFunction as CoreReflectionFunction;
use function array_merge;

class AggregateSourceStubber implements SourceStubber
Expand All @@ -21,13 +19,13 @@ public function __construct(SourceStubber $sourceStubber, SourceStubber ...$othe
/**
* {@inheritDoc}
*/
public function generateClassStub(CoreReflectionClass $classReflection) : ?string
public function generateClassStub(string $className) : ?StubData
{
foreach ($this->sourceStubbers as $sourceStubber) {
$stub = $sourceStubber->generateClassStub($classReflection);
$stubData = $sourceStubber->generateClassStub($className);

if ($stub !== null) {
return $stub;
if ($stubData !== null) {
return $stubData;
}
}

Expand All @@ -37,13 +35,13 @@ public function generateClassStub(CoreReflectionClass $classReflection) : ?strin
/**
* {@inheritDoc}
*/
public function generateFunctionStub(CoreReflectionFunction $functionReflection) : ?string
public function generateFunctionStub(string $functionName) : ?StubData
{
foreach ($this->sourceStubbers as $sourceStubber) {
$stub = $sourceStubber->generateFunctionStub($functionReflection);
$stubData = $sourceStubber->generateFunctionStub($functionName);

if ($stub !== null) {
return $stub;
if ($stubData !== null) {
return $stubData;
}
}

Expand Down
Loading

0 comments on commit 89795a1

Please sign in to comment.