Skip to content

Commit

Permalink
Merge pull request #74 from Roave/fix/#67-ignore-not-found-classes-by…
Browse files Browse the repository at this point in the history
…-stubbing-them-to-empty-classes

#67 stub out dependencies that cannot be located by using empty classes
  • Loading branch information
Ocramius authored May 27, 2018
2 parents cd87d1f + 3b48d6b commit 9e95a60
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/LocateDependencies/LocateDependenciesViaComposer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Assert\Assert;
use Composer\Installer;
use Roave\BackwardCompatibility\SourceLocator\StaticClassMapSourceLocator;
use Roave\BackwardCompatibility\SourceLocator\StubClassSourceLocator;
use Roave\BetterReflection\Reflection\ReflectionClass;
use Roave\BetterReflection\Reflection\ReflectionProperty;
use Roave\BetterReflection\Reflector\ClassReflector;
Expand Down Expand Up @@ -80,6 +81,7 @@ public function __invoke(string $installationPath) : SourceLocator
$this->sourceLocatorFromAutoloadStatic($generatedAutoloadClass),
$this->sourceLocatorFromAutoloadFiles($generatedAutoloadClass),
new PhpInternalSourceLocator($this->astLocator),
new StubClassSourceLocator($this->astLocator),
]);
}

Expand Down
41 changes: 41 additions & 0 deletions src/SourceLocator/StubClassSourceLocator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Roave\BackwardCompatibility\SourceLocator;

use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\SourceLocator\Located\LocatedSource;
use Roave\BetterReflection\SourceLocator\Type\AbstractSourceLocator;
use function array_slice;
use function count;
use function explode;
use function implode;
use function sprintf;

final class StubClassSourceLocator extends AbstractSourceLocator
{
/**
* {@inheritDoc}
*/
protected function createLocatedSource(Identifier $identifier) : ?LocatedSource
{
if (! $identifier->isClass()) {
return null;
}

if ($identifier->getName() === Identifier::WILDCARD) {
return null;
}

$fqcn = $identifier->getName();
$classNameParts = explode('\\', $fqcn);
$shortName = array_slice($classNameParts, -1)[0];
$namespaceName = implode('\\', array_slice($classNameParts, 0, count($classNameParts) - 1));

return new LocatedSource(
sprintf('<?php namespace %s{interface %s {}}', $namespaceName, $shortName),
null
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use PHPUnit\Framework\TestCase;
use Roave\BackwardCompatibility\LocateDependencies\LocateDependenciesViaComposer;
use Roave\BackwardCompatibility\SourceLocator\StaticClassMapSourceLocator;
use Roave\BackwardCompatibility\SourceLocator\StubClassSourceLocator;
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\SourceLocator\Ast\Locator;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
Expand Down Expand Up @@ -122,7 +123,7 @@ public function testWillLocateDependencies() : void

$locators = $reflectionLocators->getValue($locator);

self::assertCount(3, $locators);
self::assertCount(4, $locators);
self::assertEquals(
new StaticClassMapSourceLocator(
[
Expand All @@ -147,6 +148,7 @@ public function testWillLocateDependencies() : void
$locators[1]
);
self::assertInstanceOf(PhpInternalSourceLocator::class, $locators[2]);
self::assertInstanceOf(StubClassSourceLocator::class, $locators[3]);
}

public function testWillLocateDependenciesEvenWithoutAutoloadFiles() : void
Expand Down Expand Up @@ -180,7 +182,7 @@ public function testWillLocateDependenciesEvenWithoutAutoloadFiles() : void

$locators = $reflectionLocators->getValue($locator);

self::assertCount(3, $locators);
self::assertCount(4, $locators);
self::assertEquals(
new StaticClassMapSourceLocator(
[
Expand All @@ -193,5 +195,6 @@ public function testWillLocateDependenciesEvenWithoutAutoloadFiles() : void
);
self::assertEquals(new AggregateSourceLocator(), $locators[1]);
self::assertInstanceOf(PhpInternalSourceLocator::class, $locators[2]);
self::assertInstanceOf(StubClassSourceLocator::class, $locators[3]);
}
}
81 changes: 81 additions & 0 deletions test/unit/SourceLocator/StubClassSourceLocatorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<?php

declare(strict_types=1);

namespace RoaveTest\BackwardCompatibility\SourceLocator;

use PHPUnit\Framework\TestCase;
use Roave\BackwardCompatibility\SourceLocator\StubClassSourceLocator;
use Roave\BetterReflection\BetterReflection;
use Roave\BetterReflection\Identifier\Identifier;
use Roave\BetterReflection\Identifier\IdentifierType;
use Roave\BetterReflection\Reflection\ReflectionClass;
use Roave\BetterReflection\Reflector\Reflector;

/**
* @covers \Roave\BackwardCompatibility\SourceLocator\StubClassSourceLocator
*/
final class StubClassSourceLocatorTest extends TestCase
{
/** @var StubClassSourceLocator */
private $stubLocator;

/** @var Reflector */
private $reflector;

protected function setUp() : void
{
parent::setUp();

$betterReflection = new BetterReflection();

$this->stubLocator = new StubClassSourceLocator($betterReflection->astLocator());
$this->reflector = $betterReflection->classReflector();
}

public function testWillNotRetrieveSymbolsByType() : void
{
self::assertEmpty($this->stubLocator->locateIdentifiersByType(
$this->reflector,
new IdentifierType(IdentifierType::IDENTIFIER_CLASS)
));
}

public function testWillNotRetrieveFunctionReflections() : void
{
self::assertNull($this->stubLocator->locateIdentifier(
$this->reflector,
new Identifier('foo', new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION))
));
}

public function testWillReflectNonNamespacedClass() : void
{
/** @var ReflectionClass $class */
$class = $this->stubLocator->locateIdentifier(
$this->reflector,
new Identifier('AClass', new IdentifierType(IdentifierType::IDENTIFIER_CLASS))
);

self::assertInstanceOf(ReflectionClass::class, $class);

self::assertSame('AClass', $class->getName());
self::assertTrue($class->isInterface());
self::assertFalse($class->inNamespace());
}

public function testWillReflectNamespacedClass() : void
{
/** @var ReflectionClass $class */
$class = $this->stubLocator->locateIdentifier(
$this->reflector,
new Identifier('Foo\Bar\AClass', new IdentifierType(IdentifierType::IDENTIFIER_CLASS))
);

self::assertInstanceOf(ReflectionClass::class, $class);

self::assertSame('Foo\Bar\AClass', $class->getName());
self::assertTrue($class->isInterface());
self::assertTrue($class->inNamespace());
}
}

0 comments on commit 9e95a60

Please sign in to comment.