88use Phpactor \WorseReflection \Core \Name ;
99use Phpactor \WorseReflection \Core \Reflector \SourceCodeReflector ;
1010use RuntimeException ;
11+ use function Amp \asyncCall ;
12+ use function Amp \delay ;
1113
1214class WorkspaceIndex
1315{
@@ -29,9 +31,25 @@ class WorkspaceIndex
2931 */
3032 private $ documentToNameMap = [];
3133
32- public function __construct (SourceCodeReflector $ reflector )
34+ /**
35+ * @var TextDocument|null
36+ */
37+ private $ documentToUpdate ;
38+
39+ /**
40+ * @var bool
41+ */
42+ private $ waiting = false ;
43+
44+ /**
45+ * @var int
46+ */
47+ private $ updateInterval ;
48+
49+ public function __construct (SourceCodeReflector $ reflector , int $ updateInterval = 1000 )
3350 {
3451 $ this ->reflector = $ reflector ;
52+ $ this ->updateInterval = $ updateInterval ;
3553 }
3654
3755 public function documentForName (Name $ name ): ?TextDocument
@@ -49,24 +67,58 @@ public function index(TextDocument $textDocument): void
4967 $ this ->updateDocument ($ textDocument );
5068 }
5169
70+ /**
71+ * Refresh the document.
72+ *
73+ * In order to prevent continuous reparsing the document will
74+ * only be refreshed at the sepecified interval.
75+ */
5276 private function updateDocument (TextDocument $ textDocument ): void
5377 {
78+ if ($ this ->waiting ) {
79+ $ this ->documentToUpdate = $ textDocument ;
80+ return ;
81+ }
82+
83+ $ this ->documentToUpdate = null ;
84+
5485 $ newNames = [];
5586 foreach ($ this ->reflector ->reflectClassesIn ($ textDocument ) as $ reflectionClass ) {
5687 $ newNames [] = $ reflectionClass ->name ()->full ();
5788 }
58-
89+
5990 foreach ($ this ->reflector ->reflectFunctionsIn ($ textDocument ) as $ reflectionFunction ) {
6091 $ newNames [] = $ reflectionFunction ->name ()->full ();
6192 }
6293
63- $ this ->updateNames ($ textDocument , $ newNames , $ this ->documentToNameMap [(string )$ textDocument ->uri ()] ?? []);
94+ $ this ->updateNames (
95+ $ textDocument ,
96+ $ newNames ,
97+ $ this ->documentToNameMap [(string )$ textDocument ->uri ()] ?? []
98+ );
99+
100+ if ($ this ->updateInterval === 0 ) {
101+ return ;
102+ }
103+
104+ $ this ->waiting = true ;
105+
106+ asyncCall (function () {
107+ yield delay ($ this ->updateInterval );
108+ $ this ->waiting = false ;
109+
110+ if (null === $ this ->documentToUpdate ) {
111+ return ;
112+ }
113+
114+ $ this ->updateDocument ($ this ->documentToUpdate );
115+ });
64116 }
65117
66118 private function updateNames (TextDocument $ textDocument , array $ newNames , array $ currentNames ): void
67119 {
68120 $ namesToRemove = array_diff ($ currentNames , $ newNames );
69-
121+
70122 foreach ($ newNames as $ name ) {
71123 $ this ->byName [$ name ] = $ textDocument ;
72124 }
0 commit comments