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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
root = true

[*.{css,html,js,json,latte,neon,php,twig,xml,yaml,yml}]
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
Expand Down
11 changes: 7 additions & 4 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,15 @@ imports:
parameters:
# processed paths
paths: []
file_extensions:
- 'php'

# exclude
exclude_paths: []
exclude_rectors: []

autoload_paths: []

rector_recipe: []

# this helps to separate opened 3rd party code vs private code approach (e.g. use of public constants)
Expand All @@ -20,7 +26,7 @@ parameters:
# lower for performance; higher to prevent bugs with fluent interfaces like https://github.com/rectorphp/rector/issues/1646, or https://github.com/rectorphp/rector/issues/2444
nested_chain_method_call_limit: 30

# importing FQN names
# importing FQN names; false disables "import_short_classes" and "import_doc_blocks" options bellow
auto_import_names: false
# e.g. import \DateTime
import_short_classes: true
Expand All @@ -29,6 +35,3 @@ parameters:

# what PHP version is used for features, composer.json version, then local PHP version is used by default
php_version_features: null

file_extensions:
- 'php'
1 change: 0 additions & 1 deletion config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ services:
- '../src/Rector/**/*Rector.php'
- '../src/Testing/PHPUnit/*'
- '../src/RectorDefinition/*'
- '../src/PhpParser/Node/*Info.php'
- '../src/Exception/*'
- '../src/DependencyInjection/CompilerPass/*'
- '../src/DependencyInjection/Loader/*'
Expand Down
4 changes: 2 additions & 2 deletions ecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ parameters:
# @todo split to multiple rectors
- "rules/php-spec-to-phpunit/src/Rector/MethodCall/PhpSpecPromisesToPHPUnitAssertRector.php"

- "packages/better-php-doc-parser/src/PhpDocNode/Doctrine/Property_/ColumnTagValueNode.php"
- "packages/better-php-doc-parser/src/PhpDocNode/Doctrine/Property_/JoinColumnTagValueNode.php"
- 'packages/better-php-doc-parser/src/PhpDocNode/**/*TagValueNode.php'
#
- "rules/coding-style/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php"

# per node logic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\TagAwareNodeInterface;
use Rector\Core\BetterPhpDocParser\Utils\ArrayItemStaticHelper;
use Rector\BetterPhpDocParser\Utils\ArrayItemStaticHelper;

abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpDocTagValueNode
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function __toString(): string
$contentItems = [];

if ($this->on !== null) {
$contentItems['on'] = $this->on;
$contentItems['on'] = sprintf('on="%s"', $this->on);
}

if ($this->field) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\BetterPhpDocParser\PhpDocNode\Gedmo;

use Nette\Utils\Strings;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface;
use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;

Expand All @@ -14,14 +15,130 @@ final class SlugTagValueNode extends AbstractTagValueNode implements ShortNameAw
*/
private $fields = [];

public function __construct(array $fields)
{
/**
* @var bool
*/
private $updatable = false;

/**
* @var string
*/
private $style;

/**
* @var bool
*/
private $unique = false;

/**
* @var string|null
*/
private $uniqueBase;

/**
* @var string
*/
private $separator;

/**
* @var string
*/
private $prefix;

/**
* @var string
*/
private $suffix;

/**
* @var mixed[]
*/
private $handlers = [];

/**
* @var string|null
*/
private $dateFormat;

/**
* @var bool
*/
private $isFirstArgumentExplicit = true;

public function __construct(
array $fields,
bool $updatable,
string $style,
bool $unique,
?string $uniqueBase,
string $separator,
string $prefix,
string $suffix,
array $handlers,
?string $dateFormat,
?string $originalContent = null
) {
$this->fields = $fields;
$this->updatable = $updatable;
$this->style = $style;
$this->unique = $unique;
$this->uniqueBase = $uniqueBase;
$this->separator = $separator;
$this->prefix = $prefix;
$this->suffix = $suffix;
$this->handlers = $handlers;

$this->resolveOriginalContentSpacingAndOrder($originalContent);
$this->dateFormat = $dateFormat;

if ($originalContent !== null) {

// @todo make generic to abstrat class
$this->isFirstArgumentExplicit = (bool) Strings::contains($originalContent, 'fields=');
}
}

public function __toString(): string
{
return '(fields=' . $this->printArrayItem($this->fields) . ')';
$contentItems['fields'] = $this->createFields();

if ($this->updatable) {
$contentItems['updatable'] = sprintf('updatable=%s', $this->updatable ? 'true' : 'false');
}

if ($this->style !== '') {
$contentItems['style'] = sprintf('style="%s"', $this->style);
}

if ($this->unique) {
$contentItems['unique'] = sprintf('unique=%s', $this->unique ? 'true' : 'false');
}

if ($this->uniqueBase) {
$contentItems['unique_base'] = sprintf('unique_base="%s"', $this->uniqueBase);
}

if ($this->separator !== '') {
$contentItems['separator'] = sprintf('separator="%s"', $this->separator);
}

if ($this->prefix !== '') {
$contentItems['prefix'] = sprintf('prefix="%s"', $this->prefix);
}

if ($this->suffix !== '') {
$contentItems['suffix'] = sprintf('suffix="%s"', $this->suffix);
}

if ($this->dateFormat) {
$contentItems['dateFormat'] = sprintf('dateFormat="%s"', $this->dateFormat);
}

if ($this->handlers !== []) {
$contentItems['handlers'] = $this->printArrayItem($this->handlers, 'handlers');
}

return $this->printContentItems($contentItems);
}

public function getFields(): array
Expand All @@ -33,4 +150,13 @@ public function getShortName(): string
{
return '@Gedmo\Slug';
}

private function createFields(): string
{
if ($this->isFirstArgumentExplicit) {
return sprintf('fields=%s', $this->printArrayItem($this->fields));
}

return $this->printArrayItem($this->fields);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public function __construct(

// covers https://github.com/rectorphp/rector/issues/2994#issuecomment-598712339

// @todo make generic to abstrat class
if ($originalContent !== null) {
$this->isPathExplicit = (bool) Strings::contains($originalContent, 'path=');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,20 @@ public function createFromNodeAndTokens(Node $node, TokenIterator $tokenIterator
return null;
}

return new SlugTagValueNode($slug->fields);
$annotationContent = $this->annotationContentResolver->resolveFromTokenIterator($tokenIterator);

return new SlugTagValueNode(
$slug->fields,
$slug->updatable,
$slug->style,
$slug->unique,
$slug->unique_base,
$slug->separator,
$slug->prefix,
$slug->suffix,
$slug->handlers,
$slug->dateFormat,
$annotationContent
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Rector\Core\BetterPhpDocParser\Utils;
namespace Rector\BetterPhpDocParser\Utils;

use Nette\Utils\Strings;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

declare(strict_types=1);

namespace Rector\BetterPhpDocParser\Tests\PhpDocParser;

use Iterator;
use PhpParser\Node;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
use Rector\BetterPhpDocParser\Printer\PhpDocInfoPrinter;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\HttpKernel\RectorKernel;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\Testing\StaticFixtureProvider;
use Rector\FileSystemRector\Parser\FileInfoParser;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;

abstract class AbstractPhpDocInfoTest extends AbstractKernelTestCase
{
/**
* @var FileInfoParser
*/
private $fileInfoParser;

/**
* @var BetterNodeFinder
*/
private $betterNodeFinder;

/**
* @var PhpDocInfoPrinter
*/
private $phpDocInfoPrinter;

protected function setUp(): void
{
$this->bootKernel(RectorKernel::class);

$this->fileInfoParser = self::$container->get(FileInfoParser::class);

$this->betterNodeFinder = self::$container->get(BetterNodeFinder::class);
$this->phpDocInfoPrinter = self::$container->get(PhpDocInfoPrinter::class);
}

/**
* @param class-string $nodeType
*/
protected function doTestPrintedPhpDocInfo(string $filePath, string $nodeType, string $tagValueNodeType): void
{
$this->ensureIsNodeType($nodeType);

$nodeWithPhpDocInfo = $this->parseFileAndGetFirstNodeOfType($filePath, $nodeType);

$docComment = $nodeWithPhpDocInfo->getDocComment();
if ($docComment === null) {
throw new ShouldNotHappenException(sprintf('Doc comments for "%s" file cannot not be empty', $filePath));
}

$originalDocCommentText = $docComment->getText();
$printedPhpDocInfo = $this->printNodePhpDocInfoToString($nodeWithPhpDocInfo);

$this->assertSame($originalDocCommentText, $printedPhpDocInfo);

$this->doTestContainsTagValueNodeType($nodeWithPhpDocInfo, $tagValueNodeType);
}

protected function yieldFilesFromDirectory(string $directory, string $suffix = '*.php'): Iterator
{
return StaticFixtureProvider::yieldFilesFromDirectory($directory, $suffix);
}

private function doTestContainsTagValueNodeType(Node $node, string $tagValueNodeType): void
{
/** @var PhpDocInfo $phpDocInfo */
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
$phpDocInfo->hasByType($tagValueNodeType);
}

/**
* @param class-string $nodeType
*/
private function parseFileAndGetFirstNodeOfType(string $filePath, string $nodeType): Node
{
$nodes = $this->fileInfoParser->parseFileInfoToNodesAndDecorate(new SmartFileInfo($filePath));

return $this->betterNodeFinder->findFirstInstanceOf($nodes, $nodeType);
}

private function printNodePhpDocInfoToString(Node $node): string
{
$phpDocInfo = $node->getAttribute(AttributeKey::PHP_DOC_INFO);
if ($phpDocInfo === null) {
throw new ShouldNotHappenException();
}

return $this->phpDocInfoPrinter->printFormatPreserving($phpDocInfo);
}

/**
* @param class-string $nodeType
*/
private function ensureIsNodeType(string $nodeType): void
{
if (is_a($nodeType, Node::class, true)) {
return;
}

throw new ShouldNotHappenException(sprintf('"%s" must be type of "%s"', $nodeType, Node::class));
}
}
Loading