mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 08:50:50 +00:00
apply privatization
This commit is contained in:
parent
91d1a1e397
commit
626287ec76
130
CHANGELOG.md
130
CHANGELOG.md
|
@ -9,6 +9,80 @@ PRs and issues are linked, so you can find more about it. Thanks to [ChangelogLi
|
|||
|
||||
<!-- changelog-linker -->
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- [#3080] [CodeQuality] Add ArrayKeysAndInArrayToIssetRector
|
||||
- [#3070] [DeadCode] Add empty() + count($values) > 0 checks to RemoveUnusedNonEmptyArrayBeforeForeachRector
|
||||
- [#3068] [DeadCode] Add RemoveAssignOfVoidReturnFunctionRector
|
||||
- [#3062] [DeadCode] Add RemoveUnusedFunctionRector
|
||||
- [#3066] [DeadCode] Add RemoveUnusedNonEmptyArrayBeforeForeachRector
|
||||
- [#3047] [PHPUnit] Add CreateMockToCreateStubRector
|
||||
- [#3081] [TypeDeclaration] Add class method param type resolving by property
|
||||
- [#3058] [PHP 7.4] Add default null type on properties
|
||||
- [#3059] [PHP 7.4] Add restoration null default only
|
||||
- [#3057] [PHP 7.4] Add id tag support + remove array on collection property
|
||||
- [#3078] Add Safe 0.7 set
|
||||
- [#3072] [PHP 8.0] Add StrContainsRector
|
||||
|
||||
### Changed
|
||||
|
||||
- [#3082] [CodeQuality] use array_key_exists instead of isset
|
||||
- [#3056] [PHP 7.4] Improve TypedPropertyRector for Doctrine collection
|
||||
- [#3051] improve GeneratedValueTagValueNode
|
||||
- [#3063] [PHP 5.5] Prevent error on non-string value in PregReplaceEModifierRector
|
||||
- [#3040] Proofread docs, Thanks to [@greg0ire]
|
||||
- [#3039] Proofread readme, Thanks to [@greg0ire]
|
||||
- [#3083] use just one type of printing
|
||||
|
||||
### Fixed
|
||||
|
||||
- [#3050] Fix assert choice tag value node with class constant reference
|
||||
- [#3049] fix union type on ReturnTypeDeclarationRector
|
||||
- [#3052] fix content resolving
|
||||
- [#3054] skip if not used with the `array []` operator fixes [#3053], Thanks to [@derflocki]
|
||||
- [#3065] Fix multiple annotation reading of same type at class method
|
||||
- [#3069] Fix Route separating key
|
||||
- [#3077] Fix auto import
|
||||
- [#3079] Fix annotation in requirements of [@Route]
|
||||
- [#3064] [PHP 7.4] Fix ChangeReflectionTypeToStringToGetNameRector
|
||||
|
||||
### Removed
|
||||
|
||||
- [#3071] remove ctor dependency on property/assign removal
|
||||
- [#3076] [PHP 8.0] drop preg_match support from StrContains, too vague
|
||||
|
||||
## [v0.7.7] - 2020-03-20
|
||||
|
||||
### Added
|
||||
|
||||
- [#3024] add DoctrineBehaviors 2.0
|
||||
- [#3019] add fix for getIterator() on Finder for Array spread
|
||||
- [#3034] Add checkstyle output format
|
||||
- [#3021] add phpunit 9 rector to convert non-strict assertContains, Thanks to [@nightlinus]
|
||||
- [#3023] add DoctrineBehaviors 2.0
|
||||
|
||||
### Changed
|
||||
|
||||
- [#3032] [DeadCode] Skip shifted variable
|
||||
- [#3015] Rector CI is now exclusive for non-fork pushes + PRs, Thanks to [@JanMikes]
|
||||
- [#3013] Commit rector processed changes from CI, Thanks to [@JanMikes]
|
||||
- [#3036] Run cs after rector ci, Thanks to [@JanMikes]
|
||||
- [#3027] ForToForeachRector fixture, Thanks to [@crishoj]
|
||||
|
||||
### Fixed
|
||||
|
||||
- [#3029] Fix other loop
|
||||
- [#3022] PHP 7.4 deprecation fix, Thanks to [@alexeyshockov]
|
||||
- [#3030] fix no-space change reprint in case of dual comment
|
||||
- [#3035] Fix typo in README.md, Thanks to [@pgrimaud]
|
||||
- [#3031] fix asterisk indent
|
||||
|
||||
### Removed
|
||||
|
||||
- [#3016] Delete DogFoodClass, Thanks to [@JanMikes]
|
||||
|
||||
## [v0.7.4] - 2020-03-11
|
||||
|
||||
### Added
|
||||
|
@ -2650,3 +2724,59 @@ PRs and issues are linked, so you can find more about it. Thanks to [ChangelogLi
|
|||
[#2982]: https://github.com/rectorphp/rector/pull/2982
|
||||
[#2981]: https://github.com/rectorphp/rector/pull/2981
|
||||
[#2980]: https://github.com/rectorphp/rector/pull/2980
|
||||
[#3083]: https://github.com/rectorphp/rector/pull/3083
|
||||
[#3082]: https://github.com/rectorphp/rector/pull/3082
|
||||
[#3081]: https://github.com/rectorphp/rector/pull/3081
|
||||
[#3080]: https://github.com/rectorphp/rector/pull/3080
|
||||
[#3079]: https://github.com/rectorphp/rector/pull/3079
|
||||
[#3078]: https://github.com/rectorphp/rector/pull/3078
|
||||
[#3077]: https://github.com/rectorphp/rector/pull/3077
|
||||
[#3076]: https://github.com/rectorphp/rector/pull/3076
|
||||
[#3072]: https://github.com/rectorphp/rector/pull/3072
|
||||
[#3071]: https://github.com/rectorphp/rector/pull/3071
|
||||
[#3070]: https://github.com/rectorphp/rector/pull/3070
|
||||
[#3069]: https://github.com/rectorphp/rector/pull/3069
|
||||
[#3068]: https://github.com/rectorphp/rector/pull/3068
|
||||
[#3066]: https://github.com/rectorphp/rector/pull/3066
|
||||
[#3065]: https://github.com/rectorphp/rector/pull/3065
|
||||
[#3064]: https://github.com/rectorphp/rector/pull/3064
|
||||
[#3063]: https://github.com/rectorphp/rector/pull/3063
|
||||
[#3062]: https://github.com/rectorphp/rector/pull/3062
|
||||
[#3059]: https://github.com/rectorphp/rector/pull/3059
|
||||
[#3058]: https://github.com/rectorphp/rector/pull/3058
|
||||
[#3057]: https://github.com/rectorphp/rector/pull/3057
|
||||
[#3056]: https://github.com/rectorphp/rector/pull/3056
|
||||
[#3054]: https://github.com/rectorphp/rector/pull/3054
|
||||
[#3053]: https://github.com/rectorphp/rector/pull/3053
|
||||
[#3052]: https://github.com/rectorphp/rector/pull/3052
|
||||
[#3051]: https://github.com/rectorphp/rector/pull/3051
|
||||
[#3050]: https://github.com/rectorphp/rector/pull/3050
|
||||
[#3049]: https://github.com/rectorphp/rector/pull/3049
|
||||
[#3047]: https://github.com/rectorphp/rector/pull/3047
|
||||
[#3040]: https://github.com/rectorphp/rector/pull/3040
|
||||
[#3039]: https://github.com/rectorphp/rector/pull/3039
|
||||
[#3036]: https://github.com/rectorphp/rector/pull/3036
|
||||
[#3035]: https://github.com/rectorphp/rector/pull/3035
|
||||
[#3034]: https://github.com/rectorphp/rector/pull/3034
|
||||
[#3032]: https://github.com/rectorphp/rector/pull/3032
|
||||
[#3031]: https://github.com/rectorphp/rector/pull/3031
|
||||
[#3030]: https://github.com/rectorphp/rector/pull/3030
|
||||
[#3029]: https://github.com/rectorphp/rector/pull/3029
|
||||
[#3027]: https://github.com/rectorphp/rector/pull/3027
|
||||
[#3024]: https://github.com/rectorphp/rector/pull/3024
|
||||
[#3023]: https://github.com/rectorphp/rector/pull/3023
|
||||
[#3022]: https://github.com/rectorphp/rector/pull/3022
|
||||
[#3021]: https://github.com/rectorphp/rector/pull/3021
|
||||
[#3019]: https://github.com/rectorphp/rector/pull/3019
|
||||
[#3016]: https://github.com/rectorphp/rector/pull/3016
|
||||
[#3015]: https://github.com/rectorphp/rector/pull/3015
|
||||
[#3013]: https://github.com/rectorphp/rector/pull/3013
|
||||
[v0.7.7]: https://github.com/rectorphp/rector/compare/v0.7.4...v0.7.7
|
||||
[v0.7.4]: https://github.com/rectorphp/rector/compare/v0.7.3...v0.7.4
|
||||
[@pgrimaud]: https://github.com/pgrimaud
|
||||
[@nightlinus]: https://github.com/nightlinus
|
||||
[@greg0ire]: https://github.com/greg0ire
|
||||
[@derflocki]: https://github.com/derflocki
|
||||
[@crishoj]: https://github.com/crishoj
|
||||
[@alexeyshockov]: https://github.com/alexeyshockov
|
||||
[@Route]: https://github.com/Route
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Rector\\Core\\": "src",
|
||||
"Rector\\Architecture\\": "rules/architecture/src",
|
||||
"Rector\\AttributeAwarePhpDoc\\": "packages/attribute-aware-php-doc/src",
|
||||
"Rector\\Autodiscovery\\": "rules/autodiscovery/src",
|
||||
|
@ -58,10 +57,11 @@
|
|||
"Rector\\CakePHPToSymfony\\": "rules/cakephp-to-symfony/src",
|
||||
"Rector\\CakePHP\\": "rules/cakephp/src",
|
||||
"Rector\\Celebrity\\": "rules/celebrity/src",
|
||||
"Rector\\ChangesReporting\\": "packages/changes-reporting/src",
|
||||
"Rector\\CodeQuality\\": "rules/code-quality/src",
|
||||
"Rector\\CodingStyle\\": "rules/coding-style/src",
|
||||
"Rector\\ConsoleDiffer\\": "packages/console-differ/src",
|
||||
"Rector\\ChangesReporting\\": "packages/changes-reporting/src",
|
||||
"Rector\\Core\\": "src",
|
||||
"Rector\\DeadCode\\": "rules/dead-code/src",
|
||||
"Rector\\DoctrineCodeQuality\\": "rules/doctrine-code-quality/src",
|
||||
"Rector\\DoctrineGedmoToKnplabs\\": "rules/doctrine-gedmo-to-knplabs/src",
|
||||
|
@ -103,6 +103,7 @@
|
|||
"Rector\\PhpDeglobalize\\": "rules/php-deglobalize/src",
|
||||
"Rector\\PhpSpecToPHPUnit\\": "rules/php-spec-to-phpunit/src",
|
||||
"Rector\\Polyfill\\": "packages/polyfill/src",
|
||||
"Rector\\Privatization\\": "rules/privatization/src",
|
||||
"Rector\\RectorGenerator\\": "packages/rector-generator/src",
|
||||
"Rector\\Refactoring\\": "packages/refactoring/src",
|
||||
"Rector\\RemovingStatic\\": "rules/removing-static/src",
|
||||
|
@ -126,7 +127,6 @@
|
|||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Rector\\Core\\Tests\\": "tests",
|
||||
"Rector\\Architecture\\Tests\\": "rules/architecture/tests",
|
||||
"Rector\\Autodiscovery\\Tests\\": "rules/autodiscovery/tests",
|
||||
"Rector\\BetterPhpDocParser\\Tests\\": "packages/better-php-doc-parser/tests",
|
||||
|
@ -135,6 +135,7 @@
|
|||
"Rector\\Celebrity\\Tests\\": "rules/celebrity/tests",
|
||||
"Rector\\CodeQuality\\Tests\\": "rules/code-quality/tests",
|
||||
"Rector\\CodingStyle\\Tests\\": "rules/coding-style/tests",
|
||||
"Rector\\Core\\Tests\\": "tests",
|
||||
"Rector\\DeadCode\\Tests\\": "rules/dead-code/tests",
|
||||
"Rector\\DoctrineCodeQuality\\Tests\\": "rules/doctrine-code-quality/tests",
|
||||
"Rector\\DoctrineGedmoToKnplabs\\Tests\\": "rules/doctrine-gedmo-to-knplabs/tests",
|
||||
|
@ -173,6 +174,7 @@
|
|||
"Rector\\PhpDeglobalize\\Tests\\": "rules/php-deglobalize/tests",
|
||||
"Rector\\PhpSpecToPHPUnit\\Tests\\": "rules/php-spec-to-phpunit/tests",
|
||||
"Rector\\Polyfill\\Tests\\": "packages/polyfill/tests",
|
||||
"Rector\\Privatization\\Tests\\": "rules/privatization/tests",
|
||||
"Rector\\RemovingStatic\\Tests\\": "rules/removing-static/tests",
|
||||
"Rector\\Renaming\\Tests\\": "rules/renaming/tests",
|
||||
"Rector\\Restoration\\Tests\\": "rules/restoration/tests",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# All 472 Rectors Overview
|
||||
# All 473 Rectors Overview
|
||||
|
||||
- [Projects](#projects)
|
||||
- [General](#general)
|
||||
|
@ -48,6 +48,7 @@
|
|||
- [PhpDeglobalize](#phpdeglobalize)
|
||||
- [PhpSpecToPHPUnit](#phpspectophpunit)
|
||||
- [Polyfill](#polyfill)
|
||||
- [Privatization](#privatization)
|
||||
- [Refactoring](#refactoring)
|
||||
- [RemovingStatic](#removingstatic)
|
||||
- [Renaming](#renaming)
|
||||
|
@ -4807,30 +4808,48 @@ Change Form that extends Control to Controller and decoupled FormType
|
|||
-class SomeForm extends Control
|
||||
+class SomeFormController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
|
||||
{
|
||||
- public function createComponentForm()
|
||||
+ /**
|
||||
+ * @Route(...)
|
||||
+ */
|
||||
+ public function actionSomeForm(\Symfony\Component\HttpFoundation\Request $request): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
- $form = new Form();
|
||||
- $form->addText('name', 'Your name');
|
||||
+ $form = $this->createForm(SomeFormType::class);
|
||||
+ $form->handleRequest($request);
|
||||
- public function createComponentForm()
|
||||
+ /**
|
||||
+ * @Route(...)
|
||||
+ */
|
||||
+ public function actionSomeForm(\Symfony\Component\HttpFoundation\Request $request): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
- $form = new Form();
|
||||
- $form->addText('name', 'Your name');
|
||||
+ $form = $this->createForm(SomeFormType::class);
|
||||
+ $form->handleRequest($request);
|
||||
|
||||
- $form->onSuccess[] = [$this, 'processForm'];
|
||||
- }
|
||||
- $form->onSuccess[] = [$this, 'processForm'];
|
||||
- }
|
||||
-
|
||||
- public function processForm(Form $form)
|
||||
- {
|
||||
- public function processForm(Form $form)
|
||||
- {
|
||||
- // process me
|
||||
+ if ($form->isSuccess() && $form->isValid()) {
|
||||
+ // process me
|
||||
+ }
|
||||
}
|
||||
+ if ($form->isSuccess() && $form->isValid()) {
|
||||
+ // process me
|
||||
+ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**New file**
|
||||
|
||||
```php
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class SomeFormType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $formBuilder, array $options)
|
||||
{
|
||||
$formBuilder->add('name', TextType::class, [
|
||||
'label' => 'Your name'
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### `FromHttpRequestGetHeaderToHeadersGetRector`
|
||||
|
@ -7813,6 +7832,35 @@ Remove php version checks if they are passed
|
|||
|
||||
<br>
|
||||
|
||||
## Privatization
|
||||
|
||||
### `PrivatizeLocalOnlyMethodRector`
|
||||
|
||||
- class: [`Rector\Privatization\Rector\ClassMethod\PrivatizeLocalOnlyMethodRector`](/../master/rules/privatization/src/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector.php)
|
||||
- [test fixtures](/../master/rules/privatization/tests/Rector/ClassMethod/PrivatizeLocalOnlyMethodRector/Fixture)
|
||||
|
||||
Privatize local-only use methods
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
{
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
return $this->useMe();
|
||||
}
|
||||
|
||||
- public function useMe()
|
||||
+ private function useMe()
|
||||
{
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
## Refactoring
|
||||
|
||||
### `MoveAndRenameClassRector`
|
||||
|
|
|
@ -143,19 +143,6 @@ final class PhpDocInfo
|
|||
return $this->getPhpDocNode()->getVarTagValues()[0] ?? null;
|
||||
}
|
||||
|
||||
public function getReturnTagValue(): ?AttributeAwareReturnTagValueNode
|
||||
{
|
||||
return $this->getPhpDocNode()->getReturnTagValues()[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AttributeAwareParamTagValueNode[]
|
||||
*/
|
||||
public function getParamTagValues(): array
|
||||
{
|
||||
return $this->getPhpDocNode()->getParamTagValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PhpDocTagNode[]
|
||||
*/
|
||||
|
@ -402,11 +389,6 @@ final class PhpDocInfo
|
|||
$this->addPhpDocTagNode($phpDocTagNode);
|
||||
}
|
||||
|
||||
public function isEmpty(): bool
|
||||
{
|
||||
return $this->phpDocNode->children === [];
|
||||
}
|
||||
|
||||
public function addTagValueNode(PhpDocTagValueNode $phpDocTagValueNode): void
|
||||
{
|
||||
$name = $this->resolveNameForPhpDocTagValueNode($phpDocTagValueNode);
|
||||
|
@ -440,9 +422,17 @@ final class PhpDocInfo
|
|||
$this->addTagValueNode($paramTagValueNode);
|
||||
}
|
||||
|
||||
public function getNode(): Node
|
||||
private function getReturnTagValue(): ?AttributeAwareReturnTagValueNode
|
||||
{
|
||||
return $this->node;
|
||||
return $this->getPhpDocNode()->getReturnTagValues()[0] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AttributeAwareParamTagValueNode[]
|
||||
*/
|
||||
private function getParamTagValues(): array
|
||||
{
|
||||
return $this->getPhpDocNode()->getParamTagValues();
|
||||
}
|
||||
|
||||
private function getParamTagValueByName(string $name): ?AttributeAwareParamTagValueNode
|
||||
|
|
|
@ -75,29 +75,6 @@ final class PhpDocInfoFactory
|
|||
$this->paramPhpDocNodeFactory = $paramPhpDocNodeFactory;
|
||||
}
|
||||
|
||||
public function createFromString(Node $node, string $content): PhpDocInfo
|
||||
{
|
||||
$tokens = $this->lexer->tokenize($content);
|
||||
$phpDocNode = $this->parseTokensToPhpDocNode($tokens);
|
||||
|
||||
/** @var AttributeAwarePhpDocNode $phpDocNode */
|
||||
$phpDocNode = $this->attributeAwareNodeFactory->createFromNode($phpDocNode, $content);
|
||||
|
||||
$phpDocInfo = new PhpDocInfo(
|
||||
$phpDocNode,
|
||||
$tokens,
|
||||
$content,
|
||||
$this->staticTypeMapper,
|
||||
$node,
|
||||
$this->typeComparator,
|
||||
$this->paramPhpDocNodeFactory
|
||||
);
|
||||
|
||||
$node->setAttribute(AttributeKey::PHP_DOC_INFO, $phpDocInfo);
|
||||
|
||||
return $phpDocInfo;
|
||||
}
|
||||
|
||||
public function createFromNode(Node $node): ?PhpDocInfo
|
||||
{
|
||||
/** needed for @see PhpDocNodeFactoryInterface */
|
||||
|
|
|
@ -132,10 +132,26 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
|||
);
|
||||
}
|
||||
|
||||
protected function resolveOriginalContentSpacingAndOrder(?string $originalContent): void
|
||||
{
|
||||
if ($originalContent === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->originalContent = $originalContent;
|
||||
$this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($originalContent);
|
||||
|
||||
$this->hasNewlineAfterOpening = (bool) Strings::match($originalContent, '#^(\(\s+|\n)#m');
|
||||
$this->hasNewlineBeforeClosing = (bool) Strings::match($originalContent, '#(\s+\)|\n(\s+)?)$#m');
|
||||
|
||||
$this->hasOpeningBracket = (bool) Strings::match($originalContent, '#^\(#');
|
||||
$this->hasClosingBracket = (bool) Strings::match($originalContent, '#\)$#');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocTagValueNode[] $tagValueNodes
|
||||
*/
|
||||
protected function printTagValueNodesSeparatedByComma(array $tagValueNodes): string
|
||||
private function printTagValueNodesSeparatedByComma(array $tagValueNodes): string
|
||||
{
|
||||
if ($tagValueNodes === []) {
|
||||
return '';
|
||||
|
@ -155,20 +171,4 @@ abstract class AbstractTagValueNode implements AttributeAwareNodeInterface, PhpD
|
|||
|
||||
return implode(', ', $itemsAsStrings);
|
||||
}
|
||||
|
||||
protected function resolveOriginalContentSpacingAndOrder(?string $originalContent): void
|
||||
{
|
||||
if ($originalContent === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->originalContent = $originalContent;
|
||||
$this->orderedVisibleItems = ArrayItemStaticHelper::resolveAnnotationItemsOrder($originalContent);
|
||||
|
||||
$this->hasNewlineAfterOpening = (bool) Strings::match($originalContent, '#^(\(\s+|\n)#m');
|
||||
$this->hasNewlineBeforeClosing = (bool) Strings::match($originalContent, '#(\s+\)|\n(\s+)?)$#m');
|
||||
|
||||
$this->hasOpeningBracket = (bool) Strings::match($originalContent, '#^\(#');
|
||||
$this->hasClosingBracket = (bool) Strings::match($originalContent, '#\)$#');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -143,11 +143,6 @@ final class TableTagValueNode extends AbstractDoctrineTagValueNode
|
|||
return $this->printContentItems($contentItems);
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getShortName(): string
|
||||
{
|
||||
return '@ORM\Table';
|
||||
|
|
|
@ -148,11 +148,6 @@ final class ColumnTagValueNode extends AbstractDoctrineTagValueNode
|
|||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function changeUnique(bool $unique): void
|
||||
{
|
||||
$this->unique = $unique;
|
||||
}
|
||||
|
||||
public function getType(): ?string
|
||||
{
|
||||
return $this->type;
|
||||
|
|
|
@ -22,9 +22,4 @@ final class TreeTagValueNode extends AbstractTagValueNode
|
|||
{
|
||||
return sprintf('(type="%s")', $this->type);
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,26 @@ final class MultilineSpaceFormatPreserver
|
|||
return null;
|
||||
}
|
||||
|
||||
public function setNewTextToPhpDocNode(
|
||||
/**
|
||||
* Fix multiline BC break - https://github.com/phpstan/phpdoc-parser/pull/26/files
|
||||
*/
|
||||
public function fixMultilineDescriptions(
|
||||
AttributeAwareNodeInterface $attributeAwareNode
|
||||
): AttributeAwareNodeInterface {
|
||||
if (! $attributeAwareNode->getAttribute(Attribute::ORIGINAL_CONTENT)) {
|
||||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
$nodeWithRestoredSpaces = $this->restoreOriginalSpacingInText($attributeAwareNode);
|
||||
if ($nodeWithRestoredSpaces !== null) {
|
||||
$attributeAwareNode = $nodeWithRestoredSpaces;
|
||||
$attributeAwareNode->setAttribute(Attribute::HAS_DESCRIPTION_WITH_ORIGINAL_SPACES, true);
|
||||
}
|
||||
|
||||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
private function setNewTextToPhpDocNode(
|
||||
AttributeAwareNodeInterface $attributeAwareNode,
|
||||
string $newText
|
||||
): AttributeAwareNodeInterface {
|
||||
|
@ -65,25 +84,6 @@ final class MultilineSpaceFormatPreserver
|
|||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix multiline BC break - https://github.com/phpstan/phpdoc-parser/pull/26/files
|
||||
*/
|
||||
public function fixMultilineDescriptions(
|
||||
AttributeAwareNodeInterface $attributeAwareNode
|
||||
): AttributeAwareNodeInterface {
|
||||
if (! $attributeAwareNode->getAttribute(Attribute::ORIGINAL_CONTENT)) {
|
||||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
$nodeWithRestoredSpaces = $this->restoreOriginalSpacingInText($attributeAwareNode);
|
||||
if ($nodeWithRestoredSpaces !== null) {
|
||||
$attributeAwareNode = $nodeWithRestoredSpaces;
|
||||
$attributeAwareNode->setAttribute(Attribute::HAS_DESCRIPTION_WITH_ORIGINAL_SPACES, true);
|
||||
}
|
||||
|
||||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocTextNode|AttributeAwareNodeInterface $attributeAwareNode
|
||||
*/
|
||||
|
|
|
@ -67,11 +67,6 @@ final class ErrorAndDiffCollector
|
|||
$this->nodeRemovingCommander = $nodeRemovingCommander;
|
||||
}
|
||||
|
||||
public function addError(Error $error): void
|
||||
{
|
||||
$this->errors[] = $error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Error[]
|
||||
*/
|
||||
|
@ -132,7 +127,7 @@ final class ErrorAndDiffCollector
|
|||
{
|
||||
$message = $this->exceptionCorrector->getAutoloadExceptionMessageAndAddLocation($analysedCodeException);
|
||||
|
||||
$this->addError(new Error($fileInfo, $message));
|
||||
$this->errors[] = new Error($fileInfo, $message);
|
||||
}
|
||||
|
||||
public function addErrorWithRectorClassMessageAndFileInfo(
|
||||
|
@ -149,8 +144,7 @@ final class ErrorAndDiffCollector
|
|||
if ($rectorClass) {
|
||||
$this->addErrorWithRectorClassMessageAndFileInfo($rectorClass, $throwable->getMessage(), $fileInfo);
|
||||
} else {
|
||||
$error = new Error($fileInfo, $throwable->getMessage(), $throwable->getCode());
|
||||
$this->addError($error);
|
||||
$this->errors[] = new Error($fileInfo, $throwable->getMessage(), $throwable->getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,6 @@ final class RectorChangeCollector
|
|||
$this->currentRectorProvider = $currentRectorProvider;
|
||||
}
|
||||
|
||||
public function addRectorClassWithLine(RectorInterface $rector, SmartFileInfo $smartFileInfo, int $line): void
|
||||
{
|
||||
$this->rectorWithFileAndLineChanges[] = new RectorWithFileAndLineChange(
|
||||
$rector,
|
||||
$smartFileInfo->getRealPath(),
|
||||
$line
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RectorWithFileAndLineChange[]
|
||||
*/
|
||||
|
@ -67,4 +58,13 @@ final class RectorChangeCollector
|
|||
|
||||
$this->addRectorClassWithLine($currentRector, $fileInfo, $node->getLine());
|
||||
}
|
||||
|
||||
private function addRectorClassWithLine(RectorInterface $rector, SmartFileInfo $smartFileInfo, int $line): void
|
||||
{
|
||||
$this->rectorWithFileAndLineChanges[] = new RectorWithFileAndLineChange(
|
||||
$rector,
|
||||
$smartFileInfo->getRealPath(),
|
||||
$line
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,11 +30,6 @@ final class RectorWithFileAndLineChange
|
|||
$this->realPath = $realPath;
|
||||
}
|
||||
|
||||
public function getRector(): RectorInterface
|
||||
{
|
||||
return $this->rector;
|
||||
}
|
||||
|
||||
public function getRectorDefinitionsDescription(): string
|
||||
{
|
||||
return $this->rector->getDefinition()->getDescription();
|
||||
|
|
|
@ -22,6 +22,9 @@ final class CompleteUnifiedDiffOutputBuilderFactory
|
|||
$this->privatesAccessor = new PrivatesAccessor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function create(): UnifiedDiffOutputBuilder
|
||||
{
|
||||
$unifiedDiffOutputBuilder = new UnifiedDiffOutputBuilder('');
|
||||
|
|
|
@ -194,7 +194,7 @@ abstract class AbstractFileSystemRector implements FileSystemRectorInterface
|
|||
$this->removedAndAddedFilesCollector->removeFile($smartFileInfo);
|
||||
}
|
||||
|
||||
protected function addFile(string $filePath, string $content): void
|
||||
private function addFile(string $filePath, string $content): void
|
||||
{
|
||||
$this->removedAndAddedFilesCollector->addFileWithContent($filePath, $content);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ services:
|
|||
_defaults:
|
||||
public: true
|
||||
autowire: true
|
||||
autoconfigure: true
|
||||
|
||||
Rector\NodeCollector\:
|
||||
resource: '../src'
|
||||
exclude:
|
||||
- '../src/ValueObject/*'
|
||||
|
|
|
@ -18,6 +18,7 @@ use PHPStan\Type\MixedType;
|
|||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\NodeCollector\ValueObject\ArrayCallable;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
|
@ -49,7 +50,7 @@ final class ParsedFunctionLikeNodeCollector
|
|||
|
||||
/**
|
||||
* E.g. [$this, 'someLocalMethod']
|
||||
* @var Array_[][][]
|
||||
* @var ArrayCallable[][][]
|
||||
*/
|
||||
private $arrayCallablesByTypeAndMethod = [];
|
||||
|
||||
|
@ -96,7 +97,9 @@ final class ParsedFunctionLikeNodeCollector
|
|||
return;
|
||||
}
|
||||
|
||||
$this->arrayCallablesByTypeAndMethod[$className][$methodName][] = $node;
|
||||
$arrayCallable = new ArrayCallable($className, $methodName);
|
||||
$this->arrayCallablesByTypeAndMethod[$className][$methodName][] = $arrayCallable;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -129,7 +132,7 @@ final class ParsedFunctionLikeNodeCollector
|
|||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall[]|StaticCall[]|Array_[]
|
||||
* @return MethodCall[]|StaticCall[]|ArrayCallable[]
|
||||
*/
|
||||
public function findByClassAndMethod(string $className, string $methodName): array
|
||||
{
|
||||
|
@ -215,30 +218,23 @@ final class ParsedFunctionLikeNodeCollector
|
|||
private function addCall(Node $node): void
|
||||
{
|
||||
// one node can be of multiple-class types
|
||||
$classType = $this->resolveClassType($node);
|
||||
if ($node instanceof MethodCall) {
|
||||
$classType = $this->resolveNodeClassTypes($node->var);
|
||||
} else {
|
||||
/** @var StaticCall $node */
|
||||
$classType = $this->resolveNodeClassTypes($node->class);
|
||||
}
|
||||
|
||||
$methodName = $this->nodeNameResolver->getName($node->name);
|
||||
if ($classType instanceof MixedType) { // anonymous
|
||||
return;
|
||||
}
|
||||
|
||||
$methodName = $this->nodeNameResolver->getName($node->name);
|
||||
if ($methodName === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($classType instanceof ObjectType) {
|
||||
$this->methodsCallsByTypeAndMethod[$classType->getClassName()][$methodName][] = $node;
|
||||
}
|
||||
|
||||
if ($classType instanceof UnionType) {
|
||||
foreach ($classType->getTypes() as $unionedType) {
|
||||
if (! $unionedType instanceof ObjectType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->methodsCallsByTypeAndMethod[$unionedType->getClassName()][$methodName][] = $node;
|
||||
}
|
||||
}
|
||||
$this->addCallByType($node, $classType, $methodName);
|
||||
}
|
||||
|
||||
private function isThisVariable(Node $node): bool
|
||||
|
@ -291,19 +287,20 @@ final class ParsedFunctionLikeNodeCollector
|
|||
return $this->nodeTypeResolver->resolve($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
private function resolveClassType(Node $node): Type
|
||||
private function addCallByType(Node $node, Type $classType, string $methodName): void
|
||||
{
|
||||
if ($node instanceof MethodCall) {
|
||||
if ($node->var instanceof MethodCall) {
|
||||
return $this->resolveNodeClassTypes($node);
|
||||
}
|
||||
|
||||
return $this->resolveNodeClassTypes($node->var);
|
||||
if ($classType instanceof ObjectType) {
|
||||
$this->methodsCallsByTypeAndMethod[$classType->getClassName()][$methodName][] = $node;
|
||||
}
|
||||
|
||||
return $this->resolveNodeClassTypes($node->class);
|
||||
if ($classType instanceof UnionType) {
|
||||
foreach ($classType->getTypes() as $unionedType) {
|
||||
if (! $unionedType instanceof ObjectType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->methodsCallsByTypeAndMethod[$unionedType->getClassName()][$methodName][] = $node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,10 +105,20 @@ final class ClassLikeParsedNodesFinder
|
|||
return array_merge($this->findChildrenOfClass($type), $this->findImplementersOfInterface($type));
|
||||
}
|
||||
|
||||
public function findInterface(string $class): ?Interface_
|
||||
{
|
||||
return $this->parsedNodeCollector->findInterface($class);
|
||||
}
|
||||
|
||||
public function findClass(string $name): ?Class_
|
||||
{
|
||||
return $this->parsedNodeCollector->findClass($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Interface_[]
|
||||
*/
|
||||
public function findImplementersOfInterface(string $interface): array
|
||||
private function findImplementersOfInterface(string $interface): array
|
||||
{
|
||||
$implementerInterfaces = [];
|
||||
|
||||
|
@ -125,16 +135,6 @@ final class ClassLikeParsedNodesFinder
|
|||
return $implementerInterfaces;
|
||||
}
|
||||
|
||||
public function findInterface(string $class): ?Interface_
|
||||
{
|
||||
return $this->parsedNodeCollector->findInterface($class);
|
||||
}
|
||||
|
||||
public function findClass(string $name): ?Class_
|
||||
{
|
||||
return $this->parsedNodeCollector->findClass($name);
|
||||
}
|
||||
|
||||
private function isChildOrEqualClassLike(string $desiredClass, ?string $currentClassName): bool
|
||||
{
|
||||
if ($currentClassName === null) {
|
||||
|
|
|
@ -4,8 +4,6 @@ declare(strict_types=1);
|
|||
|
||||
namespace Rector\NodeCollector\NodeFinder;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
|
@ -15,7 +13,6 @@ use Rector\NodeCollector\NodeCollector\ParsedFunctionLikeNodeCollector;
|
|||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use ReflectionClass;
|
||||
|
||||
final class FunctionLikeParsedNodesFinder
|
||||
{
|
||||
|
@ -90,59 +87,6 @@ final class FunctionLikeParsedNodesFinder
|
|||
return $this->parsedFunctionLikeNodeCollector->findMethod($className, $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo deocpule
|
||||
*/
|
||||
public function isStaticMethod(string $methodName, string $className): bool
|
||||
{
|
||||
$methodNode = $this->findMethod($methodName, $className);
|
||||
if ($methodNode !== null) {
|
||||
return $methodNode->isStatic();
|
||||
}
|
||||
|
||||
// could be static in doc type magic
|
||||
// @see https://regex101.com/r/tlvfTB/1
|
||||
if (class_exists($className) || trait_exists($className)) {
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
if (Strings::match(
|
||||
(string) $reflectionClass->getDocComment(),
|
||||
'#@method\s*static\s*(.*?)\b' . $methodName . '\b#'
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// probably magic method → we don't know
|
||||
if (! method_exists($className, $methodName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$methodReflection = $reflectionClass->getMethod($methodName);
|
||||
return $methodReflection->isStatic();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall[]|StaticCall[]|Array_[]
|
||||
*/
|
||||
public function findClassMethodCalls(ClassMethod $classMethod): array
|
||||
{
|
||||
/** @var string|null $className */
|
||||
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
|
||||
if ($className === null) { // anonymous
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var string|null $methodName */
|
||||
$methodName = $this->nodeNameResolver->getName($classMethod);
|
||||
if ($methodName === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->parsedFunctionLikeNodeCollector->findByClassAndMethod($className, $methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall[][]|StaticCall[][]
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeCollector\NodeFinder;
|
||||
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\NodeCollector\NodeCollector\ParsedFunctionLikeNodeCollector;
|
||||
use Rector\NodeCollector\ValueObject\ArrayCallable;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
final class MethodCallParsedNodesFinder
|
||||
{
|
||||
/**
|
||||
* @var ParsedFunctionLikeNodeCollector
|
||||
*/
|
||||
private $parsedFunctionLikeNodeCollector;
|
||||
|
||||
public function __construct(ParsedFunctionLikeNodeCollector $parsedFunctionLikeNodeCollector)
|
||||
{
|
||||
$this->parsedFunctionLikeNodeCollector = $parsedFunctionLikeNodeCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall[]|StaticCall[]|ArrayCallable[]
|
||||
*/
|
||||
public function findClassMethodCalls(ClassMethod $classMethod): array
|
||||
{
|
||||
/** @var string|null $className */
|
||||
$className = $classMethod->getAttribute(AttributeKey::CLASS_NAME);
|
||||
if ($className === null) { // anonymous
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var string $methodName */
|
||||
$methodName = $classMethod->getAttribute(AttributeKey::METHOD_NAME);
|
||||
|
||||
return $this->parsedFunctionLikeNodeCollector->findByClassAndMethod($className, $methodName);
|
||||
}
|
||||
}
|
59
packages/node-collector/src/StaticAnalyzer.php
Normal file
59
packages/node-collector/src/StaticAnalyzer.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeCollector;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use Rector\NodeCollector\NodeCollector\ParsedFunctionLikeNodeCollector;
|
||||
use Rector\NodeTypeResolver\ClassExistenceStaticHelper;
|
||||
use ReflectionClass;
|
||||
|
||||
final class StaticAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var ParsedFunctionLikeNodeCollector
|
||||
*/
|
||||
private $parsedFunctionLikeNodeCollector;
|
||||
|
||||
public function __construct(ParsedFunctionLikeNodeCollector $parsedFunctionLikeNodeCollector)
|
||||
{
|
||||
$this->parsedFunctionLikeNodeCollector = $parsedFunctionLikeNodeCollector;
|
||||
}
|
||||
|
||||
public function isStaticMethod(string $methodName, string $className): bool
|
||||
{
|
||||
$methodNode = $this->parsedFunctionLikeNodeCollector->findMethod($methodName, $className);
|
||||
if ($methodNode !== null) {
|
||||
return $methodNode->isStatic();
|
||||
}
|
||||
|
||||
// could be static in doc type magic
|
||||
// @see https://regex101.com/r/tlvfTB/1
|
||||
if (! ClassExistenceStaticHelper::doesClassLikeExist($className)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$reflectionClass = new ReflectionClass($className);
|
||||
if ($this->hasStaticAnnotation($methodName, $reflectionClass)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// probably magic method → we don't know
|
||||
if (! method_exists($className, $methodName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$methodReflection = $reflectionClass->getMethod($methodName);
|
||||
|
||||
return $methodReflection->isStatic();
|
||||
}
|
||||
|
||||
private function hasStaticAnnotation(string $methodName, ReflectionClass $reflectionClass): bool
|
||||
{
|
||||
return (bool) Strings::match(
|
||||
(string) $reflectionClass->getDocComment(),
|
||||
'#@method\s*static\s*(.*?)\b' . $methodName . '\b#'
|
||||
);
|
||||
}
|
||||
}
|
34
packages/node-collector/src/ValueObject/ArrayCallable.php
Normal file
34
packages/node-collector/src/ValueObject/ArrayCallable.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeCollector\ValueObject;
|
||||
|
||||
final class ArrayCallable
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $method;
|
||||
|
||||
public function __construct(string $class, string $method)
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->method = $method;
|
||||
}
|
||||
|
||||
public function getClass(): string
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
}
|
|
@ -77,36 +77,57 @@ final class PHPStanServicesFactory
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createReflectionProvider(): ReflectionProvider
|
||||
{
|
||||
return $this->container->getByType(ReflectionProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createNodeScopeResolver(): NodeScopeResolver
|
||||
{
|
||||
return $this->container->getByType(NodeScopeResolver::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createTypeSpecifier(): TypeSpecifier
|
||||
{
|
||||
return $this->container->getByType(TypeSpecifier::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createScopeFactory(): ScopeFactory
|
||||
{
|
||||
return $this->container->getByType(ScopeFactory::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createDynamicReturnTypeExtensionRegistryProvider(): DynamicReturnTypeExtensionRegistryProvider
|
||||
{
|
||||
return $this->container->getByType(DynamicReturnTypeExtensionRegistryProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createOperatorTypeSpecifyingExtensionRegistryProvider(): OperatorTypeSpecifyingExtensionRegistryProvider
|
||||
{
|
||||
return $this->container->getByType(OperatorTypeSpecifyingExtensionRegistryProvider::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function createTypeNodeResolver(): TypeNodeResolver
|
||||
{
|
||||
return $this->container->getByType(TypeNodeResolver::class);
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\Finder;
|
||||
|
||||
use Nette\Loaders\RobotLoader;
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
final class PHPStanTypeClassFinder
|
||||
{
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function find(): array
|
||||
{
|
||||
$robotLoader = new RobotLoader();
|
||||
$robotLoader->addDirectory($this->getPhpstanPharSrcTypeDirectoryPath());
|
||||
|
||||
$robotLoader->setTempDirectory(sys_get_temp_dir() . '/_phpstan_types');
|
||||
$robotLoader->acceptFiles = ['*Type.php'];
|
||||
$robotLoader->rebuild();
|
||||
|
||||
$classLikesToFilePaths = $robotLoader->getIndexedClasses();
|
||||
$classLikes = array_keys($classLikesToFilePaths);
|
||||
|
||||
return $this->filterClassesOnly($classLikes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see https://github.com/dg/nette-robot-loader/blob/593c0e40e511c0b0700610a6a3964a210219139f/tests/Loaders/RobotLoader.phar.phpt#L33
|
||||
*/
|
||||
private function getPhpstanPharSrcTypeDirectoryPath(): string
|
||||
{
|
||||
$phpstanPharRealpath = realpath(__DIR__ . '/../../../../vendor/phpstan/phpstan/phpstan.phar');
|
||||
|
||||
return 'phar://' . $phpstanPharRealpath . '/src/Type';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $classLikes
|
||||
* @return string[]
|
||||
*/
|
||||
private function filterClassesOnly(array $classLikes): array
|
||||
{
|
||||
$classes = [];
|
||||
foreach ($classLikes as $classLike) {
|
||||
if (! class_exists($classLike)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Strings::match($classLike, '#\\\\Accessory\\\\#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classes[] = $classLike;
|
||||
}
|
||||
return $classes;
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ final class AttributeKey
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_SHORT_NAME = 'class_short_name';
|
||||
public const CLASS_SHORT_NAME = 'classShortName';
|
||||
|
||||
/**
|
||||
* @todo split Class node, interface node and trait node, to be compatible with other SpecificNode|null, values
|
||||
|
@ -65,6 +65,11 @@ final class AttributeKey
|
|||
*/
|
||||
public const METHOD_NODE = ClassMethod::class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const FUNCTION_NODE = Function_::class;
|
||||
|
||||
/**
|
||||
* Internal php-parser name.
|
||||
* Do not change this even if you want!
|
||||
|
@ -112,6 +117,9 @@ final class AttributeKey
|
|||
public const FILE_INFO = SmartFileInfo::class;
|
||||
|
||||
/**
|
||||
* Internal php-parser name.
|
||||
* Do not change this even if you want!
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const START_TOKEN_POSITION = 'startTokenPos';
|
||||
|
@ -125,12 +133,7 @@ final class AttributeKey
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const IS_UNREACHABLE = 'is_unreachable';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const FUNCTION_NODE = Function_::class;
|
||||
public const IS_UNREACHABLE = 'isUnreachable';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@ -140,5 +143,5 @@ final class AttributeKey
|
|||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const METHOD_CALL_NODE_CALLER_NAME = 'method_call_variable_name';
|
||||
public const METHOD_CALL_NODE_CALLER_NAME = 'methodCallVariableName';
|
||||
}
|
||||
|
|
|
@ -7,7 +7,9 @@ namespace Rector\NodeTypeResolver\NodeTypeResolver;
|
|||
use PhpParser\Builder\Property;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Nop;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\Type\MixedType;
|
||||
|
@ -19,6 +21,7 @@ use Rector\NodeNameResolver\NodeNameResolver;
|
|||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\NodeTypeResolver\NodeTypeResolver;
|
||||
use Rector\NodeTypeResolver\PHPStan\Collector\TraitNodeScopeCollector;
|
||||
use Rector\StaticTypeMapper\StaticTypeMapper;
|
||||
use ReflectionProperty;
|
||||
|
||||
|
@ -52,16 +55,23 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
*/
|
||||
private $staticTypeMapper;
|
||||
|
||||
/**
|
||||
* @var TraitNodeScopeCollector
|
||||
*/
|
||||
private $traitNodeScopeCollector;
|
||||
|
||||
public function __construct(
|
||||
ParsedNodeCollector $parsedNodeCollector,
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
BetterPhpDocParser $betterPhpDocParser,
|
||||
StaticTypeMapper $staticTypeMapper
|
||||
StaticTypeMapper $staticTypeMapper,
|
||||
TraitNodeScopeCollector $traitNodeScopeCollector
|
||||
) {
|
||||
$this->parsedNodeCollector = $parsedNodeCollector;
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->betterPhpDocParser = $betterPhpDocParser;
|
||||
$this->staticTypeMapper = $staticTypeMapper;
|
||||
$this->traitNodeScopeCollector = $traitNodeScopeCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,58 +97,77 @@ final class PropertyFetchTypeResolver implements NodeTypeResolverInterface
|
|||
{
|
||||
// compensate 3rd party non-analysed property reflection
|
||||
$vendorPropertyType = $this->getVendorPropertyFetchType($node);
|
||||
if ($vendorPropertyType !== null) {
|
||||
if (! $vendorPropertyType instanceof MixedType) {
|
||||
return $vendorPropertyType;
|
||||
}
|
||||
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($scope === null) {
|
||||
return new MixedType();
|
||||
$classNode = $node->getAttribute(AttributeKey::CLASS_NODE);
|
||||
if ($classNode instanceof Trait_) {
|
||||
/** @var string $traitName */
|
||||
$traitName = $classNode->getAttribute(AttributeKey::CLASS_NAME);
|
||||
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $this->traitNodeScopeCollector->getScopeForTraitAndNode($traitName, $node);
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope === null) {
|
||||
$classNode = $node->getAttribute(AttributeKey::CLASS_NODE);
|
||||
// fallback to class, since property fetches are not scoped by PHPStan
|
||||
if ($classNode instanceof ClassLike) {
|
||||
$scope = $classNode->getAttribute(AttributeKey::SCOPE);
|
||||
}
|
||||
|
||||
if ($scope === null) {
|
||||
return new MixedType();
|
||||
}
|
||||
}
|
||||
|
||||
return $scope->getType($node);
|
||||
}
|
||||
|
||||
private function getVendorPropertyFetchType(PropertyFetch $propertyFetch): ?Type
|
||||
private function getVendorPropertyFetchType(PropertyFetch $propertyFetch): Type
|
||||
{
|
||||
$varObjectType = $this->nodeTypeResolver->resolve($propertyFetch->var);
|
||||
|
||||
if (! $varObjectType instanceof TypeWithClassName) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$class = $this->parsedNodeCollector->findClass($varObjectType->getClassName());
|
||||
if ($class !== null) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
// 3rd party code
|
||||
$propertyName = $this->nodeNameResolver->getName($propertyFetch->name);
|
||||
if ($propertyName === null) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
if (! property_exists($varObjectType->getClassName(), $propertyName)) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
// property is used
|
||||
$propertyReflection = new ReflectionProperty($varObjectType->getClassName(), $propertyName);
|
||||
if (! $propertyReflection->getDocComment()) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$phpDocNode = $this->betterPhpDocParser->parseString((string) $propertyReflection->getDocComment());
|
||||
$varTagValues = $phpDocNode->getVarTagValues();
|
||||
|
||||
if (! isset($varTagValues[0])) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
$typeNode = $varTagValues[0]->type;
|
||||
if (! $typeNode instanceof TypeNode) {
|
||||
return null;
|
||||
return new MixedType();
|
||||
}
|
||||
|
||||
return $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType($typeNode, new Nop());
|
||||
|
|
|
@ -50,9 +50,4 @@ final class PropertyTypeResolver implements NodeTypeResolverInterface
|
|||
|
||||
return $this->nodeTypeResolver->resolve($propertyFetchNode);
|
||||
}
|
||||
|
||||
public function setNodeTypeResolver(NodeTypeResolver $nodeTypeResolver): void
|
||||
{
|
||||
$this->nodeTypeResolver = $nodeTypeResolver;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ final class StaticTypeAnalyzer
|
|||
return $this->isAlwaysTruableUnionType($type);
|
||||
}
|
||||
|
||||
public function isNullable(Type $type): bool
|
||||
private function isNullable(Type $type): bool
|
||||
{
|
||||
if (! $type instanceof UnionType) {
|
||||
return false;
|
||||
|
|
|
@ -52,12 +52,7 @@ final class VendorLockResolver
|
|||
return false;
|
||||
}
|
||||
|
||||
return $this->isParamChangeVendorLockedIn($node, $paramPosition);
|
||||
}
|
||||
|
||||
public function isParamChangeVendorLockedIn(ClassMethod $classMethod, int $paramPosition): bool
|
||||
{
|
||||
return $this->classMethodParamVendorLockResolver->isVendorLocked($classMethod, $paramPosition);
|
||||
return $this->classMethodParamVendorLockResolver->isVendorLocked($node, $paramPosition);
|
||||
}
|
||||
|
||||
public function isReturnChangeVendorLockedIn(ClassMethod $classMethod): bool
|
||||
|
|
|
@ -5,7 +5,7 @@ includes:
|
|||
- 'vendor/phpstan/phpstan/conf/bleedingEdge.neon'
|
||||
|
||||
parameters:
|
||||
# checkGenericClassInNonGenericObjectType: false
|
||||
checkGenericClassInNonGenericObjectType: false
|
||||
level: max
|
||||
|
||||
# to allow installing with various phsptan versions without reporting old errors here
|
||||
|
@ -246,4 +246,4 @@ parameters:
|
|||
- '#Access to an undefined property PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode\:\:\$description#'
|
||||
|
||||
- '#Method Rector\\Php80\\Rector\\NotIdentical\\StrContainsRector\:\:matchNotIdenticalToFalse\(\) should return PhpParser\\Node\\Expr\\FuncCall\|null but returns PhpParser\\Node\\Expr#'
|
||||
- '#Method Rector\\Php80\\Rector\\NotIdentical\\StrContainsRector\:\:matchPossibleFuncCallToFalseOrZero\(\) should return PhpParser\\Node\\Expr\\FuncCall\|null but returns PhpParser\\Node\\Expr#'
|
||||
- '#Method Rector\\NodeCollector\\StaticAnalyzer\:\:hasStaticAnnotation\(\) has parameter \$reflectionClass with generic class ReflectionClass but does not specify its types\: T#'
|
||||
|
|
|
@ -5,12 +5,14 @@ parameters:
|
|||
- 'dead-code'
|
||||
- 'nette-utils-code-quality'
|
||||
- 'solid'
|
||||
- 'privatization'
|
||||
|
||||
paths:
|
||||
- 'src'
|
||||
- 'rules'
|
||||
- 'packages'
|
||||
- 'tests'
|
||||
- 'utils'
|
||||
|
||||
exclude_paths:
|
||||
- '/Fixture/'
|
||||
|
|
|
@ -37,23 +37,6 @@ final class DoctrineNodeFactory
|
|||
$this->phpDocInfoFactory = $phpDocInfoFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates:
|
||||
* $this->repository = $entityManager->getRepository(\EntityClass::class);
|
||||
*/
|
||||
public function createRepositoryAssign(string $entityClass): Assign
|
||||
{
|
||||
$repositoryPropertyFetch = new PropertyFetch(new Variable('this'), new Identifier('repository'));
|
||||
|
||||
$entityClassReference = new ClassConstFetch(new FullyQualified($entityClass), 'class');
|
||||
|
||||
$getRepositoryMethodCall = new MethodCall(new Variable('entityManager'), 'getRepository', [
|
||||
new Arg($entityClassReference),
|
||||
]);
|
||||
|
||||
return new Assign($repositoryPropertyFetch, $getRepositoryMethodCall);
|
||||
}
|
||||
|
||||
public function createRepositoryProperty(): Property
|
||||
{
|
||||
$repositoryPropertyBuilder = $this->builderFactory->property('repository');
|
||||
|
@ -82,4 +65,21 @@ final class DoctrineNodeFactory
|
|||
->addStmt($assign)
|
||||
->getNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates:
|
||||
* $this->repository = $entityManager->getRepository(\EntityClass::class);
|
||||
*/
|
||||
private function createRepositoryAssign(string $entityClass): Assign
|
||||
{
|
||||
$repositoryPropertyFetch = new PropertyFetch(new Variable('this'), new Identifier('repository'));
|
||||
|
||||
$entityClassReference = new ClassConstFetch(new FullyQualified($entityClass), 'class');
|
||||
|
||||
$getRepositoryMethodCall = new MethodCall(new Variable('entityManager'), 'getRepository', [
|
||||
new Arg($entityClassReference),
|
||||
]);
|
||||
|
||||
return new Assign($repositoryPropertyFetch, $getRepositoryMethodCall);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ final class EventSubscriberClassFactory
|
|||
return dirname($fileInfo->getRealPath()) . DIRECTORY_SEPARATOR . $eventSubscriberClassName . '.php';
|
||||
}
|
||||
|
||||
public function createEventSubscriberClassName(Class_ $class): string
|
||||
private function createEventSubscriberClassName(Class_ $class): string
|
||||
{
|
||||
$className = $class->getAttribute(AttributeKey::CLASS_SHORT_NAME);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ use PhpParser\Node\Stmt\Trait_;
|
|||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeCollector\NodeFinder\MethodCallParsedNodesFinder;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +20,16 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
*/
|
||||
final class RemoveUnusedPrivateMethodRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var MethodCallParsedNodesFinder
|
||||
*/
|
||||
private $methodCallParsedNodesFinder;
|
||||
|
||||
public function __construct(MethodCallParsedNodesFinder $methodCallParsedNodesFinder)
|
||||
{
|
||||
$this->methodCallParsedNodesFinder = $methodCallParsedNodesFinder;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Remove unused private method', [
|
||||
|
@ -68,7 +79,7 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($node);
|
||||
$classMethodCalls = $this->methodCallParsedNodesFinder->findClassMethodCalls($node);
|
||||
if ($classMethodCalls !== []) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ PHP
|
|||
|
||||
/** @var ClassMethod $method */
|
||||
foreach ($classMethodsToCheck as $method) {
|
||||
if (! $this->methodHasNoStmtsLeft($method)) {
|
||||
if (! $this->hasMethodSomeStmtsLeft($method)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ PHP
|
|||
return $node;
|
||||
}
|
||||
|
||||
protected function methodHasNoStmtsLeft(ClassMethod $classMethod): bool
|
||||
private function hasMethodSomeStmtsLeft(ClassMethod $classMethod): bool
|
||||
{
|
||||
foreach ((array) $classMethod->stmts as $stmt) {
|
||||
if (! $this->isNodeRemoved($stmt)) {
|
||||
|
|
|
@ -40,27 +40,6 @@ final class UnusedClassResolver
|
|||
$this->parsedNodeCollector = $parsedNodeCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getUsedClassNames(): array
|
||||
{
|
||||
if (! PHPUnitEnvironment::isPHPUnitRun() && $this->cachedUsedClassNames !== []) {
|
||||
return $this->cachedUsedClassNames;
|
||||
}
|
||||
|
||||
$cachedUsedClassNames = array_merge(
|
||||
$this->getParamNodesClassNames(),
|
||||
$this->getNewNodesClassNames(),
|
||||
$this->getStaticCallClassNames(),
|
||||
$this->getClassConstantFetchNames()
|
||||
);
|
||||
|
||||
$cachedUsedClassNames = $this->sortAndUniqueArray($cachedUsedClassNames);
|
||||
|
||||
return $this->cachedUsedClassNames = $cachedUsedClassNames;
|
||||
}
|
||||
|
||||
public function isClassWithoutInterfaceAndNotController(Class_ $class): bool
|
||||
{
|
||||
if ($class->implements !== []) {
|
||||
|
@ -82,6 +61,27 @@ final class UnusedClassResolver
|
|||
return $this->nodeNameResolver->isNames($class, $this->getUsedClassNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
private function getUsedClassNames(): array
|
||||
{
|
||||
if (! PHPUnitEnvironment::isPHPUnitRun() && $this->cachedUsedClassNames !== []) {
|
||||
return $this->cachedUsedClassNames;
|
||||
}
|
||||
|
||||
$cachedUsedClassNames = array_merge(
|
||||
$this->getParamNodesClassNames(),
|
||||
$this->getNewNodesClassNames(),
|
||||
$this->getStaticCallClassNames(),
|
||||
$this->getClassConstantFetchNames()
|
||||
);
|
||||
|
||||
$cachedUsedClassNames = $this->sortAndUniqueArray($cachedUsedClassNames);
|
||||
|
||||
return $this->cachedUsedClassNames = $cachedUsedClassNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
|
|
|
@ -39,7 +39,7 @@ final class EntityIdNodeFactory
|
|||
return $uuidProperty;
|
||||
}
|
||||
|
||||
public function decoratePropertyWithIdAnnotations(Property $property): void
|
||||
private function decoratePropertyWithIdAnnotations(Property $property): void
|
||||
{
|
||||
/** @var PhpDocInfo $phpDocInfo */
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
|
|
@ -63,7 +63,7 @@ final class EntityUuidNodeFactory
|
|||
return new Expression($assign);
|
||||
}
|
||||
|
||||
public function decoratePropertyWithUuidAnnotations(Property $property, bool $isNullable, bool $isId): void
|
||||
private function decoratePropertyWithUuidAnnotations(Property $property, bool $isNullable, bool $isId): void
|
||||
{
|
||||
$this->clearVarAndOrmAnnotations($property);
|
||||
$this->replaceIntSerializerTypeWithString($property);
|
||||
|
|
|
@ -77,16 +77,6 @@ final class DoctrineDocBlockResolver
|
|||
return $doctrineRelationTagValueNode->getTargetEntity();
|
||||
}
|
||||
|
||||
public function hasPropertyDoctrineIdTag(Property $property): bool
|
||||
{
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
if ($phpDocInfo === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $phpDocInfo->hasByType(IdTagValueNode::class);
|
||||
}
|
||||
|
||||
public function getDoctrineRelationTagValueNode(Property $property): ?DoctrineRelationTagValueNodeInterface
|
||||
{
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
@ -122,6 +112,13 @@ final class DoctrineDocBlockResolver
|
|||
return $this->isDoctrineEntityClass($classNode);
|
||||
}
|
||||
|
||||
private function hasPropertyDoctrineIdTag(Property $property): bool
|
||||
{
|
||||
$phpDocInfo = $property->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
||||
return $phpDocInfo ? $phpDocInfo->hasByType(IdTagValueNode::class) : false;
|
||||
}
|
||||
|
||||
private function isDoctrineEntityClassNode(Class_ $class): bool
|
||||
{
|
||||
$phpDocInfo = $class->getAttribute(AttributeKey::PHP_DOC_INFO);
|
||||
|
@ -152,10 +149,6 @@ final class DoctrineDocBlockResolver
|
|||
// dummy check of 3rd party code without running it
|
||||
$docCommentContent = (string) $reflectionClass->getDocComment();
|
||||
|
||||
if (Strings::contains($docCommentContent, '@ORM\Entity')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Strings::contains($docCommentContent, '@ORM\Embeddable');
|
||||
return (bool) Strings::match($docCommentContent, '#@ORM\\\\(Entity|Embeddable)#');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,46 +62,50 @@ use Nette\Application\UI\Control;
|
|||
|
||||
class SomeForm extends Control
|
||||
{
|
||||
public function createComponentForm()
|
||||
{
|
||||
$form = new Form();
|
||||
$form->addText('name', 'Your name');
|
||||
public function createComponentForm()
|
||||
{
|
||||
$form = new Form();
|
||||
$form->addText('name', 'Your name');
|
||||
|
||||
$form->onSuccess[] = [$this, 'processForm'];
|
||||
}
|
||||
$form->onSuccess[] = [$this, 'processForm'];
|
||||
}
|
||||
|
||||
public function processForm(Form $form)
|
||||
{
|
||||
public function processForm(Form $form)
|
||||
{
|
||||
// process me
|
||||
}
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
class SomeFormController extends \Symfony\Bundle\FrameworkBundle\Controller\AbstractController
|
||||
{
|
||||
/**
|
||||
* @Route(...)
|
||||
*/
|
||||
public function actionSomeForm(\Symfony\Component\HttpFoundation\Request $request): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$form = $this->createForm(SomeFormType::class);
|
||||
$form->handleRequest($request);
|
||||
/**
|
||||
* @Route(...)
|
||||
*/
|
||||
public function actionSomeForm(\Symfony\Component\HttpFoundation\Request $request): \Symfony\Component\HttpFoundation\Response
|
||||
{
|
||||
$form = $this->createForm(SomeFormType::class);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSuccess() && $form->isValid()) {
|
||||
// process me
|
||||
}
|
||||
}
|
||||
if ($form->isSuccess() && $form->isValid()) {
|
||||
// process me
|
||||
}
|
||||
}
|
||||
}
|
||||
PHP
|
||||
,
|
||||
<<<'PHP'
|
||||
class SomeFormType extends \Symfony\Component\Form\AbstractType
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class SomeFormType extends AbstractType
|
||||
{
|
||||
public function buildForm(\Symfony\Component\Form\FormBuilderInterface $formBuilder, array $options)
|
||||
public function buildForm(FormBuilderInterface $formBuilder, array $options)
|
||||
{
|
||||
$formBuilder->add('name', \Symfony\Component\Form\Extension\Core\Type\TextType::class, [
|
||||
'label' => 'Your name'
|
||||
$formBuilder->add('name', TextType::class, [
|
||||
'label' => 'Your name'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,7 +132,7 @@ final class RouteInfoFactory
|
|||
}
|
||||
|
||||
if (method_exists($presenterClass, 'run')) {
|
||||
return new RouteInfo($presenterClass, 'run', $routePath, null, $methods);
|
||||
return new RouteInfo($presenterClass, 'run', $routePath, $methods);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +177,6 @@ final class RouteInfoFactory
|
|||
return null;
|
||||
}
|
||||
|
||||
return new RouteInfo($controllerClass, $methodName, $routePath, null, []);
|
||||
return new RouteInfo($controllerClass, $methodName, $routePath, []);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ final class SymfonyFormAbstractTypeFactory
|
|||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param MethodCall[] $methodCalls
|
||||
*/
|
||||
public function createFromNetteFormMethodCalls(array $methodCalls): Class_
|
||||
|
|
|
@ -21,11 +21,6 @@ final class RouteInfo
|
|||
*/
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
|
@ -34,17 +29,11 @@ final class RouteInfo
|
|||
/**
|
||||
* @param string[] $httpMethods
|
||||
*/
|
||||
public function __construct(
|
||||
string $class,
|
||||
string $method,
|
||||
string $path,
|
||||
?string $name = null,
|
||||
array $httpMethods = []
|
||||
) {
|
||||
public function __construct(string $class, string $method, string $path, array $httpMethods = [])
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->method = $method;
|
||||
$this->path = $path;
|
||||
$this->name = $name;
|
||||
$this->httpMethods = $httpMethods;
|
||||
}
|
||||
|
||||
|
@ -63,11 +52,6 @@ final class RouteInfo
|
|||
return $this->path;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
|
|
|
@ -68,7 +68,7 @@ final class EregToPcreTransformer
|
|||
}
|
||||
|
||||
// converts the ERE $s into the PCRE $r. triggers error on any invalid input.
|
||||
public function ere2pcre(string $content, bool $ignorecase): string
|
||||
private function ere2pcre(string $content, bool $ignorecase): string
|
||||
{
|
||||
if ($ignorecase) {
|
||||
if (isset($this->icache[$content])) {
|
||||
|
|
|
@ -11,6 +11,7 @@ use PHPUnit\Framework\TestCase;
|
|||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeCollector\StaticAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
/**
|
||||
|
@ -19,6 +20,16 @@ use Rector\NodeTypeResolver\Node\AttributeKey;
|
|||
*/
|
||||
final class ThisCallOnStaticMethodToStaticCallRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var StaticAnalyzer
|
||||
*/
|
||||
private $staticAnalyzer;
|
||||
|
||||
public function __construct(StaticAnalyzer $staticAnalyzer)
|
||||
{
|
||||
$this->staticAnalyzer = $staticAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition('Changes $this->call() to static method to static call', [
|
||||
|
@ -89,7 +100,7 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
$isStaticMethod = $this->functionLikeParsedNodesFinder->isStaticMethod($methodName, $className);
|
||||
$isStaticMethod = $this->staticAnalyzer->isStaticMethod($methodName, $className);
|
||||
if (! $isStaticMethod) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ use Rector\Core\PhpParser\Node\Manipulator\ClassMethodManipulator;
|
|||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeCollector\StaticAnalyzer;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use ReflectionClass;
|
||||
|
||||
|
@ -31,9 +32,15 @@ final class StaticCallOnNonStaticToInstanceCallRector extends AbstractRector
|
|||
*/
|
||||
private $classMethodManipulator;
|
||||
|
||||
public function __construct(ClassMethodManipulator $classMethodManipulator)
|
||||
/**
|
||||
* @var StaticAnalyzer
|
||||
*/
|
||||
private $staticAnalyzer;
|
||||
|
||||
public function __construct(ClassMethodManipulator $classMethodManipulator, StaticAnalyzer $staticAnalyzer)
|
||||
{
|
||||
$this->classMethodManipulator = $classMethodManipulator;
|
||||
$this->staticAnalyzer = $staticAnalyzer;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
|
@ -97,7 +104,7 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
$isStaticMethod = $this->functionLikeParsedNodesFinder->isStaticMethod($methodName, $className);
|
||||
$isStaticMethod = $this->staticAnalyzer->isStaticMethod($methodName, $className);
|
||||
if ($isStaticMethod) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,6 @@ use PhpParser\Node\Stmt\ClassMethod;
|
|||
use PHPStan\PhpDocParser\Ast\PhpDoc\GenericTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
|
||||
use PHPStan\Type\ArrayType;
|
||||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\AttributeAwarePhpDoc\Ast\PhpDoc\AttributeAwareParamTagValueNode;
|
||||
|
@ -206,20 +204,6 @@ PHP
|
|||
return 'provideDataFor' . ucfirst($methodName);
|
||||
}
|
||||
|
||||
private function resolveUniqueArrayStaticType(Array_ $array): Type
|
||||
{
|
||||
$isNestedArray = $this->isNestedArray($array);
|
||||
|
||||
$uniqueArrayStaticType = $this->resolveUniqueArrayStaticTypes($array);
|
||||
|
||||
if ($isNestedArray && $uniqueArrayStaticType instanceof ArrayType) {
|
||||
// unwrap one level up
|
||||
return $uniqueArrayStaticType->getItemType();
|
||||
}
|
||||
|
||||
return $uniqueArrayStaticType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ParamAndArgValueObject[]
|
||||
*/
|
||||
|
@ -296,21 +280,6 @@ PHP
|
|||
return false;
|
||||
}
|
||||
|
||||
private function resolveUniqueArrayStaticTypes(Array_ $array): Type
|
||||
{
|
||||
$itemStaticTypes = [];
|
||||
foreach ($array->items as $arrayItem) {
|
||||
$arrayItemStaticType = $this->getStaticType($arrayItem->value);
|
||||
if ($arrayItemStaticType instanceof MixedType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$itemStaticTypes[] = new ArrayType(new MixedType(), $arrayItemStaticType);
|
||||
}
|
||||
|
||||
return $this->typeFactory->createMixedPassedOrUnionType($itemStaticTypes);
|
||||
}
|
||||
|
||||
private function resolveItemStaticType(Array_ $array, bool $isNestedArray): Type
|
||||
{
|
||||
$staticTypes = [];
|
||||
|
@ -380,8 +349,7 @@ PHP
|
|||
|
||||
$this->dataProviderClassMethodRecipes[] = new DataProviderClassMethodRecipe(
|
||||
$dataProviderMethodName,
|
||||
$methodCall->args,
|
||||
$this->resolveUniqueArrayStaticType($firstArgumentValue)
|
||||
$methodCall->args
|
||||
);
|
||||
|
||||
$methodCall->args = [];
|
||||
|
|
|
@ -100,7 +100,7 @@ final class AssertComparisonToSpecificMethodRector extends AbstractPHPUnitRector
|
|||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
public function changeOrderArguments(Node $node): void
|
||||
private function changeArgumentsOrder(Node $node): void
|
||||
{
|
||||
$oldArguments = $node->args;
|
||||
|
||||
|
@ -137,7 +137,7 @@ final class AssertComparisonToSpecificMethodRector extends AbstractPHPUnitRector
|
|||
'assertFalse' => $falseMethodName,
|
||||
]);
|
||||
|
||||
$this->changeOrderArguments($node);
|
||||
$this->changeArgumentsOrder($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ final class AssertFalseStrposToContainsRector extends AbstractPHPUnitRector
|
|||
}
|
||||
|
||||
$this->identifierManipulator->renameNodeWithMap($node, self::RENAME_METHODS_MAP);
|
||||
$this->changeOrderArguments($node);
|
||||
$this->changeArgumentsOrder($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ final class AssertFalseStrposToContainsRector extends AbstractPHPUnitRector
|
|||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
public function changeOrderArguments(Node $node): void
|
||||
private function changeArgumentsOrder(Node $node): void
|
||||
{
|
||||
$oldArguments = $node->args;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ final class AssertInstanceOfComparisonRector extends AbstractPHPUnitRector
|
|||
return null;
|
||||
}
|
||||
$this->identifierManipulator->renameNodeWithMap($node, self::RENAME_METHODS_MAP);
|
||||
$this->changeOrderArguments($node);
|
||||
$this->changeArgumentsOrder($node);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ final class AssertInstanceOfComparisonRector extends AbstractPHPUnitRector
|
|||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
public function changeOrderArguments(Node $node): void
|
||||
private function changeArgumentsOrder(Node $node): void
|
||||
{
|
||||
$oldArguments = $node->args;
|
||||
/** @var Instanceof_ $comparison */
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Rector\PHPUnit\ValueObject;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
use PHPStan\Type\Type;
|
||||
|
||||
final class DataProviderClassMethodRecipe
|
||||
{
|
||||
|
@ -19,19 +18,13 @@ final class DataProviderClassMethodRecipe
|
|||
*/
|
||||
private $args = [];
|
||||
|
||||
/**
|
||||
* @var Type|null
|
||||
*/
|
||||
private $type;
|
||||
|
||||
/**
|
||||
* @param Arg[] $args
|
||||
*/
|
||||
public function __construct(string $methodName, array $args, ?Type $type)
|
||||
public function __construct(string $methodName, array $args)
|
||||
{
|
||||
$this->methodName = $methodName;
|
||||
$this->args = $args;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getMethodName(): string
|
||||
|
@ -46,9 +39,4 @@ final class DataProviderClassMethodRecipe
|
|||
{
|
||||
return $this->args;
|
||||
}
|
||||
|
||||
public function getType(): ?Type
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ PHP
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($this->lastStatementBreaksFlow($node)) {
|
||||
if ($this->doesLastStatementBreakFlow($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ PHP
|
|||
return null;
|
||||
}
|
||||
|
||||
protected function lastStatementBreaksFlow(Node $node): bool
|
||||
private function doesLastStatementBreakFlow(Node $node): bool
|
||||
{
|
||||
$lastStmt = end($node->stmts);
|
||||
return ! ($lastStmt instanceof Return_
|
||||
|
|
|
@ -222,7 +222,7 @@ final class ServiceMapProvider
|
|||
);
|
||||
} else {
|
||||
unset($data['name']);
|
||||
$tagValueObjects[$key] = new Tag($name, $data);
|
||||
$tagValueObjects[$key] = new Tag($name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,11 +28,6 @@ final class ServiceMap
|
|||
return isset($this->services[$id]);
|
||||
}
|
||||
|
||||
public function getService(string $id): ?ServiceDefinition
|
||||
{
|
||||
return $this->services[$id] ?? null;
|
||||
}
|
||||
|
||||
public function getServiceType(string $id): ?Type
|
||||
{
|
||||
$serviceDefinition = $this->getService($id);
|
||||
|
@ -75,4 +70,9 @@ final class ServiceMap
|
|||
|
||||
return $servicesWithTag;
|
||||
}
|
||||
|
||||
private function getService(string $id): ?ServiceDefinition
|
||||
{
|
||||
return $this->services[$id] ?? null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,24 +13,13 @@ final class Tag implements TagInterface
|
|||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $data = [];
|
||||
|
||||
public function __construct(string $name, array $data)
|
||||
public function __construct(string $name)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getData(): array
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Rector\TypeDeclaration\Rector\ClassMethod;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
|
@ -14,6 +13,8 @@ use PHPStan\Type\Type;
|
|||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Core\RectorDefinition\CodeSample;
|
||||
use Rector\Core\RectorDefinition\RectorDefinition;
|
||||
use Rector\NodeCollector\NodeFinder\MethodCallParsedNodesFinder;
|
||||
use Rector\NodeCollector\ValueObject\ArrayCallable;
|
||||
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
|
||||
|
||||
/**
|
||||
|
@ -28,9 +29,15 @@ final class AddMethodCallBasedParamTypeRector extends AbstractRector
|
|||
*/
|
||||
private $typeFactory;
|
||||
|
||||
public function __construct(TypeFactory $typeFactory)
|
||||
/**
|
||||
* @var MethodCallParsedNodesFinder
|
||||
*/
|
||||
private $methodCallParsedNodesFinder;
|
||||
|
||||
public function __construct(TypeFactory $typeFactory, MethodCallParsedNodesFinder $methodCallParsedNodesFinder)
|
||||
{
|
||||
$this->typeFactory = $typeFactory;
|
||||
$this->methodCallParsedNodesFinder = $methodCallParsedNodesFinder;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
|
@ -91,8 +98,7 @@ PHP
|
|||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($node);
|
||||
|
||||
$classMethodCalls = $this->methodCallParsedNodesFinder->findClassMethodCalls($node);
|
||||
$classParameterTypes = $this->getCallTypesByPosition($classMethodCalls);
|
||||
|
||||
foreach ($classParameterTypes as $position => $argumentStaticType) {
|
||||
|
@ -110,7 +116,7 @@ PHP
|
|||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall[]|StaticCall[]|Array_[] $classMethodCalls
|
||||
* @param MethodCall[]|StaticCall[]|ArrayCallable[] $classMethodCalls
|
||||
* @return Type[]
|
||||
*/
|
||||
private function getCallTypesByPosition(array $classMethodCalls): array
|
||||
|
|
|
@ -79,6 +79,9 @@ final class Configuration
|
|||
$this->setOnlyRector($onlyRector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
public function setFirstResolverConfig(?string $firstResolvedConfig): void
|
||||
{
|
||||
$this->configFilePath = $firstResolvedConfig;
|
||||
|
|
|
@ -9,4 +9,9 @@ interface CodeSampleInterface
|
|||
public function getCodeBefore(): string;
|
||||
|
||||
public function getCodeAfter(): string;
|
||||
|
||||
/**
|
||||
* Content of newly created file
|
||||
*/
|
||||
public function getExtraFileContent(): ?string;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ final class RectorContainerFactory
|
|||
}
|
||||
|
||||
/**
|
||||
* @api
|
||||
* @param string[] $configFiles
|
||||
*/
|
||||
public function createFromConfigs(array $configFiles): ContainerInterface
|
||||
|
|
|
@ -68,50 +68,6 @@ final class CallReflectionResolver
|
|||
return $this->resolveMethodCall($node);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FunctionReflection|MethodReflection|null
|
||||
*/
|
||||
public function resolveFunctionCall(FuncCall $funcCall)
|
||||
{
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $funcCall->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($funcCall->name instanceof Name) {
|
||||
try {
|
||||
return $this->reflectionProvider->getFunction($funcCall->name, $scope);
|
||||
} catch (FunctionNotFoundException $functionNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->typeToCallReflectionResolverRegistry->resolve($scope->getType($funcCall->name), $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
public function resolveMethodCall(Node $node): ?MethodReflection
|
||||
{
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
if ($scope === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classType = $this->nodeTypeResolver->resolve($node instanceof MethodCall ? $node->var : $node->class);
|
||||
$methodName = $this->nodeNameResolver->getName($node->name);
|
||||
|
||||
if ($methodName === null || ! $classType->hasMethod($methodName)->yes()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $classType->getMethod($methodName, $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FunctionReflection|MethodReflection|null $reflection
|
||||
* @param FuncCall|MethodCall|StaticCall $node
|
||||
|
@ -141,4 +97,48 @@ final class CallReflectionResolver
|
|||
|
||||
return $parametersAcceptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FunctionReflection|MethodReflection|null
|
||||
*/
|
||||
private function resolveFunctionCall(FuncCall $funcCall)
|
||||
{
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $funcCall->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
if ($funcCall->name instanceof Name) {
|
||||
try {
|
||||
return $this->reflectionProvider->getFunction($funcCall->name, $scope);
|
||||
} catch (FunctionNotFoundException $functionNotFoundException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($scope === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->typeToCallReflectionResolverRegistry->resolve($scope->getType($funcCall->name), $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MethodCall|StaticCall $node
|
||||
*/
|
||||
private function resolveMethodCall(Node $node): ?MethodReflection
|
||||
{
|
||||
/** @var Scope|null $scope */
|
||||
$scope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
if ($scope === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$classType = $this->nodeTypeResolver->resolve($node instanceof MethodCall ? $node->var : $node->class);
|
||||
$methodName = $this->nodeNameResolver->getName($node->name);
|
||||
|
||||
if ($methodName === null || ! $classType->hasMethod($methodName)->yes()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $classType->getMethod($methodName, $scope);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,36 +87,20 @@ final class BetterNodeDumper extends NodeDumper
|
|||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $attribute
|
||||
*/
|
||||
protected function dumpAttributeValue($attribute): string
|
||||
{
|
||||
if ($attribute === null) {
|
||||
return 'null';
|
||||
} elseif ($attribute === false) {
|
||||
return 'false';
|
||||
} elseif ($attribute === true) {
|
||||
return 'true';
|
||||
} elseif (is_scalar($attribute)) {
|
||||
return (string) $attribute;
|
||||
}
|
||||
return str_replace("\n", "\n ", $this->dumpRecursive($attribute));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
protected function getFilteredAttributes(Node $node) : array
|
||||
private function getFilteredAttributes(Node $node) : array
|
||||
{
|
||||
$attributes = $node->getAttributes();
|
||||
if ($this->filterAttributes !== []) {
|
||||
$attributes = array_intersect_key($attributes, array_flip($this->filterAttributes));
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
protected function dumpSubNodes(Node $node): string
|
||||
private function dumpSubNodes(Node $node): string
|
||||
{
|
||||
$r = '';
|
||||
foreach ($node->getSubNodeNames() as $key) {
|
||||
|
@ -153,15 +137,15 @@ final class BetterNodeDumper extends NodeDumper
|
|||
|
||||
}
|
||||
|
||||
protected function dumpNode(Node $node): string
|
||||
private function dumpNode(Node $node): string
|
||||
{
|
||||
$spl_object_hash = spl_object_hash($node);
|
||||
$splObjectHash = spl_object_hash($node);
|
||||
|
||||
if (isset($this->printedNodes[$spl_object_hash])) {
|
||||
return $node->getType() . ' #' . $this->printedNodes[$spl_object_hash];
|
||||
if (isset($this->printedNodes[$splObjectHash])) {
|
||||
return $node->getType() . ' #' . $this->printedNodes[$splObjectHash];
|
||||
}
|
||||
$this->printedNodes[$spl_object_hash] = $this->nodeIds++;
|
||||
$r = $node->getType() . ' #' . $this->printedNodes[$spl_object_hash];
|
||||
$this->printedNodes[$splObjectHash] = $this->nodeIds++;
|
||||
$r = $node->getType() . ' #' . $this->printedNodes[$splObjectHash];
|
||||
|
||||
if ($this->dumpPositions ) {
|
||||
$r .= $this->dumpPosition($node);
|
||||
|
|
|
@ -5,7 +5,6 @@ declare(strict_types=1);
|
|||
namespace Rector\Core\PhpParser\Node\Manipulator;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\AssignOp;
|
||||
|
@ -38,76 +37,17 @@ final class AssignManipulator
|
|||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var PropertyFetchManipulator
|
||||
*/
|
||||
private $propertyFetchManipulator;
|
||||
|
||||
/**
|
||||
* @var BetterStandardPrinter
|
||||
*/
|
||||
private $betterStandardPrinter;
|
||||
|
||||
public function __construct(
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
PropertyFetchManipulator $propertyFetchManipulator,
|
||||
BetterStandardPrinter $betterStandardPrinter
|
||||
) {
|
||||
public function __construct(NodeNameResolver $nodeNameResolver, BetterStandardPrinter $betterStandardPrinter)
|
||||
{
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->propertyFetchManipulator = $propertyFetchManipulator;
|
||||
$this->betterStandardPrinter = $betterStandardPrinter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks:
|
||||
* $this->x = y;
|
||||
* $this->x[] = y;
|
||||
*/
|
||||
public function isLocalPropertyAssign(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof Assign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (bool) $this->propertyFetchManipulator->matchPropertyFetch($node->var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is: "$this->value = <$value>"
|
||||
*
|
||||
* @param string[] $propertyNames
|
||||
*/
|
||||
public function isLocalPropertyAssignWithPropertyNames(Node $node, array $propertyNames): bool
|
||||
{
|
||||
if (! $this->isLocalPropertyAssign($node)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Assign $node */
|
||||
$propertyFetch = $this->propertyFetchManipulator->matchPropertyFetch($node->var);
|
||||
if ($propertyFetch === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->nodeNameResolver->isNames($propertyFetch, $propertyNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Covers:
|
||||
* - $this->propertyName = <$expr>;
|
||||
* - self::$propertyName = <$expr>;
|
||||
* - $this->propertyName[] = <$expr>;
|
||||
* - self::$propertyName[] = <$expr>;
|
||||
*/
|
||||
public function matchPropertyAssignExpr(Assign $assign, string $propertyName): ?Expr
|
||||
{
|
||||
if (! $this->isLocalPropertyAssignWithPropertyNames($assign, [$propertyName])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $assign->expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches:
|
||||
* each() = [1, 2];
|
||||
|
|
|
@ -69,7 +69,6 @@ final class ChildAndParentClassManipulator
|
|||
if ($parentClassName !== '' && method_exists($parentClassName, '__construct')) {
|
||||
$parentConstructCallNode = $this->nodeFactory->createParentConstructWithParams([]);
|
||||
$classMethod->stmts[] = new Expression($parentConstructCallNode);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -93,9 +93,11 @@ final class ClassDependencyManipulator
|
|||
$constructorMethod = $this->nodeFactory->createPublicMethod(self::CONSTRUCTOR);
|
||||
|
||||
$this->classMethodAssignManipulator->addParameterAndAssignToMethod($constructorMethod, $name, $type, $assign);
|
||||
|
||||
$this->childAndParentClassManipulator->completeParentConstructor($classNode, $constructorMethod);
|
||||
|
||||
$this->classInsertManipulator->addAsFirstMethod($classNode, $constructorMethod);
|
||||
|
||||
$this->childAndParentClassManipulator->completeChildConstructors($classNode, $constructorMethod);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,25 +50,6 @@ final class ClassInsertManipulator
|
|||
$class->stmts[] = $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] ...$types
|
||||
*/
|
||||
public function addStatementToClassBeforeTypes(Class_ $class, Stmt $stmt, string ...$types): void
|
||||
{
|
||||
foreach ($types as $type) {
|
||||
foreach ($class->stmts as $key => $classStmt) {
|
||||
if (! $classStmt instanceof $type) {
|
||||
continue;
|
||||
}
|
||||
$class->stmts = $this->insertBefore($class->stmts, $stmt, $key);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$class->stmts[] = $stmt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Stmt[] $nodes
|
||||
* @return Stmt[]
|
||||
|
@ -106,6 +87,25 @@ final class ClassInsertManipulator
|
|||
$this->addStatementToClassBeforeTypes($class, $trait, TraitUse::class, Property::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] ...$types
|
||||
*/
|
||||
private function addStatementToClassBeforeTypes(Class_ $class, Stmt $stmt, string ...$types): void
|
||||
{
|
||||
foreach ($types as $type) {
|
||||
foreach ($class->stmts as $key => $classStmt) {
|
||||
if (! $classStmt instanceof $type) {
|
||||
continue;
|
||||
}
|
||||
$class->stmts = $this->insertBefore($class->stmts, $stmt, $key);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$class->stmts[] = $stmt;
|
||||
}
|
||||
|
||||
private function tryInsertBeforeFirstMethod(Class_ $classNode, Stmt $stmt): bool
|
||||
{
|
||||
foreach ($classNode->stmts as $key => $classStmt) {
|
||||
|
|
|
@ -75,15 +75,6 @@ final class ClassMethodAssignManipulator
|
|||
return $this->variableManipulator->filterOutReadOnlyVariables($readOnlyVariableAssigns, $classMethod);
|
||||
}
|
||||
|
||||
public function isExplicitlyReferenced(Node $node): bool
|
||||
{
|
||||
if ($node instanceof Arg || $node instanceof ClosureUse || $node instanceof Param) {
|
||||
return $node->byRef;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public function addParameterAndAssignToMethod(
|
||||
ClassMethod $classMethod,
|
||||
string $name,
|
||||
|
@ -98,6 +89,15 @@ final class ClassMethodAssignManipulator
|
|||
$classMethod->stmts[] = new Expression($assign);
|
||||
}
|
||||
|
||||
private function isExplicitlyReferenced(Node $node): bool
|
||||
{
|
||||
if ($node instanceof Arg || $node instanceof ClosureUse || $node instanceof Param) {
|
||||
return $node->byRef;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Assign[] $variableAssigns
|
||||
* @return Assign[]
|
||||
|
@ -118,6 +118,11 @@ final class ClassMethodAssignManipulator
|
|||
}
|
||||
|
||||
foreach ($node->var->items as $arrayItem) {
|
||||
// empty item
|
||||
if ($arrayItem === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $arrayItem->value instanceof Variable) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -174,17 +174,6 @@ final class ClassMethodManipulator
|
|||
return $paramName;
|
||||
}
|
||||
|
||||
public function removeParameter(Param $param, ClassMethod $classMethod): void
|
||||
{
|
||||
foreach ($classMethod->params as $key => $constructorParam) {
|
||||
if (! $this->nodeNameResolver->areNamesEqual($constructorParam, $param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($classMethod->params[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
public function removeUnusedParameters(ClassMethod $classMethod): void
|
||||
{
|
||||
foreach ($classMethod->getParams() as $param) {
|
||||
|
@ -207,6 +196,17 @@ final class ClassMethodManipulator
|
|||
return null;
|
||||
}
|
||||
|
||||
private function removeParameter(Param $param, ClassMethod $classMethod): void
|
||||
{
|
||||
foreach ($classMethod->params as $key => $constructorParam) {
|
||||
if (! $this->nodeNameResolver->areNamesEqual($constructorParam, $param)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unset($classMethod->params[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
private function isMethodInParent(string $class, string $method): bool
|
||||
{
|
||||
foreach (class_parents($class) as $parentClass) {
|
||||
|
|
|
@ -127,24 +127,6 @@ final class IfManipulator
|
|||
return null;
|
||||
}
|
||||
|
||||
public function isIfWithOnlyStmtIf(If_ $if): bool
|
||||
{
|
||||
if (! $this->isIfWithoutElseAndElseIfs($if)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->hasOnlyStmtOfType($if, If_::class);
|
||||
}
|
||||
|
||||
public function hasOnlyStmtOfType(If_ $if, string $desiredType): bool
|
||||
{
|
||||
if (count($if->stmts) !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_a($if->stmts[0], $desiredType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return If_[]
|
||||
*/
|
||||
|
@ -173,15 +155,6 @@ final class IfManipulator
|
|||
return $ifs;
|
||||
}
|
||||
|
||||
public function isIfWithElse(If_ $if): bool
|
||||
{
|
||||
if ($if->else === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! (bool) $if->elseifs;
|
||||
}
|
||||
|
||||
public function isIfAndElseWithSameVariableAssignAsLastStmts(If_ $if, Expr $desiredExpr): bool
|
||||
{
|
||||
if (! $this->isIfWithElse($if)) {
|
||||
|
@ -289,6 +262,33 @@ final class IfManipulator
|
|||
return $this->hasOnlyStmtOfType($node, Foreach_::class);
|
||||
}
|
||||
|
||||
private function isIfWithOnlyStmtIf(If_ $if): bool
|
||||
{
|
||||
if (! $this->isIfWithoutElseAndElseIfs($if)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->hasOnlyStmtOfType($if, If_::class);
|
||||
}
|
||||
|
||||
private function hasOnlyStmtOfType(If_ $if, string $desiredType): bool
|
||||
{
|
||||
if (count($if->stmts) !== 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return is_a($if->stmts[0], $desiredType);
|
||||
}
|
||||
|
||||
private function isIfWithElse(If_ $if): bool
|
||||
{
|
||||
if ($if->else === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ! (bool) $if->elseifs;
|
||||
}
|
||||
|
||||
private function matchComparedAndReturnedNode(NotIdentical $notIdentical, Return_ $returnNode): ?Expr
|
||||
{
|
||||
if ($this->betterStandardPrinter->areNodesEqual(
|
||||
|
|
|
@ -60,7 +60,7 @@ final class PropertyFetchAssignManipulator
|
|||
* Matches:
|
||||
* "$this->someValue = $<variableName>;"
|
||||
*/
|
||||
public function isVariableAssignToThisPropertyFetch(Node $node, string $variableName): bool
|
||||
private function isVariableAssignToThisPropertyFetch(Node $node, string $variableName): bool
|
||||
{
|
||||
if (! $node instanceof Assign) {
|
||||
return false;
|
||||
|
|
|
@ -5,10 +5,8 @@ declare(strict_types=1);
|
|||
namespace Rector\Core\PhpParser\Node\Manipulator;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\StaticPropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PHPStan\Reflection\ReflectionProvider;
|
||||
|
@ -142,26 +140,6 @@ final class PropertyFetchManipulator
|
|||
return $this->nodeNameResolver->isName($node->var, 'this');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PropertyFetch|StaticPropertyFetch|null
|
||||
*/
|
||||
public function matchPropertyFetch(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof PropertyFetch) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof StaticPropertyFetch) {
|
||||
return $node;
|
||||
}
|
||||
|
||||
if ($node instanceof ArrayDimFetch) {
|
||||
return $this->matchPropertyFetch($node->var);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches:
|
||||
* "$this->someValue = $<variableName>;"
|
||||
|
|
|
@ -6,7 +6,6 @@ namespace Rector\Core\Rector\AbstractRector;
|
|||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
|
@ -24,6 +23,8 @@ use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
|
|||
use Rector\DeadCode\NodeManipulator\LivingCodeManipulator;
|
||||
use Rector\NodeCollector\NodeCollector\ParsedNodeCollector;
|
||||
use Rector\NodeCollector\NodeFinder\FunctionLikeParsedNodesFinder;
|
||||
use Rector\NodeCollector\NodeFinder\MethodCallParsedNodesFinder;
|
||||
use Rector\NodeCollector\ValueObject\ArrayCallable;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
||||
/**
|
||||
|
@ -53,6 +54,11 @@ trait ComplexRemovalTrait
|
|||
*/
|
||||
private $propertyManipulator;
|
||||
|
||||
/**
|
||||
* @var MethodCallParsedNodesFinder
|
||||
*/
|
||||
private $methodCallParsedNodesFinder;
|
||||
|
||||
/**
|
||||
* @required
|
||||
*/
|
||||
|
@ -60,12 +66,14 @@ trait ComplexRemovalTrait
|
|||
PropertyManipulator $propertyManipulator,
|
||||
ParsedNodeCollector $parsedNodeCollector,
|
||||
LivingCodeManipulator $livingCodeManipulator,
|
||||
BetterStandardPrinter $betterStandardPrinter
|
||||
BetterStandardPrinter $betterStandardPrinter,
|
||||
MethodCallParsedNodesFinder $methodCallParsedNodesFinder
|
||||
): void {
|
||||
$this->parsedNodeCollector = $parsedNodeCollector;
|
||||
$this->propertyManipulator = $propertyManipulator;
|
||||
$this->livingCodeManipulator = $livingCodeManipulator;
|
||||
$this->betterStandardPrinter = $betterStandardPrinter;
|
||||
$this->methodCallParsedNodesFinder = $methodCallParsedNodesFinder;
|
||||
}
|
||||
|
||||
abstract protected function removeNode(Node $node): void;
|
||||
|
@ -74,9 +82,9 @@ trait ComplexRemovalTrait
|
|||
{
|
||||
$this->removeNode($classMethod);
|
||||
|
||||
$classMethodCalls = $this->functionLikeParsedNodesFinder->findClassMethodCalls($classMethod);
|
||||
$classMethodCalls = $this->methodCallParsedNodesFinder->findClassMethodCalls($classMethod);
|
||||
foreach ($classMethodCalls as $classMethodCall) {
|
||||
if ($classMethodCall instanceof Array_) {
|
||||
if ($classMethodCall instanceof ArrayCallable) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ final class CodeSample implements CodeSampleInterface
|
|||
return $this->codeAfter;
|
||||
}
|
||||
|
||||
public function getExtraFileAfter(): ?string
|
||||
public function getExtraFileContent(): ?string
|
||||
{
|
||||
return $this->extraFileContent;
|
||||
}
|
||||
|
|
|
@ -23,14 +23,24 @@ final class ConfiguredCodeSample implements CodeSampleInterface
|
|||
*/
|
||||
private $configuration = [];
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $extraFileContent;
|
||||
|
||||
/**
|
||||
* @param mixed[] $configuration
|
||||
*/
|
||||
public function __construct(string $codeBefore, string $codeAfter, array $configuration)
|
||||
{
|
||||
public function __construct(
|
||||
string $codeBefore,
|
||||
string $codeAfter,
|
||||
array $configuration,
|
||||
?string $extraFileContent = null
|
||||
) {
|
||||
$this->codeBefore = $codeBefore;
|
||||
$this->codeAfter = $codeAfter;
|
||||
$this->configuration = $configuration;
|
||||
$this->extraFileContent = $extraFileContent;
|
||||
}
|
||||
|
||||
public function getCodeBefore(): string
|
||||
|
@ -50,4 +60,9 @@ final class ConfiguredCodeSample implements CodeSampleInterface
|
|||
{
|
||||
return $this->configuration;
|
||||
}
|
||||
|
||||
public function getExtraFileContent(): ?string
|
||||
{
|
||||
return $this->extraFileContent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ final class FunctionReflectionHelper
|
|||
return $this->expandAnnotatedClasses($reflectionFunction, $annotatedThrownClasses);
|
||||
}
|
||||
|
||||
public function expandAnnotatedClasses(ReflectionFunction $reflectionFunction, array $classNames): array
|
||||
private function expandAnnotatedClasses(ReflectionFunction $reflectionFunction, array $classNames): array
|
||||
{
|
||||
$functionNode = $this->functionParser->parseFunction($reflectionFunction);
|
||||
if (! $functionNode instanceof Namespace_) {
|
||||
|
|
|
@ -172,7 +172,7 @@ final class ScannedErrorToRectorResolver
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
$arguments[] = new Argument($match['name'], $position, $match['type'] ?? '');
|
||||
$arguments[] = new Argument($position, $match['type'] ?? '');
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
|
|
|
@ -11,20 +11,14 @@ final class Argument
|
|||
*/
|
||||
private $position;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $type;
|
||||
|
||||
public function __construct(string $name, int $position, string $type = '')
|
||||
public function __construct(int $position, string $type = '')
|
||||
{
|
||||
$this->position = $position;
|
||||
$this->name = $name;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
|
@ -33,11 +27,6 @@ final class Argument
|
|||
return $this->position;
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function getType(): string
|
||||
{
|
||||
return $this->type;
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Nette\Utils\FileSystem;
|
||||
use Nette\Utils\Json;
|
||||
use Nette\Utils\Strings;
|
||||
|
||||
require __DIR__ . '/../../../vendor/autoload.php';
|
||||
|
||||
$composerJson = __DIR__ . '/../../../composer.json';
|
||||
|
||||
$composerContent = FileSystem::read($composerJson);
|
||||
$jsonContent = Json::decode($composerContent, Json::FORCE_ARRAY);
|
||||
|
||||
// 1. unset primary here
|
||||
unset($jsonContent['autoload']['psr-4']['Rector\\Core\\']);
|
||||
unset($jsonContent['autoload-dev']['psr-4']['Rector\\Core\\Tests\\']);
|
||||
|
||||
// 2. sort by namespaces
|
||||
ksort($jsonContent['autoload']['psr-4']);
|
||||
ksort($jsonContent['autoload-dev']['psr-4']);
|
||||
|
||||
// 3. make core first
|
||||
$jsonContent['autoload']['psr-4'] = array_merge(['Rector\\Core\\' => 'src'], $jsonContent['autoload']['psr-4']);
|
||||
$jsonContent['autoload-dev']['psr-4'] = array_merge(
|
||||
['Rector\\Core\\Tests\\' => 'tests'],
|
||||
$jsonContent['autoload-dev']['psr-4']
|
||||
);
|
||||
|
||||
$newComposerJsonContent = Json::encode($jsonContent, Json::PRETTY) . PHP_EOL;
|
||||
$newComposerJsonContent = inlineSections($newComposerJsonContent, ['keywords', 'bin']);
|
||||
$newComposerJsonContent = inlineAuthorSection($newComposerJsonContent);
|
||||
|
||||
FileSystem::write($composerJson, $newComposerJsonContent);
|
||||
|
||||
echo 'DONE';
|
||||
|
||||
|
||||
// used from: https://github.com/Symplify/Symplify/blob/64e1e07c87b1ec5551df07482d68c5085e76824a/packages/MonorepoBuilder/src/FileSystem/JsonFileManager.php#L70
|
||||
function inlineSections(string $jsonContent, array $inlineSections): string
|
||||
{
|
||||
foreach ($inlineSections as $inlineSection) {
|
||||
$pattern = '#("' . preg_quote($inlineSection, '#') . '": )\[(.*?)\](,)#ms';
|
||||
$jsonContent = Strings::replace($jsonContent, $pattern, function (array $match): string {
|
||||
$inlined = Strings::replace($match[2], '#\s+#', ' ');
|
||||
$inlined = trim($inlined);
|
||||
$inlined = '[' . $inlined . ']';
|
||||
|
||||
return $match[1] . $inlined . $match[3];
|
||||
});
|
||||
}
|
||||
|
||||
return $jsonContent;
|
||||
}
|
||||
|
||||
function inlineAuthorSection(string $jsonContent): string
|
||||
{
|
||||
$authorsPattern = '#("authors":\s+\[)(?<authors>.*?)(\])#s';
|
||||
|
||||
$match = Strings::match($jsonContent, $authorsPattern);
|
||||
|
||||
$authorsContent = $match['authors'];
|
||||
$authorsContent = Strings::replace($authorsContent, '#,\s+#', ', ');
|
||||
$authorsContent = Strings::replace($authorsContent, '#{\s+#', '{ ');
|
||||
$authorsContent = Strings::replace($authorsContent, '#\s+}#', ' }');
|
||||
$authorsContent = Strings::replace($authorsContent, '#}, {#', "},\n {");
|
||||
|
||||
$authorsContent = trim($authorsContent);
|
||||
$authorsContent = ' ' . $authorsContent;
|
||||
|
||||
return Strings::replace($jsonContent, $authorsPattern, "$1\n" . $authorsContent . "\n $3");
|
||||
}
|
|
@ -15,6 +15,11 @@ use Symplify\PackageBuilder\Console\Command\CommandNaming;
|
|||
|
||||
final class DumpRectorsCommand extends AbstractCommand
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const OUTPUT_FORMAT_OPTION = 'output-format';
|
||||
|
||||
/**
|
||||
* @var DumpRectorsOutputFormatterInterface[]
|
||||
*/
|
||||
|
@ -41,7 +46,7 @@ final class DumpRectorsCommand extends AbstractCommand
|
|||
$this->setName(CommandNaming::classToName(self::class));
|
||||
$this->setDescription('[Docs] Dump overview of all Rectors');
|
||||
$this->addOption(
|
||||
'output-format',
|
||||
self::OUTPUT_FORMAT_OPTION,
|
||||
'o',
|
||||
InputOption::VALUE_REQUIRED,
|
||||
'Output format for Rectors [json, markdown]',
|
||||
|
@ -59,7 +64,7 @@ final class DumpRectorsCommand extends AbstractCommand
|
|||
$generalRectors = $this->rectorsFinder->findInDirectory(__DIR__ . '/../../../../src');
|
||||
|
||||
foreach ($this->dumpRectorsOutputFormatterInterfaces as $outputFormatter) {
|
||||
if ($outputFormatter->getName() !== $input->getOption('output-format')) {
|
||||
if ($outputFormatter->getName() !== $input->getOption(self::OUTPUT_FORMAT_OPTION)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,6 +211,14 @@ final class MarkdownDumpRectorsOutputFormatter implements DumpRectorsOutputForma
|
|||
);
|
||||
|
||||
$this->printCodeWrapped($diff, 'diff');
|
||||
|
||||
$extraFileContent = $codeSample->getExtraFileContent();
|
||||
if ($extraFileContent !== null) {
|
||||
$this->symfonyStyle->newLine();
|
||||
$this->symfonyStyle->writeln('**New file**');
|
||||
$this->symfonyStyle->newLine();
|
||||
$this->printCodeWrapped($extraFileContent, 'php');
|
||||
}
|
||||
}
|
||||
|
||||
private function printCodeWrapped(string $content, string $format): void
|
||||
|
|
|
@ -8,6 +8,11 @@ use Nette\Loaders\RobotLoader;
|
|||
|
||||
final class NodeClassFinder
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private const EXCLUDED_CLASSES = ['PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode'];
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
|
@ -40,7 +45,6 @@ final class NodeClassFinder
|
|||
$classLikesToPaths = $robotLoader->getIndexedClasses();
|
||||
|
||||
$classLikes = array_keys($classLikesToPaths);
|
||||
$excludedClasses = ['PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode'];
|
||||
|
||||
// keep only classes, skip interfaces
|
||||
$classes = [];
|
||||
|
@ -52,6 +56,6 @@ final class NodeClassFinder
|
|||
$classes[] = $classLike;
|
||||
}
|
||||
|
||||
return array_diff($classes, $excludedClasses);
|
||||
return array_diff($classes, self::EXCLUDED_CLASSES);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,9 +31,9 @@ use PHPStan\Type\Type;
|
|||
abstract class AbstractResolvedNameReturnTypeExtension implements DynamicMethodReturnTypeExtension
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
* @var class-string[]
|
||||
*/
|
||||
private $alwaysNamedTypes = [
|
||||
private const ALWAYS_NAMED_TYPES = [
|
||||
ClassMethod::class,
|
||||
Trait_::class,
|
||||
Interface_::class,
|
||||
|
@ -57,7 +57,7 @@ abstract class AbstractResolvedNameReturnTypeExtension implements DynamicMethodR
|
|||
return $returnType;
|
||||
}
|
||||
|
||||
if (in_array($argumentValueType->getClassName(), $this->alwaysNamedTypes, true)) {
|
||||
if (in_array($argumentValueType->getClassName(), self::ALWAYS_NAMED_TYPES, true)) {
|
||||
return new StringType();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ final class GetAttributeReturnTypeExtension implements DynamicMethodReturnTypeEx
|
|||
/**
|
||||
* @var string[]|string[][]
|
||||
*/
|
||||
private $argumentKeyToReturnType = [
|
||||
private const ARGUMENT_KEY_TO_RETURN_TYPE = [
|
||||
AttributeKey::class . '::FILE_INFO' => SmartFileInfo::class,
|
||||
AttributeKey::class . '::RESOLVED_NAME' => Name::class,
|
||||
AttributeKey::class . '::CLASS_NODE' => ClassLike::class,
|
||||
|
@ -86,11 +86,11 @@ final class GetAttributeReturnTypeExtension implements DynamicMethodReturnTypeEx
|
|||
return $returnType;
|
||||
}
|
||||
|
||||
if (! isset($this->argumentKeyToReturnType[$argumentValue])) {
|
||||
if (! isset(self::ARGUMENT_KEY_TO_RETURN_TYPE[$argumentValue])) {
|
||||
return $returnType;
|
||||
}
|
||||
|
||||
$knownReturnType = $this->argumentKeyToReturnType[$argumentValue];
|
||||
$knownReturnType = self::ARGUMENT_KEY_TO_RETURN_TYPE[$argumentValue];
|
||||
if ($knownReturnType === 'string') {
|
||||
return new UnionType([new StringType(), new NullType()]);
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@ use PHPStan\Type\DynamicMethodReturnTypeExtension;
|
|||
use PHPStan\Type\MixedType;
|
||||
use PHPStan\Type\ObjectType;
|
||||
use PHPStan\Type\Type;
|
||||
use Rector\NodeContainer\ParsedNodesByType;
|
||||
use Rector\NodeCollector\NodeCollector\ParsedNodeCollector;
|
||||
|
||||
final class ParsedNodesByTypeReturnTypeExtension implements DynamicMethodReturnTypeExtension
|
||||
{
|
||||
public function getClass(): string
|
||||
{
|
||||
return ParsedNodesByType::class;
|
||||
return ParsedNodeCollector::class;
|
||||
}
|
||||
|
||||
public function isMethodSupported(MethodReflection $methodReflection): bool
|
||||
|
@ -47,10 +47,8 @@ final class ParsedNodesByTypeReturnTypeExtension implements DynamicMethodReturnT
|
|||
|
||||
private function resolveArgumentValue(Expr $expr): ?string
|
||||
{
|
||||
if ($expr instanceof ClassConstFetch) {
|
||||
if ($expr->class instanceof Name) {
|
||||
return $expr->class->toString();
|
||||
}
|
||||
if ($expr instanceof ClassConstFetch && $expr->class instanceof Name) {
|
||||
return $expr->class->toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -68,11 +68,7 @@ final class PreventParentMethodVisibilityOverrideRule implements Rule
|
|||
return true;
|
||||
}
|
||||
|
||||
if ($reflectionMethod->isPrivate() && $classMethod->isPrivate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $reflectionMethod->isPrivate() && $classMethod->isPrivate();
|
||||
}
|
||||
|
||||
private function resolveReflectionMethodVisibilityAsStrings(ReflectionMethod $reflectionMethod): string
|
||||
|
|
Loading…
Reference in New Issue
Block a user