[SimplePhpDocParser] Add README + getParam*() helper methods (#4393)

This commit is contained in:
Tomas Votruba 2020-10-11 16:17:43 +02:00 committed by GitHub
parent a4b4b474cb
commit 01514ab9a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
86 changed files with 425 additions and 222 deletions

View File

@ -20,6 +20,10 @@ jobs:
name: 'PHPStan'
run: composer phpstan
-
name: 'PHPStan for config'
run: composer phpstan-config
-
name: 'Show command'
run: bin/rector show --config rector-ci.php --ansi

View File

@ -80,6 +80,7 @@ final class ComposerJsonManipulator
}
/**
* @param mixed[] $json
* @return mixed[]
*/
private function removeDevKeys(array $json): array
@ -92,6 +93,7 @@ final class ComposerJsonManipulator
/**
* Use phpstan/phpstan-src, because the phpstan.phar cannot be packed into rector.phar
* @param mixed[] $json
* @return mixed[]
*/
private function replacePHPStanWithPHPStanSrc(array $json): array
@ -118,6 +120,7 @@ final class ComposerJsonManipulator
}
/**
* @param mixed[] $json
* @return mixed[]
*/
private function addDevDependenciesFromPHPStan(array $json, string $phpstanVersion): array

View File

@ -303,13 +303,8 @@
"vendor/bin/ecs check --fix --ansi",
"vendor/bin/ecs check-markdown README.md docs/rector_rules_overview.md --fix --ansi"
],
"phpstan": [
"vendor/bin/phpstan analyse --ansi --error-format symplify",
"vendor/bin/phpstan analyse config --ansi --error-format symplify"
],
"phpstan-config": [
"vendor/bin/phpstan analyse config --ansi --error-format symplify"
],
"phpstan": "vendor/bin/phpstan analyse --ansi --error-format symplify",
"phpstan-config": "vendor/bin/phpstan analyse config --ansi --error-format symplify",
"changelog": [
"vendor/bin/changelog-linker dump-merges --in-categories --ansi",
"vendor/bin/changelog-linker link --ansi",

View File

@ -98,7 +98,6 @@ return static function (ContainerConfigurator $containerConfigurator): void {
// buggy with specific markdown snippet file in docs/rules_overview.md
ArrayListItemNewlineFixer::class => null,
BlankLineAfterOpeningTagFixer::class => null,
StrictComparisonFixer::class => [__DIR__ . '/rules/polyfill/src/ConditionEvaluator.php'],
]);

View File

@ -5,11 +5,11 @@ declare(strict_types=1);
namespace Rector\AttributeAwarePhpDoc\Ast\PhpDoc;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use Rector\BetterPhpDocParser\Attributes\Attribute\AttributeTrait;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\SimplePhpDocParser\ValueObject\Ast\PhpDoc\SimplePhpDocNode;
final class AttributeAwarePhpDocNode extends PhpDocNode implements AttributeAwareNodeInterface
final class AttributeAwarePhpDocNode extends SimplePhpDocNode implements AttributeAwareNodeInterface
{
use AttributeTrait;

View File

@ -100,6 +100,9 @@ trait ArrayPartPhpDocTagPrinterTrait
return ! $tagValueNodeConfiguration->getKeysByQuotedStatus()[$key];
}
/**
* @param mixed[] $item
*/
private function quoteKeys(array $item, string $key, string $json, string $originalContent): string
{
foreach (array_keys($item) as $itemKey) {

View File

@ -4,7 +4,6 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocInfo;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Param;
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
@ -13,7 +12,6 @@ use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocChildNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\ThrowsTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
@ -22,6 +20,7 @@ use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwarePhpDocTagNode;
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareReturnTagValueNode;
use Rector\BetterPhpDocParser\Annotation\StaticAnnotationNaming;
use Rector\BetterPhpDocParser\Attributes\Ast\AttributeAwareNodeFactory;
use Rector\BetterPhpDocParser\Attributes\Ast\PhpDoc\SpacelessPhpDocTagNode;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\AttributeAwareNodeInterface;
use Rector\BetterPhpDocParser\Contract\PhpDocNode\ShortNameAwareTagInterface;
@ -85,6 +84,11 @@ final class PhpDocInfo
*/
private $phpDocRemover;
/**
* @var AttributeAwareNodeFactory
*/
private $attributeAwareNodeFactory;
/**
* @param mixed[] $tokens
*/
@ -95,7 +99,8 @@ final class PhpDocInfo
StaticTypeMapper $staticTypeMapper,
Node $node,
PhpDocTypeChanger $phpDocTypeChanger,
PhpDocRemover $phpDocRemover
PhpDocRemover $phpDocRemover,
AttributeAwareNodeFactory $attributeAwareNodeFactory
) {
$this->phpDocNode = $attributeAwarePhpDocNode;
$this->tokens = $tokens;
@ -105,6 +110,7 @@ final class PhpDocInfo
$this->node = $node;
$this->phpDocTypeChanger = $phpDocTypeChanger;
$this->phpDocRemover = $phpDocRemover;
$this->attributeAwareNodeFactory = $attributeAwareNodeFactory;
}
public function getOriginalContent(): string
@ -224,6 +230,9 @@ final class PhpDocInfo
return (bool) $this->getByType($type);
}
/**
* @param string[] $names
*/
public function hasByNames(array $names): bool
{
foreach ($names as $name) {
@ -408,14 +417,17 @@ final class PhpDocInfo
public function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
{
/** @var AttributeAwareParamTagValueNode $paramTagValue */
foreach ($this->phpDocNode->getParamTagValues() as $paramTagValue) {
if (Strings::match($paramTagValue->parameterName, '#^(\$)?' . $name . '$#')) {
return $paramTagValue;
}
$paramTagValueNode = $this->phpDocNode->getParam($name);
if ($paramTagValueNode === null) {
return null;
}
return null;
$attributeAwareParamTagValueNode = $this->attributeAwareNodeFactory->createFromNode($paramTagValueNode, '');
if (! $attributeAwareParamTagValueNode instanceof AttributeAwareParamTagValueNode) {
throw new ShouldNotHappenException();
}
return $attributeAwareParamTagValueNode;
}
private function getTypeOrMixed(?PhpDocTagValueNode $phpDocTagValueNode): Type
@ -473,13 +485,9 @@ final class PhpDocInfo
{
$throwsTypes = [];
foreach ($this->getTagsByName('throws') as $throwsPhpDocNode) {
if (! $throwsPhpDocNode->value instanceof ThrowsTagValueNode) {
continue;
}
foreach ($this->phpDocNode->getThrowsTagValues() as $throwsPhpDocNode) {
$throwsTypes[] = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType(
$throwsPhpDocNode->value,
$throwsPhpDocNode,
$this->node
);
}

View File

@ -111,6 +111,9 @@ final class PhpDocInfoFactory
return $this->createFromPhpDocNode($attributeAwarePhpDocNode, '', [], $node);
}
/**
* @param mixed[][] $tokens
*/
private function parseTokensToPhpDocNode(array $tokens): AttributeAwarePhpDocNode
{
$tokenIterator = new TokenIterator($tokens);
@ -139,6 +142,9 @@ final class PhpDocInfoFactory
}
}
/**
* @param mixed[] $tokens
*/
private function createFromPhpDocNode(
AttributeAwarePhpDocNode $attributeAwarePhpDocNode,
string $content,
@ -158,8 +164,10 @@ final class PhpDocInfoFactory
$this->staticTypeMapper,
$node,
$this->phpDocTypeChanger,
$this->phpDocRemover
$this->phpDocRemover,
$this->attributeAwareNodeFactory
);
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
return $phpDocInfo;

View File

@ -80,6 +80,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
);
}
/**
* @param mixed[] $items
*/
protected function printItems(array $items): string
{
$items = $this->completeItemsQuotes($items);
@ -184,6 +187,9 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
return $this->tagValueNodeConfiguration->hasOpeningBracket() && $this->tagValueNodeConfiguration->hasClosingBracket();
}
/**
* @param mixed[] $value
*/
private function correctArraySingleItemPrint(array $value, string $arrayItemAsString): string
{
if (count($value) !== 1) {

View File

@ -95,6 +95,7 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode implements Si
}
/**
* @param mixed[] $items
* @return mixed[]
*/
private function addCustomItems(array $items): array

View File

@ -10,6 +10,9 @@ use Rector\BetterPhpDocParser\PhpDocNode\AbstractTagValueNode;
final class SlugTagValueNode extends AbstractTagValueNode implements ShortNameAwareTagInterface, SilentKeyNodeInterface
{
/**
* @return mixed[]
*/
public function getFields(): array
{
return $this->items['fields'];

View File

@ -13,6 +13,7 @@ use Rector\BetterPhpDocParser\ValueObject\TagValueNodeConfiguration;
trait PrintTagValueNodeTrait
{
/**
* @param mixed[] $items
* @return mixed[]
*/
protected function makeKeysExplicit(array $items): array
@ -34,6 +35,7 @@ trait PrintTagValueNodeTrait
}
/**
* @param mixed[] $items
* @param string[] $skipKeys
* @return mixed[]
*/

View File

@ -35,6 +35,9 @@ final class SymfonyRouteTagValueNode extends AbstractTagValueNode implements Sho
return $this->printItems($items);
}
/**
* @param string[] $methods
*/
public function changeMethods(array $methods): void
{
$this->tagValueNodeConfiguration->addOrderedVisibleItem('methods');

View File

@ -4,6 +4,7 @@ declare(strict_types=1);
namespace Rector\BetterPhpDocParser\PhpDocNodeFactory\Doctrine\Class_;
use Doctrine\ORM\Mapping\UniqueConstraint;
use Nette\Utils\Strings;
use Rector\BetterPhpDocParser\Annotation\AnnotationItemsResolver;
use Rector\BetterPhpDocParser\PhpDocNode\Doctrine\Class_\UniqueConstraintTagValueNode;
@ -26,6 +27,7 @@ final class UniqueConstraintPhpDocNodeFactory
}
/**
* @param UniqueConstraint[]|null $uniqueConstraints
* @return UniqueConstraintTagValueNode[]
*/
public function createUniqueConstraintTagValueNodes(?array $uniqueConstraints, string $annotationContent): array

View File

@ -29,8 +29,8 @@ final class ClassAnnotationMatcher
$tag = ltrim($tag, '@');
/** @var Use_[]|null $useNodes */
$useNodes = $node->getAttribute(AttributeKey::USE_NODES);
/** @var Use_[] $useNodes */
$useNodes = (array) $node->getAttribute(AttributeKey::USE_NODES);
$fullyQualifiedClass = $this->resolveFullyQualifiedClass($useNodes, $node, $tag);
$this->fullyQualifiedNameByHash[$uniqueHash] = $fullyQualifiedClass;
@ -38,9 +38,12 @@ final class ClassAnnotationMatcher
return $fullyQualifiedClass;
}
private function resolveFullyQualifiedClass(?array $useNodes, Node $node, string $tag): string
/**
* @param Use_[] $uses
*/
private function resolveFullyQualifiedClass(array $uses, Node $node, string $tag): string
{
if ($useNodes === null) {
if ($uses === []) {
/** @var string|null $namespace */
$namespace = $node->getAttribute(AttributeKey::NAMESPACE_NAME);
if ($namespace !== null) {
@ -53,7 +56,7 @@ final class ClassAnnotationMatcher
return $tag;
}
return $this->matchFullAnnotationClassWithUses($tag, $useNodes) ?? $tag;
return $this->matchFullAnnotationClassWithUses($tag, $uses) ?? $tag;
}
/**

View File

@ -92,6 +92,9 @@ final class ArrayItemStaticHelper
return $contentItems;
}
/**
* @param mixed[] $itemsOrder
*/
private static function isNotEmptyAndHasSilentKey(string $content, ?string $silentKey, array $itemsOrder): bool
{
if (! Strings::match($content, self::NON_EMPTY_SILENT_KEY_REGEX)) {

View File

@ -39,7 +39,7 @@ final class TagValueNodeConfiguration
private $arrayEqualSign;
/**
* @var array
* @var array<string, bool>
*/
private $keysByQuotedStatus = [];
@ -49,7 +49,7 @@ final class TagValueNodeConfiguration
private $originalContent;
/**
* @var array|null
* @var string[]|null
*/
private $orderedVisibleItems;
@ -58,6 +58,10 @@ final class TagValueNodeConfiguration
*/
private $silentKey;
/**
* @param array<string, bool> $keysByQuotedStatus
* @param string[] $orderedVisibleItems
*/
public function __construct(
?string $originalContent = null,
?array $orderedVisibleItems = null,
@ -87,6 +91,9 @@ final class TagValueNodeConfiguration
return $this->originalContent;
}
/**
* @return string[]|null
*/
public function getOrderedVisibleItems(): ?array
{
return $this->orderedVisibleItems;
@ -113,7 +120,7 @@ final class TagValueNodeConfiguration
}
/**
* @return mixed[]
* @return array<string, bool>
*/
public function getKeysByQuotedStatus(): array
{

View File

@ -25,6 +25,7 @@ final class ArrayPartPhpDocTagPrinterTest extends TestCase
}
/**
* @param mixed[] $items
* @dataProvider provideData()
*/
public function test(array $items, string $key, string $expectedContent): void

View File

@ -46,6 +46,7 @@ final class ChangedFilesDetectorTest extends AbstractRectorTestCase
}
/**
* @param string[] $dependantFiles
* @dataProvider provideData()
*/
public function testGetDependentFileInfos(string $filePathName, array $dependantFiles): void

View File

@ -7,7 +7,7 @@ namespace Rector\DoctrineAnnotationGenerated\DataCollector;
final class ResolvedConstantStaticCollector
{
/**
* @var mixed[]
* @var array<string, mixed>
*/
private static $valuesByIdentifier = [];
@ -26,7 +26,7 @@ final class ResolvedConstantStaticCollector
}
/**
* @return mixed[]
* @return array<string, mixed>
*/
public static function provide(): array
{

View File

@ -75,6 +75,7 @@ final class ConstantReferenceIdentifierRestorer
}
/**
* @param array<string, mixed> $identifierToResolvedValues
* @param mixed $value
* @return mixed|null
*/
@ -91,6 +92,10 @@ final class ConstantReferenceIdentifierRestorer
return null;
}
/**
* @param mixed[] $value
* @param array<string, mixed> $identifierToResolvedValues
*/
private function restoreNestedValue(
array $value,
array $identifierToResolvedValues,

View File

@ -29,6 +29,7 @@ final class RectorsDocumentationPrinterTest extends AbstractKernelTestCase
}
/**
* @param string[] $rectorClasses
* @dataProvider provideData()
*/
public function test(array $rectorClasses, bool $isRectorProject, string $expectedContentFilePath): void
@ -55,7 +56,7 @@ final class RectorsDocumentationPrinterTest extends AbstractKernelTestCase
}
/**
* @param class-string[] $rectorClasses
* @param string[] $rectorClasses
* @return RectorInterface[]
*/
private function createRectorsFromRectorClasses(array $rectorClasses): array

View File

@ -264,6 +264,10 @@ final class NodeNameResolver
return $this->getName($classLike->name);
}
/**
* @param mixed[] $backtrace
* @return mixed[]|null
*/
private function matchRectorBacktraceCall(array $backtrace): ?array
{
foreach ($backtrace as $singleTrace) {

View File

@ -156,6 +156,7 @@ final class PHPStanServicesFactory
}
/**
* @param string[] $additionalConfigFiles
* @return mixed[]
*/
private function appendPhpstanPHPUnitExtensionIfExists(

View File

@ -236,6 +236,9 @@ final class PHPStanNodeScopeResolver
return $classLike->name->toString();
}
/**
* @param string[] $dependentFiles
*/
private function reportCacheDebug(SmartFileInfo $smartFileInfo, array $dependentFiles): void
{
if (! $this->configuration->isCacheDebug()) {

View File

@ -76,6 +76,7 @@ final class PhpAttributteGroupFactory
}
/**
* @param mixed[] $items
* @return Arg[]
*/
private function createArgsFromItems(array $items, ?string $silentKey = null): array
@ -122,6 +123,9 @@ final class PhpAttributteGroupFactory
return new AttributeGroup([$attribute]);
}
/**
* @param mixed[] $items
*/
private function isArrayArguments(array $items): bool
{
foreach (array_keys($items) as $key) {

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\PostRector\Rector;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Namespace_;
use Rector\CodingStyle\Application\UseImportsAdder;
@ -119,6 +120,9 @@ final class UseAddingPostRector extends AbstractPostRector
return new RectorDefinition('Post Rector that adds use statements');
}
/**
* @param Node[] $nodes
*/
private function getSmartFileInfo(array $nodes): ?SmartFileInfo
{
foreach ($nodes as $node) {

View File

@ -94,6 +94,9 @@ final class ComposerPackageAutoloadUpdater
);
}
/**
* @param mixed[] $composerJson
*/
private function isPackageAlreadyLoaded(array $composerJson, Package $package): bool
{
foreach (['autoload', self::AUTOLOAD_DEV] as $autoloadSection) {

View File

@ -44,6 +44,7 @@ final class FileGenerator
}
/**
* @param SmartFileInfo[] $templateFileInfos
* @param string[] $templateVariables
* @return string[]
*/
@ -67,6 +68,9 @@ final class FileGenerator
return $generatedFilePaths;
}
/**
* @param array<string, mixed> $templateVariables
*/
private function generateFileInfoWithTemplateVariables(
SmartFileInfo $smartFileInfo,
array $templateVariables,

View File

@ -28,6 +28,7 @@ final class OverrideGuard
}
/**
* @param array<string, mixed> $templateVariables
* @param SmartFileInfo[] $templateFileInfos
*/
public function isUnwantedOverride(
@ -52,6 +53,9 @@ final class OverrideGuard
return false;
}
/**
* @param array<string, mixed> $templateVariables
*/
private function doesFileInfoAlreadyExist(
array $templateVariables,
RectorRecipe $rectorRecipe,

View File

@ -84,6 +84,9 @@ final class RectorRecipe
*/
private $extraFileContent;
/**
* @param class-string[] $nodeTypes
*/
public function __construct(
string $name,
array $nodeTypes,

View File

@ -0,0 +1,78 @@
# Simple PHP Doc Parser
Simple service integration of phpstan/phpdoc-parser, with few extra goodies for practical use
## 1. Install
```bash
composer require rector/simple-php-doc-parser
```
## 2. Register Bundle
Register bundle in your project:
```php
// app/bundles.php
return [
Rector\SimplePhpDocParser\Bundle\SimplePhpDocParserBundle::class => [
'all' => true,
],
];
```
or via Kernel:
```php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Rector\SimplePhpDocParser\Bundle\SimplePhpDocParserBundle;
final class AppKernel extends Kernel
{
/**
* @return BundleInterface[]
*/
public function registerBundles(): array
{
return [new SimplePhpDocParserBundle()];
}
}
```
## 3. Usage
Required services `Rector\SimplePhpDocParser\SimplePhpDocParser` in constructor, where you need it, and use it:
```php
use Rector\SimplePhpDocParser\SimplePhpDocParser;
final class SomeClass
{
/**
* @var SimplePhpDocParser
*/
private $simplePhpDocParser;
public function __construct(SimplePhpDocParser $simplePhpDocParser)
{
$this->simplePhpDocParser = $simplePhpDocParser;
}
public function some()
{
$docBlock = '/** @param int $name */';
/** @var \PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode $phpDocNode */
$phpDocNode = $this->simplePhpDocParser->parseDocBlock($docBlock);
// param extras
/** @var \PHPStan\PhpDocParser\Ast\Type\TypeNode $nameParamType */
$nameParamType = $phpDocNode->getParamType('name');
/** @var \PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode $nameParamTagValueNode */
$nameParamTagValueNode = $phpDocNode->getParam('name');
}
}
```

View File

@ -1,6 +1,6 @@
{
"name": "rector/simple-php-doc-parser",
"description": "Simple service integration of phpstan/phpdoc-parser",
"description": "Simple service integration of phpstan/phpdoc-parser, with few extra goodies for practical use",
"license": "MIT",
"require": {
"php": "^7.2.4|^8.0",

View File

@ -4,10 +4,10 @@ declare(strict_types=1);
namespace Rector\SimplePhpDocParser;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Lexer\Lexer;
use PHPStan\PhpDocParser\Parser\PhpDocParser;
use PHPStan\PhpDocParser\Parser\TokenIterator;
use Rector\SimplePhpDocParser\ValueObject\Ast\PhpDoc\SimplePhpDocNode;
/**
* @see \Rector\SimplePhpDocParser\Tests\SimplePhpDocParser\SimplePhpDocParserTest
@ -30,11 +30,12 @@ final class SimplePhpDocParser
$this->lexer = $lexer;
}
public function parseDocBlock(string $docBlock): PhpDocNode
public function parseDocBlock(string $docBlock): SimplePhpDocNode
{
$tokens = $this->lexer->tokenize($docBlock);
$tokenIterator = new TokenIterator($tokens);
return $this->phpDocParser->parse($tokenIterator);
$phpDocNode = $this->phpDocParser->parse($tokenIterator);
return new SimplePhpDocNode($phpDocNode->children);
}
}

View File

@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Rector\SimplePhpDocParser\ValueObject\Ast\PhpDoc;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
/**
* @notfinal on purpose, so it can be extended by 3rd party
*/
class SimplePhpDocNode extends PhpDocNode
{
public function getParam(string $desiredParamName): ?ParamTagValueNode
{
$desiredParamNameWithDollar = '$' . ltrim($desiredParamName, '$');
foreach ($this->getParamTagValues() as $paramTagValueNode) {
if ($paramTagValueNode->parameterName !== $desiredParamNameWithDollar) {
continue;
}
return $paramTagValueNode;
}
return null;
}
public function getParamType(string $desiredParamName): ?TypeNode
{
$paramTagValueNode = $this->getParam($desiredParamName);
if ($paramTagValueNode === null) {
return null;
}
return $paramTagValueNode->type;
}
}

View File

@ -0,0 +1,3 @@
/**
* @param string $name
*/

View File

@ -6,6 +6,7 @@ namespace Rector\SimplePhpDocParser\Tests\SimplePhpDocParser;
use Rector\Core\HttpKernel\RectorKernel;
use Rector\SimplePhpDocParser\SimplePhpDocParser;
use Rector\SimplePhpDocParser\ValueObject\Ast\PhpDoc\SimplePhpDocNode;
use Symplify\PackageBuilder\Tests\AbstractKernelTestCase;
use Symplify\SmartFileSystem\SmartFileInfo;
@ -22,13 +23,28 @@ final class SimplePhpDocParserTest extends AbstractKernelTestCase
$this->simplePhpDocParser = self::$container->get(SimplePhpDocParser::class);
}
public function test(): void
public function testVar(): void
{
$fileInfo = new SmartFileInfo(__DIR__ . '/Fixture/basic_doc.txt');
$smartFileInfo = new SmartFileInfo(__DIR__ . '/Fixture/var_int.txt');
$phpDocNode = $this->simplePhpDocParser->parseDocBlock($fileInfo->getContents());
$phpDocNode = $this->simplePhpDocParser->parseDocBlock($smartFileInfo->getContents());
$this->assertInstanceOf(SimplePhpDocNode::class, $phpDocNode);
$varTagValues = $phpDocNode->getVarTagValues();
$this->assertCount(1, $varTagValues);
}
public function testParam(): void
{
$smartFileInfo = new SmartFileInfo(__DIR__ . '/Fixture/param_string_name.txt');
$phpDocNode = $this->simplePhpDocParser->parseDocBlock($smartFileInfo->getContents());
$this->assertInstanceOf(SimplePhpDocNode::class, $phpDocNode);
// DX friendly
$paramType = $phpDocNode->getParamType('name');
$withDollarParamType = $phpDocNode->getParamType('$name');
$this->assertSame($paramType, $withDollarParamType);
}
}

View File

@ -123,6 +123,8 @@ parameters:
checkGenericClassInNonGenericObjectType: false
excludes_analyse:
# iterable types
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
@ -131,6 +133,9 @@ parameters:
- utils/phpstan-extensions/src/Rule/PreventParentMethodVisibilityOverrideRule.php
- utils/phpstan-extensions/src/Rule/KeepRectorNamespaceForRectorRule.php
- packages/rector-generator/templates/*
# this invalidates whole cache everytime
- 'packages/symfony-php-config/*'
- 'packages/simple-php-doc-parser'
# generated files
- 'packages/doctrine-annotation-generated/src/ConstantPreservingDocParser.php'
@ -152,8 +157,8 @@ parameters:
ignoreErrors:
# @todo remove
# iterable types
- '#with no value type specified in iterable type array#'
- '#type specified in iterable type (array|iterable)#'
# - '#with no value type specified in iterable type array#'
# - '#type specified in iterable type (array|iterable)#'
# false positive
- '#PHPDoc tag \@param for parameter \$node with type float is incompatible with native type PhpParser\\Node#'
@ -752,11 +757,6 @@ parameters:
- rules/symfony-code-quality/src/Rector/Class_/EventListenerToEventSubscriberRector.php # 247
- utils/doctrine-annotation-parser-syncer/src/Rector/Namespace_/RenameAnnotationReaderClassRector.php # 41
- utils/doctrine-annotation-parser-syncer/src/Rector/Namespace_/RenameDocParserClassRector.php # 41
- utils/phpstan-extensions/src/Rule/ValueObjectHasNoValueObjectSuffixRule.php # 45
- utils/phpstan-extensions/src/Rule/ValueObjectHasNoValueObjectSuffixRule.php # 59
- utils/phpstan-extensions/src/Rule/ValueObjectHasNoValueObjectSuffixRule.php # 60
- utils/phpstan-extensions/src/Rule/ValueObjectHasNoValueObjectSuffixRule.php # 75
- utils/phpstan-extensions/src/Rule/ValueObjectHasNoValueObjectSuffixRule.php # 79
-
message: '#Add regex101\.com link to that shows the regex in practise, so it will be easier to maintain in case of bug/extension in the future#'

View File

@ -45,6 +45,9 @@ final class UseImportsTraverser
$this->traverseForType($stmts, $callable, Use_::TYPE_NORMAL);
}
/**
* @param Stmt[] $stmts
*/
private function traverseForType(array $stmts, callable $callable, int $desiredType): void
{
$this->callableNodeTraverser->traverseNodesWithCallable($stmts, function (Node $node) use (

View File

@ -78,6 +78,7 @@ final class DocAliasResolver
}
/**
* @param string[] $possibleDocAliases
* @return string[]
*/
private function appendPossibleAliases(Type $varType, array $possibleDocAliases): array

View File

@ -22,7 +22,7 @@ final class UseClassKeywordForClassNameResolutionRector extends AbstractRector
* @var string
* @see https://regex101.com/r/Vv41Qr/1/
*/
private const CLASS_BEFORE_STATIC_ACCESS_REGEX = '#([\\\\a-zA-Z0-9_\\x80-\\xff]*)::#';
private const CLASS_BEFORE_STATIC_ACCESS_REGEX = '#(?<class_name>[\\\\a-zA-Z0-9_\\x80-\\xff]*)::#';
public function getDefinition(): RectorDefinition
{
@ -70,18 +70,31 @@ CODE_SAMPLE
}
/**
* @return mixed[]
* @return string[]
*/
public function getExistingClasses(String_ $string): array
{
/** @var mixed[] $matches */
$matches = Strings::matchAll($string->value, self::CLASS_BEFORE_STATIC_ACCESS_REGEX, PREG_PATTERN_ORDER);
if (! isset($matches['class_name'])) {
return [];
}
return array_filter($matches[1], function (string $className): bool {
return class_exists($className);
});
$classNames = [];
foreach ($matches['class_name'] as $matchedClassName) {
if (! class_exists($matchedClassName)) {
continue;
}
$classNames[] = $matchedClassName;
}
return $classNames;
}
/**
* @param string[] $classNames
* @return mixed[]
*/
public function getParts(String_ $string, array $classNames): array

View File

@ -34,7 +34,7 @@ use ReflectionFunction;
final class AnnotateThrowablesRector extends AbstractRector
{
/**
* @var array
* @var string[]
*/
private $throwablesToAnnotate = [];
@ -273,6 +273,10 @@ CODE_SAMPLE
return $callePhpDocInfo->getThrowsClassNames();
}
/**
* @param string[] $foundThrownThrowables
* @param string[] $alreadyAnnotatedThrowables
*/
private function diffThrowables(array $foundThrownThrowables, array $alreadyAnnotatedThrowables): int
{
$normalizeNamespace = static function (string $class): string {
@ -296,7 +300,7 @@ CODE_SAMPLE
}
/**
* @return array<class-string>
* @return class-string[]
*/
private function extractMethodReturns(FullyQualified $fullyQualified, Identifier $identifier): array
{
@ -311,7 +315,7 @@ CODE_SAMPLE
}
/**
* @return array<class-string>
* @return class-string[]
*/
private function extractMethodThrows(FullyQualified $fullyQualified, Identifier $identifier): array
{

View File

@ -4,6 +4,8 @@ declare(strict_types=1);
namespace Rector\CodingStyle\ValueObject;
use PhpParser\Node\Expr;
final class ConcatStringAndPlaceholders
{
/**
@ -12,10 +14,13 @@ final class ConcatStringAndPlaceholders
private $content;
/**
* @var array
* @var Expr[]
*/
private $placeholderNodes = [];
/**
* @param Expr[] $placeholderNodes
*/
public function __construct(string $content, array $placeholderNodes)
{
$this->content = $content;
@ -28,7 +33,7 @@ final class ConcatStringAndPlaceholders
}
/**
* @return mixed[]
* @return Expr[]
*/
public function getPlaceholderNodes(): array
{

View File

@ -28,6 +28,9 @@ final class DecoupledClassMethodMatcher
$this->nodeTypeResolver = $nodeTypeResolver;
}
/**
* @param array<string, array<mixed>> $methodNamesByClass
*/
public function matchDecoupled(ClassMethod $classMethod, array $methodNamesByClass): ?DecoupleClassMethodMatch
{
$classLike = $classMethod->getAttribute(AttributeKey::CLASS_NODE);

View File

@ -35,7 +35,7 @@ final class DecoupleClassMethodToOwnClassRector extends AbstractRector implement
public const METHOD_NAMES_BY_CLASS = '$methodNamesByClass';
/**
* @var mixed[][]
* @var array<string, string[]>
*/
private $methodNamesByClass = [];
@ -209,6 +209,9 @@ CODE_SAMPLE
]);
}
/**
* @param mixed[] $configuration
*/
public function configure(array $configuration): void
{
$this->methodNamesByClass = $configuration[self::METHOD_NAMES_BY_CLASS] ?? [];

View File

@ -195,6 +195,9 @@ CODE_SAMPLE
return $phpDocInfo->hasByType(TreeLevelTagValueNode::class);
}
/**
* @param string[] $removedPropertyNames
*/
private function removeClassMethodsForProperties(Class_ $class, array $removedPropertyNames): void
{
foreach ($removedPropertyNames as $removedPropertyName) {

View File

@ -15,6 +15,7 @@ use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
@ -106,6 +107,9 @@ CODE_SAMPLE
return $node;
}
/**
* @param Type[] $methodParameterTypes
*/
private function refactorArg(Arg $arg, array $methodParameterTypes, int $key): void
{
if (! isset($methodParameterTypes[$key])) {

View File

@ -143,6 +143,7 @@ CODE_SAMPLE
/**
* Find all includes and see if any match what we want to insert
* @param Node[] $nodes
*/
private function hasIncludeAlready(array $nodes): bool
{

View File

@ -121,6 +121,9 @@ abstract class AbstractFluentChainMethodCallRector extends AbstractRector
return new AssignAndRootExprAndNodesToAdd($assignAndRootExpr, $nodesToAdd);
}
/**
* @param MethodCall[] $chainMethodCalls
*/
protected function areAllClassMethodLocatedInSameClass(array $chainMethodCalls): bool
{
// are method calls located in the same class?

View File

@ -7,6 +7,7 @@ namespace Rector\Naming\PhpArray;
final class ArrayFilter
{
/**
* @param mixed[] $values
* @return string[]
*/
public function filterWithAtLeastTwoOccurences(array $values): array

View File

@ -65,6 +65,7 @@ final class SymfonyFormAbstractTypeFactory
}
/**
* @param MethodCall[] $methodCalls
* @return Expression[]
*/
private function createBuildFormMethodCalls(array $methodCalls, Variable $formBuilderVariable): array

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Nette\NodeFactory;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\MethodCall;
@ -62,6 +63,9 @@ final class ActionRenderFactory
}
}
/**
* @param Expr[] $templateVariables
*/
private function createTemplateVariablesArray(array $templateVariables): Array_
{
$array = new Array_();

View File

@ -15,7 +15,7 @@ final class MagicTemplatePropertyCalls
private $nodesToRemove = [];
/**
* @var Node[]
* @var Expr[]
*/
private $templateVariables = [];
@ -25,7 +25,7 @@ final class MagicTemplatePropertyCalls
private $templateFileExpr;
/**
* @param Node[] $templateVariables
* @param Expr[] $templateVariables
* @param Node[] $nodesToRemove
*/
public function __construct(?Expr $templateFileExpr, array $templateVariables, array $nodesToRemove)
@ -41,7 +41,7 @@ final class MagicTemplatePropertyCalls
}
/**
* @return Node[]
* @return Expr[]
*/
public function getTemplateVariables(): array
{

View File

@ -8,5 +8,8 @@ interface RankeableInterface
{
public function getName(): string;
/**
* @return bool[]|int[]
*/
public function getRanks(): array;
}

View File

@ -22,7 +22,7 @@ use Rector\Core\RectorDefinition\RectorDefinition;
final class AddRemovedDefaultValuesRector extends AbstractRector
{
/**
* @var mixed[][]
* @var array<string, array<string, array<int, mixed[]>>>
*/
private const METHOD_NAMES_BY_TYPE_WITH_VALUE = [
'PHPExcel' => [
@ -663,6 +663,7 @@ CODE_SAMPLE
/**
* @param StaticCall|MethodCall $node
* @param array<int, mixed> $defaultValuesByPosition
*/
private function refactorArgs(Node $node, array $defaultValuesByPosition): void
{

View File

@ -189,6 +189,9 @@ final class EregToPcreTransformer
return [implode('|', $r), $i];
}
/**
* @param mixed[] $r
*/
private function processBracket(string $content, int $i, int $l, array &$r, int $rr): int
{
// special case
@ -255,6 +258,9 @@ final class EregToPcreTransformer
return $content;
}
/**
* @param mixed[] $r
*/
private function processCurlyBracket(string $s, int $i, array &$r, int $rr): int
{
$ii = strpos($s, '}', $i);

View File

@ -57,7 +57,7 @@ CODE_SAMPLE
}
/**
* @param double $node
* @param Double $node
*/
public function refactor(Node $node): ?Node
{

View File

@ -160,6 +160,9 @@ final class TokenManipulator
});
}
/**
* @param Node[] $nodes
*/
public function refactorTokenIsKind(array $nodes, Expr $singleTokenExpr): void
{
$this->callableNodeTraverser->traverseNodesWithCallable($nodes, function (Node $node) use (

View File

@ -183,6 +183,9 @@ CODE_SAMPLE
return $nodes;
}
/**
* @param Stmt[] $newStmtsSet
*/
private function refactorClassLike(
SmartFileInfo $smartFileInfo,
bool $shouldDeleteFile,

View File

@ -103,6 +103,8 @@ final class ClassRenamer
/**
* Replace types in @var/@param/@return/@throws,
* Doctrine @ORM entity targetClass, Serialize, Assert etc.
*
* @param array<string, string> $oldToNewClasses
*/
private function refactorPhpDoc(Node $node, array $oldToNewClasses): void
{
@ -120,6 +122,9 @@ final class ClassRenamer
$this->phpDocClassRenamer->changeTypeInAnnotationTypes($node, $oldToNewClasses);
}
/**
* @param array<string, string> $oldToNewClasses
*/
private function refactorName(Name $name, array $oldToNewClasses): ?Name
{
$stringName = $this->nodeNameResolver->getName($name);
@ -149,6 +154,9 @@ final class ClassRenamer
return $name;
}
/**
* @param array<string, string> $oldToNewClasses
*/
private function refactorNamespace(Namespace_ $namespace, array $oldToNewClasses): ?Node
{
$name = $this->nodeNameResolver->getName($namespace);
@ -178,6 +186,9 @@ final class ClassRenamer
return $namespace;
}
/**
* @param array<string, string> $oldToNewClasses
*/
private function refactorClassLike(ClassLike $classLike, array $oldToNewClasses): ?Node
{
// rename interfaces
@ -257,6 +268,9 @@ final class ClassRenamer
return true;
}
/**
* @param array<string, string> $oldToNewClasses
*/
private function getClassOfNamespaceToRefactor(Namespace_ $namespace, array $oldToNewClasses): ?ClassLike
{
$foundClass = $this->betterNodeFinder->findFirst($namespace, function (Node $node) use (

View File

@ -169,6 +169,9 @@ CODE_SAMPLE
return $stringsToReplace;
}
/**
* @param string[] $stringsToReplace
*/
private function replaceStringsWithClassConstReferences(Class_ $class, array $stringsToReplace): void
{
$this->traverseNodesWithCallable($class, function (Node $node) use ($stringsToReplace): ?ClassConstFetch {

View File

@ -6,6 +6,7 @@ namespace Rector\SymfonyPhpConfig\Rector\ArrayItem;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ClassConstFetch;
@ -47,7 +48,7 @@ final class ReplaceArrayWithObjectRector extends AbstractRector implements Confi
private $arguments = [];
/**
* @var array
* @var Expr[]
*/
private $nestedArguments = [];

View File

@ -122,6 +122,7 @@ final class ServiceMapProvider
}
/**
* @param mixed[] $def
* @return mixed[]
*/
private function createTagFromXmlElement(array $def): array
@ -190,6 +191,7 @@ final class ServiceMapProvider
}
/**
* @param mixed[] $data
* @return mixed[]
*/
private function unWrapAttributes(array $data): array
@ -206,6 +208,8 @@ final class ServiceMapProvider
}
/**
* @param mixed[] $value
* @param mixed[] $data
* @param string|int $key
* @return mixed[]
*/

View File

@ -26,6 +26,9 @@ final class MethodCallToAnotherMethodCallWithArguments
*/
private $newArguments = [];
/**
* @param mixed[] $newArguments
*/
public function __construct(string $type, string $oldMethod, string $newMethod, array $newArguments)
{
$this->type = $type;

View File

@ -22,7 +22,7 @@ final class PropertyToMethod
private $newGetMethod;
/**
* @var array
* @var mixed[]
*/
private $newGetArguments = [];
@ -31,6 +31,9 @@ final class PropertyToMethod
*/
private $newSetMethod;
/**
* @param mixed[] $newGetArguments
*/
public function __construct(
string $oldType,
string $oldProperty,

View File

@ -168,6 +168,9 @@ final class TypeNormalizer
return $this->typeFactory->createMixedPassedOrUnionType($nonNeverTypes);
}
/**
* @param array<string|int, Type> $nonConstantValueTypes
*/
private function createArrayTypeFromNonConstantValueTypes(array $nonConstantValueTypes): ArrayType
{
$nonConstantValueTypes = array_values($nonConstantValueTypes);

View File

@ -12,6 +12,7 @@ final class ConfigShifter
* Shift input config as last, so the parameters override previous rules loaded from sets
*
* @param SmartFileInfo[] $configFileInfos
* @return SmartFileInfo[]
* @noRector
*/
public function shiftInputConfigAsLast(array $configFileInfos, ?SmartFileInfo $inputConfigFileInfo): array

View File

@ -24,6 +24,9 @@ final class ConfigureCallValuesCollector
$this->parametersMerger = new ParametersMerger();
}
/**
* @return mixed[]
*/
public function getConfigureCallValues(string $rectorClass): array
{
return $this->configureCallValuesByRectorClass[$rectorClass] ?? [];

View File

@ -8,6 +8,9 @@ use Symfony\Component\Yaml\Yaml;
final class YamlPrinter
{
/**
* @param mixed[] $yaml
*/
public function printYamlToString(array $yaml): string
{
return Yaml::dump($yaml, 10, 4, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK);

View File

@ -31,6 +31,9 @@ final class StmtsManipulator
$this->betterStandardPrinter = $betterStandardPrinter;
}
/**
* @param Stmt[] $stmts
*/
public function getUnwrappedLastStmt(array $stmts): ?Node
{
$lastStmtKey = array_key_last($stmts);

View File

@ -114,6 +114,11 @@ final class BetterStandardPrinter extends Standard
$this->docBlockManipulator = $docBlockManipulator;
}
/**
* @param Node[] $stmts
* @param Node[] $origStmts
* @param mixed[] $origTokens
*/
public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens): string
{
$newStmts = $this->resolveNewStmts($stmts);
@ -435,6 +440,7 @@ final class BetterStandardPrinter extends Standard
}
/**
* @param Node[] $stmts
* @return Node[]|mixed[]
*/
private function resolveNewStmts(array $stmts): array
@ -495,6 +501,9 @@ final class BetterStandardPrinter extends Standard
return Strings::replace($printerNode, self::START_DOUBLE_SLASH_COMMENT_REGEX);
}
/**
* @param Node[] $nodes
*/
private function moveCommentsFromAttributeObjectToCommentsAttribute(array $nodes): void
{
// move phpdoc from node to "comment" attribute

View File

@ -98,6 +98,9 @@ trait NameResolverTrait
return $this->isName($node->name, $name);
}
/**
* @param string[] $names
*/
protected function isLocalMethodCallsNamed(Node $node, array $names): bool
{
foreach ($names as $name) {

View File

@ -56,6 +56,7 @@ final class FunctionAnnotationResolver
}
/**
* @param mixed[] $classNames
* @return mixed[]
*/
private function expandAnnotatedClasses(ReflectionFunction $reflectionFunction, array $classNames): array

View File

@ -55,6 +55,9 @@ final class MarkdownNodeInfosPrinter
return $this->implodeLinesWithSpace($contentLines);
}
/**
* @param string[] $contentLines
*/
private function implodeLinesWithSpace(array $contentLines): string
{
return implode(PHP_EOL . PHP_EOL, $contentLines);
@ -71,6 +74,9 @@ final class MarkdownNodeInfosPrinter
return $this->implodeLinesWithSpace($contentLines);
}
/**
* @param string[] $contentLines
*/
private function implodeLines(array $contentLines): string
{
return implode(PHP_EOL, $contentLines);

View File

@ -19,10 +19,6 @@ services:
class: Rector\PHPStanExtensions\Rule\CheckGetNodeTypesReturnPhpParserNodeRule
tags: [phpstan.rules.rule]
-
class: Rector\PHPStanExtensions\Rule\ValueObjectHasNoValueObjectSuffixRule
tags: [phpstan.rules.rule]
-
class: Rector\PHPStanExtensions\Rule\RectorRuleAndValueObjectHaveSameStartsRule
tags: [phpstan.rules.rule]

View File

@ -1,81 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Rule;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
/**
* @see \Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixRule\ValueObjectHasNoValueObjectSuffixRuleTest
*/
final class ValueObjectHasNoValueObjectSuffixRule implements Rule
{
/**
* @var string
*/
public const ERROR = 'Value Object class name "%s" is incorrect. The correct class name is "%s".';
/**
* @see https://regex101.com/r/3jsBnt/1
* @var string
*/
private const VALUE_OBJECT_REGEX = '#ValueObject$#';
/**
* @var string
*/
private const VALUE_OBJECT_NAMESPACE = 'ValueObject';
public function getNodeType(): string
{
return Class_::class;
}
/**
* @param Class_ $node
* @return string[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($node->name === null) {
return [];
}
if (! $this->hasValueObjectNamespace($node)) {
return [];
}
if (! $this->hasValueObjectSuffix($node)) {
return [];
}
return [sprintf(
self::ERROR,
$node->name->toString(),
Strings::replace($node->name->toString(), self::VALUE_OBJECT_REGEX, '')
)];
}
private function hasValueObjectNamespace(Class_ $class): bool
{
if ($class->namespacedName->parts === null) {
return false;
}
return in_array(self::VALUE_OBJECT_NAMESPACE, $class->namespacedName->parts, true);
}
private function hasValueObjectSuffix(Class_ $class): bool
{
if ($class->name === null) {
return false;
}
return Strings::match($class->name->toString(), self::VALUE_OBJECT_REGEX) !== null;
}
}

View File

@ -16,6 +16,7 @@ final class CheckGetNodeTypesReturnPhpParserNodeRuleTest extends AbstractService
{
/**
* @dataProvider provideData()
* @param array<string|string[]|int[]> $expectedErrorsWithLines
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{

View File

@ -13,6 +13,7 @@ final class ConfigurableRectorRuleTest extends AbstractServiceAwareRuleTestCase
{
/**
* @dataProvider provideData()
* @param array<string|string[]|int[]> $expectedErrorsWithLines
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{

View File

@ -13,6 +13,7 @@ final class KeepRectorNamespaceForRectorRuleTest extends AbstractServiceAwareRul
{
/**
* @dataProvider provideData()
* @param array<string|string[]|int[]> $expectedErrorsWithLines
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{

View File

@ -13,6 +13,7 @@ final class RectorRuleAndValueObjectHaveSameStartsRuleTest extends AbstractServi
{
/**
* @dataProvider provideData()
* @param array<string|string[]|int[]> $expectedErrorsWithLines
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{

View File

@ -14,6 +14,7 @@ final class RequireRectorCategoryByGetNodeTypesRuleTest extends AbstractServiceA
{
/**
* @dataProvider provideData()
* @param array<string|string[]|int[]> $expectedErrorsWithLines
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixRule\Fixture;
class SkipNoValueObjectInNamespace
{
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixRule\Fixture\ValueObject;
class MoneyValueObject
{
}

View File

@ -1,11 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixRule\Fixture;
class SkipValueObjectWithoutValueObjectSuffix
{
}

View File

@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\PHPStanExtensions\Tests\Rule\ValueObjectHasNoValueObjectSuffixRule;
use Iterator;
use PHPStan\Rules\Rule;
use Rector\PHPStanExtensions\Rule\ValueObjectHasNoValueObjectSuffixRule;
use Symplify\PHPStanExtensions\Testing\AbstractServiceAwareRuleTestCase;
final class ValueObjectHasNoValueObjectSuffixRuleTest extends AbstractServiceAwareRuleTestCase
{
/**
* @dataProvider provideData()
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{
$this->analyse([$filePath], $expectedErrorsWithLines);
}
public function provideData(): Iterator
{
yield [__DIR__ . '/Fixture/SkipNoValueObjectInNamespace.php', []];
yield [__DIR__ . '/Fixture/ValueObject/SkipValueObjectWithoutValueObjectSuffix.php', []];
$errorMessage = sprintf(ValueObjectHasNoValueObjectSuffixRule::ERROR, 'MoneyValueObject', 'Money');
yield [__DIR__ . '/Fixture/ValueObject/MoneyValueObject.php', [[$errorMessage, 8]]];
}
protected function getRule(): Rule
{
return new ValueObjectHasNoValueObjectSuffixRule();
}
}