Permalink
Browse files

Merge pull request #1004 from ApiGen/nelson

Fixes in @see annotations, added tests
  • Loading branch information...
vlastavesely committed Oct 1, 2017
2 parents 9ada55b + 8fbaaa6 commit e381f7cef4194571cc9303a5fa8842a352d7eabb
View
@@ -11,7 +11,7 @@
"bin": ["bin/apigen"],
"require": {
"php": "^7.1",
"roave/better-reflection": "dev-master#a402048",
"roave/better-reflection": "dev-master#c87d856",
"kukulich/fshl": "^2.1",
"latte/latte": "^2.4",
@@ -33,7 +33,7 @@
"tracy/tracy": "^2.4",
"phpunit/phpunit": "^6.0",
"phpstan/phpstan": "^0.8",
"symplify/easy-coding-standard": "^2.2"
"symplify/easy-coding-standard": "2.3.1"
},
"autoload": {
"psr-4": {
@@ -64,7 +64,8 @@
"packages/Reflection/tests/Reflection/Function_/FunctionParameterReflection/Source/functionWithConstant.php",
"packages/Reflection/tests/Reflection/Function_/FunctionParameterReflection/Source/functionWithVariadic.php",
"packages/Reflection/tests/Reflection/Function_/FunctionParameterReflection/Source/functionWithClass.php",
"packages/Annotation/tests/AnnotationSubscriber/SeeAnnotationSubscriberSource/SomeClassWithSeeAnnotations.php"
"packages/Annotation/tests/AnnotationSubscriber/SeeAnnotationSubscriberSource/SomeClassWithSeeAnnotations.php",
"packages/Annotation/tests/AnnotationSubscriber/SeeAnnotationSubscriberSource/SomeFunction.php"
]
},
"scripts": {
@@ -32,6 +32,7 @@ parameters:
- PhpCsFixer\Fixer\Phpdoc\PhpdocAlignFixer
- PhpCsFixer\Fixer\Operator\NewWithBracesFixer
- PhpCsFixer\Fixer\Phpdoc\PhpdocInlineTagFixer
- PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer
# resolve later
- Symplify\CodingStandard\Sniffs\DependencyInjection\NoClassInstantiationSniff
@@ -3,10 +3,13 @@
namespace ApiGen\Annotation\FqsenResolver;
use ApiGen\Reflection\Contract\Reflection\AbstractReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Class_\AbstractClassElementInterface;
use ApiGen\Reflection\Contract\Reflection\Class_\ClassMethodReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Class_\ClassPropertyReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Class_\ClassReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Function_\FunctionReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Interface_\AbstractInterfaceElementInterface;
use ApiGen\Reflection\Contract\Reflection\Trait_\AbstractTraitElementInterface;
use ApiGen\Reflection\ReflectionStorage;
use Nette\Utils\Strings;
use phpDocumentor\Reflection\FqsenResolver;
@@ -45,10 +48,7 @@ public function __construct(
*/
public function resolveReflectionFromNameAndReflection(string $name, AbstractReflectionInterface $reflection)
{
$reflectionName = $reflection->getName();
if ($reflection instanceof ClassMethodReflectionInterface) {
$reflectionName = $reflection->getDeclaringClassName();
}
$reflectionName = $this->getReflectionName($reflection);
$isProperty = false;
$propertyName = '';
@@ -73,7 +73,7 @@ public function resolveReflectionFromNameAndReflection(string $name, AbstractRef
}
if ($isFunction) {
$namespace = $reflection->getDeclaringClass()->getNamespaceName();
$namespace = $this->getNamespace($reflection);
$functionReflections = $this->reflectionStorage->getFunctionReflections();
$namespacedFunctionName = $namespace . '\\' . $functionName;
@@ -87,23 +87,65 @@ public function resolveReflectionFromNameAndReflection(string $name, AbstractRef
$classReflectionName = ltrim($classReflectionName, '\\');
// @todo return only string on non resolved existing class
$classReflections = $this->reflectionStorage->getClassReflections();
/** @var ClassReflectionInterface|InterfaceReflectionInterface|TraitReflectionInterface */
$classyReflection = $this->getClassyReflection($classReflectionName);
if (! isset($classReflections[$classReflectionName])) {
if ($classyReflection === null) {
// @todo or autoresolve class that exists?
return $name;
}
$classReflection = $classReflections[$classReflectionName];
if ($isProperty) {
return $classReflection->getProperty($propertyName);
return $classyReflection->getProperty($propertyName);
}
if ($isMethod) {
return $classReflection->getMethod($methodName);
return $classyReflection->getMethod($methodName);
}
return $classyReflection;
}
private function getReflectionName(AbstractReflectionInterface $reflection): string
{
if ($reflection instanceof AbstractClassElementInterface) {
return $reflection->getDeclaringClassName();
} elseif ($reflection instanceof AbstractInterfaceElementInterface) {
return $reflection->getDeclaringInterfaceName();
} elseif ($reflection instanceof AbstractTraitElementInterface) {
return $reflection->getDeclaringTraitName();
}
return $reflection->getName();
}
private function getClassyReflection(string $name): ?AbstractReflectionInterface
{
$classyReflections = $this->reflectionStorage->getClassReflections() +
$this->reflectionStorage->getInterfaceReflections() +
$this->reflectionStorage->getTraitReflections();
foreach ($classyReflections as $reflection) {
if ($reflection->getName() === $name) {
return $reflection;
}
}
return null;
}
private function getNamespace(AbstractReflectionInterface $reflection): ?string
{
if ($reflection instanceof AbstractClassElementInterface) {
return $reflection->getDeclaringClass()->getNamespaceName();
} elseif ($reflection instanceof AbstractInterfaceElementInterface) {
return $reflection->getDeclaringInterface()->getNamespaceName();
} elseif ($reflection instanceof AbstractTraitElementInterface) {
return $reflection->getDeclaringTrait()->getNamespaceName();
} elseif ($reflection instanceof FunctionReflectionInterface) {
return $reflection->getNamespaceName();
}
return $classReflection;
return null;
}
}
@@ -0,0 +1,13 @@
<?php declare(strict_types=1);
namespace ApiGen\Annotation\Tests\AnnotationSubscriber\SeeAnnotationSubscriberSource;
interface InterfaceWithSeeAnnotationsInterface
{
/**
* Test.
*
* @see SomeClassWithSeeAnnotations::returnArray()
*/
public function someSexyMethod(): int;
}
@@ -0,0 +1,16 @@
<?php declare(strict_types=1);
namespace ApiGen\Annotation\Tests\AnnotationSubscriber\SeeAnnotationSubscriberSource;
function anotherFunction(): void
{
}
/**
* Test.
*
* @see anotherFunction()
*/
function someFunction(): void
{
}
@@ -4,9 +4,12 @@
use ApiGen\Annotation\AnnotationDecorator;
use ApiGen\Annotation\AnnotationList;
use ApiGen\Annotation\Tests\AnnotationSubscriber\SeeAnnotationSubscriberSource\InterfaceWithSeeAnnotationsInterface;
use ApiGen\Annotation\Tests\AnnotationSubscriber\SeeAnnotationSubscriberSource\SomeClassWithSeeAnnotations;
use ApiGen\Reflection\Contract\Reflection\Class_\ClassMethodReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Class_\ClassReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Function_\FunctionReflectionInterface;
use ApiGen\Reflection\Contract\Reflection\Interface_\InterfaceReflectionInterface;
use ApiGen\Tests\AbstractParserAwareTestCase;
final class SeeAnnotationSubscriberTest extends AbstractParserAwareTestCase
@@ -26,13 +29,29 @@
*/
private $methodReflection;
/**
* @var FunctionReflectionInterface
*/
private $functionReflection;
/**
* @var InterfaceReflectionInterface
*/
private $interfaceReflection;
protected function setUp(): void
{
$this->parser->parseFilesAndDirectories([__DIR__ . '/SeeAnnotationSubscriberSource']);
$this->annotationDecorator = $this->container->get(AnnotationDecorator::class);
$this->classReflection = $this->reflectionStorage->getClassReflections()[SomeClassWithSeeAnnotations::class];
$this->methodReflection = $this->classReflection->getMethod('returnArray');
$this->functionReflection = $this->reflectionStorage->getFunctionReflections()[
'ApiGen\Annotation\Tests\AnnotationSubscriber\SeeAnnotationSubscriberSource\someFunction'
];
$this->interfaceReflection = $this->reflectionStorage->getInterfaceReflections()[
InterfaceWithSeeAnnotationsInterface::class
];
}
public function testPropertyOnMissingClassReflection(): void
@@ -89,6 +108,14 @@ public function testMissingFunction(): void
public function testFunction(): void
{
$seeFunctionAnnotation = $this->functionReflection->getAnnotation(AnnotationList::SEE)[0];
$this->assertSame(
'<code><a href="function-ApiGen.Annotation.Tests.AnnotationSubscriber.SeeAnnotationSubscriberSource'
. '.anotherFunction.html">anotherFunction()</a></code>',
$this->annotationDecorator->decorate($seeFunctionAnnotation, $this->functionReflection)
);
$seeFunctionAnnotation = $this->methodReflection->getAnnotation(AnnotationList::SEE)[5];
$this->assertSame(
@@ -97,4 +124,16 @@ public function testFunction(): void
$this->annotationDecorator->decorate($seeFunctionAnnotation, $this->methodReflection)
);
}
public function testInterface(): void
{
$seeMethodAnnotation = $this->interfaceReflection->getMethod('someSexyMethod')
->getAnnotation(AnnotationList::SEE)[0];
$this->assertSame(
'<code><a href="class-ApiGen.Annotation.Tests.AnnotationSubscriber.SeeAnnotationSubscriberSource'
. '.SomeClassWithSeeAnnotations.html#_returnArray">SomeClassWithSeeAnnotations::returnArray()</a></code>',
$this->annotationDecorator->decorate($seeMethodAnnotation, $this->interfaceReflection)
);
}
}
@@ -2,6 +2,7 @@
namespace ApiGen\BetterReflection\SourceLocator;
use Roave\BetterReflection\SourceLocator\Ast\Locator as AstLocator;
use Roave\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\ComposerSourceLocator;
use Roave\BetterReflection\SourceLocator\Type\SourceLocator;
@@ -19,6 +20,16 @@
*/
private const STANDARD_AUTOLOAD_LOCATION = '/vendor/autoload.php';
/**
* @var AstLocator
*/
private $astLocator;
public function __construct(AstLocator $astLocator)
{
$this->astLocator = $astLocator;
}
/**
* @param string[] $directories
*/
@@ -58,6 +69,6 @@ private function createAutoloadPath(string $directory): string
*/
private function createComposerSourceLocator(string $autoloadPath): ComposerSourceLocator
{
return new ComposerSourceLocator(include $autoloadPath);
return new ComposerSourceLocator(include $autoloadPath, $this->astLocator);
}
}
@@ -7,8 +7,7 @@ services:
# cached AST Locator
Roave\BetterReflection\SourceLocator\Ast\PhpParserLocator: ~
Roave\BetterReflection\SourceLocator\Ast\Locator:
alias: Roave\BetterReflection\SourceLocator\Ast\PhpParserLocator
Roave\BetterReflection\SourceLocator\Ast\Locator: ~
# nikic\PHP-Parser
PhpParser\Parser:
@@ -193,7 +193,7 @@ private function parseClassElements(SourceLocator $sourceLocator): void
private function parseFunctions(SourceLocator $sourceLocator): void
{
$functionReflector = new FunctionReflector($sourceLocator);
$functionReflector = new FunctionReflector($sourceLocator, new ClassReflector($sourceLocator));
$functionReflections = $this->transformBetterFunctionReflections($functionReflector);
$this->reflectionStorage->setFunctionReflections($functionReflections);
}
@@ -33,7 +33,7 @@ public function __construct(ReflectionParameter $betterParameterReflection)
public function getTypeHint(): string
{
$types = (string) $this->betterParameterReflection->getTypeHint();
$types = (string) $this->betterParameterReflection->getType();
$types = $this->removeClassPreSlashes($types);
if ($types) {
return $types;
@@ -0,0 +1,47 @@
<?php declare(strict_types=1);
namespace ApiGen\Reflection\Tests\Parser;
use ApiGen\Reflection\Parser\Parser;
use ApiGen\Reflection\ReflectionStorage;
use ApiGen\Reflection\Tests\Parser\Source\ChildOfObject;
use ApiGen\Reflection\Tests\Parser\Source\Object;
use ApiGen\Tests\AbstractContainerAwareTestCase;
final class ObjectClassTest extends AbstractContainerAwareTestCase
{
/**
* @var Parser
*/
private $parser;
/**
* @var ReflectionStorage
*/
private $reflectionStorage;
public function setUp(): void
{
$this->parser = $this->container->get(Parser::class);
$this->parser->parseFilesAndDirectories([__DIR__ . '/Source']);
$this->reflectionStorage = $this->container->get(ReflectionStorage::class);
}
public function testDirect(): void
{
$classReflections = $this->reflectionStorage->getClassReflections();
$this->assertCount(4, $classReflections);
$this->assertArrayHasKey(Object::class, $classReflections);
$this->assertSame(Object::class, $classReflections[Object::class]->getName());
}
public function testGetParent(): void
{
$classReflections = $this->reflectionStorage->getClassReflections();
$classReflection = $classReflections[ChildOfObject::class]->getParentClass();
$this->assertSame(Object::class, $classReflection->getName());
}
}
@@ -14,7 +14,7 @@ public function test(): void
$this->parser->parseFilesAndDirectories([__DIR__ . '/Source']);
$classReflections = $this->reflectionStorage->getClassReflections();
$this->assertCount(2, $classReflections);
$this->assertCount(4, $classReflections);
$classReflection = $classReflections[ClassWithParentFromAnotherSource::class];
@@ -0,0 +1,7 @@
<?php declare(strict_types=1);
namespace ApiGen\Reflection\Tests\Parser\Source;
final class ChildOfObject extends Object
{
}
@@ -0,0 +1,7 @@
<?php declare(strict_types=1);
namespace ApiGen\Reflection\Tests\Parser\Source;
class Object
{
}

0 comments on commit e381f7c

Please sign in to comment.