2022-04-27 07:50:13 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Psalm\Internal\Provider;
|
|
|
|
|
2022-04-27 07:51:23 +02:00
|
|
|
use InvalidArgumentException;
|
|
|
|
use PhpParser\Node\Stmt;
|
|
|
|
|
2022-04-27 07:50:13 +02:00
|
|
|
use function array_key_exists;
|
|
|
|
use function array_search;
|
|
|
|
use function array_splice;
|
|
|
|
use function count;
|
|
|
|
use function is_null;
|
|
|
|
use function key;
|
|
|
|
use function reset;
|
|
|
|
|
|
|
|
/**
|
2022-04-27 07:51:23 +02:00
|
|
|
* @internal Owned by StatementsProvider
|
2022-04-27 07:50:13 +02:00
|
|
|
* @todo: track variables size instead
|
|
|
|
*/
|
2022-04-27 07:51:23 +02:00
|
|
|
final class StatementsVolatileCache
|
2022-04-27 07:50:13 +02:00
|
|
|
{
|
|
|
|
/**
|
2022-04-27 07:51:23 +02:00
|
|
|
* @var array<string, list<Stmt>>
|
2022-04-27 07:50:13 +02:00
|
|
|
*/
|
2022-12-14 01:52:54 +01:00
|
|
|
protected array $cache = [];
|
2022-04-27 07:50:13 +02:00
|
|
|
|
|
|
|
/**
|
2022-04-27 07:51:23 +02:00
|
|
|
* @var array<int, string>
|
2022-04-27 07:50:13 +02:00
|
|
|
*/
|
2022-12-14 01:52:54 +01:00
|
|
|
protected array $access = [];
|
2022-04-27 07:50:13 +02:00
|
|
|
|
2022-12-14 01:52:54 +01:00
|
|
|
protected int $max_size;
|
2022-04-27 07:50:13 +02:00
|
|
|
|
2022-12-14 01:52:54 +01:00
|
|
|
protected static ?StatementsVolatileCache $instance = null;
|
2022-04-27 07:50:13 +02:00
|
|
|
|
|
|
|
public function __construct(int $max_size = 4096)
|
|
|
|
{
|
|
|
|
$this->max_size = $max_size;
|
|
|
|
}
|
|
|
|
|
2022-04-27 07:51:23 +02:00
|
|
|
public static function getInstance(): StatementsVolatileCache
|
2022-04-27 07:50:13 +02:00
|
|
|
{
|
|
|
|
if (is_null(self::$instance)) {
|
|
|
|
self::$instance = new self();
|
|
|
|
}
|
|
|
|
|
|
|
|
return self::$instance;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function has(string $key): bool
|
|
|
|
{
|
|
|
|
return array_key_exists($key, $this->cache);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-04-27 07:51:23 +02:00
|
|
|
* @return list<Stmt>
|
|
|
|
* @throws InvalidArgumentException
|
2022-04-27 07:50:13 +02:00
|
|
|
*/
|
2022-04-27 07:51:23 +02:00
|
|
|
public function get(string $key): array
|
2022-04-27 07:50:13 +02:00
|
|
|
{
|
|
|
|
if (! $this->has($key)) {
|
2022-04-27 07:51:23 +02:00
|
|
|
throw new InvalidArgumentException('Given $key does not exists');
|
2022-04-27 07:50:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$access_index = array_search($key, $this->access);
|
|
|
|
if (false !== $access_index) {
|
|
|
|
array_splice($this->access, $access_index, 1);
|
|
|
|
}
|
|
|
|
$this->access[] = $key;
|
|
|
|
|
|
|
|
return $this->cache[$key];
|
|
|
|
}
|
|
|
|
|
2022-04-27 07:51:23 +02:00
|
|
|
/**
|
|
|
|
* @param list<Stmt> $content
|
|
|
|
*/
|
|
|
|
public function set(string $key, array $content): void
|
2022-04-27 07:50:13 +02:00
|
|
|
{
|
|
|
|
if (count($this->cache) > $this->max_size) {
|
|
|
|
reset($this->access);
|
|
|
|
|
|
|
|
$oldest_key_index = key($this->access);
|
|
|
|
|
|
|
|
if (! is_null($oldest_key_index)) {
|
|
|
|
$oldest_key = $this->access[$oldest_key_index];
|
|
|
|
unset($this->cache[$oldest_key]);
|
|
|
|
unset($this->access[$oldest_key_index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-27 07:51:23 +02:00
|
|
|
$this->cache[$key] = $content;
|
2022-04-27 07:50:13 +02:00
|
|
|
$this->access[] = $key;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function clearCache(): void
|
|
|
|
{
|
|
|
|
$this->cache = [];
|
|
|
|
$this->access = [];
|
|
|
|
}
|
|
|
|
}
|