Skip to content

Commit d781e34

Browse files
committed
Improve memory consumption
1 parent 25cb765 commit d781e34

11 files changed

Lines changed: 118 additions & 6 deletions

File tree

conf/config.neon

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1514,6 +1514,12 @@ services:
15141514
autowired: no
15151515

15161516
currentPhpVersionSimpleParser:
1517+
class: PHPStan\Parser\CleaningParser
1518+
arguments:
1519+
wrappedParser: @currentPhpVersionSimpleDirectParser
1520+
autowired: no
1521+
1522+
currentPhpVersionSimpleDirectParser:
15171523
class: PHPStan\Parser\SimpleParser
15181524
arguments:
15191525
parser: @currentPhpVersionPhpParser

src/Command/CommandHelper.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,11 +375,16 @@ public static function begin(
375375
/** @var FileFinder $fileFinder */
376376
$fileFinder = $container->getService('fileFinderAnalyse');
377377

378+
$pathRoutingParser = $container->getService('pathRoutingParser');
379+
378380
/** @var \Closure(): (array{string[], bool}) $filesCallback */
379-
$filesCallback = static function () use ($fileFinder, $paths): array {
381+
$filesCallback = static function () use ($fileFinder, $pathRoutingParser, $paths): array {
380382
$fileFinderResult = $fileFinder->findFiles($paths);
383+
$files = $fileFinderResult->getFiles();
384+
385+
$pathRoutingParser->setAnalysedFiles($files);
381386

382-
return [$fileFinderResult->getFiles(), $fileFinderResult->isOnlyFiles()];
387+
return [$files, $fileFinderResult->isOnlyFiles()];
383388
};
384389

385390
return new InceptionResult(

src/Parser/CleaningParser.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Parser;
4+
5+
use PhpParser\Node\Stmt;
6+
use PhpParser\NodeTraverser;
7+
8+
class CleaningParser implements Parser
9+
{
10+
11+
private Parser $wrappedParser;
12+
13+
private NodeTraverser $traverser;
14+
15+
public function __construct(Parser $wrappedParser)
16+
{
17+
$this->wrappedParser = $wrappedParser;
18+
$this->traverser = new NodeTraverser();
19+
$this->traverser->addVisitor(new CleaningVisitor());
20+
}
21+
22+
public function parseFile(string $file): array
23+
{
24+
return $this->clean($this->wrappedParser->parseFile($file));
25+
}
26+
27+
public function parseString(string $sourceCode): array
28+
{
29+
return $this->clean($this->wrappedParser->parseString($sourceCode));
30+
}
31+
32+
/**
33+
* @param Stmt[] $ast
34+
* @return Stmt[]
35+
*/
36+
private function clean(array $ast): array
37+
{
38+
/** @var Stmt[] */
39+
return $this->traverser->traverse($ast);
40+
}
41+
42+
}

src/Parser/CleaningVisitor.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Parser;
4+
5+
use PhpParser\Node;
6+
use PhpParser\NodeVisitorAbstract;
7+
8+
class CleaningVisitor extends NodeVisitorAbstract
9+
{
10+
11+
public function enterNode(Node $node): ?Node
12+
{
13+
if ($node instanceof Node\Stmt\Function_) {
14+
$node->stmts = [];
15+
return $node;
16+
}
17+
18+
if ($node instanceof Node\Stmt\ClassMethod) {
19+
$node->stmts = [];
20+
return $node;
21+
}
22+
23+
if ($node instanceof Node\Expr\Closure) {
24+
$node->stmts = [];
25+
return $node;
26+
}
27+
28+
return null;
29+
}
30+
31+
}

src/Parser/PathRoutingParser.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class PathRoutingParser implements Parser
1515

1616
private Parser $php8Parser;
1717

18+
/** @var bool[] filePath(string) => bool(true) */
19+
private array $analysedFiles = [];
20+
1821
public function __construct(
1922
FileHelper $fileHelper,
2023
Parser $currentPhpVersionRichParser,
@@ -28,13 +31,25 @@ public function __construct(
2831
$this->php8Parser = $php8Parser;
2932
}
3033

34+
/**
35+
* @param string[] $files
36+
*/
37+
public function setAnalysedFiles(array $files): void
38+
{
39+
$this->analysedFiles = array_fill_keys($files, true);
40+
}
41+
3142
public function parseFile(string $file): array
3243
{
3344
$file = $this->fileHelper->normalizePath($file, '/');
3445
if (strpos($file, 'vendor/jetbrains/phpstorm-stubs') !== false) {
3546
return $this->php8Parser->parseFile($file);
3647
}
3748

49+
if (!isset($this->analysedFiles[$file])) {
50+
return $this->currentPhpVersionSimpleParser->parseFile($file);
51+
}
52+
3853
return $this->currentPhpVersionRichParser->parseFile($file);
3954
}
4055

src/PhpDoc/StubValidator.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ public function validate(array $stubFiles, bool $debug): array
8989
$nodeScopeResolver = $container->getByType(NodeScopeResolver::class);
9090
$nodeScopeResolver->setAnalysedFiles($stubFiles);
9191

92+
$pathRoutingParser = $container->getService('pathRoutingParser');
93+
$pathRoutingParser->setAnalysedFiles($stubFiles);
94+
9295
$analysedFiles = array_fill_keys($stubFiles, true);
9396

9497
$errors = [];

src/Reflection/Php/PhpClassReflectionExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -935,7 +935,7 @@ private function inferAndCachePropertyTypes(
935935
}
936936

937937
$methodNode = $this->findConstructorNode($constructor->getName(), $classNode->stmts);
938-
if ($methodNode === null || $methodNode->stmts === null) {
938+
if ($methodNode === null || $methodNode->stmts === null || count($methodNode->stmts) === 0) {
939939
return $this->propertyTypesCache[$declaringClass->getName()] = [];
940940
}
941941

src/Reflection/Php/PhpFunctionReflection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ private function isVariadic(): bool
170170
if ($modifiedTime === false) {
171171
$modifiedTime = time();
172172
}
173-
$variableCacheKey = sprintf('%d-v1', $modifiedTime);
173+
$variableCacheKey = sprintf('%d-v2', $modifiedTime);
174174
$key = sprintf('variadic-function-%s-%s', $functionName, $fileName);
175175
$cachedResult = $this->cache->load($key, $variableCacheKey);
176176
if ($cachedResult === null) {

src/Reflection/Php/PhpMethodReflection.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,7 @@ private function isVariadic(): bool
274274
$modifiedTime = time();
275275
}
276276
$key = sprintf('variadic-method-%s-%s-%s', $declaringClass->getName(), $this->reflection->getName(), $filename);
277-
$variableCacheKey = sprintf('%d-v2', $modifiedTime);
277+
$variableCacheKey = sprintf('%d-v3', $modifiedTime);
278278
$cachedResult = $this->cache->load($key, $variableCacheKey);
279279
if ($cachedResult === null || !is_bool($cachedResult)) {
280280
$nodes = $this->parser->parseFile($filename);

src/Testing/TestCase.neon

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,5 @@ services:
44
cacheStorage:
55
class: PHPStan\Cache\MemoryCacheStorage
66
arguments!: []
7+
pathRoutingParser!:
8+
factory: @currentPhpVersionRichParser

0 commit comments

Comments
 (0)