Skip to content

Commit 96aa998

Browse files
authored
Make Index an EventEmitter (#255)
1 parent 43a91b0 commit 96aa998

File tree

15 files changed

+286
-38
lines changed

15 files changed

+286
-38
lines changed

src/ComposerScripts.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ public static function parseStubs()
5858
$document = new PhpDocument($uri, $content, $index, $parser, $docBlockFactory, $definitionResolver);
5959
}
6060

61+
$index->setComplete();
62+
6163
echo "Saving Index\n";
6264

6365
$index->save();

src/Index/AbstractAggregateIndex.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,100 @@
44
namespace LanguageServer\Index;
55

66
use LanguageServer\Definition;
7+
use Sabre\Event\EmitterTrait;
78

89
abstract class AbstractAggregateIndex implements ReadableIndex
910
{
11+
use EmitterTrait;
12+
1013
/**
1114
* Returns all indexes managed by the aggregate index
1215
*
1316
* @return ReadableIndex[]
1417
*/
1518
abstract protected function getIndexes(): array;
1619

20+
public function __construct()
21+
{
22+
foreach ($this->getIndexes() as $index) {
23+
$this->registerIndex($index);
24+
}
25+
}
26+
27+
/**
28+
* @param ReadableIndex $index
29+
*/
30+
protected function registerIndex(ReadableIndex $index)
31+
{
32+
$index->on('complete', function () {
33+
if ($this->isComplete()) {
34+
$this->emit('complete');
35+
}
36+
});
37+
$index->on('static-complete', function () {
38+
if ($this->isStaticComplete()) {
39+
$this->emit('static-complete');
40+
}
41+
});
42+
$index->on('definition-added', function () {
43+
$this->emit('definition-added');
44+
});
45+
}
46+
47+
/**
48+
* Marks this index as complete
49+
*
50+
* @return void
51+
*/
52+
public function setComplete()
53+
{
54+
foreach ($this->getIndexes() as $index) {
55+
$index->setComplete();
56+
}
57+
}
58+
59+
/**
60+
* Marks this index as complete for static definitions and references
61+
*
62+
* @return void
63+
*/
64+
public function setStaticComplete()
65+
{
66+
foreach ($this->getIndexes() as $index) {
67+
$index->setStaticComplete();
68+
}
69+
}
70+
71+
/**
72+
* Returns true if this index is complete
73+
*
74+
* @return bool
75+
*/
76+
public function isComplete(): bool
77+
{
78+
foreach ($this->getIndexes() as $index) {
79+
if (!$index->isComplete()) {
80+
return false;
81+
}
82+
}
83+
return true;
84+
}
85+
86+
/**
87+
* Returns true if this index is complete for static definitions or references
88+
*
89+
* @return bool
90+
*/
91+
public function isStaticComplete(): bool
92+
{
93+
foreach ($this->getIndexes() as $index) {
94+
if (!$index->isStaticComplete()) {
95+
return false;
96+
}
97+
}
98+
return true;
99+
}
100+
17101
/**
18102
* Returns an associative array [string => Definition] that maps fully qualified symbol names
19103
* to Definitions

src/Index/DependenciesIndex.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ protected function getIndexes(): array
2727
public function getDependencyIndex(string $packageName): Index
2828
{
2929
if (!isset($this->indexes[$packageName])) {
30-
$this->indexes[$packageName] = new Index;
30+
$index = new Index;
31+
$this->indexes[$packageName] = $index;
32+
$this->registerIndex($index);
3133
}
3234
return $this->indexes[$packageName];
3335
}

src/Index/GlobalIndex.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function __construct(StubsIndex $stubsIndex, ProjectIndex $projectIndex)
2626
{
2727
$this->stubsIndex = $stubsIndex;
2828
$this->projectIndex = $projectIndex;
29+
parent::__construct();
2930
}
3031

3132
/**

src/Index/Index.php

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
namespace LanguageServer\Index;
55

66
use LanguageServer\Definition;
7+
use Sabre\Event\EmitterTrait;
78

89
/**
910
* Represents the index of a project or dependency
1011
* Serializable for caching
1112
*/
1213
class Index implements ReadableIndex
1314
{
15+
use EmitterTrait;
16+
1417
/**
1518
* An associative array that maps fully qualified symbol names to Definitions
1619
*
@@ -25,6 +28,61 @@ class Index implements ReadableIndex
2528
*/
2629
private $references = [];
2730

31+
/**
32+
* @var bool
33+
*/
34+
private $complete = false;
35+
36+
/**
37+
* @var bool
38+
*/
39+
private $staticComplete = false;
40+
41+
/**
42+
* Marks this index as complete
43+
*
44+
* @return void
45+
*/
46+
public function setComplete()
47+
{
48+
if (!$this->isStaticComplete()) {
49+
$this->setStaticComplete();
50+
}
51+
$this->complete = true;
52+
$this->emit('complete');
53+
}
54+
55+
/**
56+
* Marks this index as complete for static definitions and references
57+
*
58+
* @return void
59+
*/
60+
public function setStaticComplete()
61+
{
62+
$this->staticComplete = true;
63+
$this->emit('static-complete');
64+
}
65+
66+
/**
67+
* Returns true if this index is complete
68+
*
69+
* @return bool
70+
*/
71+
public function isComplete(): bool
72+
{
73+
return $this->complete;
74+
}
75+
76+
/**
77+
* Returns true if this index is complete
78+
*
79+
* @return bool
80+
*/
81+
public function isStaticComplete(): bool
82+
{
83+
return $this->staticComplete;
84+
}
85+
2886
/**
2987
* Returns an associative array [string => Definition] that maps fully qualified symbol names
3088
* to Definitions
@@ -65,6 +123,7 @@ public function getDefinition(string $fqn, bool $globalFallback = false)
65123
public function setDefinition(string $fqn, Definition $definition)
66124
{
67125
$this->definitions[$fqn] = $definition;
126+
$this->emit('definition-added');
68127
}
69128

70129
/**

src/Index/ProjectIndex.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public function __construct(Index $sourceIndex, DependenciesIndex $dependenciesI
2626
{
2727
$this->sourceIndex = $sourceIndex;
2828
$this->dependenciesIndex = $dependenciesIndex;
29+
parent::__construct();
2930
}
3031

3132
/**

src/Index/ReadableIndex.php

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,31 @@
44
namespace LanguageServer\Index;
55

66
use LanguageServer\Definition;
7+
use Sabre\Event\EmitterInterface;
78

89
/**
910
* The ReadableIndex interface provides methods to lookup definitions and references
11+
*
12+
* @event definition-added Emitted when a definition was added
13+
* @event static-complete Emitted when definitions and static references are complete
14+
* @event complete Emitted when the index is complete
1015
*/
11-
interface ReadableIndex
16+
interface ReadableIndex extends EmitterInterface
1217
{
18+
/**
19+
* Returns true if this index is complete
20+
*
21+
* @return bool
22+
*/
23+
public function isComplete(): bool;
24+
25+
/**
26+
* Returns true if definitions and static references are complete
27+
*
28+
* @return bool
29+
*/
30+
public function isStaticComplete(): bool;
31+
1332
/**
1433
* Returns an associative array [string => Definition] that maps fully qualified symbol names
1534
* to Definitions

src/LanguageServer.php

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
100100
*/
101101
protected $globalIndex;
102102

103+
/**
104+
* @var ProjectIndex
105+
*/
106+
protected $projectIndex;
107+
103108
/**
104109
* @var DefinitionResolver
105110
*/
@@ -182,21 +187,22 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath =
182187

183188
$dependenciesIndex = new DependenciesIndex;
184189
$sourceIndex = new Index;
185-
$projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
190+
$this->projectIndex = new ProjectIndex($sourceIndex, $dependenciesIndex);
186191
$stubsIndex = StubsIndex::read();
187-
$this->globalIndex = new GlobalIndex($stubsIndex, $projectIndex);
192+
$this->globalIndex = new GlobalIndex($stubsIndex, $this->projectIndex);
188193

189194
// The DefinitionResolver should look in stubs, the project source and dependencies
190195
$this->definitionResolver = new DefinitionResolver($this->globalIndex);
191196

192197
$this->documentLoader = new PhpDocumentLoader(
193198
$this->contentRetriever,
194-
$projectIndex,
199+
$this->projectIndex,
195200
$this->definitionResolver
196201
);
197202

198203
if ($rootPath !== null) {
199-
yield $this->index($rootPath);
204+
yield $this->beforeIndex($rootPath);
205+
$this->index($rootPath)->otherwise('\\LanguageServer\\crash');
200206
}
201207

202208
// Find composer.json
@@ -225,7 +231,13 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath =
225231
);
226232
}
227233
if ($this->workspace === null) {
228-
$this->workspace = new Server\Workspace($projectIndex, $dependenciesIndex, $sourceIndex, $this->composerLock, $this->documentLoader);
234+
$this->workspace = new Server\Workspace(
235+
$this->projectIndex,
236+
$dependenciesIndex,
237+
$sourceIndex,
238+
$this->composerLock,
239+
$this->documentLoader
240+
);
229241
}
230242

231243
$serverCapabilities = new ServerCapabilities();
@@ -278,6 +290,15 @@ public function exit()
278290
exit(0);
279291
}
280292

293+
/**
294+
* Called before indexing, can return a Promise
295+
*
296+
* @param string $rootPath
297+
*/
298+
protected function beforeIndex(string $rootPath)
299+
{
300+
}
301+
281302
/**
282303
* Will read and parse the passed source files in the project and add them to the appropiate indexes
283304
*
@@ -295,8 +316,8 @@ protected function index(string $rootPath): Promise
295316

296317
$startTime = microtime(true);
297318

298-
foreach (['Collecting definitions and static references', 'Collecting dynamic references'] as $run) {
299-
$this->client->window->logMessage(MessageType::INFO, $run);
319+
foreach (['Collecting definitions and static references', 'Collecting dynamic references'] as $run => $text) {
320+
$this->client->window->logMessage(MessageType::INFO, $text);
300321
foreach ($uris as $i => $uri) {
301322
if ($this->documentLoader->isOpen($uri)) {
302323
continue;
@@ -325,6 +346,11 @@ protected function index(string $rootPath): Promise
325346
);
326347
}
327348
}
349+
if ($run === 0) {
350+
$this->projectIndex->setStaticComplete();
351+
} else {
352+
$this->projectIndex->setComplete();
353+
}
328354
$duration = (int)(microtime(true) - $startTime);
329355
$mem = (int)(memory_get_usage(true) / (1024 * 1024));
330356
$this->client->window->logMessage(

0 commit comments

Comments
 (0)