mirror of https://github.com/rectorphp/rector.git
Updated Rector to commit 5b3d656a003e72540050d47e00285341a96b5796
5b3d656a00
[Custom] Add "detect-node" command to help with writing custom rules (#5576)
This commit is contained in:
parent
af18c3962f
commit
7bb5d0c0c4
|
@ -6,9 +6,9 @@ namespace Rector\DeadCode\Rector\Foreach_;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Foreach_;
|
||||
use PhpParser\NodeFinder;
|
||||
use Rector\Contract\PhpParser\Node\StmtsAwareInterface;
|
||||
use Rector\NodeManipulator\StmtsManipulator;
|
||||
use Rector\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
|
@ -19,17 +19,17 @@ final class RemoveUnusedForeachKeyRector extends AbstractRector
|
|||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\PhpParser\Node\BetterNodeFinder
|
||||
* @var \PhpParser\NodeFinder
|
||||
*/
|
||||
private $betterNodeFinder;
|
||||
private $nodeFinder;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\NodeManipulator\StmtsManipulator
|
||||
*/
|
||||
private $stmtsManipulator;
|
||||
public function __construct(BetterNodeFinder $betterNodeFinder, StmtsManipulator $stmtsManipulator)
|
||||
public function __construct(NodeFinder $nodeFinder, StmtsManipulator $stmtsManipulator)
|
||||
{
|
||||
$this->betterNodeFinder = $betterNodeFinder;
|
||||
$this->nodeFinder = $nodeFinder;
|
||||
$this->stmtsManipulator = $stmtsManipulator;
|
||||
}
|
||||
public function getRuleDefinition() : RuleDefinition
|
||||
|
@ -72,7 +72,7 @@ CODE_SAMPLE
|
|||
continue;
|
||||
}
|
||||
$keyVar = $stmt->keyVar;
|
||||
$isNodeUsed = (bool) $this->betterNodeFinder->findFirst($stmt->stmts, function (Node $node) use($keyVar) : bool {
|
||||
$isNodeUsed = (bool) $this->nodeFinder->findFirst($stmt->stmts, function (Node $node) use($keyVar) : bool {
|
||||
return $this->nodeComparator->areNodesEqual($node, $keyVar);
|
||||
});
|
||||
if ($isNodeUsed) {
|
||||
|
|
|
@ -19,12 +19,12 @@ final class VersionResolver
|
|||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const PACKAGE_VERSION = '667983116e7c8ec828a0b9b1877f90e4faf532e0';
|
||||
public const PACKAGE_VERSION = '5b3d656a003e72540050d47e00285341a96b5796';
|
||||
/**
|
||||
* @api
|
||||
* @var string
|
||||
*/
|
||||
public const RELEASE_DATE = '2024-02-07 20:20:49';
|
||||
public const RELEASE_DATE = '2024-02-07 17:26:36';
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\Console\Command;
|
||||
|
||||
use Throwable;
|
||||
use RectorPrefix202402\Nette\Utils\Strings;
|
||||
use Rector\CustomRules\SimpleNodeDumper;
|
||||
use Rector\PhpParser\Parser\SimplePhpParser;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Command\Command;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Input\InputInterface;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Input\InputOption;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Output\OutputInterface;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Question\Question;
|
||||
use RectorPrefix202402\Symfony\Component\Console\Style\SymfonyStyle;
|
||||
final class DetectNodeCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Symfony\Component\Console\Style\SymfonyStyle
|
||||
*/
|
||||
private $symfonyStyle;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \Rector\PhpParser\Parser\SimplePhpParser
|
||||
*/
|
||||
private $simplePhpParser;
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/Fe8n73/1
|
||||
*/
|
||||
private const CLASS_NAME_REGEX = '#(?<class_name>PhpParser(.*?))\\(#ms';
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/uQFuvL/1
|
||||
*/
|
||||
private const PROPERTY_KEY_REGEX = '#(?<key>[\\w\\d]+)\\:#';
|
||||
public function __construct(SymfonyStyle $symfonyStyle, SimplePhpParser $simplePhpParser)
|
||||
{
|
||||
$this->symfonyStyle = $symfonyStyle;
|
||||
$this->simplePhpParser = $simplePhpParser;
|
||||
parent::__construct();
|
||||
}
|
||||
protected function configure() : void
|
||||
{
|
||||
$this->setName('detect-node');
|
||||
$this->setDescription('Detects node for provided PHP content');
|
||||
$this->addOption('loop', null, InputOption::VALUE_NONE, 'Keep open so you can try multiple inputs');
|
||||
$this->setAliases(['dump-node']);
|
||||
// @todo invoke https://github.com/matthiasnoback/php-ast-inspector/
|
||||
// $this->addOption('file');
|
||||
}
|
||||
protected function execute(InputInterface $input, OutputInterface $output) : int
|
||||
{
|
||||
if ((bool) $input->getOption('loop')) {
|
||||
while (\true) {
|
||||
$this->askQuestionAndDumpNode();
|
||||
}
|
||||
}
|
||||
$this->askQuestionAndDumpNode();
|
||||
return self::SUCCESS;
|
||||
}
|
||||
private function addConsoleColors(string $contents) : string
|
||||
{
|
||||
// decorate class names
|
||||
$colorContents = Strings::replace($contents, self::CLASS_NAME_REGEX, static function (array $match) : string {
|
||||
return '<fg=green>' . $match['class_name'] . '</>(';
|
||||
});
|
||||
// decorate keys
|
||||
return Strings::replace($colorContents, self::PROPERTY_KEY_REGEX, static function (array $match) : string {
|
||||
return '<fg=yellow>' . $match['key'] . '</>:';
|
||||
});
|
||||
}
|
||||
private function askQuestionAndDumpNode() : void
|
||||
{
|
||||
$question = new Question('Write short PHP code snippet');
|
||||
$phpContents = $this->symfonyStyle->askQuestion($question);
|
||||
try {
|
||||
$nodes = $this->simplePhpParser->parseString($phpContents);
|
||||
} catch (Throwable $exception) {
|
||||
$this->symfonyStyle->warning('Provide valid PHP code');
|
||||
return;
|
||||
}
|
||||
$dumpedNodesContents = SimpleNodeDumper::dump($nodes);
|
||||
// colorize
|
||||
$colorContents = $this->addConsoleColors($dumpedNodesContents);
|
||||
$this->symfonyStyle->writeln($colorContents);
|
||||
$this->symfonyStyle->newLine();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
|
||||
declare (strict_types=1);
|
||||
namespace Rector\CustomRules;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Include_;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\GroupUse;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PhpParser\Node\Stmt\UseUse;
|
||||
/**
|
||||
* Inspired by @see \PhpParser\NodeDumper
|
||||
*/
|
||||
final class SimpleNodeDumper
|
||||
{
|
||||
/**
|
||||
* @param Node[]|Node|mixed[] $node
|
||||
*/
|
||||
public static function dump($node, bool $rootNode = \true) : string
|
||||
{
|
||||
// display single root node directly to avoid useless nesting in output
|
||||
if (\is_array($node) && \count($node) === 1 && $rootNode) {
|
||||
$node = $node[0];
|
||||
}
|
||||
if ($node instanceof Node) {
|
||||
return self::dumpSingleNode($node);
|
||||
}
|
||||
if (self::isStringList($node)) {
|
||||
return \json_encode($node, 0);
|
||||
}
|
||||
$result = '[';
|
||||
foreach ($node as $key => $value) {
|
||||
$result .= "\n " . $key . ': ';
|
||||
if ($value === null) {
|
||||
$result .= 'null';
|
||||
} elseif ($value === \false) {
|
||||
$result .= 'false';
|
||||
} elseif ($value === \true) {
|
||||
$result .= 'true';
|
||||
} elseif (\is_string($value)) {
|
||||
$result .= '"' . $value . '"';
|
||||
} elseif (\is_scalar($value)) {
|
||||
$result .= $value;
|
||||
} else {
|
||||
$result .= \str_replace("\n", "\n ", self::dump($value, \false));
|
||||
}
|
||||
}
|
||||
if (\count($node) === 0) {
|
||||
$result .= ']';
|
||||
} else {
|
||||
$result .= "\n]";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* @param mixed[] $items
|
||||
*/
|
||||
private static function isStringList(array $items) : bool
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
if (!\is_string($item)) {
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
return \true;
|
||||
}
|
||||
/**
|
||||
* @param mixed $flags
|
||||
*/
|
||||
private static function dumpFlags($flags) : string
|
||||
{
|
||||
$strs = [];
|
||||
if (($flags & Class_::MODIFIER_PUBLIC) !== 0) {
|
||||
$strs[] = 'MODIFIER_PUBLIC';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_PROTECTED) !== 0) {
|
||||
$strs[] = 'MODIFIER_PROTECTED';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_PRIVATE) !== 0) {
|
||||
$strs[] = 'MODIFIER_PRIVATE';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_ABSTRACT) !== 0) {
|
||||
$strs[] = 'MODIFIER_ABSTRACT';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_STATIC) !== 0) {
|
||||
$strs[] = 'MODIFIER_STATIC';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_FINAL) !== 0) {
|
||||
$strs[] = 'MODIFIER_FINAL';
|
||||
}
|
||||
if (($flags & Class_::MODIFIER_READONLY) !== 0) {
|
||||
$strs[] = 'MODIFIER_READONLY';
|
||||
}
|
||||
if ($strs !== []) {
|
||||
return \implode(' | ', $strs) . ' (' . $flags . ')';
|
||||
}
|
||||
return (string) $flags;
|
||||
}
|
||||
/**
|
||||
* @param int|float|string $type
|
||||
*/
|
||||
private static function dumpIncludeType($type) : string
|
||||
{
|
||||
$map = [Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE'];
|
||||
if (!isset($map[$type])) {
|
||||
return (string) $type;
|
||||
}
|
||||
return $map[$type] . ' (' . $type . ')';
|
||||
}
|
||||
/**
|
||||
* @param mixed $type
|
||||
*/
|
||||
private static function dumpUseType($type) : string
|
||||
{
|
||||
$map = [Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', Use_::TYPE_NORMAL => 'TYPE_NORMAL', Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', Use_::TYPE_CONSTANT => 'TYPE_CONSTANT'];
|
||||
if (!isset($map[$type])) {
|
||||
return (string) $type;
|
||||
}
|
||||
return $map[$type] . ' (' . $type . ')';
|
||||
}
|
||||
private static function dumpSingleNode(Node $node) : string
|
||||
{
|
||||
$result = \get_class($node);
|
||||
// print simple nodes on same line, to make output more readable
|
||||
if ($node instanceof Variable && \is_string($node->name)) {
|
||||
$result .= '( name: "' . $node->name . '" )';
|
||||
} elseif ($node instanceof Identifier) {
|
||||
$result .= '( name: "' . $node->name . '" )';
|
||||
} elseif ($node instanceof Name) {
|
||||
$result .= '( parts: ' . \json_encode($node->getParts(), 0) . ' )';
|
||||
} elseif ($node instanceof Scalar && $node->getSubNodeNames() === ['value']) {
|
||||
if (\is_string($node->value)) {
|
||||
$result .= '( value: "' . $node->value . '" )';
|
||||
} else {
|
||||
$result .= '( value: ' . $node->value . ' )';
|
||||
}
|
||||
} else {
|
||||
$result .= '(';
|
||||
foreach ($node->getSubNodeNames() as $key) {
|
||||
$result .= "\n " . $key . ': ';
|
||||
$value = $node->{$key};
|
||||
if ($value === null) {
|
||||
$result .= 'null';
|
||||
} elseif ($value === \false) {
|
||||
$result .= 'false';
|
||||
} elseif ($value === \true) {
|
||||
$result .= 'true';
|
||||
} elseif (\is_scalar($value)) {
|
||||
if ($key === 'flags' || $key === 'newModifier') {
|
||||
$result .= self::dumpFlags($value);
|
||||
} elseif ($key === 'type' && $node instanceof Include_) {
|
||||
$result .= self::dumpIncludeType($value);
|
||||
} elseif ($key === 'type' && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) {
|
||||
$result .= self::dumpUseType($value);
|
||||
} elseif (\is_string($value)) {
|
||||
$result .= '"' . $value . '"';
|
||||
} else {
|
||||
$result .= $value;
|
||||
}
|
||||
} else {
|
||||
$result .= \str_replace("\n", "\n ", self::dump($value, \false));
|
||||
}
|
||||
}
|
||||
$result .= "\n)";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@ use Rector\Config\RectorConfig;
|
|||
use Rector\Configuration\ConfigInitializer;
|
||||
use Rector\Configuration\RenamedClassesDataCollector;
|
||||
use Rector\Console\Command\CustomRuleCommand;
|
||||
use Rector\Console\Command\DetectNodeCommand;
|
||||
use Rector\Console\Command\ListRulesCommand;
|
||||
use Rector\Console\Command\ProcessCommand;
|
||||
use Rector\Console\Command\SetupCICommand;
|
||||
|
@ -259,13 +260,13 @@ final class LazyContainerFactory
|
|||
$rectorConfig->singleton(SetupCICommand::class);
|
||||
$rectorConfig->singleton(ListRulesCommand::class);
|
||||
$rectorConfig->singleton(CustomRuleCommand::class);
|
||||
$rectorConfig->singleton(DetectNodeCommand::class);
|
||||
$rectorConfig->when(ListRulesCommand::class)->needs('$rectors')->giveTagged(RectorInterface::class);
|
||||
// dev
|
||||
if (\class_exists(MissingInSetCommand::class)) {
|
||||
$rectorConfig->singleton(MissingInSetCommand::class);
|
||||
$rectorConfig->singleton(OutsideAnySetCommand::class);
|
||||
}
|
||||
$rectorConfig->alias(TypeParser::class, BetterTypeParser::class);
|
||||
$rectorConfig->singleton(FileProcessor::class);
|
||||
$rectorConfig->singleton(PostFileProcessor::class);
|
||||
// phpdoc-parser
|
||||
|
@ -308,6 +309,8 @@ final class LazyContainerFactory
|
|||
$this->registerTagged($rectorConfig, self::PHP_PARSER_NODE_MAPPER_CLASSES, PhpParserNodeMapperInterface::class);
|
||||
$this->registerTagged($rectorConfig, self::PHP_DOC_NODE_DECORATOR_CLASSES, PhpDocNodeDecoratorInterface::class);
|
||||
$this->registerTagged($rectorConfig, self::BASE_PHP_DOC_NODE_VISITORS, BasePhpDocNodeVisitorInterface::class);
|
||||
// PHP 8.0 attributes
|
||||
$this->registerTagged($rectorConfig, self::ANNOTATION_TO_ATTRIBUTE_MAPPER_CLASSES, AnnotationToAttributeMapperInterface::class);
|
||||
$this->registerTagged($rectorConfig, self::TYPE_MAPPER_CLASSES, TypeMapperInterface::class);
|
||||
$this->registerTagged($rectorConfig, self::PHPDOC_TYPE_MAPPER_CLASSES, PhpDocTypeMapperInterface::class);
|
||||
$this->registerTagged($rectorConfig, self::NODE_NAME_RESOLVER_CLASSES, NodeNameResolverInterface::class);
|
||||
|
@ -320,10 +323,9 @@ final class LazyContainerFactory
|
|||
$symfonyStyleFactory = $container->make(SymfonyStyleFactory::class);
|
||||
return $symfonyStyleFactory->create();
|
||||
});
|
||||
$this->registerTagged($rectorConfig, self::ANNOTATION_TO_ATTRIBUTE_MAPPER_CLASSES, AnnotationToAttributeMapperInterface::class);
|
||||
$rectorConfig->when(AnnotationToAttributeMapper::class)->needs('$annotationToAttributeMappers')->giveTagged(AnnotationToAttributeMapperInterface::class);
|
||||
$rectorConfig->when(OutputFormatterCollector::class)->needs('$outputFormatters')->giveTagged(OutputFormatterInterface::class);
|
||||
// #[Required]-like setter
|
||||
// required-like setter
|
||||
$rectorConfig->afterResolving(ArrayAnnotationToAttributeMapper::class, static function (ArrayAnnotationToAttributeMapper $arrayAnnotationToAttributeMapper, Container $container) : void {
|
||||
$annotationToAttributesMapper = $container->make(AnnotationToAttributeMapper::class);
|
||||
$arrayAnnotationToAttributeMapper->autowire($annotationToAttributesMapper);
|
||||
|
@ -345,10 +347,6 @@ final class LazyContainerFactory
|
|||
$phpStanStaticTypeMapper = $container->make(PHPStanStaticTypeMapper::class);
|
||||
$unionTypeMapper->autowire($phpStanStaticTypeMapper);
|
||||
});
|
||||
$rectorConfig->singleton(Parser::class, static function (Container $container) {
|
||||
$phpstanServiceFactory = $container->make(PHPStanServicesFactory::class);
|
||||
return $phpstanServiceFactory->createPHPStanParser();
|
||||
});
|
||||
$rectorConfig->afterResolving(CurlyListNodeAnnotationToAttributeMapper::class, static function (CurlyListNodeAnnotationToAttributeMapper $curlyListNodeAnnotationToAttributeMapper, Container $container) : void {
|
||||
$annotationToAttributeMapper = $container->make(AnnotationToAttributeMapper::class);
|
||||
$curlyListNodeAnnotationToAttributeMapper->autowire($annotationToAttributeMapper);
|
||||
|
|
|
@ -84,7 +84,7 @@ final class ArrayCallableMethodMatcher
|
|||
$className = $callerType->getClassName();
|
||||
$secondItemValue = $items[1]->value;
|
||||
if ($values === null) {
|
||||
return new ArrayCallableDynamicMethod($firstItemValue, $className, $secondItemValue);
|
||||
return new ArrayCallableDynamicMethod();
|
||||
}
|
||||
if ($this->shouldSkipAssociativeArray($values)) {
|
||||
return null;
|
||||
|
|
|
@ -3,45 +3,7 @@
|
|||
declare (strict_types=1);
|
||||
namespace Rector\NodeCollector\ValueObject;
|
||||
|
||||
use PhpParser\Node\Expr;
|
||||
use Rector\Validation\RectorAssert;
|
||||
/**
|
||||
* @api
|
||||
*/
|
||||
final class ArrayCallableDynamicMethod
|
||||
{
|
||||
/**
|
||||
* @readonly
|
||||
* @var \PhpParser\Node\Expr
|
||||
*/
|
||||
private $callerExpr;
|
||||
/**
|
||||
* @readonly
|
||||
* @var string
|
||||
*/
|
||||
private $class;
|
||||
/**
|
||||
* @readonly
|
||||
* @var \PhpParser\Node\Expr
|
||||
*/
|
||||
private $method;
|
||||
public function __construct(Expr $callerExpr, string $class, Expr $method)
|
||||
{
|
||||
$this->callerExpr = $callerExpr;
|
||||
$this->class = $class;
|
||||
$this->method = $method;
|
||||
RectorAssert::className($class);
|
||||
}
|
||||
public function getClass() : string
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
public function getMethod() : Expr
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
public function getCallerExpr() : Expr
|
||||
{
|
||||
return $this->callerExpr;
|
||||
}
|
||||
// marker type
|
||||
}
|
||||
|
|
|
@ -4,11 +4,13 @@ declare (strict_types=1);
|
|||
namespace Rector\PhpParser\Parser;
|
||||
|
||||
use RectorPrefix202402\Nette\Utils\FileSystem;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\Parser;
|
||||
use PhpParser\ParserFactory;
|
||||
use Rector\NodeTypeResolver\PHPStan\Scope\NodeVisitor\AssignedToNodeVisitor;
|
||||
use Throwable;
|
||||
final class SimplePhpParser
|
||||
{
|
||||
/**
|
||||
|
@ -24,13 +26,13 @@ final class SimplePhpParser
|
|||
public function __construct()
|
||||
{
|
||||
$parserFactory = new ParserFactory();
|
||||
$this->phpParser = $parserFactory->create(ParserFactory::PREFER_PHP7);
|
||||
$this->phpParser = $parserFactory->create(ParserFactory::ONLY_PHP7);
|
||||
$this->nodeTraverser = new NodeTraverser();
|
||||
$this->nodeTraverser->addVisitor(new AssignedToNodeVisitor());
|
||||
}
|
||||
/**
|
||||
* @api tests
|
||||
* @return Stmt[]
|
||||
* @return Node[]
|
||||
*/
|
||||
public function parseFile(string $filePath) : array
|
||||
{
|
||||
|
@ -38,14 +40,51 @@ final class SimplePhpParser
|
|||
return $this->parseString($fileContent);
|
||||
}
|
||||
/**
|
||||
* @return Stmt[]
|
||||
* @return Node[]
|
||||
*/
|
||||
public function parseString(string $fileContent) : array
|
||||
{
|
||||
$stmts = $this->phpParser->parse($fileContent);
|
||||
if ($stmts === null) {
|
||||
$fileContent = $this->ensureFileContentsHasOpeningTag($fileContent);
|
||||
$hasAddedSemicolon = \false;
|
||||
try {
|
||||
$nodes = $this->phpParser->parse($fileContent);
|
||||
} catch (Throwable $exception) {
|
||||
// try adding missing closing semicolon ;
|
||||
$fileContent .= ';';
|
||||
$hasAddedSemicolon = \true;
|
||||
$nodes = $this->phpParser->parse($fileContent);
|
||||
}
|
||||
if ($nodes === null) {
|
||||
return [];
|
||||
}
|
||||
return $this->nodeTraverser->traverse($stmts);
|
||||
$nodes = $this->restoreExpressionPreWrap($nodes, $hasAddedSemicolon);
|
||||
return $this->nodeTraverser->traverse($nodes);
|
||||
}
|
||||
private function ensureFileContentsHasOpeningTag(string $fileContent) : string
|
||||
{
|
||||
if (\strncmp(\trim($fileContent), '<?php', \strlen('<?php')) !== 0) {
|
||||
// prepend with PHP opening tag to make parse PHP code
|
||||
return '<?php ' . $fileContent;
|
||||
}
|
||||
return $fileContent;
|
||||
}
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @return Node[]
|
||||
*/
|
||||
private function restoreExpressionPreWrap(array $nodes, bool $hasAddedSemicolon) : array
|
||||
{
|
||||
if (!$hasAddedSemicolon) {
|
||||
return $nodes;
|
||||
}
|
||||
if (\count($nodes) !== 1) {
|
||||
return $nodes;
|
||||
}
|
||||
// remove added semicolon to be honest about Expression
|
||||
$onlyStmt = $nodes[0];
|
||||
if (!$onlyStmt instanceof Expression) {
|
||||
return $nodes;
|
||||
}
|
||||
return [$onlyStmt->expr];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,9 @@ declare (strict_types=1);
|
|||
namespace Rector\PostRector\Contract\Rector;
|
||||
|
||||
use PhpParser\NodeVisitor;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface PostRectorInterface extends NodeVisitor
|
||||
{
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ abstract class AbstractRectorTestCase extends \Rector\Testing\PHPUnit\AbstractLa
|
|||
/** @var ResetableInterface $resetable */
|
||||
$resetable->reset();
|
||||
}
|
||||
$this->forgetRectorsRulesAndCollectors();
|
||||
$this->forgetRectorsRules();
|
||||
$rectorConfig->resetRuleConfigurations();
|
||||
// this has to be always empty, so we can add new rules with their configuration
|
||||
$this->assertEmpty($rectorConfig->tagged(RectorInterface::class));
|
||||
|
@ -136,7 +136,7 @@ abstract class AbstractRectorTestCase extends \Rector\Testing\PHPUnit\AbstractLa
|
|||
FileSystem::write($inputFilePath, $inputFileContents, null);
|
||||
$this->doTestFileMatchesExpectedContent($inputFilePath, $inputFileContents, $expectedFileContents, $fixtureFilePath);
|
||||
}
|
||||
protected function forgetRectorsRulesAndCollectors() : void
|
||||
private function forgetRectorsRules() : void
|
||||
{
|
||||
$rectorConfig = self::getContainer();
|
||||
// 1. forget tagged services
|
||||
|
|
|
@ -22,4 +22,4 @@ if (PHP_VERSION_ID < 50600) {
|
|||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3::getLoader();
|
||||
return ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3::getLoader();
|
||||
|
|
|
@ -1183,6 +1183,7 @@ return array(
|
|||
'Rector\\Configuration\\RenamedClassesDataCollector' => $baseDir . '/src/Configuration/RenamedClassesDataCollector.php',
|
||||
'Rector\\Configuration\\VendorMissAnalyseGuard' => $baseDir . '/src/Configuration/VendorMissAnalyseGuard.php',
|
||||
'Rector\\Console\\Command\\CustomRuleCommand' => $baseDir . '/src/Console/Command/CustomRuleCommand.php',
|
||||
'Rector\\Console\\Command\\DetectNodeCommand' => $baseDir . '/src/Console/Command/DetectNodeCommand.php',
|
||||
'Rector\\Console\\Command\\ListRulesCommand' => $baseDir . '/src/Console/Command/ListRulesCommand.php',
|
||||
'Rector\\Console\\Command\\ProcessCommand' => $baseDir . '/src/Console/Command/ProcessCommand.php',
|
||||
'Rector\\Console\\Command\\SetupCICommand' => $baseDir . '/src/Console/Command/SetupCICommand.php',
|
||||
|
@ -1200,6 +1201,7 @@ return array(
|
|||
'Rector\\Contract\\Rector\\ConfigurableRectorInterface' => $baseDir . '/src/Contract/Rector/ConfigurableRectorInterface.php',
|
||||
'Rector\\Contract\\Rector\\RectorInterface' => $baseDir . '/src/Contract/Rector/RectorInterface.php',
|
||||
'Rector\\Contract\\Rector\\ScopeAwareRectorInterface' => $baseDir . '/src/Contract/Rector/ScopeAwareRectorInterface.php',
|
||||
'Rector\\CustomRules\\SimpleNodeDumper' => $baseDir . '/src/CustomRules/SimpleNodeDumper.php',
|
||||
'Rector\\DeadCode\\ConditionEvaluator' => $baseDir . '/rules/DeadCode/ConditionEvaluator.php',
|
||||
'Rector\\DeadCode\\ConditionResolver' => $baseDir . '/rules/DeadCode/ConditionResolver.php',
|
||||
'Rector\\DeadCode\\Contract\\ConditionInterface' => $baseDir . '/rules/DeadCode/Contract/ConditionInterface.php',
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
// autoload_real.php @generated by Composer
|
||||
|
||||
class ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3
|
||||
class ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3
|
||||
{
|
||||
private static $loader;
|
||||
|
||||
|
@ -22,17 +22,17 @@ class ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3
|
|||
return self::$loader;
|
||||
}
|
||||
|
||||
spl_autoload_register(array('ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3', 'loadClassLoader'), true, true);
|
||||
spl_autoload_register(array('ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3', 'loadClassLoader'), true, true);
|
||||
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3', 'loadClassLoader'));
|
||||
spl_autoload_unregister(array('ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3', 'loadClassLoader'));
|
||||
|
||||
require __DIR__ . '/autoload_static.php';
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3::getInitializer($loader));
|
||||
call_user_func(\Composer\Autoload\ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3::getInitializer($loader));
|
||||
|
||||
$loader->setClassMapAuthoritative(true);
|
||||
$loader->register(true);
|
||||
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3::$files;
|
||||
$filesToLoad = \Composer\Autoload\ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3::$files;
|
||||
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
|
||||
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
|
||||
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
namespace Composer\Autoload;
|
||||
|
||||
class ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3
|
||||
class ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3
|
||||
{
|
||||
public static $files = array (
|
||||
'ad155f8f1cf0d418fe49e248db8c661b' => __DIR__ . '/..' . '/react/promise/src/functions_include.php',
|
||||
|
@ -1397,6 +1397,7 @@ class ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3
|
|||
'Rector\\Configuration\\RenamedClassesDataCollector' => __DIR__ . '/../..' . '/src/Configuration/RenamedClassesDataCollector.php',
|
||||
'Rector\\Configuration\\VendorMissAnalyseGuard' => __DIR__ . '/../..' . '/src/Configuration/VendorMissAnalyseGuard.php',
|
||||
'Rector\\Console\\Command\\CustomRuleCommand' => __DIR__ . '/../..' . '/src/Console/Command/CustomRuleCommand.php',
|
||||
'Rector\\Console\\Command\\DetectNodeCommand' => __DIR__ . '/../..' . '/src/Console/Command/DetectNodeCommand.php',
|
||||
'Rector\\Console\\Command\\ListRulesCommand' => __DIR__ . '/../..' . '/src/Console/Command/ListRulesCommand.php',
|
||||
'Rector\\Console\\Command\\ProcessCommand' => __DIR__ . '/../..' . '/src/Console/Command/ProcessCommand.php',
|
||||
'Rector\\Console\\Command\\SetupCICommand' => __DIR__ . '/../..' . '/src/Console/Command/SetupCICommand.php',
|
||||
|
@ -1414,6 +1415,7 @@ class ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3
|
|||
'Rector\\Contract\\Rector\\ConfigurableRectorInterface' => __DIR__ . '/../..' . '/src/Contract/Rector/ConfigurableRectorInterface.php',
|
||||
'Rector\\Contract\\Rector\\RectorInterface' => __DIR__ . '/../..' . '/src/Contract/Rector/RectorInterface.php',
|
||||
'Rector\\Contract\\Rector\\ScopeAwareRectorInterface' => __DIR__ . '/../..' . '/src/Contract/Rector/ScopeAwareRectorInterface.php',
|
||||
'Rector\\CustomRules\\SimpleNodeDumper' => __DIR__ . '/../..' . '/src/CustomRules/SimpleNodeDumper.php',
|
||||
'Rector\\DeadCode\\ConditionEvaluator' => __DIR__ . '/../..' . '/rules/DeadCode/ConditionEvaluator.php',
|
||||
'Rector\\DeadCode\\ConditionResolver' => __DIR__ . '/../..' . '/rules/DeadCode/ConditionResolver.php',
|
||||
'Rector\\DeadCode\\Contract\\ConditionInterface' => __DIR__ . '/../..' . '/rules/DeadCode/Contract/ConditionInterface.php',
|
||||
|
@ -2661,9 +2663,9 @@ class ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3
|
|||
public static function getInitializer(ClassLoader $loader)
|
||||
{
|
||||
return \Closure::bind(function () use ($loader) {
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitf637847380e2ddf55dcae18dded1d2b3::$classMap;
|
||||
$loader->prefixLengthsPsr4 = ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3::$prefixLengthsPsr4;
|
||||
$loader->prefixDirsPsr4 = ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3::$prefixDirsPsr4;
|
||||
$loader->classMap = ComposerStaticInitd8a5ed51c42e9e1b169fafa71fcb8ab3::$classMap;
|
||||
|
||||
}, null, ClassLoader::class);
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ if (!function_exists('humbug_phpscoper_expose_class')) {
|
|||
}
|
||||
}
|
||||
humbug_phpscoper_expose_class('AutoloadIncluder', 'RectorPrefix202402\AutoloadIncluder');
|
||||
humbug_phpscoper_expose_class('ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3', 'RectorPrefix202402\ComposerAutoloaderInitf637847380e2ddf55dcae18dded1d2b3');
|
||||
humbug_phpscoper_expose_class('ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3', 'RectorPrefix202402\ComposerAutoloaderInitd8a5ed51c42e9e1b169fafa71fcb8ab3');
|
||||
humbug_phpscoper_expose_class('Product', 'RectorPrefix202402\Product');
|
||||
|
||||
// Function aliases. For more information see:
|
||||
|
|
Loading…
Reference in New Issue