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
12 changes: 11 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,16 @@ branches:
- /^feature\/.*$/
- /^optimization\/.*$/

before_script: travis_retry composer install --no-interaction
matrix:
fast_finish: true
include:
- php: '7.0'
env: PHPDOCUMENTOR_REFLECTION_DOCBLOCK="^2.0"

before_script:
- if [ -n "$PHPDOCUMENTOR_REFLECTION_DOCBLOCK" ]; then
composer require "phpdocumentor/reflection-docblock:${PHPDOCUMENTOR_REFLECTION_DOCBLOCK}" --no-update;
fi;
- travis_retry composer update --no-interaction

script: vendor/bin/phpspec run -fpretty -v
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,17 @@
"email": "marcello.duarte@gmail.com"
}
],

"require": {
"php": "^5.3|^7.0",
"phpdocumentor/reflection-docblock": "~2.0",
"sebastian/comparator": "~1.1",
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2",
"sebastian/comparator": "^1.1",
"doctrine/instantiator": "^1.0.2",
"sebastian/recursion-context": "~1.0"
"sebastian/recursion-context": "^1.0"
},

"require-dev": {
"phpspec/phpspec": "~2.0"
"phpspec/phpspec": "^2.0"
},

"autoload": {
Expand Down
24 changes: 13 additions & 11 deletions src/Prophecy/Doubler/ClassPatch/MagicCallPatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,27 @@

namespace Prophecy\Doubler\ClassPatch;

use phpDocumentor\Reflection\DocBlock;
use Prophecy\Doubler\Generator\Node\ClassNode;
use Prophecy\Doubler\Generator\Node\MethodNode;
use Prophecy\PhpDocumentor\ClassAndInterfaceTagRetriever;
use Prophecy\PhpDocumentor\MethodTagRetrieverInterface;

/**
* Discover Magical API using "@method" PHPDoc format.
*
* @author Thomas Tourlourat <thomas@tourlourat.com>
* @author Kévin Dunglas <dunglas@gmail.com>
* @author Théo FIDRY <theo.fidry@gmail.com>
*/
class MagicCallPatch implements ClassPatchInterface
{
private $tagRetriever;

public function __construct(MethodTagRetrieverInterface $tagRetriever = null)
{
$this->tagRetriever = null === $tagRetriever ? new ClassAndInterfaceTagRetriever() : $tagRetriever;
}

/**
* Support any class
*
Expand All @@ -44,15 +54,7 @@ public function apply(ClassNode $node)
$parentClass = $node->getParentClass();
$reflectionClass = new \ReflectionClass($parentClass);

$phpdoc = new DocBlock($reflectionClass->getDocComment());

$tagList = $phpdoc->getTagsByName('method');

$interfaces = $reflectionClass->getInterfaces();
foreach($interfaces as $interface) {
$phpdoc = new DocBlock($interface);
$tagList = array_merge($tagList, $phpdoc->getTagsByName('method'));
}
$tagList = $this->tagRetriever->getTagList($reflectionClass);

foreach($tagList as $tag) {
$methodName = $tag->getMethodName();
Expand All @@ -62,7 +64,7 @@ public function apply(ClassNode $node)
}

if (!$reflectionClass->hasMethod($methodName)) {
$methodNode = new MethodNode($tag->getMethodName());
$methodNode = new MethodNode($methodName);
$methodNode->setStatic($tag->isStatic());

$node->addMethod($methodNode);
Expand Down
69 changes: 69 additions & 0 deletions src/Prophecy/PhpDocumentor/ClassAndInterfaceTagRetriever.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

/*
* This file is part of the Prophecy.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
* Marcello Duarte <marcello.duarte@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Prophecy\PhpDocumentor;

use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
use phpDocumentor\Reflection\DocBlock\Tags\Method;

/**
* @author Théo FIDRY <theo.fidry@gmail.com>
*
* @internal
*/
final class ClassAndInterfaceTagRetriever implements MethodTagRetrieverInterface
{
private $classRetriever;

public function __construct(MethodTagRetrieverInterface $classRetriever = null)
{
if (null !== $classRetriever) {
$this->classRetriever = $classRetriever;

return;
}

$this->classRetriever = class_exists('phpDocumentor\Reflection\DocBlockFactory') && class_exists('phpDocumentor\Reflection\Types\ContextFactory')
? new ClassTagRetriever()
: new LegacyClassTagRetriever()
;
}

/**
* @param \ReflectionClass $reflectionClass
*
* @return LegacyMethodTag[]|Method[]
*/
public function getTagList(\ReflectionClass $reflectionClass)
{
return array_merge(
$this->classRetriever->getTagList($reflectionClass),
$this->getInterfacesTagList($reflectionClass)
);
}

/**
* @param \ReflectionClass $reflectionClass
*
* @return LegacyMethodTag[]|Method[]
*/
private function getInterfacesTagList(\ReflectionClass $reflectionClass)
{
$interfaces = $reflectionClass->getInterfaces();
$tagList = array();

foreach($interfaces as $interface) {
$tagList = array_merge($tagList, $this->classRetriever->getTagList($interface));
}

return $tagList;
}
}
52 changes: 52 additions & 0 deletions src/Prophecy/PhpDocumentor/ClassTagRetriever.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the Prophecy.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
* Marcello Duarte <marcello.duarte@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Prophecy\PhpDocumentor;

use phpDocumentor\Reflection\DocBlock\Tags\Method;
use phpDocumentor\Reflection\DocBlockFactory;
use phpDocumentor\Reflection\Types\ContextFactory;

/**
* @author Théo FIDRY <theo.fidry@gmail.com>
*
* @internal
*/
final class ClassTagRetriever implements MethodTagRetrieverInterface
{
private $docBlockFactory;
private $contextFactory;

public function __construct()
{
$this->docBlockFactory = DocBlockFactory::createInstance();
$this->contextFactory = new ContextFactory();
}

/**
* @param \ReflectionClass $reflectionClass
*
* @return Method[]
*/
public function getTagList(\ReflectionClass $reflectionClass)
{
try {
$phpdoc = $this->docBlockFactory->create(
$reflectionClass,
$this->contextFactory->createFromReflector($reflectionClass)
);

return $phpdoc->getTagsByName('method');
} catch (\InvalidArgumentException $e) {
return array();
}
}
}
35 changes: 35 additions & 0 deletions src/Prophecy/PhpDocumentor/LegacyClassTagRetriever.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

/*
* This file is part of the Prophecy.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
* Marcello Duarte <marcello.duarte@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Prophecy\PhpDocumentor;

use phpDocumentor\Reflection\DocBlock;
use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;

/**
* @author Théo FIDRY <theo.fidry@gmail.com>
*
* @internal
*/
final class LegacyClassTagRetriever implements MethodTagRetrieverInterface
{
/**
* @param \ReflectionClass $reflectionClass
*
* @return LegacyMethodTag[]
*/
public function getTagList(\ReflectionClass $reflectionClass)
{
$phpdoc = new DocBlock($reflectionClass->getDocComment());

return $phpdoc->getTagsByName('method');
}
}
30 changes: 30 additions & 0 deletions src/Prophecy/PhpDocumentor/MethodTagRetrieverInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

/*
* This file is part of the Prophecy.
* (c) Konstantin Kudryashov <ever.zet@gmail.com>
* Marcello Duarte <marcello.duarte@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Prophecy\PhpDocumentor;

use phpDocumentor\Reflection\DocBlock\Tag\MethodTag as LegacyMethodTag;
use phpDocumentor\Reflection\DocBlock\Tags\Method;

/**
* @author Théo FIDRY <theo.fidry@gmail.com>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please mark this interface and all its implementations as @internal

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

*
* @internal
*/
interface MethodTagRetrieverInterface
{
/**
* @param \ReflectionClass $reflectionClass
*
* @return LegacyMethodTag[]|Method[]
*/
public function getTagList(\ReflectionClass $reflectionClass);
}