mirror of
https://github.com/rectorphp/rector.git
synced 2024-07-02 23:53:30 +00:00
add Sensio TemplateTagValueNode
This commit is contained in:
parent
8811c900ea
commit
e6de2a7d38
|
@ -87,7 +87,10 @@
|
||||||
"Rector\\TypeDeclaration\\": "packages/TypeDeclaration/src",
|
"Rector\\TypeDeclaration\\": "packages/TypeDeclaration/src",
|
||||||
"Rector\\Utils\\DocumentationGenerator\\": "utils/DocumentationGenerator/src",
|
"Rector\\Utils\\DocumentationGenerator\\": "utils/DocumentationGenerator/src",
|
||||||
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src"
|
"Rector\\Utils\\RectorGenerator\\": "utils/RectorGenerator/src"
|
||||||
}
|
},
|
||||||
|
"classmap": [
|
||||||
|
"stubs"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
1
ecs.yaml
1
ecs.yaml
|
@ -57,6 +57,7 @@ parameters:
|
||||||
- '*tests/*/Fixture/*'
|
- '*tests/*/Fixture/*'
|
||||||
- '*tests/*/Expected/*'
|
- '*tests/*/Expected/*'
|
||||||
- '*utils/ContributorTools/templates/*'
|
- '*utils/ContributorTools/templates/*'
|
||||||
|
- 'stubs/*'
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff.Underscore: ~
|
PHP_CodeSniffer\Standards\PSR2\Sniffs\Methods\MethodDeclarationSniff.Underscore: ~
|
||||||
|
|
|
@ -282,6 +282,22 @@ final class PhpDocInfo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $type
|
||||||
|
*/
|
||||||
|
public function matchChildValueNodeOfType(string $type): ?PhpDocTagValueNode
|
||||||
|
{
|
||||||
|
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
||||||
|
if ($phpDocChildNode instanceof PhpDocTagNode) {
|
||||||
|
if (is_a($phpDocChildNode->value, $type, true)) {
|
||||||
|
return $phpDocChildNode->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
|
private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
|
||||||
{
|
{
|
||||||
$phpDocNode = $this->getPhpDocNode();
|
$phpDocNode = $this->getPhpDocNode();
|
||||||
|
@ -308,20 +324,4 @@ final class PhpDocInfo
|
||||||
|
|
||||||
return $phpDocTagValueNode->getAttribute(Attribute::TYPE_AS_ARRAY);
|
return $phpDocTagValueNode->getAttribute(Attribute::TYPE_AS_ARRAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $type
|
|
||||||
*/
|
|
||||||
private function matchChildValueNodeOfType(string $type): ?PhpDocTagValueNode
|
|
||||||
{
|
|
||||||
foreach ($this->phpDocNode->children as $phpDocChildNode) {
|
|
||||||
if ($phpDocChildNode instanceof PhpDocTagNode) {
|
|
||||||
if (is_a($phpDocChildNode->value, $type, true)) {
|
|
||||||
return $phpDocChildNode->value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\BetterPhpDocParser\PhpDocParser;
|
||||||
|
|
||||||
|
use Nette\Utils\Strings;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||||
|
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||||
|
use Rector\Configuration\CurrentNodeProvider;
|
||||||
|
use Rector\DoctrinePhpDocParser\AnnotationReader\NodeAnnotationReader;
|
||||||
|
|
||||||
|
abstract class AbstractPhpDocParser
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var NodeAnnotationReader
|
||||||
|
*/
|
||||||
|
protected $nodeAnnotationReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var CurrentNodeProvider
|
||||||
|
*/
|
||||||
|
private $currentNodeProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @required
|
||||||
|
*/
|
||||||
|
public function autowireAbstractPhpDocParser(
|
||||||
|
CurrentNodeProvider $currentNodeProvider,
|
||||||
|
NodeAnnotationReader $nodeAnnotationReader
|
||||||
|
): void {
|
||||||
|
$this->currentNodeProvider = $currentNodeProvider;
|
||||||
|
$this->nodeAnnotationReader = $nodeAnnotationReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCurrentPhpNode(): Node
|
||||||
|
{
|
||||||
|
return $this->currentNodeProvider->getNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function resolveAnnotationContent(TokenIterator $tokenIterator): string
|
||||||
|
{
|
||||||
|
$clonedTokenIterator = clone $tokenIterator;
|
||||||
|
|
||||||
|
$singleLineContent = $clonedTokenIterator->joinUntil(
|
||||||
|
Lexer::TOKEN_END,
|
||||||
|
Lexer::TOKEN_PHPDOC_EOL,
|
||||||
|
Lexer::TOKEN_CLOSE_PHPDOC
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($singleLineContent === '' || Strings::match($singleLineContent, '#^\((.*?)\)$#m')) {
|
||||||
|
$annotationContent = $singleLineContent;
|
||||||
|
$tokenIterator->joinUntil(Lexer::TOKEN_END, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC);
|
||||||
|
} else { // multiline - content
|
||||||
|
// skip all tokens for this annotation, so next annotation can work with tokens after this one
|
||||||
|
$annotationContent = $tokenIterator->joinUntil(Lexer::TOKEN_END, Lexer::TOKEN_CLOSE_PHPDOC);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->cleanMultilineAnnotationContent($annotationContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function cleanMultilineAnnotationContent(string $annotationContent): string
|
||||||
|
{
|
||||||
|
return Strings::replace($annotationContent, '#(\s+)\*(\s+)#m', '$1$3');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc;
|
||||||
|
|
||||||
|
use Nette\Utils\Json;
|
||||||
|
use Nette\Utils\Strings;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||||
|
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||||
|
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
||||||
|
|
||||||
|
abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpDocTagValueNode
|
||||||
|
{
|
||||||
|
use AttributeTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $item
|
||||||
|
*/
|
||||||
|
protected function printArrayItem(array $item, string $key): string
|
||||||
|
{
|
||||||
|
$json = Json::encode($item);
|
||||||
|
$json = Strings::replace($json, '#,#', ', ');
|
||||||
|
$json = Strings::replace($json, '#\[(.*?)\]#', '{$1}');
|
||||||
|
|
||||||
|
return sprintf('%s=%s', $key, $json);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,12 +5,15 @@ namespace Rector\DoctrinePhpDocParser\AnnotationReader;
|
||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use Doctrine\Common\Annotations\AnnotationReader;
|
||||||
use Doctrine\ORM\Mapping\Annotation;
|
use Doctrine\ORM\Mapping\Annotation;
|
||||||
use PhpParser\Node\Stmt\Class_;
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\ClassMethod;
|
||||||
use PhpParser\Node\Stmt\Property;
|
use PhpParser\Node\Stmt\Property;
|
||||||
use Rector\Exception\ShouldNotHappenException;
|
use Rector\Exception\ShouldNotHappenException;
|
||||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
|
use ReflectionMethod;
|
||||||
use ReflectionProperty;
|
use ReflectionProperty;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
final class NodeAnnotationReader
|
final class NodeAnnotationReader
|
||||||
{
|
{
|
||||||
|
@ -30,6 +33,19 @@ final class NodeAnnotationReader
|
||||||
$this->nameResolver = $nameResolver;
|
$this->nameResolver = $nameResolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function readMethodAnnotation(ClassMethod $classMethod, string $annotationClassName): Template
|
||||||
|
{
|
||||||
|
/** @var string $className */
|
||||||
|
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
|
||||||
|
|
||||||
|
/** @var string $methodName */
|
||||||
|
$methodName = $this->nameResolver->getName($classMethod);
|
||||||
|
|
||||||
|
$reflectionMethod = new ReflectionMethod($className, $methodName);
|
||||||
|
|
||||||
|
return $this->annotationReader->getMethodAnnotation($reflectionMethod, $annotationClassName);
|
||||||
|
}
|
||||||
|
|
||||||
public function readDoctrineClassAnnotation(Class_ $class, string $annotationClassName): Annotation
|
public function readDoctrineClassAnnotation(Class_ $class, string $annotationClassName): Annotation
|
||||||
{
|
{
|
||||||
$classReflection = $this->createClassReflectionFromNode($class);
|
$classReflection = $this->createClassReflectionFromNode($class);
|
||||||
|
|
|
@ -2,35 +2,18 @@
|
||||||
|
|
||||||
namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc;
|
namespace Rector\DoctrinePhpDocParser\Ast\PhpDoc;
|
||||||
|
|
||||||
use Nette\Utils\Json;
|
|
||||||
use Nette\Utils\Strings;
|
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
use Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc\AbstractTagValueNode;
|
||||||
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
|
||||||
use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
|
use Rector\DoctrinePhpDocParser\Array_\ArrayItemStaticHelper;
|
||||||
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
|
use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
|
||||||
|
|
||||||
abstract class AbstractDoctrineTagValueNode implements AttributeAwareNodeInterface, DoctrineTagNodeInterface
|
abstract class AbstractDoctrineTagValueNode extends AbstractTagValueNode implements DoctrineTagNodeInterface
|
||||||
{
|
{
|
||||||
use AttributeTrait;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]|null
|
* @var string[]|null
|
||||||
*/
|
*/
|
||||||
protected $orderedVisibleItems;
|
protected $orderedVisibleItems;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param mixed[] $item
|
|
||||||
*/
|
|
||||||
protected function printArrayItem(array $item, string $key): string
|
|
||||||
{
|
|
||||||
$json = Json::encode($item);
|
|
||||||
$json = Strings::replace($json, '#,#', ', ');
|
|
||||||
$json = Strings::replace($json, '#\[(.*?)\]#', '{$1}');
|
|
||||||
|
|
||||||
return sprintf('%s=%s', $key, $json);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $contentItems
|
* @param string[] $contentItems
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,10 +16,8 @@ use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt\Class_;
|
use PhpParser\Node\Stmt\Class_;
|
||||||
use PhpParser\Node\Stmt\Property;
|
use PhpParser\Node\Stmt\Property;
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
|
||||||
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||||
use Rector\Configuration\CurrentNodeProvider;
|
use Rector\BetterPhpDocParser\PhpDocParser\AbstractPhpDocParser;
|
||||||
use Rector\DoctrinePhpDocParser\AnnotationReader\NodeAnnotationReader;
|
|
||||||
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_\EntityTagValueNode;
|
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Class_\EntityTagValueNode;
|
||||||
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\ColumnTagValueNode;
|
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\ColumnTagValueNode;
|
||||||
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\IdTagValueNode;
|
use Rector\DoctrinePhpDocParser\Ast\PhpDoc\Property_\IdTagValueNode;
|
||||||
|
@ -34,66 +32,31 @@ use Rector\DoctrinePhpDocParser\Contract\Ast\PhpDoc\DoctrineTagNodeInterface;
|
||||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses following ORM annotations:
|
* Parses various ORM annotations
|
||||||
* - ORM\Entity
|
|
||||||
*/
|
*/
|
||||||
final class OrmTagParser
|
final class OrmTagParser extends AbstractPhpDocParser
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* @var CurrentNodeProvider
|
|
||||||
*/
|
|
||||||
private $currentNodeProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var NodeAnnotationReader
|
|
||||||
*/
|
|
||||||
private $nodeAnnotationReader;
|
|
||||||
|
|
||||||
public function __construct(
|
|
||||||
CurrentNodeProvider $currentNodeProvider,
|
|
||||||
NodeAnnotationReader $nodeAnnotationReader
|
|
||||||
) {
|
|
||||||
$this->currentNodeProvider = $currentNodeProvider;
|
|
||||||
$this->nodeAnnotationReader = $nodeAnnotationReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
||||||
{
|
{
|
||||||
/** @var Class_|Property $node */
|
/** @var Class_|Property $currentPhpNode */
|
||||||
$node = $this->currentNodeProvider->getNode();
|
$currentPhpNode = $this->getCurrentPhpNode();
|
||||||
|
|
||||||
$clonedTokenIterator = clone $tokenIterator;
|
$annotationContent = $this->resolveAnnotationContent($tokenIterator);
|
||||||
|
|
||||||
$singleLineContent = $clonedTokenIterator->joinUntil(
|
|
||||||
Lexer::TOKEN_END,
|
|
||||||
Lexer::TOKEN_PHPDOC_EOL,
|
|
||||||
Lexer::TOKEN_CLOSE_PHPDOC
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($singleLineContent === '' || Strings::match($singleLineContent, '#^\((.*?)\)$#m')) {
|
|
||||||
$annotationContent = $singleLineContent;
|
|
||||||
$tokenIterator->joinUntil(Lexer::TOKEN_END, Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC);
|
|
||||||
} else { // multiline - content
|
|
||||||
// skip all tokens for this annotation, so next annotation can work with tokens after this one
|
|
||||||
$annotationContent = $tokenIterator->joinUntil(Lexer::TOKEN_END, Lexer::TOKEN_CLOSE_PHPDOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
$annotationContent = $this->cleanMultilineAnnotationContent($annotationContent);
|
|
||||||
|
|
||||||
// Entity tags
|
// Entity tags
|
||||||
if ($node instanceof Class_) {
|
if ($currentPhpNode instanceof Class_) {
|
||||||
if ($tag === EntityTagValueNode::SHORT_NAME) {
|
if ($tag === EntityTagValueNode::SHORT_NAME) {
|
||||||
return $this->createEntityTagValueNode($node, $annotationContent);
|
return $this->createEntityTagValueNode($currentPhpNode, $annotationContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($tag === TableTagValueNode::SHORT_NAME) {
|
if ($tag === TableTagValueNode::SHORT_NAME) {
|
||||||
return $this->createTableTagValueNode($node, $annotationContent);
|
return $this->createTableTagValueNode($currentPhpNode, $annotationContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Property tags
|
// Property tags
|
||||||
if ($node instanceof Property) {
|
if ($currentPhpNode instanceof Property) {
|
||||||
return $this->createPropertyTagValueNode($tag, $node, $annotationContent);
|
return $this->createPropertyTagValueNode($tag, $currentPhpNode, $annotationContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -142,20 +105,25 @@ final class OrmTagParser
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createEntityTagValueNode(Class_ $node, string $annotationContent): EntityTagValueNode
|
private function createIdTagValueNode(): IdTagValueNode
|
||||||
|
{
|
||||||
|
return new IdTagValueNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createEntityTagValueNode(Class_ $class, string $annotationContent): EntityTagValueNode
|
||||||
{
|
{
|
||||||
/** @var Entity $entity */
|
/** @var Entity $entity */
|
||||||
$entity = $this->nodeAnnotationReader->readDoctrineClassAnnotation($node, Entity::class);
|
$entity = $this->nodeAnnotationReader->readDoctrineClassAnnotation($class, Entity::class);
|
||||||
|
|
||||||
return new EntityTagValueNode($entity->repositoryClass, $entity->readOnly, $this->resolveAnnotationItemsOrder(
|
return new EntityTagValueNode($entity->repositoryClass, $entity->readOnly, $this->resolveAnnotationItemsOrder(
|
||||||
$annotationContent
|
$annotationContent
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createTableTagValueNode(Class_ $node, string $annotationContent): TableTagValueNode
|
private function createTableTagValueNode(Class_ $class, string $annotationContent): TableTagValueNode
|
||||||
{
|
{
|
||||||
/** @var Table $table */
|
/** @var Table $table */
|
||||||
$table = $this->nodeAnnotationReader->readDoctrineClassAnnotation($node, Table::class);
|
$table = $this->nodeAnnotationReader->readDoctrineClassAnnotation($class, Table::class);
|
||||||
|
|
||||||
return new TableTagValueNode(
|
return new TableTagValueNode(
|
||||||
$table->name,
|
$table->name,
|
||||||
|
@ -348,14 +316,4 @@ final class OrmTagParser
|
||||||
$annotationContent
|
$annotationContent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function cleanMultilineAnnotationContent(string $annotationContent): string
|
|
||||||
{
|
|
||||||
return Strings::replace($annotationContent, '#(\s+)\*(\s+)#m', '$1$3');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createIdTagValueNode(): IdTagValueNode
|
|
||||||
{
|
|
||||||
return new IdTagValueNode();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,4 +5,4 @@ services:
|
||||||
|
|
||||||
Rector\Sensio\:
|
Rector\Sensio\:
|
||||||
resource: '../src/'
|
resource: '../src/'
|
||||||
exclude: '../src/{Rector/**/*Rector.php}'
|
exclude: '../src/{Rector/**/*Rector.php,PhpDocParser/Ast/PhpDoc/*}'
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Sensio\Extension;
|
||||||
|
|
||||||
|
use Nette\Utils\Strings;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||||
|
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||||
|
use Rector\BetterPhpDocParser\Contract\PhpDocParserExtensionInterface;
|
||||||
|
use Rector\Sensio\PhpDocParser\SensioPhpDocTagParser;
|
||||||
|
|
||||||
|
final class SensioPhpDocParserExtension implements PhpDocParserExtensionInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var SensioPhpDocTagParser
|
||||||
|
*/
|
||||||
|
private $sensioPhpDocTagParser;
|
||||||
|
|
||||||
|
public function __construct(SensioPhpDocTagParser $sensioPhpDocTagParser)
|
||||||
|
{
|
||||||
|
$this->sensioPhpDocTagParser = $sensioPhpDocTagParser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function matchTag(string $tag): bool
|
||||||
|
{
|
||||||
|
return (bool) Strings::match($tag, '#^@Template$#');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
||||||
|
{
|
||||||
|
return $this->sensioPhpDocTagParser->parse($tokenIterator, $tag);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Sensio\PhpDocParser\Ast\PhpDoc;
|
||||||
|
|
||||||
|
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
||||||
|
use Rector\BetterPhpDocParser\PhpDocParser\Ast\PhpDoc\AbstractTagValueNode;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
|
final class TemplateTagValueNode extends AbstractTagValueNode
|
||||||
|
{
|
||||||
|
use AttributeTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const SHORT_NAME = '@Template';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const CLASS_NAME = Template::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string|null
|
||||||
|
*/
|
||||||
|
private $template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed[]
|
||||||
|
*/
|
||||||
|
private $owner = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed[]
|
||||||
|
*/
|
||||||
|
private $vars = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed[] $owner
|
||||||
|
* @param mixed[] $vars
|
||||||
|
*/
|
||||||
|
public function __construct(?string $template, array $owner, array $vars)
|
||||||
|
{
|
||||||
|
$this->template = $template;
|
||||||
|
$this->owner = $owner;
|
||||||
|
$this->vars = $vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
$contentItems = [];
|
||||||
|
|
||||||
|
if ($this->template) {
|
||||||
|
$contentItems[] = $this->template;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->owner) {
|
||||||
|
$contentItems[] = $this->printArrayItem($this->owner, 'owner');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->vars) {
|
||||||
|
$contentItems[] = $this->printArrayItem($this->vars, 'vars');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($contentItems === []) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(', ', $contentItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTemplate(): ?string
|
||||||
|
{
|
||||||
|
return $this->template;
|
||||||
|
}
|
||||||
|
}
|
60
packages/Sensio/src/PhpDocParser/SensioPhpDocTagParser.php
Normal file
60
packages/Sensio/src/PhpDocParser/SensioPhpDocTagParser.php
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Sensio\PhpDocParser;
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\AnnotationException;
|
||||||
|
use Nette\Utils\Strings;
|
||||||
|
use PhpParser\Node\Stmt\ClassMethod;
|
||||||
|
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||||
|
use PHPStan\PhpDocParser\Parser\TokenIterator;
|
||||||
|
use Rector\BetterPhpDocParser\PhpDocParser\AbstractPhpDocParser;
|
||||||
|
use Rector\Sensio\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
|
final class SensioPhpDocTagParser extends AbstractPhpDocParser
|
||||||
|
{
|
||||||
|
public function parse(TokenIterator $tokenIterator, string $tag): ?PhpDocTagValueNode
|
||||||
|
{
|
||||||
|
$currentPhpNode = $this->getCurrentPhpNode();
|
||||||
|
|
||||||
|
// this is needed to append tokens to the end of annotation, even if not used
|
||||||
|
$this->resolveAnnotationContent($tokenIterator);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($currentPhpNode instanceof ClassMethod) {
|
||||||
|
if ($tag === TemplateTagValueNode::SHORT_NAME) {
|
||||||
|
return $this->createTemplateTagValueNode($currentPhpNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (AnnotationException $annotationException) {
|
||||||
|
// this not an annotation we look for, just having the same ending
|
||||||
|
if (Strings::match(
|
||||||
|
$annotationException->getMessage(),
|
||||||
|
'#\[Semantical Error\] The annotation (.*) in (.*?) was never imported. ' .
|
||||||
|
'Did you maybe forget to add a "use" statement for this annotation?#s'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $annotationException;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createTemplateTagValueNode(ClassMethod $classMethod): TemplateTagValueNode
|
||||||
|
{
|
||||||
|
/** @var Template $templateAnnotation */
|
||||||
|
$templateAnnotation = $this->nodeAnnotationReader->readMethodAnnotation(
|
||||||
|
$classMethod,
|
||||||
|
TemplateTagValueNode::CLASS_NAME
|
||||||
|
);
|
||||||
|
|
||||||
|
return new TemplateTagValueNode(
|
||||||
|
$templateAnnotation->getTemplate(),
|
||||||
|
$templateAnnotation->getOwner(),
|
||||||
|
$templateAnnotation->getVars()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,18 +2,20 @@
|
||||||
|
|
||||||
namespace Rector\Sensio\Rector\FrameworkExtraBundle;
|
namespace Rector\Sensio\Rector\FrameworkExtraBundle;
|
||||||
|
|
||||||
use Nette\Utils\Strings;
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Arg;
|
use PhpParser\Node\Arg;
|
||||||
use PhpParser\Node\Expr\Array_;
|
use PhpParser\Node\Expr\Array_;
|
||||||
use PhpParser\Node\Expr\MethodCall;
|
use PhpParser\Node\Expr\MethodCall;
|
||||||
use PhpParser\Node\Stmt\ClassMethod;
|
use PhpParser\Node\Stmt\ClassMethod;
|
||||||
use PhpParser\Node\Stmt\Return_;
|
use PhpParser\Node\Stmt\Return_;
|
||||||
|
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
|
||||||
|
use Rector\Exception\ShouldNotHappenException;
|
||||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
|
||||||
use Rector\Rector\AbstractRector;
|
use Rector\Rector\AbstractRector;
|
||||||
use Rector\RectorDefinition\CodeSample;
|
use Rector\RectorDefinition\CodeSample;
|
||||||
use Rector\RectorDefinition\RectorDefinition;
|
use Rector\RectorDefinition\RectorDefinition;
|
||||||
use Rector\Sensio\Helper\TemplateGuesser;
|
use Rector\Sensio\Helper\TemplateGuesser;
|
||||||
|
use Rector\Sensio\PhpDocParser\Ast\PhpDoc\TemplateTagValueNode;
|
||||||
|
|
||||||
final class TemplateAnnotationRector extends AbstractRector
|
final class TemplateAnnotationRector extends AbstractRector
|
||||||
{
|
{
|
||||||
|
@ -81,7 +83,7 @@ CODE_SAMPLE
|
||||||
*/
|
*/
|
||||||
public function refactor(Node $node): ?Node
|
public function refactor(Node $node): ?Node
|
||||||
{
|
{
|
||||||
if (! $this->docBlockManipulator->hasTag($node, 'Template')) {
|
if (! $this->docBlockManipulator->hasTag($node, TemplateTagValueNode::CLASS_NAME)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +105,7 @@ CODE_SAMPLE
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove annotation
|
// remove annotation
|
||||||
$this->docBlockManipulator->removeTagFromNode($node, 'Template');
|
$this->docBlockManipulator->removeTagFromNode($node, TemplateTagValueNode::CLASS_NAME);
|
||||||
|
|
||||||
return $node;
|
return $node;
|
||||||
}
|
}
|
||||||
|
@ -122,19 +124,24 @@ CODE_SAMPLE
|
||||||
$arguments[] = $returnNode->expr;
|
$arguments[] = $returnNode->expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
$arguments = array_merge($arguments, $this->resolveArgumentsFromMethodCall($returnNode));
|
$arguments = array_merge($arguments, $this->resolveArrayArgumentsFromMethodCall($returnNode));
|
||||||
|
|
||||||
return $this->createArgs($arguments);
|
return $this->createArgs($arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function resolveTemplateName(ClassMethod $classMethod): string
|
private function resolveTemplateName(ClassMethod $classMethod): string
|
||||||
{
|
{
|
||||||
$templateTag = $this->docBlockManipulator->getTagByName($classMethod, 'Template');
|
/** @var PhpDocInfo $classMethodPhpDocInfo */
|
||||||
$content = (string) $templateTag;
|
$classMethodPhpDocInfo = $this->getPhpDocInfo($classMethod);
|
||||||
|
|
||||||
$annotationContent = Strings::match($content, '#\(("|\')(?<filename>.*?)("|\')\)#');
|
/** @var TemplateTagValueNode|null $templateTagValueNode */
|
||||||
if (isset($annotationContent['filename'])) {
|
$templateTagValueNode = $classMethodPhpDocInfo->matchChildValueNodeOfType(TemplateTagValueNode::class);
|
||||||
return $annotationContent['filename'];
|
if ($templateTagValueNode === null) {
|
||||||
|
throw new ShouldNotHappenException(__METHOD__);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($templateTagValueNode->getTemplate() !== null) {
|
||||||
|
return $templateTagValueNode->getTemplate();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->templateGuesser->resolveFromClassMethodNode($classMethod, $this->version);
|
return $this->templateGuesser->resolveFromClassMethodNode($classMethod, $this->version);
|
||||||
|
@ -142,17 +149,21 @@ CODE_SAMPLE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Already existing method call
|
* Already existing method call
|
||||||
* @return mixed[]
|
* @return Array_[]
|
||||||
*/
|
*/
|
||||||
private function resolveArgumentsFromMethodCall(Return_ $returnNode): array
|
private function resolveArrayArgumentsFromMethodCall(Return_ $returnNode): array
|
||||||
{
|
{
|
||||||
|
if (! $returnNode->expr instanceof MethodCall) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
$arguments = [];
|
$arguments = [];
|
||||||
if ($returnNode->expr instanceof MethodCall) {
|
foreach ($returnNode->expr->args as $arg) {
|
||||||
foreach ($returnNode->expr->args as $arg) {
|
if (! $arg->value instanceof Array_) {
|
||||||
if ($arg->value instanceof Array_) {
|
continue;
|
||||||
$arguments[] = $arg->value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$arguments[] = $arg->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $arguments;
|
return $arguments;
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService13Controller extends SymfonyController
|
class ClassWithNamedService13Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ class ClassWithNamedService13Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService13Controller extends SymfonyController
|
class ClassWithNamedService13Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService23Controller extends SymfonyController
|
class ClassWithNamedService23Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -32,6 +33,7 @@ class ClassWithNamedService23Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService23Controller extends SymfonyController
|
class ClassWithNamedService23Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService33Controller extends SymfonyController
|
class ClassWithNamedService33Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ class ClassWithNamedService33Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService33Controller extends SymfonyController
|
class ClassWithNamedService33Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
<?php declare (strict_types=1);
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService43 extends SymfonyController
|
class ClassWithNamedService43 extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -20,6 +21,7 @@ class ClassWithNamedService43 extends SymfonyController
|
||||||
<?php declare (strict_types=1);
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService43 extends SymfonyController
|
class ClassWithNamedService43 extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Fixture;
|
||||||
|
|
||||||
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
|
||||||
|
class SkipJustTemplateController extends SymfonyController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Template
|
||||||
|
*/
|
||||||
|
public function indexAction()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService15Controller extends SymfonyController
|
class ClassWithNamedService15Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ class ClassWithNamedService15Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService15Controller extends SymfonyController
|
class ClassWithNamedService15Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService25Controller extends SymfonyController
|
class ClassWithNamedService25Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -32,6 +33,7 @@ class ClassWithNamedService25Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService25Controller extends SymfonyController
|
class ClassWithNamedService25Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService35Controller extends SymfonyController
|
class ClassWithNamedService35Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -38,6 +39,7 @@ class ClassWithNamedService35Controller extends SymfonyController
|
||||||
namespace AppBundle\Controller;
|
namespace AppBundle\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService35Controller extends SymfonyController
|
class ClassWithNamedService35Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService45Controller extends SymfonyController
|
class ClassWithNamedService45Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -15,15 +16,6 @@ class ClassWithNamedService45Controller extends SymfonyController
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @Template()
|
|
||||||
* @Route("/", name="homepage")
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
@ -33,6 +25,7 @@ class ClassWithNamedService45Controller extends SymfonyController
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
class ClassWithNamedService45Controller extends SymfonyController
|
class ClassWithNamedService45Controller extends SymfonyController
|
||||||
{
|
{
|
||||||
|
@ -42,14 +35,6 @@ class ClassWithNamedService45Controller extends SymfonyController
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @Route("/", name="homepage")
|
|
||||||
*/
|
|
||||||
public function index()
|
|
||||||
{
|
|
||||||
return $this->render('class_with_named_service45/index.html.twig');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
|
class ClassWithNamedService55Controller extends SymfonyController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Template()
|
||||||
|
*/
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
-----
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use Rector\Sensio\Tests\Rector\FrameworkExtraBundle\TemplateAnnotationRector\Source\SymfonyController;
|
||||||
|
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
|
||||||
|
|
||||||
|
class ClassWithNamedService55Controller extends SymfonyController
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
return $this->render('class_with_named_service55/index.html.twig');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
|
@ -14,6 +14,7 @@ final class TemplateAnnotationVersion3RectorTest extends AbstractRectorTestCase
|
||||||
__DIR__ . '/Fixture/Version3/fixture2.php.inc',
|
__DIR__ . '/Fixture/Version3/fixture2.php.inc',
|
||||||
__DIR__ . '/Fixture/Version3/fixture3.php.inc',
|
__DIR__ . '/Fixture/Version3/fixture3.php.inc',
|
||||||
__DIR__ . '/Fixture/Version3/fixture4.php.inc',
|
__DIR__ . '/Fixture/Version3/fixture4.php.inc',
|
||||||
|
__DIR__ . '/Fixture/Version3/skip_just_template.php.inc',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ final class TemplateAnnotationVersion5RectorTest extends AbstractRectorTestCase
|
||||||
__DIR__ . '/Fixture/Version5/fixture2.php.inc',
|
__DIR__ . '/Fixture/Version5/fixture2.php.inc',
|
||||||
__DIR__ . '/Fixture/Version5/fixture3.php.inc',
|
__DIR__ . '/Fixture/Version5/fixture3.php.inc',
|
||||||
__DIR__ . '/Fixture/Version5/fixture4.php.inc',
|
__DIR__ . '/Fixture/Version5/fixture4.php.inc',
|
||||||
|
__DIR__ . '/Fixture/Version5/fixture5.php.inc',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,4 +11,4 @@ services:
|
||||||
|
|
||||||
Rector\Symfony\:
|
Rector\Symfony\:
|
||||||
resource: '../src/'
|
resource: '../src/'
|
||||||
exclude: '../src/{Rector/**/*Rector.php}'
|
exclude: '../src/{Rector/**/*Rector.php,PhpDocParser/Ast/PhpDoc/*}'
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Rector\Symfony\PhpDoc\Ast\PhpDoc;
|
|
||||||
|
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
|
||||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
|
||||||
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
|
||||||
|
|
||||||
final class RouteTagValueNode implements AttributeAwareNodeInterface, PhpDocTagValueNode
|
|
||||||
{
|
|
||||||
use AttributeTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public const SHORT_NAME = '@Route';
|
|
||||||
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
// TODO: Implement __toString() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
// public function __toString(): string
|
|
||||||
// {
|
|
||||||
// $contentItems = [];
|
|
||||||
//
|
|
||||||
// if ($this->type !== null) {
|
|
||||||
// $contentItems['type'] = sprintf('type="%s"', $this->type);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->name !== null) {
|
|
||||||
// $contentItems['name'] = sprintf('name="%s"', $this->name);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->length !== null) {
|
|
||||||
// $contentItems['length'] = sprintf('length=%s', $this->length);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->precision !== null) {
|
|
||||||
// $contentItems['precision'] = sprintf('precision=%s', $this->precision);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->scale !== null) {
|
|
||||||
// $contentItems['scale'] = sprintf('scale=%s', $this->scale);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->unique !== null) {
|
|
||||||
// $contentItems['unique'] = sprintf('unique=%s', $this->unique ? 'true' : 'false');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->nullable !== null) {
|
|
||||||
// $contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->options) {
|
|
||||||
// $contentItems['options'] = $this->printArrayItem($this->options, 'options');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->columnDefinition !== null) {
|
|
||||||
// $contentItems['columnDefinition'] = sprintf('columnDefinition="%s"', $this->columnDefinition);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return $this->printContentItems($contentItems);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Rector\Symfony\PhpDoc\Ast\PhpDoc;
|
|
||||||
|
|
||||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
|
||||||
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
|
|
||||||
use Rector\BetterPhpDocParser\Attributes\Contract\Ast\AttributeAwareNodeInterface;
|
|
||||||
|
|
||||||
final class TemplateTagValueNode implements AttributeAwareNodeInterface, PhpDocTagValueNode
|
|
||||||
{
|
|
||||||
use AttributeTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
public const SHORT_NAME = '@Template';
|
|
||||||
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
// TODO: Implement __toString() method.
|
|
||||||
}
|
|
||||||
|
|
||||||
// public function __toString(): string
|
|
||||||
// {
|
|
||||||
// $contentItems = [];
|
|
||||||
//
|
|
||||||
// if ($this->type !== null) {
|
|
||||||
// $contentItems['type'] = sprintf('type="%s"', $this->type);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->name !== null) {
|
|
||||||
// $contentItems['name'] = sprintf('name="%s"', $this->name);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->length !== null) {
|
|
||||||
// $contentItems['length'] = sprintf('length=%s', $this->length);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->precision !== null) {
|
|
||||||
// $contentItems['precision'] = sprintf('precision=%s', $this->precision);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->scale !== null) {
|
|
||||||
// $contentItems['scale'] = sprintf('scale=%s', $this->scale);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->unique !== null) {
|
|
||||||
// $contentItems['unique'] = sprintf('unique=%s', $this->unique ? 'true' : 'false');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->nullable !== null) {
|
|
||||||
// $contentItems['nullable'] = sprintf('nullable=%s', $this->nullable ? 'true' : 'false');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->options) {
|
|
||||||
// $contentItems['options'] = $this->printArrayItem($this->options, 'options');
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ($this->columnDefinition !== null) {
|
|
||||||
// $contentItems['columnDefinition'] = sprintf('columnDefinition="%s"', $this->columnDefinition);
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return $this->printContentItems($contentItems);
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
|
@ -30,6 +30,8 @@ parameters:
|
||||||
# part of composer
|
# part of composer
|
||||||
- 'tests/Composer/AutoloadWrongCasesEventSubscriber.php'
|
- 'tests/Composer/AutoloadWrongCasesEventSubscriber.php'
|
||||||
- '*/tests/Rector/Psr4/MultipleClassFileToPsr4ClassesRector/Expected/Just*ExceptionWithoutNamespace.php'
|
- '*/tests/Rector/Psr4/MultipleClassFileToPsr4ClassesRector/Expected/Just*ExceptionWithoutNamespace.php'
|
||||||
|
# stubs
|
||||||
|
- 'stubs/*'
|
||||||
|
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
# false positive
|
# false positive
|
||||||
|
@ -188,6 +190,7 @@ parameters:
|
||||||
- '#Method Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\:\:(.*?)\(\) should return Rector\\DoctrinePhpDocParser\\Ast\\PhpDoc\\(.*?)\|null but returns PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode\|null#'
|
- '#Method Rector\\BetterPhpDocParser\\PhpDocInfo\\PhpDocInfo\:\:(.*?)\(\) should return Rector\\DoctrinePhpDocParser\\Ast\\PhpDoc\\(.*?)\|null but returns PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode\|null#'
|
||||||
- '#Call to function property_exists\(\) with string and (.*?) will always evaluate to false#'
|
- '#Call to function property_exists\(\) with string and (.*?) will always evaluate to false#'
|
||||||
- '#Method Rector\\Console\\Option\\SetOptionResolver\:\:separateVersionedAndUnversionedSets\(\) should return array<array<string\>\> but returns array<int, array<int\|string, array<int, string\>\|string\>\>#'
|
- '#Method Rector\\Console\\Option\\SetOptionResolver\:\:separateVersionedAndUnversionedSets\(\) should return array<array<string\>\> but returns array<int, array<int\|string, array<int, string\>\|string\>\>#'
|
||||||
|
- '#Method Rector\\DoctrinePhpDocParser\\AnnotationReader\\NodeAnnotationReader\:\:readMethodAnnotation\(\) should return Sensio\\Bundle\\FrameworkExtraBundle\\Configuration\\Template but returns object\|null#'
|
||||||
|
|
||||||
# PHP 7.4 1_000 support
|
# PHP 7.4 1_000 support
|
||||||
- '#Property PhpParser\\Node\\Scalar\\DNumber\:\:\$value \(float\) does not accept string#'
|
- '#Property PhpParser\\Node\\Scalar\\DNumber\:\:\$value \(float\) does not accept string#'
|
||||||
|
|
163
stubs/Sensio/Template.php
Normal file
163
stubs/Sensio/Template.php
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Sensio\Bundle\FrameworkExtraBundle\Configuration;
|
||||||
|
|
||||||
|
use RuntimeException;
|
||||||
|
|
||||||
|
if (class_exists('Sensio\Bundle\FrameworkExtraBundle\Configuration\Template')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mimics https://github.com/sensiolabs/SensioFrameworkExtraBundle/blob/master/Configuration/Template.php, is missing localy
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Annotation
|
||||||
|
*/
|
||||||
|
class Template
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The template.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $template;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The associative array of template variables.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $vars = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the template be streamed?
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $streamable = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The controller (+action) this annotation is set to.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $owner = [];
|
||||||
|
|
||||||
|
public function __construct(array $values)
|
||||||
|
{
|
||||||
|
foreach ($values as $k => $v) {
|
||||||
|
if (! method_exists($this, $name = 'set' . $k)) {
|
||||||
|
throw new RuntimeException(sprintf('Unknown key "%s" for annotation "@%s".', $k, static::class));
|
||||||
|
}
|
||||||
|
$this->{$name}($v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the array of templates variables.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getVars()
|
||||||
|
{
|
||||||
|
return $this->vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $streamable
|
||||||
|
*/
|
||||||
|
public function setIsStreamable($streamable): void
|
||||||
|
{
|
||||||
|
$this->streamable = $streamable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isStreamable()
|
||||||
|
{
|
||||||
|
return (bool) $this->streamable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the template variables.
|
||||||
|
*
|
||||||
|
* @param array $vars The template variables
|
||||||
|
*/
|
||||||
|
public function setVars($vars): void
|
||||||
|
{
|
||||||
|
$this->vars = $vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the template logic name.
|
||||||
|
*
|
||||||
|
* @param string $template The template logic name
|
||||||
|
*/
|
||||||
|
public function setValue($template): void
|
||||||
|
{
|
||||||
|
$this->setTemplate($template);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the template.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getTemplate()
|
||||||
|
{
|
||||||
|
return $this->template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the template.
|
||||||
|
*
|
||||||
|
* @param string $template The template
|
||||||
|
*/
|
||||||
|
public function setTemplate($template): void
|
||||||
|
{
|
||||||
|
$this->template = $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the annotation alias name.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @see ConfigurationInterface
|
||||||
|
*/
|
||||||
|
public function getAliasName()
|
||||||
|
{
|
||||||
|
return 'template';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only one template directive is allowed.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
* @see ConfigurationInterface
|
||||||
|
*/
|
||||||
|
public function allowArray()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $owner
|
||||||
|
*/
|
||||||
|
public function setOwner(array $owner): void
|
||||||
|
{
|
||||||
|
$this->owner = $owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The controller (+action) this annotation is attached to.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getOwner()
|
||||||
|
{
|
||||||
|
return $this->owner;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user