Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,6 @@ parameters:
nodesByStringCountMax: 256
resolvedPhpDocBlockCacheCountMax: 2048
nameScopeMapMemoryCacheCountMax: 512
memoizingSourceLocatorEntriesCountMax: 0
phpStormStubsNodesCountMax: 64
reportUnmatchedIgnoredErrors: true
reportIgnoresWithoutComments: false
Expand Down
21 changes: 6 additions & 15 deletions conf/config.stubValidator.neon
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,16 @@ services:
arguments:
allStubFiles: %allStubFiles%
php8Parser: @php8PhpParser
memoizingSourceLocatorEntriesCountMax: %cache.memoizingSourceLocatorEntriesCountMax%

# overrides service from parsers.neon
defaultAnalysisParser!:
factory: @stubParser

# overrides service from services.neon
nodeScopeResolverReflector:
factory: @stubReflector

# overrides service from services.neon so that Reflector autowires to stubReflector
originalBetterReflectionReflector!:
factory: @stubReflector
# overrides service from services.neon so that the reflector
# (and everything above it) reflects only the stub files
betterReflectionSourceLocator!:
factory: @stubSourceLocator
autowired: false

# overrides service from services.neon
reflectionProvider:
Expand All @@ -52,16 +49,10 @@ services:
stubBetterReflectionProvider:
class: PHPStan\Reflection\BetterReflection\BetterReflectionProvider
arguments:
reflector: @stubReflector
reflector: @betterReflectionReflector
universalObjectCratesClasses: %universalObjectCratesClasses%
autowired: false

stubReflector:
class: PHPStan\BetterReflection\Reflector\DefaultReflector
arguments:
sourceLocator: @stubSourceLocator
autowired: false

stubSourceLocator:
class: PHPStan\BetterReflection\SourceLocator\Type\SourceLocator
factory: @PHPStan\PhpDoc\StubSourceLocatorFactory::create()
Expand Down
1 change: 0 additions & 1 deletion conf/parametersSchema.neon
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ parametersSchema:
nodesByStringCountMax: int(),
resolvedPhpDocBlockCacheCountMax: int(),
nameScopeMapMemoryCacheCountMax: int(),
memoizingSourceLocatorEntriesCountMax: int(),
phpStormStubsNodesCountMax: int()
])
reportUnmatchedIgnoredErrors: bool()
Expand Down
11 changes: 0 additions & 11 deletions conf/services.neon
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ services:
autowired:
- PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber

originalBetterReflectionReflector:
class: PHPStan\BetterReflection\Reflector\DefaultReflector
arguments:
sourceLocator: @betterReflectionSourceLocator
autowired: false


# not registered using attributes because we don't want to apply service tags automatically
-
class: PHPStan\Dependency\ExportedNodeVisitor
Expand Down Expand Up @@ -253,10 +246,6 @@ services:
autowired:
- PHPStan\Reflection\ReflectionProvider

nodeScopeResolverReflector:
factory: @betterReflectionReflector
autowired: false

# not registered using attributes because people often override it

exceptionTypeResolver:
Expand Down
1 change: 0 additions & 1 deletion src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,6 @@ public function __construct(
private readonly Container $container,
private readonly ReflectionProvider $reflectionProvider,
private readonly InitializerExprTypeResolver $initializerExprTypeResolver,
#[AutowiredParameter(ref: '@nodeScopeResolverReflector')]
private readonly Reflector $reflector,
private readonly ClassReflectionFactory $classReflectionFactory,
private readonly ParameterOutTypeExtensionProvider $parameterOutTypeExtensionProvider,
Expand Down
9 changes: 3 additions & 6 deletions src/PhpDoc/StubSourceLocatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use PHPStan\BetterReflection\SourceLocator\SourceStubber\PhpStormStubsSourceStubber;
use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\Composer\Psr\Psr4Mapping;
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
use PHPStan\Reflection\BetterReflection\SourceLocator\OptimizedPsrAutoloaderLocatorFactory;
Expand All @@ -26,7 +25,6 @@ public function __construct(
private OptimizedSingleFileSourceLocatorRepository $optimizedSingleFileSourceLocatorRepository,
private OptimizedPsrAutoloaderLocatorFactory $optimizedPsrAutoloaderLocatorFactory,
private array $allStubFiles,
private int $memoizingSourceLocatorEntriesCountMax,
)
{
}
Expand All @@ -52,10 +50,9 @@ public function create(): SourceLocator

$locators[] = new PhpInternalSourceLocator($astPhp8Locator, $this->phpStormStubsSourceStubber);

return new MemoizingSourceLocator(
new AggregateSourceLocator($locators),
$this->memoizingSourceLocatorEntriesCountMax === 0 ? null : $this->memoizingSourceLocatorEntriesCountMax,
);
// no MemoizingSourceLocator here - located reflections are already memoized
// by MemoizingReflector, a second cache layer would only pin them in memory twice
return new AggregateSourceLocator($locators);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\Composer\Psr\Psr4Mapping;
use PHPStan\BetterReflection\SourceLocator\Type\EvaledCodeSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
use PHPStan\DependencyInjection\AutowiredParameter;
Expand Down Expand Up @@ -75,8 +74,6 @@ public function __construct(
private bool $playgroundMode, // makes all PHPStan classes in the PHAR discoverable with PSR-4
#[AutowiredParameter]
private ?string $singleReflectionFile,
#[AutowiredParameter(ref: '%cache.memoizingSourceLocatorEntriesCountMax%')]
private int $memoizingSourceLocatorEntriesCountMax,
)
{
}
Expand Down Expand Up @@ -175,10 +172,9 @@ public function create(): SourceLocator
return new AggregateSourceLocator($locators);
};

return new MemoizingSourceLocator(
new LazySourceLocator($initializer),
$this->memoizingSourceLocatorEntriesCountMax === 0 ? null : $this->memoizingSourceLocatorEntriesCountMax,
);
// no MemoizingSourceLocator here - located reflections are already memoized
// by MemoizingReflector, a second cache layer would only pin them in memory twice
return new LazySourceLocator($initializer);
}

}
69 changes: 52 additions & 17 deletions src/Reflection/BetterReflection/Reflector/MemoizingReflector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
use PHPStan\BetterReflection\Reflection\ReflectionFunction;
use PHPStan\BetterReflection\Reflector\Exception\IdentifierNotFound;
use PHPStan\BetterReflection\Reflector\Reflector;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
use PHPStan\DependencyInjection\AutowiredParameter;
use PHPStan\DependencyInjection\AutowiredService;
use PHPStan\ShouldNotHappenException;
use function array_key_exists;
use function strtolower;

Expand All @@ -29,8 +31,8 @@ final class MemoizingReflector implements Reflector
private array $functionReflections = [];

public function __construct(
#[AutowiredParameter(ref: '@originalBetterReflectionReflector')]
private Reflector $reflector,
#[AutowiredParameter(ref: '@betterReflectionSourceLocator')]
private SourceLocator $sourceLocator,
)
{
}
Expand All @@ -51,13 +53,22 @@ public function reflectClass(string $className): ReflectionClass
return $classReflection;
}

try {
return $this->classReflections[$lowerClassName] = $this->reflector->reflectClass($className);
} catch (IdentifierNotFound $e) {
// located directly, without a DefaultReflector - created reflections capture
// the reflector passed here and resolve e.g. parent classes and interfaces
// through it, so passing $this routes those lookups through this cache too
$identifier = new Identifier($className, new IdentifierType(IdentifierType::IDENTIFIER_CLASS));
$classReflection = $this->sourceLocator->locateIdentifier($this, $identifier);
if ($classReflection === null) {
$this->classReflections[$className] = null;

throw $e;
throw IdentifierNotFound::fromIdentifier($identifier);
}

if (!$classReflection instanceof ReflectionClass) {
throw new ShouldNotHappenException();
}

return $this->classReflections[$lowerClassName] = $classReflection;
}

#[Override]
Expand All @@ -72,13 +83,19 @@ public function reflectConstant(string $constantName): ReflectionConstant
return $constantReflection;
}

try {
return $this->constantReflections[$constantName] = $this->reflector->reflectConstant($constantName);
} catch (IdentifierNotFound $e) {
$identifier = new Identifier($constantName, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT));
$constantReflection = $this->sourceLocator->locateIdentifier($this, $identifier);
if ($constantReflection === null) {
$this->constantReflections[$constantName] = null;

throw $e;
throw IdentifierNotFound::fromIdentifier($identifier);
}

if (!$constantReflection instanceof ReflectionConstant) {
throw new ShouldNotHappenException();
}

return $this->constantReflections[$constantName] = $constantReflection;
}

#[Override]
Expand All @@ -94,31 +111,49 @@ public function reflectFunction(string $functionName): ReflectionFunction
return $functionReflection;
}

try {
return $this->functionReflections[$lowerFunctionName] = $this->reflector->reflectFunction($functionName);
} catch (IdentifierNotFound $e) {
$identifier = new Identifier($functionName, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION));
$functionReflection = $this->sourceLocator->locateIdentifier($this, $identifier);
if ($functionReflection === null) {
$this->functionReflections[$lowerFunctionName] = null;

throw $e;
throw IdentifierNotFound::fromIdentifier($identifier);
}

if (!$functionReflection instanceof ReflectionFunction) {
throw new ShouldNotHappenException();
}

return $this->functionReflections[$lowerFunctionName] = $functionReflection;
}

/**
* @return list<ReflectionClass>
*/
#[Override]
public function reflectAllClasses(): iterable
{
return $this->reflector->reflectAllClasses();
/** @var list<ReflectionClass> */
return $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_CLASS));
}

/**
* @return list<ReflectionFunction>
*/
#[Override]
public function reflectAllFunctions(): iterable
{
return $this->reflector->reflectAllFunctions();
/** @var list<ReflectionFunction> */
return $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_FUNCTION));
}

/**
* @return list<ReflectionConstant>
*/
#[Override]
public function reflectAllConstants(): iterable
{
return $this->reflector->reflectAllConstants();
/** @var list<ReflectionConstant> */
return $this->sourceLocator->locateIdentifiersByType($this, new IdentifierType(IdentifierType::IDENTIFIER_CONSTANT));
}

}
1 change: 0 additions & 1 deletion src/Testing/TestCase.neon
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ services:
php8Parser: @php8PhpParser
fileExtensions: %fileExtensions%
excludePaths: %excludePaths%
memoizingSourceLocatorEntriesCountMax: %cache.memoizingSourceLocatorEntriesCountMax%

# overrides service from parsers.neon
currentPhpVersionSimpleParser!:
Expand Down
9 changes: 3 additions & 6 deletions src/Testing/TestCaseSourceLocatorFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use PHPStan\BetterReflection\SourceLocator\SourceStubber\ReflectionSourceStubber;
use PHPStan\BetterReflection\SourceLocator\Type\AggregateSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\EvaledCodeSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\MemoizingSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\PhpInternalSourceLocator;
use PHPStan\BetterReflection\SourceLocator\Type\SourceLocator;
use PHPStan\Php\PhpVersion;
Expand Down Expand Up @@ -47,7 +46,6 @@ public function __construct(
private PhpVersion $phpVersion,
private array $fileExtensions,
private ?array $excludePaths,
private int $memoizingSourceLocatorEntriesCountMax,
)
{
}
Expand Down Expand Up @@ -98,10 +96,9 @@ public function create(): SourceLocator
$locators[] = new PhpVersionBlacklistSourceLocator(new PhpInternalSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);
$locators[] = new PhpVersionBlacklistSourceLocator(new EvaledCodeSourceLocator($astLocator, $this->reflectionSourceStubber), $this->phpstormStubsSourceStubber);

return new MemoizingSourceLocator(
new AggregateSourceLocator($locators),
$this->memoizingSourceLocatorEntriesCountMax === 0 ? null : $this->memoizingSourceLocatorEntriesCountMax,
);
// no MemoizingSourceLocator here - located reflections are already memoized
// by MemoizingReflector, a second cache layer would only pin them in memory twice
return new AggregateSourceLocator($locators);
}

}
Loading