mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-22 02:36:52 +01:00
Merge pull request #1513 from rectorphp/static
Make Symfony 4.3 + phpdoc-parser 0.3.4 compatible
This commit is contained in:
commit
a69d08bac5
@ -18,23 +18,23 @@
|
||||
"nette/robot-loader": "^3.1",
|
||||
"nette/utils": "^2.5|^3.0",
|
||||
"nikic/php-parser": "^4.2.2",
|
||||
"phpstan/phpdoc-parser": "0.3.3",
|
||||
"phpstan/phpdoc-parser": "^0.3.4",
|
||||
"phpstan/phpstan": "0.11.6",
|
||||
"sebastian/diff": "^3.0",
|
||||
"symfony/console": "^3.4|^4.2",
|
||||
"symfony/dependency-injection": "^3.4|^4.2",
|
||||
"symfony/finder": "^3.4|^4.2",
|
||||
"symfony/process": "^3.4|^4.2",
|
||||
"symplify/package-builder": "^6.0"
|
||||
"symplify/package-builder": "^6.0.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "^2.14",
|
||||
"ocramius/package-versions": "^1.4",
|
||||
"phpunit/phpunit": "^7.5|^8.0",
|
||||
"symplify/changelog-linker": "^6.0",
|
||||
"symplify/easy-coding-standard": "^6.0",
|
||||
"symplify/monorepo-builder": "^6.0",
|
||||
"symplify/phpstan-extensions": "^6.0",
|
||||
"symplify/changelog-linker": "^6.0.1",
|
||||
"symplify/easy-coding-standard": "^6.0.1",
|
||||
"symplify/monorepo-builder": "^6.0.1",
|
||||
"symplify/phpstan-extensions": "^6.0.1",
|
||||
"thecodingmachine/phpstan-strict-rules": "^0.11",
|
||||
"tracy/tracy": "^2.5"
|
||||
},
|
||||
|
@ -3660,7 +3660,7 @@ Remove extra parameters
|
||||
|
||||
- class: `Rector\Php\Rector\FuncCall\PregReplaceEModifierRector`
|
||||
|
||||
The /e modifier is no longer supported, use preg_replace_callback instead
|
||||
The /e modifier is no longer supported, use preg_replace_callback instead
|
||||
|
||||
```diff
|
||||
class SomeClass
|
||||
|
@ -917,7 +917,7 @@ if (true) {
|
||||
|
||||
```php
|
||||
?>
|
||||
<strong>feel</strong><?php
|
||||
<strong>feel</strong><?php
|
||||
```
|
||||
<br>
|
||||
|
||||
|
@ -40,4 +40,9 @@ final class Attribute
|
||||
* @var string
|
||||
*/
|
||||
public const ANNOTATION_CLASS = 'annotation_class';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const ORIGINAL_CONTENT = 'original_content';
|
||||
}
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
namespace Rector\BetterPhpDocParser\PhpDocParser;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PHPStan\PhpDocParser\Ast\Node;
|
||||
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagValueNode;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTextNode;
|
||||
use PHPStan\PhpDocParser\Lexer\Lexer;
|
||||
use PHPStan\PhpDocParser\Parser\ConstExprParser;
|
||||
use PHPStan\PhpDocParser\Parser\ParserException;
|
||||
@ -106,6 +108,51 @@ final class BetterPhpDocParser extends PhpDocParser
|
||||
$attributeAwareNode = $this->attributeAwareNodeFactory->createFromNode($node);
|
||||
$attributeAwareNode->setAttribute(Attribute::PHP_DOC_NODE_INFO, new StartEndInfo($tokenStart, $tokenEnd));
|
||||
|
||||
// add original text, for keeping trimmed spaces
|
||||
if ($attributeAwareNode instanceof PhpDocTextNode) {
|
||||
$originalContent = $this->getOriginalContentFromTokenIterator($tokenIterator);
|
||||
|
||||
$currentText = $attributeAwareNode->text;
|
||||
|
||||
// we try to match original content without trimmed spaces
|
||||
$currentTextPattern = '#' . preg_quote($currentText, '#') . '#s';
|
||||
$currentTextPattern = Strings::replace($currentTextPattern, '#\s#', '\s+');
|
||||
$match = Strings::match($originalContent, $currentTextPattern);
|
||||
|
||||
if (isset($match[0])) {
|
||||
$attributeAwareNode->setAttribute(Attribute::ORIGINAL_CONTENT, $match[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return $attributeAwareNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo cache per tokens array hash
|
||||
*/
|
||||
private function getOriginalContentFromTokenIterator(TokenIterator $tokenIterator): string
|
||||
{
|
||||
$originalTokens = $this->privatesAccessor->getPrivateProperty($tokenIterator, 'tokens');
|
||||
$originalContent = '';
|
||||
|
||||
foreach ($originalTokens as $originalToken) {
|
||||
// skip opening
|
||||
if (Strings::match($originalToken[0], '#/\*\*#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip closing
|
||||
if (Strings::match($originalToken[0], '#\*\/#')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Strings::match($originalToken[0], '#^\s+\*#')) {
|
||||
$originalToken[0] = PHP_EOL;
|
||||
}
|
||||
|
||||
$originalContent .= $originalToken[0];
|
||||
}
|
||||
|
||||
return trim($originalContent);
|
||||
}
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ final class PhpDocInfoPrinter
|
||||
}
|
||||
|
||||
if ($attributeAwareNode instanceof PhpDocTagNode) {
|
||||
return $output . PHP_EOL . ' * ' . (string) $attributeAwareNode;
|
||||
return $output . PHP_EOL . ' * ' . $attributeAwareNode;
|
||||
}
|
||||
|
||||
if (! $attributeAwareNode instanceof PhpDocTextNode && ! $attributeAwareNode instanceof GenericTagValueNode && $startEndInfo) {
|
||||
@ -158,7 +158,16 @@ final class PhpDocInfoPrinter
|
||||
);
|
||||
}
|
||||
|
||||
return $output . (string) $attributeAwareNode;
|
||||
// fix multiline BC break - https://github.com/phpstan/phpdoc-parser/pull/26/files
|
||||
if ($attributeAwareNode->getAttribute(Attribute::ORIGINAL_CONTENT)) {
|
||||
$this->restoreOriginalSpacingInText($attributeAwareNode);
|
||||
}
|
||||
|
||||
$content = (string) $attributeAwareNode;
|
||||
$content = explode(PHP_EOL, $content);
|
||||
$content = implode(PHP_EOL . ' * ', $content);
|
||||
|
||||
return $output . $content;
|
||||
}
|
||||
|
||||
private function printEnd(string $output): string
|
||||
@ -277,4 +286,38 @@ final class PhpDocInfoPrinter
|
||||
|
||||
return Strings::contains($this->phpDocInfo->getOriginalContent(), $phpDocTagNode->name . ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PhpDocTextNode|AttributeAwareNodeInterface $attributeAwareNode
|
||||
*/
|
||||
private function restoreOriginalSpacingInText(AttributeAwareNodeInterface $attributeAwareNode): void
|
||||
{
|
||||
/** @var string $originalContent */
|
||||
$originalContent = $attributeAwareNode->getAttribute(Attribute::ORIGINAL_CONTENT);
|
||||
$oldSpaces = Strings::matchAll($originalContent, '#\s+#ms');
|
||||
|
||||
$newParts = Strings::split($attributeAwareNode->text, '#\s+#');
|
||||
|
||||
// we can't do this!
|
||||
if (count($oldSpaces) + 1 !== count($newParts)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$newText = '';
|
||||
foreach ($newParts as $key => $newPart) {
|
||||
$newText .= $newPart;
|
||||
if (isset($oldSpaces[$key])) {
|
||||
if (Strings::match($oldSpaces[$key][0], '#\n {1,}$#s')) {
|
||||
// remove last extra space
|
||||
$oldSpaces[$key][0] = Strings::substring($oldSpaces[$key][0], 0, -1);
|
||||
}
|
||||
|
||||
$newText .= $oldSpaces[$key][0];
|
||||
}
|
||||
}
|
||||
|
||||
if ($newText) {
|
||||
$attributeAwareNode->text = $newText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
/**
|
||||
* This is just text
|
||||
* why is this missing asterisk?
|
||||
*/
|
@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Match this code:
|
||||
* if (null === static::$instance) {
|
||||
* static::$instance = new static();
|
||||
* }
|
||||
* return static::$instance;
|
||||
*/
|
@ -33,6 +33,7 @@ final class PhpDocInfoPrinterTest extends AbstractKernelTestCase
|
||||
|
||||
/**
|
||||
* @dataProvider provideDocFilesForPrint()
|
||||
* @dataProvider provideMultiline()
|
||||
*/
|
||||
public function testPrintFormatPreserving(string $docFilePath): void
|
||||
{
|
||||
@ -67,6 +68,12 @@ final class PhpDocInfoPrinterTest extends AbstractKernelTestCase
|
||||
yield [__DIR__ . '/PhpDocInfoPrinterSource/doc13.txt'];
|
||||
}
|
||||
|
||||
public function provideMultiline(): Iterator
|
||||
{
|
||||
yield [__DIR__ . '/PhpDocInfoPrinterSource/multiline1.txt'];
|
||||
yield [__DIR__ . '/PhpDocInfoPrinterSource/multiline2.txt'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideDocFilesToEmpty()
|
||||
*/
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Rector\CodeQuality\Rector\Array_;
|
||||
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr;
|
||||
@ -15,6 +14,7 @@ use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\NodeContainer\ParsedNodesByType;
|
||||
use Rector\Rector\AbstractRector;
|
||||
|
@ -161,6 +161,11 @@ final class UseAddingCommander implements CommanderInterface
|
||||
{
|
||||
$filePath = $this->getRealPathFromNode($node);
|
||||
|
||||
// already analysed
|
||||
if (isset($this->useImportsInFilePath[$filePath])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$usedImports = $this->usedImportsResolver->resolveForNode($node);
|
||||
|
||||
foreach ($usedImports as $usedImport) {
|
||||
|
@ -8,7 +8,6 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Nop;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
namespace Rector\Php\Rector\BinaryOp;
|
||||
|
||||
use PhpParser\Node\Expr\BinaryOp\Concat;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp;
|
||||
use PhpParser\Node\Expr\BinaryOp\Concat;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
|
@ -10,6 +10,8 @@ use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Static_;
|
||||
use PhpParser\Node\Stmt\StaticVar;
|
||||
use PhpParser\Node\Stmt\Unset_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
@ -93,15 +95,7 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
$parentNode = $node->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentNode instanceof Assign || $this->isStaticVariable($parentNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
if ($nodeScope === null) {
|
||||
// possible in foreach variable
|
||||
if ($this->shouldSkipVariable($node)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -111,14 +105,12 @@ CODE_SAMPLE
|
||||
}
|
||||
|
||||
// defined 100 %
|
||||
/** @var Scope $nodeScope */
|
||||
$nodeScope = $node->getAttribute(AttributeKey::SCOPE);
|
||||
if ($nodeScope->hasVariableType($variableName)->yes()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($parentNode instanceof Unset_ || $parentNode instanceof Node\Expr\Cast\Unset_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @todo improve
|
||||
$this->undefinedVariables[] = $variableName;
|
||||
});
|
||||
@ -142,13 +134,32 @@ CODE_SAMPLE
|
||||
private function isStaticVariable(Node $parentNode): bool
|
||||
{
|
||||
// definition of static variable
|
||||
if ($parentNode instanceof Node\Stmt\StaticVar) {
|
||||
if ($parentNode instanceof StaticVar) {
|
||||
$parentParentNode = $parentNode->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentParentNode instanceof Node\Stmt\Static_) {
|
||||
if ($parentParentNode instanceof Static_) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function shouldSkipVariable(Variable $variable): bool
|
||||
{
|
||||
$parentNode = $variable->getAttribute(AttributeKey::PARENT_NODE);
|
||||
if ($parentNode instanceof Node) {
|
||||
if ($parentNode instanceof Assign || $this->isStaticVariable($parentNode)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($parentNode instanceof Unset_ || $parentNode instanceof Node\Expr\Cast\Unset_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var Scope|null $nodeScope */
|
||||
$nodeScope = $variable->getAttribute(AttributeKey::SCOPE);
|
||||
|
||||
return $nodeScope === null;
|
||||
}
|
||||
}
|
||||
|
@ -15,5 +15,7 @@ final class AutowiredEventDispatcher extends EventDispatcher
|
||||
foreach ($eventSubscribers as $eventSubscriber) {
|
||||
$this->addSubscriber($eventSubscriber);
|
||||
}
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user