Skip to content
This repository was archived by the owner on Mar 6, 2022. It is now read-only.

Commit 506381c

Browse files
BladeMFVladislav Kosev
andauthored
Fix WorkspaceIndex not reindexing when document changes. (#12)
* Fix WorkspaceIndex not reindexing when document changes. * Fix coding standards. Co-authored-by: Vladislav Kosev <[email protected]>
1 parent d22fa9a commit 506381c

File tree

2 files changed

+77
-26
lines changed

2 files changed

+77
-26
lines changed

lib/LanguageServerWorseReflection/Workspace/WorkspaceIndex.php

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ class WorkspaceIndex
2020
* @var array<string, TextDocument>
2121
*/
2222
private $byName = [];
23+
/**
24+
* @var array<string, TextDocument>
25+
*/
26+
private $documents = [];
27+
/**
28+
* @var array<string, array<string>>
29+
*/
30+
private $documentToNameMap = [];
2331

2432
public function __construct(SourceCodeReflector $reflector)
2533
{
@@ -37,41 +45,64 @@ public function documentForName(Name $name): ?TextDocument
3745

3846
public function index(TextDocument $textDocument): void
3947
{
48+
$this->documents[(string)$textDocument->uri()] = $textDocument;
49+
$this->updateDocument($textDocument);
50+
}
51+
52+
private function updateDocument(TextDocument $textDocument): void
53+
{
54+
$newNames = [];
4055
foreach ($this->reflector->reflectClassesIn($textDocument) as $reflectionClass) {
41-
$this->byName[$reflectionClass->name()->full()] = $textDocument;
56+
$newNames[] = $reflectionClass->name()->full();
4257
}
43-
58+
4459
foreach ($this->reflector->reflectFunctionsIn($textDocument) as $reflectionFunction) {
45-
$this->byName[$reflectionFunction->name()->full()] = $textDocument;
60+
$newNames[] = $reflectionFunction->name()->full();
61+
}
62+
63+
$this->updateNames($textDocument, $newNames, $this->documentToNameMap[(string)$textDocument->uri()] ?? []);
64+
}
65+
66+
private function updateNames(TextDocument $textDocument, array $newNames, array $currentNames): void
67+
{
68+
$namesToRemove = array_diff($currentNames, $newNames);
69+
70+
foreach ($newNames as $name) {
71+
$this->byName[$name] = $textDocument;
72+
}
73+
foreach ($namesToRemove as $name) {
74+
unset($this->byName[$name]);
75+
}
76+
77+
if (!empty($newNames)) {
78+
$this->documentToNameMap[(string)$textDocument->uri()] = $newNames;
79+
} else {
80+
unset($this->documentToNameMap[(string)$textDocument->uri()]);
4681
}
4782
}
4883

4984
public function update(TextDocumentUri $textDocumentUri, string $updatedText): void
5085
{
51-
foreach ($this->byName as $className => $textDocument) {
52-
if ($textDocumentUri != $textDocument->uri()) {
53-
continue;
54-
}
55-
56-
$this->byName[$className] = TextDocumentBuilder::fromTextDocument($textDocument)->text($updatedText)->build();
57-
return;
86+
$textDocument = $this->documents[(string)$textDocumentUri] ?? null;
87+
if ($textDocument === null) {
88+
throw new RuntimeException(sprintf(
89+
'Could not find document "%s"',
90+
$textDocumentUri->__toString()
91+
));
5892
}
93+
$this->updateDocument(TextDocumentBuilder::fromTextDocument($textDocument)->text($updatedText)->build());
5994
}
6095

6196
public function remove(TextDocumentUri $textDocumentUri): void
6297
{
63-
foreach ($this->byName as $className => $textDocument) {
64-
if ($textDocumentUri != $textDocument->uri()) {
65-
continue;
66-
}
67-
68-
unset($this->byName[$className]);
69-
return;
98+
$textDocument = $this->documents[(string)$textDocumentUri] ?? null;
99+
if ($textDocument === null) {
100+
throw new RuntimeException(sprintf(
101+
'Could not find document "%s"',
102+
$textDocumentUri->__toString()
103+
));
70104
}
71-
72-
throw new RuntimeException(sprintf(
73-
'Could not find document "%s"',
74-
$textDocumentUri->__toString()
75-
));
105+
$this->updateNames($textDocument, [], $this->documentToNameMap[(string)$textDocument->uri()] ?? []);
106+
unset($this->documents[(string)$textDocumentUri]);
76107
}
77108
}

tests/LanguageServerWorseReflection/Unit/Workspace/WorkspaceIndexTest.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ protected function setUp(): void
2323

2424
public function testIndexesClassesAndReturnsTextDocuments(): void
2525
{
26-
$document1 = TextDocumentBuilder::create('<?php namespace Test {class Foobar {}}')->build();
27-
$document2 = TextDocumentBuilder::create('<?php class Barfoo {}')->build();
26+
$document1 = TextDocumentBuilder::create('<?php namespace Test {class Foobar {}}')->uri('/test/Foobar')->build();
27+
$document2 = TextDocumentBuilder::create('<?php class Barfoo {}')->uri('/test/Barfoo')->build();
2828

2929
$this->index->index($document1);
3030
$this->index->index($document2);
@@ -36,8 +36,8 @@ public function testIndexesClassesAndReturnsTextDocuments(): void
3636

3737
public function testIndexesFunctionsAndReturnsTextDocuments(): void
3838
{
39-
$document1 = TextDocumentBuilder::create('<?php namespace Test {function barbar() {}}')->build();
40-
$document2 = TextDocumentBuilder::create('<?php function barfoo{}')->build();
39+
$document1 = TextDocumentBuilder::create('<?php namespace Test {function barbar() {}}')->uri('/Test/funcs')->build();
40+
$document2 = TextDocumentBuilder::create('<?php function barfoo{}')->uri('/globals')->build();
4141

4242
$this->index->index($document1);
4343
$this->index->index($document2);
@@ -59,6 +59,26 @@ public function testUpdatesExistingTextDocument(): void
5959
self::assertSame($updatedText, $this->index->documentForName(Name::fromString('Test\Foobar'))->__toString());
6060
}
6161

62+
public function testUpdateExistingEmptyDocument(): void
63+
{
64+
$document1 = TextDocumentBuilder::create('<?php')->uri('/test/foobar')->build();
65+
$this->index->index($document1);
66+
67+
$updatedText = '<?php namespace Test {class Foobar {} function foofunc{}}';
68+
$this->index->update($document1->uri(), $updatedText);
69+
70+
self::assertSame($updatedText, $this->index->documentForName(Name::fromString('Test\Foobar'))->__toString());
71+
self::assertSame($updatedText, $this->index->documentForName(Name::fromString('Test\foofunc'))->__toString());
72+
73+
$updatedText = '<?php namespace Test2 {class Foobar {} function foofunc{}}';
74+
$this->index->update($document1->uri(), $updatedText);
75+
76+
self::assertSame($updatedText, $this->index->documentForName(Name::fromString('Test2\Foobar'))->__toString());
77+
self::assertSame($updatedText, $this->index->documentForName(Name::fromString('Test2\foofunc'))->__toString());
78+
self::assertNull($this->index->documentForName(Name::fromString('Test\Foobar')));
79+
self::assertNull($this->index->documentForName(Name::fromString('Test\foofunc')));
80+
}
81+
6282
public function testRemovesTextDocument(): void
6383
{
6484
$document1 = TextDocumentBuilder::create('<?php namespace Test {class Foobar {}}')->uri('/test/foobar')->build();

0 commit comments

Comments
 (0)