@@ -20,6 +20,14 @@ class WorkspaceIndex
20
20
* @var array<string, TextDocument>
21
21
*/
22
22
private $ byName = [];
23
+ /**
24
+ * @var array<string, TextDocument>
25
+ */
26
+ private $ documents = [];
27
+ /**
28
+ * @var array<string, array<string>>
29
+ */
30
+ private $ documentToNameMap = [];
23
31
24
32
public function __construct (SourceCodeReflector $ reflector )
25
33
{
@@ -37,41 +45,64 @@ public function documentForName(Name $name): ?TextDocument
37
45
38
46
public function index (TextDocument $ textDocument ): void
39
47
{
48
+ $ this ->documents [(string )$ textDocument ->uri ()] = $ textDocument ;
49
+ $ this ->updateDocument ($ textDocument );
50
+ }
51
+
52
+ private function updateDocument (TextDocument $ textDocument ): void
53
+ {
54
+ $ newNames = [];
40
55
foreach ($ this ->reflector ->reflectClassesIn ($ textDocument ) as $ reflectionClass ) {
41
- $ this -> byName [ $ reflectionClass ->name ()->full ()] = $ textDocument ;
56
+ $ newNames [] = $ reflectionClass ->name ()->full ();
42
57
}
43
-
58
+
44
59
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 ()]);
46
81
}
47
82
}
48
83
49
84
public function update (TextDocumentUri $ textDocumentUri , string $ updatedText ): void
50
85
{
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
+ ));
58
92
}
93
+ $ this ->updateDocument (TextDocumentBuilder::fromTextDocument ($ textDocument )->text ($ updatedText )->build ());
59
94
}
60
95
61
96
public function remove (TextDocumentUri $ textDocumentUri ): void
62
97
{
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
+ ));
70
104
}
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 ]);
76
107
}
77
108
}
0 commit comments