Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@
"symplify/package-builder": "^2.5"
},
"require-dev": {
"nette/application": "^2.4",
"phpunit/phpunit": "^6.2",
"slam/php-cs-fixer-extensions": "^1.6",
"phpunit/phpunit": "^6.4",
"slam/php-cs-fixer-extensions": "^1.7",
"symfony/expression-language": "^3.3",
"symfony/form": "^3.3",
"symplify/easy-coding-standard": "^2.5.4",
"symplify/easy-coding-standard": "^2.5",
"tracy/tracy": "^2.4"
},
"autoload": {
Expand Down
1 change: 1 addition & 0 deletions easy-coding-standard.neon
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ checkers:
- 'PhpParser\Node\*'
- 'PhpParser\Comment\Doc'
- 'Rector\DeprecationExtractor\Deprecation\*'
- 'Rector\BetterReflection\SourceLocator\**'

Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
extra_skipped_classes:
Expand Down
32 changes: 31 additions & 1 deletion packages/BetterReflection/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,36 @@
# Better Reflection

This package add 2 features:
This package add 3 features:

- ignores missing functions without crashing
- `SmartClassReflector` always knows about file it's parsing thanks to `CurrentFileProvider`
- add stub file to `/stubs` directory


## Stub Files

Sometimes **we need reflection of class that is not here**.

To overcome this hard dependency on `/vendor`, we can prepare a stub file in format:

```
/stubs/Namespace.ClassName.stub
```

When class `Namespace\ClassName` and is nowhere to be found, the stub file will be used to identify it.


### How to add Stub File?

- Copy original file from Github and use `y` to get absolute link to original file (in case of debug or anything).
- Also refer Rector config with version this stub was used for.
- **Add these 2 informations to the top of stub file**:

```php
<?php

# source: https://github.com/nette/application/blob/12ce71ebb7389d2c24fa6f1a57a4348cad228c5e/src/Application/UI/ITemplate.php
# for: nette24.yml

namespace Nette\...
```
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,15 @@ final class SourceLocatorFactory
*/
private $locator;

public function __construct(Locator $locator)
/**
* @var StubSourceLocator
*/
private $stubSourceLocator;

public function __construct(Locator $locator, StubSourceLocator $stubSourceLocator)
{
$this->locator = $locator;
$this->stubSourceLocator = $stubSourceLocator;
}

public function create(): SourceLocator
Expand Down Expand Up @@ -53,6 +59,7 @@ private function createCommonLocators(): array
new PhpInternalSourceLocator($this->locator),
new EvaledCodeSourceLocator($this->locator),
new AutoloadSourceLocator($this->locator),
$this->stubSourceLocator,
];
}

Expand Down
64 changes: 64 additions & 0 deletions packages/BetterReflection/src/SourceLocator/StubSourceLocator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php declare(strict_types=1);

namespace Rector\BetterReflection\SourceLocator;

use Rector\BetterReflection\Identifier\Identifier;
use Rector\BetterReflection\Identifier\IdentifierType;
use Rector\BetterReflection\Reflection\Reflection;
use Rector\BetterReflection\Reflector\Exception\IdentifierNotFound;
use Rector\BetterReflection\Reflector\Reflector;
use Rector\BetterReflection\SourceLocator\Ast\Locator;
use Rector\BetterReflection\SourceLocator\Located\LocatedSource;
use Rector\BetterReflection\SourceLocator\Type\SourceLocator;
use Rector\BetterReflection\Stubber\SourceStubber;

/**
* Located class in local stubs, as fallback locator if any other fails.
* This allows to perform source code analyses without dependency on /vendor and analysed source code.
*/
final class StubSourceLocator implements SourceLocator
{
/**
* @var SourceStubber
*/
private $sourceStubber;

/**
* @var Locator
*/
private $astLocator;

public function __construct(Locator $locator, SourceStubber $sourceStubber)
{
$this->sourceStubber = $sourceStubber;
$this->astLocator = $locator;
}

public function locateIdentifier(Reflector $reflector, Identifier $identifier): ?Reflection
{
if (! $identifier->isClass()) {
return null;
}

$stubFileInfo = $this->sourceStubber->getStubFileInfoForName($identifier->getName());
if ($stubFileInfo === null) {
return null;
}

$locatedSource = new LocatedSource($stubFileInfo->getContents(), $stubFileInfo->getRealPath());

try {
return $this->astLocator->findReflection($reflector, $locatedSource, $identifier);
} catch (IdentifierNotFound $identifierNotFoundException) {
return null;
}
}

/**
* @return mixed[]
*/
public function locateIdentifiersByType(Reflector $reflector, IdentifierType $identifierType): array
{
return [];
}
}
59 changes: 59 additions & 0 deletions packages/BetterReflection/src/Stubber/SourceStubber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php declare(strict_types=1);

namespace Rector\BetterReflection\Stubber;

use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;

/**
* Inspired by https://github.com/Roave/BetterReflection/blob/master/src/SourceLocator/Reflection/SourceStubber.php
*/
final class SourceStubber
{
/**
* @var string
*/
private $stubDirectory;

/**
* @var SplFileInfo[]
*/
private $stubs = [];

public function __construct()
{
$this->stubDirectory = __DIR__ . '/../../stubs';
}

public function getStubFileInfoForName(string $name): ?SplFileInfo
{
$this->loadStubs();

if (! isset($this->stubs[$name])) {
return null;
}

return $this->stubs[$name];
}

private function loadStubs(): void
{
if (count($this->stubs)) {
return;
}

$finder = Finder::create()
->files()
->in($this->stubDirectory);

foreach ($finder->getIterator() as $fileInfo) {
$class = $this->fileNameToClass($fileInfo);
$this->stubs[$class] = $fileInfo;
}
}

private function fileNameToClass(SplFileInfo $fileInfo): string
{
return str_replace('.', '\\', $fileInfo->getBasename('.stub'));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

# source: https://github.com/nette/application/blob/12ce71ebb7389d2c24fa6f1a57a4348cad228c5e/src/Application/UI/ITemplate.php
# for: nette24.yml

/**
* This file is part of the Nette Framework (https://nette.org)
* Copyright (c) 2004 David Grudl (https://davidgrudl.com)
*/

declare(strict_types=1);

namespace Nette\Application\UI;


/**
* Defines template.
*/
interface ITemplate
{

/**
* Renders template to output.
*/
function render(): void;

/**
* Sets the path to the template file.
* @return static
*/
function setFile(string $file);

/**
* Returns the path to the template file.
*/
function getFile(): ?string;
}
Loading