@@ -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}
0 commit comments