4
4
namespace LanguageServer ;
5
5
6
6
use LanguageServer \Protocol \{
7
+ ConfigurationItem ,
7
8
ServerCapabilities ,
8
9
ClientCapabilities ,
9
10
TextDocumentSyncKind ,
15
16
use LanguageServer \FilesFinder \{FilesFinder , ClientFilesFinder , FileSystemFilesFinder };
16
17
use LanguageServer \ContentRetriever \{ContentRetriever , ClientContentRetriever , FileSystemContentRetriever };
17
18
use LanguageServer \Index \{DependenciesIndex , GlobalIndex , Index , ProjectIndex , StubsIndex };
18
- use LanguageServer \Cache \{FileSystemCache , ClientCache };
19
+ use LanguageServer \Cache \{Cache , FileSystemCache , ClientCache };
19
20
use AdvancedJsonRpc ;
20
21
use Sabre \Event \Promise ;
21
22
use function Sabre \Event \coroutine ;
@@ -106,6 +107,16 @@ class LanguageServer extends AdvancedJsonRpc\Dispatcher
106
107
*/
107
108
protected $ definitionResolver ;
108
109
110
+ /**
111
+ * @var string|null
112
+ */
113
+ protected $ rootPath ;
114
+
115
+ /**
116
+ * @var Cache
117
+ */
118
+ protected $ cache ;
119
+
109
120
/**
110
121
* @param ProtocolReader $reader
111
122
* @param ProtocolWriter $writer
@@ -162,14 +173,18 @@ public function __construct(ProtocolReader $reader, ProtocolWriter $writer)
162
173
*
163
174
* @param ClientCapabilities $capabilities The capabilities provided by the client (editor)
164
175
* @param string|null $rootPath The rootPath of the workspace. Is null if no folder is open.
165
- * @param int|null $processId The process Id of the parent process that started the server. Is null if the process has not been started by another process. If the parent process is not alive then the server should exit (see exit notification) its process.
166
- * @param Options $initializationOptions The options send from client to initialize the server
176
+ * @param int|null $processId The process Id of the parent process that started the server.
177
+ * Is null if the process has not been started by another process.
178
+ * If the parent process is not alive then the server should exit
179
+ * (see exit notification) its process.
167
180
* @return Promise <InitializeResult>
168
181
*/
169
- public function initialize (ClientCapabilities $ capabilities , string $ rootPath = null , int $ processId = null , Options $ initializationOptions = null ): Promise
170
- {
171
- return coroutine (function () use ($ capabilities , $ rootPath , $ processId , $ initializationOptions ) {
172
-
182
+ public function initialize (
183
+ ClientCapabilities $ capabilities ,
184
+ string $ rootPath = null ,
185
+ int $ processId = null
186
+ ): Promise {
187
+ return coroutine (function () use ($ capabilities , $ rootPath , $ processId ) {
173
188
if ($ capabilities ->xfilesProvider ) {
174
189
$ this ->filesFinder = new ClientFilesFinder ($ this ->client );
175
190
} else {
@@ -187,60 +202,115 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath =
187
202
$ this ->projectIndex = new ProjectIndex ($ sourceIndex , $ dependenciesIndex , $ this ->composerJson );
188
203
$ stubsIndex = StubsIndex::read ();
189
204
$ this ->globalIndex = new GlobalIndex ($ stubsIndex , $ this ->projectIndex );
190
- $ initializationOptions = $ initializationOptions ?? new Options ;
205
+ $ this -> rootPath = $ rootPath ;
191
206
192
207
// The DefinitionResolver should look in stubs, the project source and dependencies
193
208
$ this ->definitionResolver = new DefinitionResolver ($ this ->globalIndex );
194
-
195
209
$ this ->documentLoader = new PhpDocumentLoader (
196
210
$ this ->contentRetriever ,
197
211
$ this ->projectIndex ,
198
212
$ this ->definitionResolver
199
213
);
200
214
201
- if ($ rootPath !== null ) {
202
- yield $ this ->beforeIndex ($ rootPath );
215
+ if ($ this -> rootPath !== null ) {
216
+ yield $ this ->beforeIndex ($ this -> rootPath );
203
217
204
218
// Find composer.json
205
219
if ($ this ->composerJson === null ) {
206
- $ composerJsonFiles = yield $ this ->filesFinder ->find (Path::makeAbsolute ('**/composer.json ' , $ rootPath ));
220
+ $ composerJsonFiles = yield $ this ->filesFinder ->find (
221
+ Path::makeAbsolute ('**/composer.json ' , $ this ->rootPath )
222
+ );
207
223
sortUrisLevelOrder ($ composerJsonFiles );
208
224
209
225
if (!empty ($ composerJsonFiles )) {
210
- $ this ->composerJson = json_decode (yield $ this ->contentRetriever ->retrieve ($ composerJsonFiles [0 ]));
226
+ $ this ->composerJson = json_decode (
227
+ yield $ this ->contentRetriever ->retrieve ($ composerJsonFiles [0 ])
228
+ );
211
229
}
212
230
}
213
231
214
232
// Find composer.lock
215
233
if ($ this ->composerLock === null ) {
216
- $ composerLockFiles = yield $ this ->filesFinder ->find (Path::makeAbsolute ('**/composer.lock ' , $ rootPath ));
234
+ $ composerLockFiles = yield $ this ->filesFinder ->find (
235
+ Path::makeAbsolute ('**/composer.lock ' , $ this ->rootPath )
236
+ );
217
237
sortUrisLevelOrder ($ composerLockFiles );
218
238
219
239
if (!empty ($ composerLockFiles )) {
220
- $ this ->composerLock = json_decode (yield $ this ->contentRetriever ->retrieve ($ composerLockFiles [0 ]));
240
+ $ this ->composerLock = json_decode (
241
+ yield $ this ->contentRetriever ->retrieve ($ composerLockFiles [0 ])
242
+ );
221
243
}
222
244
}
223
245
224
- $ cache = $ capabilities ->xcacheProvider ? new ClientCache ($ this ->client ) : new FileSystemCache ;
246
+ $ this ->cache = $ capabilities ->xcacheProvider ? new ClientCache ($ this ->client ) : new FileSystemCache ;
247
+ }
248
+
249
+ $ serverCapabilities = new ServerCapabilities ();
250
+ // Ask the client to return always full documents (because we need to rebuild the AST from scratch)
251
+ $ serverCapabilities ->textDocumentSync = TextDocumentSyncKind::FULL ;
252
+ // Support "Find all symbols"
253
+ $ serverCapabilities ->documentSymbolProvider = true ;
254
+ // Support "Find all symbols in workspace"
255
+ $ serverCapabilities ->workspaceSymbolProvider = true ;
256
+ // Support "Go to definition"
257
+ $ serverCapabilities ->definitionProvider = true ;
258
+ // Support "Find all references"
259
+ $ serverCapabilities ->referencesProvider = true ;
260
+ // Support "Hover"
261
+ $ serverCapabilities ->hoverProvider = true ;
262
+ // Support "Completion"
263
+ $ serverCapabilities ->completionProvider = new CompletionOptions ;
264
+ $ serverCapabilities ->completionProvider ->resolveProvider = false ;
265
+ $ serverCapabilities ->completionProvider ->triggerCharacters = ['$ ' , '> ' ];
266
+
267
+ $ serverCapabilities ->signatureHelpProvider = new SignatureHelpOptions ();
268
+ $ serverCapabilities ->signatureHelpProvider ->triggerCharacters = ['( ' , ', ' ];
269
+
270
+ // Support global references
271
+ $ serverCapabilities ->xworkspaceReferencesProvider = true ;
272
+ $ serverCapabilities ->xdefinitionProvider = true ;
273
+ $ serverCapabilities ->xdependenciesProvider = true ;
225
274
275
+ return new InitializeResult ($ serverCapabilities );
276
+ });
277
+ }
278
+
279
+ /**
280
+ * The initialized notification is sent from the client to the server after
281
+ * the client received the result of the initialize request but before the
282
+ * client is sending any other request or notification to the server.
283
+ *
284
+ * @return Promise
285
+ */
286
+ public function initialized (): Promise
287
+ {
288
+ return coroutine (function () {
289
+ list ($ sourceIndex , $ dependenciesIndex ) = $ this ->projectIndex ->getIndexes ();
290
+ $ mapper = new \JsonMapper ();
291
+ $ configurationitem = new ConfigurationItem ();
292
+ $ configurationitem ->section = 'php ' ;
293
+ $ configuration = yield $ this ->client ->workspace ->configuration ([$ configurationitem ]);
294
+ $ options = $ mapper ->map ($ configuration [0 ], new Options ());
295
+
296
+ if ($ this ->rootPath ) {
226
297
// Index in background
227
298
$ indexer = new Indexer (
228
299
$ this ->filesFinder ,
229
- $ rootPath ,
300
+ $ this -> rootPath ,
230
301
$ this ->client ,
231
- $ cache ,
302
+ $ this -> cache ,
232
303
$ dependenciesIndex ,
233
304
$ sourceIndex ,
234
305
$ this ->documentLoader ,
235
- $ initializationOptions ,
306
+ $ options ,
236
307
$ this ->composerLock ,
237
- $ this ->composerJson ,
238
- $ initializationOptions
308
+ $ this ->composerJson
239
309
);
310
+
240
311
$ indexer ->index ()->otherwise ('\\LanguageServer \\crash ' );
241
312
}
242
313
243
-
244
314
if ($ this ->textDocument === null ) {
245
315
$ this ->textDocument = new Server \TextDocument (
246
316
$ this ->documentLoader ,
@@ -251,54 +321,26 @@ public function initialize(ClientCapabilities $capabilities, string $rootPath =
251
321
$ this ->composerLock
252
322
);
253
323
}
324
+
254
325
if ($ this ->workspace === null ) {
255
326
$ this ->workspace = new Server \Workspace (
256
327
$ this ->client ,
257
328
$ this ->projectIndex ,
258
329
$ dependenciesIndex ,
259
330
$ sourceIndex ,
331
+ $ options ,
260
332
$ this ->composerLock ,
261
333
$ this ->documentLoader ,
262
- $ this ->composerJson ,
263
- $ indexer ,
264
- $ initializationOptions
334
+ $ this ->composerJson
265
335
);
266
336
}
267
-
268
- $ serverCapabilities = new ServerCapabilities ();
269
- // Ask the client to return always full documents (because we need to rebuild the AST from scratch)
270
- $ serverCapabilities ->textDocumentSync = TextDocumentSyncKind::FULL ;
271
- // Support "Find all symbols"
272
- $ serverCapabilities ->documentSymbolProvider = true ;
273
- // Support "Find all symbols in workspace"
274
- $ serverCapabilities ->workspaceSymbolProvider = true ;
275
- // Support "Go to definition"
276
- $ serverCapabilities ->definitionProvider = true ;
277
- // Support "Find all references"
278
- $ serverCapabilities ->referencesProvider = true ;
279
- // Support "Hover"
280
- $ serverCapabilities ->hoverProvider = true ;
281
- // Support "Completion"
282
- $ serverCapabilities ->completionProvider = new CompletionOptions ;
283
- $ serverCapabilities ->completionProvider ->resolveProvider = false ;
284
- $ serverCapabilities ->completionProvider ->triggerCharacters = ['$ ' , '> ' ];
285
-
286
- $ serverCapabilities ->signatureHelpProvider = new SignatureHelpOptions ();
287
- $ serverCapabilities ->signatureHelpProvider ->triggerCharacters = ['( ' , ', ' ];
288
-
289
- // Support global references
290
- $ serverCapabilities ->xworkspaceReferencesProvider = true ;
291
- $ serverCapabilities ->xdefinitionProvider = true ;
292
- $ serverCapabilities ->xdependenciesProvider = true ;
293
-
294
- return new InitializeResult ($ serverCapabilities );
295
337
});
296
338
}
297
339
298
340
/**
299
341
* The shutdown request is sent from the client to the server. It asks the server to shut down, but to not exit
300
- * (otherwise the response might not be delivered correctly to the client). There is a separate exit notification that
301
- * asks the server to exit.
342
+ * (otherwise the response might not be delivered correctly to the client). There is a separate exit notification
343
+ * that asks the server to exit.
302
344
*
303
345
* @return void
304
346
*/
0 commit comments