Skip to content

Commit

Permalink
Merge pull request #987 from ApiGen/better-parse-exception
Browse files Browse the repository at this point in the history
[BetterReflection] improve parsing by Caching
  • Loading branch information
Tomáš Votruba committed Aug 30, 2017
2 parents a6f5669 + f5d674d commit 81775f7
Show file tree
Hide file tree
Showing 24 changed files with 370 additions and 114 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -24,7 +24,7 @@ Add to your `composer.json`:
{
"require": {
"apigen/apigen": "5.0.0-RC4",
"roave/better-reflection": "dev-master#a83ef24"
"roave/better-reflection": "dev-master#a402048"
}
}
```
Expand Down
5 changes: 3 additions & 2 deletions composer.json
Expand Up @@ -11,7 +11,7 @@
"bin": ["bin/apigen"],
"require": {
"php": "^7.1",
"roave/better-reflection": "dev-master#d9a0d26",
"roave/better-reflection": "dev-master#a402048",
"phpdocumentor/reflection-docblock": "^3.1",
"kukulich/fshl": "^2.1",

Expand Down Expand Up @@ -39,6 +39,7 @@
"psr-4": {
"ApiGen\\": "src",
"ApiGen\\Annotation\\": "packages/Annotation/src",
"ApiGen\\BetterReflection\\": "packages/BetterReflection/src",
"ApiGen\\Element\\": "packages/Element/src",
"ApiGen\\ModularConfiguration\\": "packages/ModularConfiguration/src",
"ApiGen\\Reflection\\": "packages/Reflection/src",
Expand All @@ -57,7 +58,7 @@
"packages/Element/tests/ReflectionCollector/NamespaceReflectionCollectorSource/namespacedFunction.php",
"packages/Element/tests/ReflectionCollector/NamespaceReflectionCollectorSource/NoneNamespacedClass.php",
"packages/Element/tests/ReflectionCollector/Source/deprecatedFunction.php",
"packages/Reflection/tests/Parser/DifferentVendorSources/vendor/DifferentVendor/DifferentClass.php",
"packages/Reflection/tests/Parser/DifferentVendorSources/vendor/DifferentVendor/DifferentClass.php",
"packages/Reflection/tests/Parser/DifferentVendorSources/src/MyVendor/MyClass.php",
"packages/Reflection/tests/Reflection/Function_/FunctionReflection/Source/SomeFunction.php",
"packages/Reflection/tests/Reflection/Function_/FunctionParameterReflection/Source/functionWithConstant.php",
Expand Down
2 changes: 0 additions & 2 deletions easy-coding-standard.neon
Expand Up @@ -23,7 +23,6 @@ checkers:
usefulAnnotations:
- @dataProvider
- @deprecated
- @todo
enableEachParameterAndReturnInspection: true

parameters:
Expand All @@ -33,7 +32,6 @@ parameters:
- PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer
- PhpCsFixer\Fixer\Operator\NewWithBracesFixer
- PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer
- Symplify\CodingStandard\Fixer\Php\ClassStringToClassConstantFixer

skip:
SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff:
Expand Down
2 changes: 1 addition & 1 deletion packages/Annotation/README.md
Expand Up @@ -19,7 +19,7 @@ Here are you options:

## How to Modify Description

Sometimes you need to modify your description: decorate HTML, Markdown or anyhting else:
Sometimes you need to modify your description: decorate HTML, Markdown or anything else:

```php
/**
Expand Down
6 changes: 6 additions & 0 deletions packages/Annotation/src/config/services.yml
@@ -0,0 +1,6 @@
services:
_defaults:
autowire: true

ApiGen\Annotation\:
resource: '..'
34 changes: 34 additions & 0 deletions packages/BetterReflection/src/Parser/ParserFactory.php
@@ -0,0 +1,34 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\Parser;

use PhpParser\Lexer;
use PhpParser\Parser;
use PhpParser\ParserFactory as NikicParserFactory;
use Roave\BetterReflection\SourceLocator\Ast\Parser\MemoizingParser;

final class ParserFactory
{
/**
* @var Lexer
*/
private $lexer;

/**
* @var NikicParserFactory
*/
private $nikicParserFactory;

public function __construct(Lexer $lexer, NikicParserFactory $nikicParserFactory)
{
$this->lexer = $lexer;
$this->nikicParserFactory = $nikicParserFactory;
}

public function create(): Parser
{
$nativeParser = $this->nikicParserFactory->create(NikicParserFactory::PREFER_PHP7, $this->lexer);

return new MemoizingParser($nativeParser);
}
}
@@ -0,0 +1,39 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\SourceLocator;

use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\DirectoriesSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

final class DirectorySourceLocatorFactory
{
/**
* @var AstLocator
*/
private $astLocator;
/**
* @var ProjectVendorSourceLocatorFactory
*/
private $projectVendorSourceLocatorFactory;

public function __construct(
AstLocator $astLocator,
ProjectVendorSourceLocatorFactory $projectVendorSourceLocatorFactory
) {
$this->astLocator = $astLocator;
$this->projectVendorSourceLocatorFactory = $projectVendorSourceLocatorFactory;
}

/**
* @param string[] $directories
*/
public function createFromDirectories(array $directories): SourceLocator
{
return new AggregateSourceLocator([
new DirectoriesSourceLocator($directories, $this->astLocator),
$this->projectVendorSourceLocatorFactory->createFromDirectories($directories),
]);
}
}
@@ -0,0 +1,42 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\SourceLocator;

use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\AutoloadSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

final class FallbackSourceLocatorFactory
{
/**
* @var AstLocator
*/
private $astLocator;

/**
* @var ProjectVendorSourceLocatorFactory
*/
private $projectVendorSourceLocatorFactory;

public function __construct(
AstLocator $astLocator,
ProjectVendorSourceLocatorFactory $projectVendorSourceLocatorFactory
) {
$this->astLocator = $astLocator;
$this->projectVendorSourceLocatorFactory = $projectVendorSourceLocatorFactory;
}

/**
* @param string[] $directories
*/
public function createFromDirecotires(array $directories): SourceLocator
{
return new AggregateSourceLocator([
new AutoloadSourceLocator($this->astLocator),
new PhpInternalSourceLocator($this->astLocator),
$this->projectVendorSourceLocatorFactory->createFromDirectories($directories),
]);
}
}
@@ -0,0 +1,35 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\SourceLocator;

use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SingleFileSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

final class FileSourceLocatorFactory
{
/**
* @var AstLocator
*/
private $astLocator;

public function __construct(AstLocator $astLocator)
{
$this->astLocator = $astLocator;
}

/**
* @param string[] $files
*/
public function createFromFiles(array $files): SourceLocator
{
$locators = [];

foreach ($files as $file) {
$locators[] = new SingleFileSourceLocator($file, $this->astLocator);
}

return new AggregateSourceLocator($locators);
}
}
@@ -0,0 +1,43 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\SourceLocator;

use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\ComposerSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

/**
* This service will try to find project's autoload, to be able to parse its classes.
* It might be the same as autoload of ApiGen, but it might differ.
* E.g. in case you create ApiGen with "composer create-project".
*/
final class ProjectVendorSourceLocatorFactory
{
/**
* @param string[] $directories
*/
public function createFromDirectories(array $directories): SourceLocator
{
$composerSourceLocator = $this->tryToFindProjectAutoload($directories);
if ($composerSourceLocator !== null) {
return $composerSourceLocator;
}

return new AggregateSourceLocator;
}

/**
* @param string[] $directories
*/
private function tryToFindProjectAutoload(array $directories): ?ComposerSourceLocator
{
foreach ($directories as $directory) {
$autoload = dirname($directory) . '/vendor/autoload.php';
if (is_file($autoload)) {
return new ComposerSourceLocator(include $autoload);
}
}

return null;
}
}
@@ -0,0 +1,54 @@
<?php declare(strict_types=1);

namespace ApiGen\BetterReflection\SourceLocator;

use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;

final class SourceLocatorsFactory
{
/**
* @var DirectorySourceLocatorFactory
*/
private $directorySourceLocatorFactory;

/**
* @var FileSourceLocatorFactory
*/
private $fileSourceLocatorFactory;

/**
* @var FallbackSourceLocatorFactory
*/
private $fallbackSourceLocatorFactory;

public function __construct(
DirectorySourceLocatorFactory $directorySourceLocatorFactory,
FileSourceLocatorFactory $fileSourceLocatorFactory,
FallbackSourceLocatorFactory $fallbackSourceLocatorFactory
) {
$this->directorySourceLocatorFactory = $directorySourceLocatorFactory;
$this->fileSourceLocatorFactory = $fileSourceLocatorFactory;
$this->fallbackSourceLocatorFactory = $fallbackSourceLocatorFactory;
}

/**
* @param string[] $directories
* @param string[] $files
*/
public function createFromDirectoriesAndFiles(array $directories, array $files): SourceLocator
{
$locators = [];
if ($directories) {
$locators[] = $this->directorySourceLocatorFactory->createFromDirectories($directories);
}

if ($files) {
$locators[] = $this->fileSourceLocatorFactory->createFromFiles($files);
}

$locators[] = $this->fallbackSourceLocatorFactory->createFromDirecotires($directories);

return new AggregateSourceLocator($locators);
}
}
17 changes: 17 additions & 0 deletions packages/BetterReflection/src/config/services.yml
@@ -0,0 +1,17 @@
services:
_defaults:
autowire: true

ApiGen\BetterReflection\:
resource: '..'

# cached AST Locator
Roave\BetterReflection\SourceLocator\Ast\PhpParserLocator: ~
Roave\BetterReflection\SourceLocator\Ast\Locator:
alias: Roave\BetterReflection\SourceLocator\Ast\PhpParserLocator

# nikic\PHP-Parser
PhpParser\Parser:
factory: ['@ApiGen\BetterReflection\Parser\ParserFactory', 'create']
PhpParser\Lexer: ~
PhpParser\ParserFactory: ~
6 changes: 6 additions & 0 deletions packages/Element/src/config/services.yml
@@ -0,0 +1,6 @@
services:
_defaults:
autowire: true

ApiGen\Element\:
resource: '..'
3 changes: 2 additions & 1 deletion packages/Element/tests/AutocompleteElementsTest.php
Expand Up @@ -7,6 +7,7 @@
use ApiGen\Reflection\ReflectionStorage;
use ApiGen\StringRouting\Route\ReflectionRoute;
use ApiGen\Tests\AbstractContainerAwareTestCase;
use NoneNamespacedClass;

final class AutocompleteElementsTest extends AbstractContainerAwareTestCase
{
Expand Down Expand Up @@ -76,7 +77,7 @@ public function provideDataForLabelsTest(): array
[$this->namespacePrefix],
[$this->namespacePrefix . '\SubNamespace'],
['none'],
['NoneNamespacedClass'],
[NoneNamespacedClass::class],
[$this->namespacePrefix . '\namespacedFunction()'],
[$this->namespacePrefix . '\NamespacedClass'],
[$this->namespacePrefix . '\SubNamespace\SubNamespacedInterface'],
Expand Down
7 changes: 7 additions & 0 deletions packages/ModularConfiguration/src/config/services.yml
@@ -0,0 +1,7 @@
services:
_defaults:
autowire: true

ApiGen\ModularConfiguration\:
resource: '..'
exclude: '../{Exception}'

0 comments on commit 81775f7

Please sign in to comment.