mirror of
https://github.com/danog/psalm.git
synced 2024-11-27 12:55:26 +01:00
Merge pull request #7876 from vognev/feature/vendor-cache
cache statements even without persistent parser cache
This commit is contained in:
commit
55a45a935c
@ -55,6 +55,11 @@ class StatementsProvider
|
||||
*/
|
||||
private $file_storage_cache_provider;
|
||||
|
||||
/**
|
||||
* @var StatementsVolatileCache
|
||||
*/
|
||||
private $statements_volatile_cache;
|
||||
|
||||
/**
|
||||
* @var array<string, array<string, bool>>
|
||||
*/
|
||||
@ -104,6 +109,7 @@ class StatementsProvider
|
||||
$this->parser_cache_provider = $parser_cache_provider;
|
||||
$this->this_modified_time = filemtime(__FILE__);
|
||||
$this->file_storage_cache_provider = $file_storage_cache_provider;
|
||||
$this->statements_volatile_cache = StatementsVolatileCache::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,19 +132,26 @@ class StatementsProvider
|
||||
|
||||
$config = Config::getInstance();
|
||||
|
||||
$file_content_hash = md5($version . $file_contents);
|
||||
|
||||
if (!$this->parser_cache_provider
|
||||
|| (!$config->isInProjectDirs($file_path) && strpos($file_path, 'vendor'))
|
||||
) {
|
||||
$cache_key = "${file_content_hash}:${php_version}";
|
||||
if ($this->statements_volatile_cache->has($cache_key)) {
|
||||
return $this->statements_volatile_cache->get($cache_key);
|
||||
}
|
||||
|
||||
$progress->debug('Parsing ' . $file_path . "\n");
|
||||
|
||||
$has_errors = false;
|
||||
|
||||
$stmts = self::parseStatements($file_contents, $php_version, $has_errors, $file_path);
|
||||
|
||||
return $stmts ?: [];
|
||||
}
|
||||
$this->statements_volatile_cache->set($cache_key, $stmts);
|
||||
|
||||
$file_content_hash = md5($version . $file_contents);
|
||||
return $stmts;
|
||||
}
|
||||
|
||||
$stmts = $this->parser_cache_provider->loadStatementsFromCache(
|
||||
$file_path,
|
||||
|
108
src/Psalm/Internal/Provider/StatementsVolatileCache.php
Normal file
108
src/Psalm/Internal/Provider/StatementsVolatileCache.php
Normal file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Internal\Provider;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use PhpParser\Node\Stmt;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* @internal Owned by StatementsProvider
|
||||
* @todo: track variables size instead
|
||||
*/
|
||||
final class StatementsVolatileCache
|
||||
{
|
||||
/**
|
||||
* @var array<string, list<Stmt>>
|
||||
*/
|
||||
protected $cache = [];
|
||||
|
||||
/**
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $access = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
protected $max_size;
|
||||
|
||||
/**
|
||||
* @var ?StatementsVolatileCache
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
public function __construct(int $max_size = 4096)
|
||||
{
|
||||
$this->max_size = $max_size;
|
||||
}
|
||||
|
||||
public static function getInstance(): StatementsVolatileCache
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return list<Stmt>
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
public function get(string $key): array
|
||||
{
|
||||
if (! $this->has($key)) {
|
||||
throw new InvalidArgumentException('Given $key does not exists');
|
||||
}
|
||||
|
||||
$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];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param list<Stmt> $content
|
||||
*/
|
||||
public function set(string $key, array $content): void
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
$this->cache[$key] = $content;
|
||||
$this->access[] = $key;
|
||||
}
|
||||
|
||||
public function clearCache(): void
|
||||
{
|
||||
$this->cache = [];
|
||||
$this->access = [];
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ use Psalm\Internal\Provider\ClassLikeStorageProvider;
|
||||
use Psalm\Internal\Provider\FileReferenceProvider;
|
||||
use Psalm\Internal\Provider\FileStorageProvider;
|
||||
use Psalm\Internal\Provider\StatementsProvider;
|
||||
use Psalm\Internal\Provider\StatementsVolatileCache;
|
||||
use Psalm\Internal\Scanner\ParsedDocblock;
|
||||
use Psalm\Internal\Type\TypeTokenizer;
|
||||
use Psalm\IssueBuffer;
|
||||
@ -38,5 +39,6 @@ abstract class RuntimeCaches
|
||||
StatementsProvider::clearLexer();
|
||||
StatementsProvider::clearParser();
|
||||
ParsedDocblock::resetNewlineBetweenAnnotations();
|
||||
StatementsVolatileCache::getInstance()->clearCache();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user