mirror of
https://github.com/danog/psalm.git
synced 2024-12-02 09:37:59 +01:00
Remove file map cache when re-analyzing files (#5084)
* Remove file map cache when re-analyzing files When the project is re-analyzed under the single thread condition (not using a process pool), the filemaps are not cleared before re-analyzing files. This means that file maps only get appended to. If you delete the contents of a file via the LSP, the file map will still be populated with all the old values for example. In doing this I had to write a few more tests to check my assumptions too, so adding those additional tests. * Rename test * Formatting * Formatting again!
This commit is contained in:
parent
6c0b2f8cb9
commit
c837535c9d
@ -576,6 +576,11 @@ class Analyzer
|
|||||||
$i = 0;
|
$i = 0;
|
||||||
|
|
||||||
foreach ($this->files_to_analyze as $file_path => $_) {
|
foreach ($this->files_to_analyze as $file_path => $_) {
|
||||||
|
// Remove all current maps for the file, so new analysis doesn't
|
||||||
|
// only append to existing data.
|
||||||
|
unset($this->reference_map[$file_path]);
|
||||||
|
unset($this->type_map[$file_path]);
|
||||||
|
unset($this->argument_map[$file_path]);
|
||||||
$analysis_worker($i, $file_path);
|
$analysis_worker($i, $file_path);
|
||||||
++$i;
|
++$i;
|
||||||
|
|
||||||
|
@ -1318,4 +1318,40 @@ class AnalyzedMethodTest extends \Psalm\Tests\TestCase
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testFileMapsUpdated(): void
|
||||||
|
{
|
||||||
|
$codebase = $this->project_analyzer->getCodebase();
|
||||||
|
|
||||||
|
$config = $codebase->config;
|
||||||
|
$config->throw_exception = false;
|
||||||
|
|
||||||
|
$this->file_provider->registerFile('somefile.php', '
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function foo() : void {
|
||||||
|
}
|
||||||
|
|
||||||
|
foo();
|
||||||
|
');
|
||||||
|
|
||||||
|
$codebase->addFilesToAnalyze(['somefile.php' => 'somefile.php']);
|
||||||
|
$codebase->scanFiles();
|
||||||
|
$codebase->analyzer->analyzeFiles($this->project_analyzer, 1, false);
|
||||||
|
|
||||||
|
$maps = $codebase->analyzer->getMapsForFile('somefile.php');
|
||||||
|
|
||||||
|
$this->assertNotEmpty($maps[0]);
|
||||||
|
|
||||||
|
$this->file_provider->setOpenContents('somefile.php', '');
|
||||||
|
|
||||||
|
$codebase->reloadFiles($this->project_analyzer, ['somefile.php']);
|
||||||
|
$codebase->analyzer->analyzeFiles($this->project_analyzer, 1, false);
|
||||||
|
|
||||||
|
$updated_maps = $codebase->analyzer->getMapsForFile('somefile.php');
|
||||||
|
|
||||||
|
$this->assertSame([], $updated_maps[0]);
|
||||||
|
$this->assertSame([], $updated_maps[1]);
|
||||||
|
$this->assertSame([], $updated_maps[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,13 @@ class FakeFileProvider extends \Psalm\Internal\Provider\FileProvider
|
|||||||
$this->fake_files[$file_path] = $file_contents;
|
$this->fake_files[$file_path] = $file_contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setOpenContents(string $file_path, string $file_contents): void
|
||||||
|
{
|
||||||
|
if (isset($this->fake_files[strtolower($file_path)])) {
|
||||||
|
$this->fake_files[strtolower($file_path)] = $file_contents;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getModifiedTime(string $file_path): int
|
public function getModifiedTime(string $file_path): int
|
||||||
{
|
{
|
||||||
if (isset($this->fake_file_times[$file_path])) {
|
if (isset($this->fake_file_times[$file_path])) {
|
||||||
|
103
tests/LanguageServer/FileMapTest.php
Normal file
103
tests/LanguageServer/FileMapTest.php
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?php
|
||||||
|
namespace Psalm\Tests\LanguageServer;
|
||||||
|
|
||||||
|
use LanguageServerProtocol\Position;
|
||||||
|
use Psalm\Context;
|
||||||
|
use Psalm\Internal\Analyzer\ProjectAnalyzer;
|
||||||
|
use Psalm\Internal\Provider\Providers;
|
||||||
|
use Psalm\Tests\Internal\Provider;
|
||||||
|
use Psalm\Tests\TestConfig;
|
||||||
|
|
||||||
|
class FileMapTest extends \Psalm\Tests\TestCase
|
||||||
|
{
|
||||||
|
public function setUp() : void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->file_provider = new \Psalm\Tests\Internal\Provider\FakeFileProvider();
|
||||||
|
|
||||||
|
$config = new TestConfig();
|
||||||
|
|
||||||
|
$providers = new Providers(
|
||||||
|
$this->file_provider,
|
||||||
|
new \Psalm\Tests\Internal\Provider\ParserInstanceCacheProvider(),
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
new Provider\FakeFileReferenceCacheProvider(),
|
||||||
|
new \Psalm\Tests\Internal\Provider\ProjectCacheProvider()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->project_analyzer = new ProjectAnalyzer(
|
||||||
|
$config,
|
||||||
|
$providers
|
||||||
|
);
|
||||||
|
$this->project_analyzer->setPhpVersion('7.3');
|
||||||
|
$this->project_analyzer->getCodebase()->store_node_types = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapIsUpdatedOnReloadFiles(): void
|
||||||
|
{
|
||||||
|
$codebase = $this->project_analyzer->getCodebase();
|
||||||
|
$config = $codebase->config;
|
||||||
|
$config->throw_exception = false;
|
||||||
|
|
||||||
|
$this->addFile(
|
||||||
|
'somefile.php',
|
||||||
|
'<?php
|
||||||
|
class A {
|
||||||
|
function __construct( string $var ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$a = new A( "foo" );'
|
||||||
|
);
|
||||||
|
|
||||||
|
$codebase->file_provider->openFile('somefile.php');
|
||||||
|
$codebase->scanFiles();
|
||||||
|
$this->analyzeFile('somefile.php', new Context());
|
||||||
|
[ $type_map ] = $codebase->analyzer->getMapsForFile('somefile.php');
|
||||||
|
|
||||||
|
$this->assertTrue(!empty($type_map));
|
||||||
|
|
||||||
|
$codebase->file_provider->setOpenContents('somefile.php', '');
|
||||||
|
$codebase->reloadFiles($this->project_analyzer, ['somefile.php']);
|
||||||
|
[ $type_map ] = $codebase->analyzer->getMapsForFile('somefile.php');
|
||||||
|
|
||||||
|
$this->assertSame([], $type_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testGetTypeMap(): void
|
||||||
|
{
|
||||||
|
$codebase = $this->project_analyzer->getCodebase();
|
||||||
|
$config = $codebase->config;
|
||||||
|
$config->throw_exception = false;
|
||||||
|
|
||||||
|
$this->addFile(
|
||||||
|
'somefile.php',
|
||||||
|
'<?php
|
||||||
|
class A {
|
||||||
|
function __construct( string $var ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$a = new A( "foo" );'
|
||||||
|
);
|
||||||
|
|
||||||
|
$codebase->file_provider->openFile('somefile.php');
|
||||||
|
$codebase->scanFiles();
|
||||||
|
$this->analyzeFile('somefile.php', new Context());
|
||||||
|
[ $type_map ] = $codebase->analyzer->getMapsForFile('somefile.php');
|
||||||
|
|
||||||
|
$this->assertSame(
|
||||||
|
[
|
||||||
|
155 => [
|
||||||
|
156,
|
||||||
|
'A',
|
||||||
|
],
|
||||||
|
146 => [
|
||||||
|
148,
|
||||||
|
'146-147:A',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
$type_map
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user