mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-07 11:50:51 +00:00
[Php55] Handle crash on concat variable single quote on PregReplaceEModifierRector (#2483)
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
28ed5cf916
commit
6f164da439
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Tests\Php55\Rector\FuncCall\PregReplaceEModifierRector\Fixture;
|
||||
|
||||
class ConcatVariable
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$test = 'become : ';
|
||||
$string ='string';
|
||||
echo preg_replace("#([a-z]*)#e", "'".$test."' . strtoupper('\\1')", $string);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Tests\Php55\Rector\FuncCall\PregReplaceEModifierRector\Fixture;
|
||||
|
||||
class ConcatVariable
|
||||
{
|
||||
public function run()
|
||||
{
|
||||
$test = 'become : ';
|
||||
$string ='string';
|
||||
echo preg_replace_callback('#([a-z]*)#', function ($matches) use ($test) {
|
||||
return $test . strtoupper($matches[1]);
|
||||
}, $string);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -102,9 +102,7 @@ CODE_SAMPLE
|
|||
/** @var Arg $secondArgument */
|
||||
$secondArgument = $node->args[1];
|
||||
$secondArgumentValue = $secondArgument->value;
|
||||
$anonymousFunction = $this->anonymousFunctionFactory->createAnonymousFunctionFromString(
|
||||
$secondArgumentValue
|
||||
);
|
||||
$anonymousFunction = $this->anonymousFunctionFactory->createAnonymousFunctionFromExpr($secondArgumentValue);
|
||||
if (! $anonymousFunction instanceof Closure) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -39,11 +39,11 @@ use PHPStan\Type\MixedType;
|
|||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\VoidType;
|
||||
use Rector\Core\Contract\PhpParser\NodePrinterInterface;
|
||||
use Rector\Core\Exception\ShouldNotHappenException;
|
||||
use Rector\Core\PhpParser\AstResolver;
|
||||
use Rector\Core\PhpParser\Comparing\NodeComparator;
|
||||
use Rector\Core\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Core\PhpParser\Node\NodeFactory;
|
||||
use Rector\Core\PhpParser\Parser\InlineCodeParser;
|
||||
use Rector\Core\PhpParser\Parser\SimplePhpParser;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
|
@ -71,7 +71,8 @@ final class AnonymousFunctionFactory
|
|||
private readonly NodeComparator $nodeComparator,
|
||||
private readonly AstResolver $astResolver,
|
||||
private readonly NodePrinterInterface $nodePrinter,
|
||||
private readonly PrivatesAccessor $privatesAccessor
|
||||
private readonly PrivatesAccessor $privatesAccessor,
|
||||
private readonly InlineCodeParser $inlineCodeParser
|
||||
) {
|
||||
}
|
||||
|
||||
|
@ -142,14 +143,11 @@ final class AnonymousFunctionFactory
|
|||
return $anonymousFunction;
|
||||
}
|
||||
|
||||
public function createAnonymousFunctionFromString(Expr $expr): ?Closure
|
||||
public function createAnonymousFunctionFromExpr(Expr $expr): ?Closure
|
||||
{
|
||||
if (! $expr instanceof String_) {
|
||||
// not supported yet
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
$stringValue = $this->inlineCodeParser->stringify($expr);
|
||||
|
||||
$phpCode = '<?php ' . $expr->value . ';';
|
||||
$phpCode = '<?php ' . $stringValue . ';';
|
||||
$contentStmts = $this->simplePhpParser->parseString($phpCode);
|
||||
|
||||
$anonymousFunction = new Closure();
|
||||
|
@ -179,6 +177,15 @@ final class AnonymousFunctionFactory
|
|||
$anonymousFunction->stmts[] = new Return_($stmt);
|
||||
$anonymousFunction->params[] = new Param(new Variable('matches'));
|
||||
|
||||
$variables = $expr instanceof Variable
|
||||
? []
|
||||
: $this->betterNodeFinder->findInstanceOf($expr, Variable::class);
|
||||
|
||||
$anonymousFunction->uses = array_map(
|
||||
fn (Variable $variable): ClosureUse => new ClosureUse($variable),
|
||||
$variables
|
||||
);
|
||||
|
||||
return $anonymousFunction;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ final class InlineCodeParser
|
|||
*/
|
||||
private const ENDING_SEMI_COLON_REGEX = '#;(\s+)?$#';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @see https://regex101.com/r/8fDjnR/1
|
||||
*/
|
||||
private const VARIABLE_IN_SINGLE_QUOTED_REGEX = '#\'(?<variable>\$.*)\'#U';
|
||||
|
||||
public function __construct(
|
||||
private readonly NodePrinterInterface $nodePrinter,
|
||||
private readonly NodeScopeAndMetadataDecorator $nodeScopeAndMetadataDecorator,
|
||||
|
@ -83,7 +89,12 @@ final class InlineCodeParser
|
|||
}
|
||||
|
||||
if ($expr instanceof Concat) {
|
||||
return $this->stringify($expr->left) . $this->stringify($expr->right);
|
||||
$string = $this->stringify($expr->left) . $this->stringify($expr->right);
|
||||
return Strings::replace(
|
||||
$string,
|
||||
self::VARIABLE_IN_SINGLE_QUOTED_REGEX,
|
||||
fn (array $match) => $match['variable']
|
||||
);
|
||||
}
|
||||
|
||||
return $this->nodePrinter->print($expr);
|
||||
|
|
Loading…
Reference in New Issue
Block a user