@difizen/libro-language-client 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (298) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/es/common/api.d.ts +38 -0
  4. package/es/common/api.d.ts.map +1 -0
  5. package/es/common/api.js +9 -0
  6. package/es/common/callHierarchy.d.ts +39 -0
  7. package/es/common/callHierarchy.d.ts.map +1 -0
  8. package/es/common/callHierarchy.js +139 -0
  9. package/es/common/client.d.ts +482 -0
  10. package/es/common/client.d.ts.map +1 -0
  11. package/es/common/client.js +2731 -0
  12. package/es/common/codeAction.d.ts +22 -0
  13. package/es/common/codeAction.d.ts.map +1 -0
  14. package/es/common/codeAction.js +149 -0
  15. package/es/common/codeConverter.d.ts +81 -0
  16. package/es/common/codeConverter.d.ts.map +1 -0
  17. package/es/common/codeConverter.js +1040 -0
  18. package/es/common/codeLens.d.ts +26 -0
  19. package/es/common/codeLens.d.ts.map +1 -0
  20. package/es/common/codeLens.js +125 -0
  21. package/es/common/colorProvider.d.ts +27 -0
  22. package/es/common/colorProvider.d.ts.map +1 -0
  23. package/es/common/colorProvider.js +104 -0
  24. package/es/common/completion.d.ts +22 -0
  25. package/es/common/completion.d.ts.map +1 -0
  26. package/es/common/completion.js +130 -0
  27. package/es/common/configuration.d.ts +71 -0
  28. package/es/common/configuration.d.ts.map +1 -0
  29. package/es/common/configuration.js +292 -0
  30. package/es/common/declaration.d.ts +18 -0
  31. package/es/common/declaration.d.ts.map +1 -0
  32. package/es/common/declaration.js +88 -0
  33. package/es/common/definition.d.ts +18 -0
  34. package/es/common/definition.d.ts.map +1 -0
  35. package/es/common/definition.js +80 -0
  36. package/es/common/diagnostic.d.ts +125 -0
  37. package/es/common/diagnostic.d.ts.map +1 -0
  38. package/es/common/diagnostic.js +1442 -0
  39. package/es/common/documentHighlight.d.ts +17 -0
  40. package/es/common/documentHighlight.d.ts.map +1 -0
  41. package/es/common/documentHighlight.js +73 -0
  42. package/es/common/documentLink.d.ts +21 -0
  43. package/es/common/documentLink.d.ts.map +1 -0
  44. package/es/common/documentLink.js +90 -0
  45. package/es/common/documentSymbol.d.ts +20 -0
  46. package/es/common/documentSymbol.d.ts.map +1 -0
  47. package/es/common/documentSymbol.js +134 -0
  48. package/es/common/executeCommand.d.ts +22 -0
  49. package/es/common/executeCommand.d.ts.map +1 -0
  50. package/es/common/executeCommand.js +117 -0
  51. package/es/common/features.d.ts +421 -0
  52. package/es/common/features.d.ts.map +1 -0
  53. package/es/common/features.js +576 -0
  54. package/es/common/fileOperations.d.ts +118 -0
  55. package/es/common/fileOperations.d.ts.map +1 -0
  56. package/es/common/fileOperations.js +705 -0
  57. package/es/common/fileSystemWatcher.d.ts +19 -0
  58. package/es/common/fileSystemWatcher.d.ts.map +1 -0
  59. package/es/common/fileSystemWatcher.js +173 -0
  60. package/es/common/foldingRange.d.ts +22 -0
  61. package/es/common/foldingRange.d.ts.map +1 -0
  62. package/es/common/foldingRange.js +127 -0
  63. package/es/common/formatting.d.ts +41 -0
  64. package/es/common/formatting.d.ts.map +1 -0
  65. package/es/common/formatting.js +233 -0
  66. package/es/common/hover.d.ts +18 -0
  67. package/es/common/hover.d.ts.map +1 -0
  68. package/es/common/hover.js +80 -0
  69. package/es/common/implementation.d.ts +18 -0
  70. package/es/common/implementation.d.ts.map +1 -0
  71. package/es/common/implementation.js +88 -0
  72. package/es/common/inlayHint.d.ts +23 -0
  73. package/es/common/inlayHint.d.ts.map +1 -0
  74. package/es/common/inlayHint.js +187 -0
  75. package/es/common/inlineCompletion.d.ts +20 -0
  76. package/es/common/inlineCompletion.d.ts.map +1 -0
  77. package/es/common/inlineCompletion.js +74 -0
  78. package/es/common/inlineValue.d.ts +21 -0
  79. package/es/common/inlineValue.d.ts.map +1 -0
  80. package/es/common/inlineValue.js +124 -0
  81. package/es/common/linkedEditingRange.d.ts +23 -0
  82. package/es/common/linkedEditingRange.d.ts.map +1 -0
  83. package/es/common/linkedEditingRange.js +94 -0
  84. package/es/common/notebook.d.ts +97 -0
  85. package/es/common/notebook.d.ts.map +1 -0
  86. package/es/common/notebook.js +1444 -0
  87. package/es/common/progress.d.ts +12 -0
  88. package/es/common/progress.d.ts.map +1 -0
  89. package/es/common/progress.js +75 -0
  90. package/es/common/progressPart.d.ts +25 -0
  91. package/es/common/progressPart.d.ts.map +1 -0
  92. package/es/common/progressPart.js +147 -0
  93. package/es/common/protocolCallHierarchyItem.d.ts +9 -0
  94. package/es/common/protocolCallHierarchyItem.d.ts.map +1 -0
  95. package/es/common/protocolCallHierarchyItem.js +34 -0
  96. package/es/common/protocolCodeAction.d.ts +7 -0
  97. package/es/common/protocolCodeAction.d.ts.map +1 -0
  98. package/es/common/protocolCodeAction.js +32 -0
  99. package/es/common/protocolCodeLens.d.ts +7 -0
  100. package/es/common/protocolCodeLens.d.ts.map +1 -0
  101. package/es/common/protocolCodeLens.js +29 -0
  102. package/es/common/protocolCompletionItem.d.ts +13 -0
  103. package/es/common/protocolCompletionItem.d.ts.map +1 -0
  104. package/es/common/protocolCompletionItem.js +29 -0
  105. package/es/common/protocolConverter.d.ts +174 -0
  106. package/es/common/protocolConverter.d.ts.map +1 -0
  107. package/es/common/protocolConverter.js +1982 -0
  108. package/es/common/protocolDiagnostic.d.ts +20 -0
  109. package/es/common/protocolDiagnostic.d.ts.map +1 -0
  110. package/es/common/protocolDiagnostic.js +46 -0
  111. package/es/common/protocolDocumentLink.d.ts +8 -0
  112. package/es/common/protocolDocumentLink.d.ts.map +1 -0
  113. package/es/common/protocolDocumentLink.js +29 -0
  114. package/es/common/protocolInlayHint.d.ts +8 -0
  115. package/es/common/protocolInlayHint.d.ts.map +1 -0
  116. package/es/common/protocolInlayHint.js +29 -0
  117. package/es/common/protocolTypeHierarchyItem.d.ts +9 -0
  118. package/es/common/protocolTypeHierarchyItem.d.ts.map +1 -0
  119. package/es/common/protocolTypeHierarchyItem.js +34 -0
  120. package/es/common/protocolWorkspaceSymbol.d.ts +9 -0
  121. package/es/common/protocolWorkspaceSymbol.d.ts.map +1 -0
  122. package/es/common/protocolWorkspaceSymbol.js +36 -0
  123. package/es/common/reference.d.ts +22 -0
  124. package/es/common/reference.d.ts.map +1 -0
  125. package/es/common/reference.js +78 -0
  126. package/es/common/rename.d.ts +29 -0
  127. package/es/common/rename.d.ts.map +1 -0
  128. package/es/common/rename.js +132 -0
  129. package/es/common/selectionRange.d.ts +18 -0
  130. package/es/common/selectionRange.d.ts.map +1 -0
  131. package/es/common/selectionRange.js +108 -0
  132. package/es/common/semanticTokens.d.ts +36 -0
  133. package/es/common/semanticTokens.d.ts.map +1 -0
  134. package/es/common/semanticTokens.js +226 -0
  135. package/es/common/signatureHelp.d.ts +18 -0
  136. package/es/common/signatureHelp.d.ts.map +1 -0
  137. package/es/common/signatureHelp.js +103 -0
  138. package/es/common/textSynchronization.d.ts +104 -0
  139. package/es/common/textSynchronization.d.ts.map +1 -0
  140. package/es/common/textSynchronization.js +771 -0
  141. package/es/common/typeDefinition.d.ts +18 -0
  142. package/es/common/typeDefinition.d.ts.map +1 -0
  143. package/es/common/typeDefinition.js +89 -0
  144. package/es/common/typeHierarchy.d.ts +33 -0
  145. package/es/common/typeHierarchy.d.ts.map +1 -0
  146. package/es/common/typeHierarchy.js +138 -0
  147. package/es/common/utils/async.d.ts +42 -0
  148. package/es/common/utils/async.d.ts.map +1 -0
  149. package/es/common/utils/async.js +441 -0
  150. package/es/common/utils/is.d.ts +13 -0
  151. package/es/common/utils/is.d.ts.map +1 -0
  152. package/es/common/utils/is.js +52 -0
  153. package/es/common/utils/uuid.d.ts +23 -0
  154. package/es/common/utils/uuid.d.ts.map +1 -0
  155. package/es/common/utils/uuid.js +85 -0
  156. package/es/common/vscodeAdaptor/convertor.d.ts +7 -0
  157. package/es/common/vscodeAdaptor/convertor.d.ts.map +1 -0
  158. package/es/common/vscodeAdaptor/convertor.js +66 -0
  159. package/es/common/vscodeAdaptor/diagnosticCollection.d.ts +33 -0
  160. package/es/common/vscodeAdaptor/diagnosticCollection.d.ts.map +1 -0
  161. package/es/common/vscodeAdaptor/diagnosticCollection.js +310 -0
  162. package/es/common/vscodeAdaptor/extHostTypes.d.ts +1496 -0
  163. package/es/common/vscodeAdaptor/extHostTypes.d.ts.map +1 -0
  164. package/es/common/vscodeAdaptor/extHostTypes.js +3825 -0
  165. package/es/common/vscodeAdaptor/fileWatcher.d.ts +19 -0
  166. package/es/common/vscodeAdaptor/fileWatcher.d.ts.map +1 -0
  167. package/es/common/vscodeAdaptor/fileWatcher.js +45 -0
  168. package/es/common/vscodeAdaptor/hostTypeUtil.d.ts +192 -0
  169. package/es/common/vscodeAdaptor/hostTypeUtil.d.ts.map +1 -0
  170. package/es/common/vscodeAdaptor/hostTypeUtil.js +566 -0
  171. package/es/common/vscodeAdaptor/libro-fs.d.ts +21 -0
  172. package/es/common/vscodeAdaptor/libro-fs.d.ts.map +1 -0
  173. package/es/common/vscodeAdaptor/libro-fs.js +64 -0
  174. package/es/common/vscodeAdaptor/libroWindow.d.ts +21 -0
  175. package/es/common/vscodeAdaptor/libroWindow.d.ts.map +1 -0
  176. package/es/common/vscodeAdaptor/libroWindow.js +75 -0
  177. package/es/common/vscodeAdaptor/libroWorkspace.d.ts +33 -0
  178. package/es/common/vscodeAdaptor/libroWorkspace.d.ts.map +1 -0
  179. package/es/common/vscodeAdaptor/libroWorkspace.js +250 -0
  180. package/es/common/vscodeAdaptor/lspEnv.d.ts +8 -0
  181. package/es/common/vscodeAdaptor/lspEnv.d.ts.map +1 -0
  182. package/es/common/vscodeAdaptor/lspEnv.js +31 -0
  183. package/es/common/vscodeAdaptor/monaco-converter.d.ts +229 -0
  184. package/es/common/vscodeAdaptor/monaco-converter.d.ts.map +1 -0
  185. package/es/common/vscodeAdaptor/monaco-converter.js +1613 -0
  186. package/es/common/vscodeAdaptor/monacoLanguages.d.ts +48 -0
  187. package/es/common/vscodeAdaptor/monacoLanguages.d.ts.map +1 -0
  188. package/es/common/vscodeAdaptor/monacoLanguages.js +484 -0
  189. package/es/common/vscodeAdaptor/services.d.ts +85 -0
  190. package/es/common/vscodeAdaptor/services.d.ts.map +1 -0
  191. package/es/common/vscodeAdaptor/services.js +3 -0
  192. package/es/common/vscodeAdaptor/typings.d.ts +10 -0
  193. package/es/common/vscodeAdaptor/util.d.ts +3 -0
  194. package/es/common/vscodeAdaptor/util.d.ts.map +1 -0
  195. package/es/common/vscodeAdaptor/util.js +6 -0
  196. package/es/common/vscodeAdaptor/vscodeAdaptor.d.ts +77 -0
  197. package/es/common/vscodeAdaptor/vscodeAdaptor.d.ts.map +1 -0
  198. package/es/common/vscodeAdaptor/vscodeAdaptor.js +124 -0
  199. package/es/common/workspaceFolder.d.ts +32 -0
  200. package/es/common/workspaceFolder.d.ts.map +1 -0
  201. package/es/common/workspaceFolder.js +204 -0
  202. package/es/common/workspaceSymbol.d.ts +21 -0
  203. package/es/common/workspaceSymbol.d.ts.map +1 -0
  204. package/es/common/workspaceSymbol.js +101 -0
  205. package/es/constants.d.ts +2 -0
  206. package/es/constants.d.ts.map +1 -0
  207. package/es/constants.js +1 -0
  208. package/es/index.d.ts +6 -0
  209. package/es/index.d.ts.map +1 -0
  210. package/es/index.js +5 -0
  211. package/es/libro-language-client-contribution.d.ts +10 -0
  212. package/es/libro-language-client-contribution.d.ts.map +1 -0
  213. package/es/libro-language-client-contribution.js +143 -0
  214. package/es/libro-language-client-manager.d.ts +34 -0
  215. package/es/libro-language-client-manager.d.ts.map +1 -0
  216. package/es/libro-language-client-manager.js +277 -0
  217. package/es/libro-language-client.d.ts +27 -0
  218. package/es/libro-language-client.d.ts.map +1 -0
  219. package/es/libro-language-client.js +141 -0
  220. package/es/module.d.ts +3 -0
  221. package/es/module.d.ts.map +1 -0
  222. package/es/module.js +13 -0
  223. package/package.json +69 -0
  224. package/src/common/api.ts +155 -0
  225. package/src/common/callHierarchy.ts +269 -0
  226. package/src/common/client.ts +3192 -0
  227. package/src/common/codeAction.ts +237 -0
  228. package/src/common/codeConverter.ts +1409 -0
  229. package/src/common/codeLens.ts +188 -0
  230. package/src/common/colorProvider.ts +192 -0
  231. package/src/common/completion.ts +281 -0
  232. package/src/common/configuration.ts +338 -0
  233. package/src/common/declaration.ts +140 -0
  234. package/src/common/definition.ts +138 -0
  235. package/src/common/diagnostic.ts +1408 -0
  236. package/src/common/documentHighlight.ts +140 -0
  237. package/src/common/documentLink.ts +180 -0
  238. package/src/common/documentSymbol.ts +186 -0
  239. package/src/common/executeCommand.ts +129 -0
  240. package/src/common/features.ts +1157 -0
  241. package/src/common/fileOperations.ts +635 -0
  242. package/src/common/fileSystemWatcher.ts +184 -0
  243. package/src/common/foldingRange.ts +160 -0
  244. package/src/common/formatting.ts +465 -0
  245. package/src/common/hover.ts +133 -0
  246. package/src/common/implementation.ts +142 -0
  247. package/src/common/inlayHint.ts +201 -0
  248. package/src/common/inlineCompletion.ts +160 -0
  249. package/src/common/inlineValue.ts +158 -0
  250. package/src/common/linkedEditingRange.ts +141 -0
  251. package/src/common/notebook.ts +1443 -0
  252. package/src/common/progress.ts +61 -0
  253. package/src/common/progressPart.ts +151 -0
  254. package/src/common/protocolCallHierarchyItem.ts +29 -0
  255. package/src/common/protocolCodeAction.ts +17 -0
  256. package/src/common/protocolCodeLens.ts +15 -0
  257. package/src/common/protocolCompletionItem.ts +22 -0
  258. package/src/common/protocolConverter.ts +2627 -0
  259. package/src/common/protocolDiagnostic.ts +47 -0
  260. package/src/common/protocolDocumentLink.ts +17 -0
  261. package/src/common/protocolInlayHint.ts +21 -0
  262. package/src/common/protocolTypeHierarchyItem.ts +29 -0
  263. package/src/common/protocolWorkspaceSymbol.ts +39 -0
  264. package/src/common/reference.ts +144 -0
  265. package/src/common/rename.ts +230 -0
  266. package/src/common/selectionRange.ts +136 -0
  267. package/src/common/semanticTokens.ts +383 -0
  268. package/src/common/signatureHelp.ts +170 -0
  269. package/src/common/textSynchronization.ts +819 -0
  270. package/src/common/typeDefinition.ts +146 -0
  271. package/src/common/typeHierarchy.ts +248 -0
  272. package/src/common/utils/async.ts +354 -0
  273. package/src/common/utils/is.ts +63 -0
  274. package/src/common/utils/uuid.ts +136 -0
  275. package/src/common/vscodeAdaptor/convertor.ts +73 -0
  276. package/src/common/vscodeAdaptor/diagnosticCollection.ts +238 -0
  277. package/src/common/vscodeAdaptor/extHostTypes.ts +4498 -0
  278. package/src/common/vscodeAdaptor/fileWatcher.ts +36 -0
  279. package/src/common/vscodeAdaptor/hostTypeUtil.ts +539 -0
  280. package/src/common/vscodeAdaptor/libro-fs.ts +51 -0
  281. package/src/common/vscodeAdaptor/libroWindow.ts +85 -0
  282. package/src/common/vscodeAdaptor/libroWorkspace.ts +261 -0
  283. package/src/common/vscodeAdaptor/lspEnv.ts +16 -0
  284. package/src/common/vscodeAdaptor/monaco-converter.ts +1800 -0
  285. package/src/common/vscodeAdaptor/monacoLanguages.ts +511 -0
  286. package/src/common/vscodeAdaptor/services.ts +278 -0
  287. package/src/common/vscodeAdaptor/typings.d.ts +10 -0
  288. package/src/common/vscodeAdaptor/util.ts +7 -0
  289. package/src/common/vscodeAdaptor/vscodeAdaptor.ts +122 -0
  290. package/src/common/workspaceFolder.ts +236 -0
  291. package/src/common/workspaceSymbol.ts +166 -0
  292. package/src/constants.ts +1 -0
  293. package/src/index.spec.ts +7 -0
  294. package/src/index.ts +5 -0
  295. package/src/libro-language-client-contribution.ts +49 -0
  296. package/src/libro-language-client-manager.ts +131 -0
  297. package/src/libro-language-client.ts +100 -0
  298. package/src/module.ts +19 -0
@@ -0,0 +1,3192 @@
1
+ /* eslint-disable @typescript-eslint/no-this-alias */
2
+ /* eslint-disable promise/always-return */
3
+ /* eslint-disable promise/catch-or-return */
4
+ /* --------------------------------------------------------------------------------------------
5
+ * Copyright (c) Microsoft Corporation. All rights reserved.
6
+ * Licensed under the MIT License. See License.txt in the project root for license information.
7
+ * ------------------------------------------------------------------------------------------ */
8
+
9
+ import type {
10
+ Message,
11
+ MessageSignature,
12
+ Logger,
13
+ RequestType0,
14
+ RequestType,
15
+ NotificationType0,
16
+ NotificationType,
17
+ ProtocolRequestType,
18
+ ProtocolRequestType0,
19
+ RequestHandler,
20
+ RequestHandler0,
21
+ GenericRequestHandler,
22
+ ProtocolNotificationType,
23
+ ProtocolNotificationType0,
24
+ NotificationHandler,
25
+ NotificationHandler0,
26
+ GenericNotificationHandler,
27
+ Tracer,
28
+ TraceOptions,
29
+ Event,
30
+ ClientCapabilities,
31
+ WorkspaceEdit,
32
+ RegistrationParams,
33
+ UnregistrationParams,
34
+ InitializeParams,
35
+ InitializeResult,
36
+ ServerCapabilities,
37
+ TextDocumentSyncOptions,
38
+ DocumentSelector,
39
+ FileEvent,
40
+ PublishDiagnosticsParams,
41
+ ApplyWorkspaceEditParams,
42
+ ProgressType,
43
+ ProgressToken,
44
+ ShowDocumentParams,
45
+ ShowDocumentResult,
46
+ Diagnostic,
47
+ ApplyWorkspaceEditResult,
48
+ CancellationStrategy,
49
+ InitializeError,
50
+ WorkDoneProgressBegin,
51
+ WorkDoneProgressReport,
52
+ WorkDoneProgressEnd,
53
+ WillSaveTextDocumentNotification,
54
+ WillSaveTextDocumentWaitUntilRequest,
55
+ DidSaveTextDocumentNotification,
56
+ DidCloseTextDocumentNotification,
57
+ DidCreateFilesNotification,
58
+ DidRenameFilesNotification,
59
+ DidDeleteFilesNotification,
60
+ WillRenameFilesRequest,
61
+ WillCreateFilesRequest,
62
+ WillDeleteFilesRequest,
63
+ CompletionRequest,
64
+ HoverRequest,
65
+ SignatureHelpRequest,
66
+ DefinitionRequest,
67
+ ReferencesRequest,
68
+ DocumentHighlightRequest,
69
+ CodeActionRequest,
70
+ CodeLensRequest,
71
+ DocumentFormattingRequest,
72
+ DocumentRangeFormattingRequest,
73
+ DocumentOnTypeFormattingRequest,
74
+ RenameRequest,
75
+ DocumentSymbolRequest,
76
+ DocumentLinkRequest,
77
+ DocumentColorRequest,
78
+ DeclarationRequest,
79
+ FoldingRangeRequest,
80
+ ImplementationRequest,
81
+ SelectionRangeRequest,
82
+ TypeDefinitionRequest,
83
+ CallHierarchyPrepareRequest,
84
+ SemanticTokensRegistrationType,
85
+ LinkedEditingRangeRequest,
86
+ TypeHierarchyPrepareRequest,
87
+ InlineValueRequest,
88
+ InlayHintRequest,
89
+ WorkspaceSymbolRequest,
90
+ TextDocumentRegistrationOptions,
91
+ FileOperationRegistrationOptions,
92
+ ConnectionOptions,
93
+ DocumentDiagnosticRequest,
94
+ NotebookDocumentSyncRegistrationOptions,
95
+ MessageStrategy,
96
+ DidOpenTextDocumentParams,
97
+ InlineCompletionRequest,
98
+ InlineCompletionRegistrationOptions,
99
+ ExecuteCommandRequest,
100
+ ExecuteCommandOptions,
101
+ HandlerResult,
102
+ } from '@difizen/vscode-languageserver-protocol';
103
+ import {
104
+ RAL,
105
+ ResponseError,
106
+ MessageReader,
107
+ MessageWriter,
108
+ Trace,
109
+ TraceFormat,
110
+ Emitter,
111
+ createProtocolConnection,
112
+ RegistrationRequest,
113
+ UnregistrationRequest,
114
+ InitializeRequest,
115
+ TextDocumentSyncKind,
116
+ InitializedNotification,
117
+ ShutdownRequest,
118
+ ExitNotification,
119
+ LogMessageNotification,
120
+ MessageType,
121
+ ShowMessageNotification,
122
+ ShowMessageRequest,
123
+ TelemetryEventNotification,
124
+ DidChangeTextDocumentNotification,
125
+ DidChangeWatchedFilesNotification,
126
+ PublishDiagnosticsNotification,
127
+ ApplyWorkspaceEditRequest,
128
+ TextDocumentEdit,
129
+ ResourceOperationKind,
130
+ FailureHandlingKind,
131
+ DiagnosticTag,
132
+ LSPErrorCodes,
133
+ ShowDocumentRequest,
134
+ WorkDoneProgress,
135
+ SemanticTokensRequest,
136
+ SemanticTokensRangeRequest,
137
+ SemanticTokensDeltaRequest,
138
+ DidOpenTextDocumentNotification,
139
+ PositionEncodingKind,
140
+ NotebookDocumentSyncRegistrationType,
141
+ ErrorCodes,
142
+ CodeLensResolveRequest,
143
+ CompletionResolveRequest,
144
+ CodeActionResolveRequest,
145
+ InlayHintResolveRequest,
146
+ DocumentLinkResolveRequest,
147
+ WorkspaceSymbolResolveRequest,
148
+ CancellationToken as ProtocolCancellationToken,
149
+ } from '@difizen/vscode-languageserver-protocol';
150
+ import type {
151
+ TextDocument,
152
+ Disposable,
153
+ OutputChannel,
154
+ FileSystemWatcher as VFileSystemWatcher,
155
+ DiagnosticCollection,
156
+ Diagnostic as VDiagnostic,
157
+ CancellationToken,
158
+ WorkspaceEdit as VWorkspaceEdit,
159
+ MessageItem,
160
+ WorkspaceFolder as VWorkspaceFolder,
161
+ TextDocumentShowOptions,
162
+ FileCreateEvent,
163
+ FileRenameEvent,
164
+ FileDeleteEvent,
165
+ FileWillCreateEvent,
166
+ FileWillRenameEvent,
167
+ FileWillDeleteEvent,
168
+ CompletionItemProvider,
169
+ HoverProvider,
170
+ SignatureHelpProvider,
171
+ DefinitionProvider,
172
+ ReferenceProvider,
173
+ DocumentHighlightProvider,
174
+ CodeActionProvider,
175
+ DocumentFormattingEditProvider,
176
+ DocumentRangeFormattingEditProvider,
177
+ OnTypeFormattingEditProvider,
178
+ RenameProvider,
179
+ DocumentSymbolProvider,
180
+ DocumentLinkProvider,
181
+ DeclarationProvider,
182
+ ImplementationProvider,
183
+ DocumentColorProvider,
184
+ SelectionRangeProvider,
185
+ TypeDefinitionProvider,
186
+ CallHierarchyProvider,
187
+ LinkedEditingRangeProvider,
188
+ TypeHierarchyProvider,
189
+ WorkspaceSymbolProvider,
190
+ ProviderResult,
191
+ TextEdit as VTextEdit,
192
+ InlineCompletionItemProvider,
193
+ } from 'vscode';
194
+
195
+ import type { CallHierarchyMiddleware } from './callHierarchy.js';
196
+ import { CallHierarchyFeature } from './callHierarchy.js';
197
+ import type { CodeActionMiddleware } from './codeAction.js';
198
+ import { CodeActionFeature } from './codeAction.js';
199
+ import * as c2p from './codeConverter.js';
200
+ import type { CodeLensMiddleware, CodeLensProviderShape } from './codeLens.js';
201
+ import { CodeLensFeature } from './codeLens.js';
202
+ import { ColorProviderFeature } from './colorProvider.js';
203
+ import type { ColorProviderMiddleware } from './colorProvider.js';
204
+ import { CompletionItemFeature } from './completion.js';
205
+ import type { CompletionMiddleware } from './completion.js';
206
+ import { ConfigurationFeature, SyncConfigurationFeature } from './configuration.js';
207
+ import type {
208
+ ConfigurationMiddleware,
209
+ $ConfigurationOptions,
210
+ DidChangeConfigurationMiddleware,
211
+ SynchronizeOptions,
212
+ } from './configuration.js';
213
+ import type { DeclarationMiddleware } from './declaration.js';
214
+ import { DeclarationFeature } from './declaration.js';
215
+ import { DefinitionFeature } from './definition.js';
216
+ import type { DefinitionMiddleware } from './definition.js';
217
+ import { DiagnosticFeature } from './diagnostic.js';
218
+ import type {
219
+ DiagnosticProviderMiddleware,
220
+ DiagnosticProviderShape,
221
+ $DiagnosticPullOptions,
222
+ } from './diagnostic.js';
223
+ import { DocumentHighlightFeature } from './documentHighlight.js';
224
+ import type { DocumentHighlightMiddleware } from './documentHighlight.js';
225
+ import { DocumentLinkFeature } from './documentLink.js';
226
+ import type { DocumentLinkMiddleware } from './documentLink.js';
227
+ import { DocumentSymbolFeature } from './documentSymbol.js';
228
+ import type { DocumentSymbolMiddleware } from './documentSymbol.js';
229
+ import { ExecuteCommandFeature } from './executeCommand.js';
230
+ import type { ExecuteCommandMiddleware } from './executeCommand.js';
231
+ import { DynamicFeature, ensure, LSPCancellationError } from './features.js';
232
+ import type {
233
+ FeatureClient,
234
+ TextDocumentSendFeature,
235
+ RegistrationData,
236
+ StaticFeature,
237
+ TextDocumentProviderFeature,
238
+ WorkspaceProviderFeature,
239
+ } from './features.js';
240
+ import type { FileOperationsMiddleware } from './fileOperations.js';
241
+ import {
242
+ DidCreateFilesFeature,
243
+ DidDeleteFilesFeature,
244
+ DidRenameFilesFeature,
245
+ WillCreateFilesFeature,
246
+ WillDeleteFilesFeature,
247
+ WillRenameFilesFeature,
248
+ } from './fileOperations.js';
249
+ import { FileSystemWatcherFeature } from './fileSystemWatcher.js';
250
+ import { FoldingRangeFeature } from './foldingRange.js';
251
+ import type {
252
+ FoldingRangeProviderMiddleware,
253
+ FoldingRangeProviderShape,
254
+ } from './foldingRange.js';
255
+ import type { FormattingMiddleware } from './formatting.js';
256
+ import {
257
+ DocumentFormattingFeature,
258
+ DocumentOnTypeFormattingFeature,
259
+ DocumentRangeFormattingFeature,
260
+ } from './formatting.js';
261
+ import { HoverFeature } from './hover.js';
262
+ import type { HoverMiddleware } from './hover.js';
263
+ import { ImplementationFeature } from './implementation.js';
264
+ import type { ImplementationMiddleware } from './implementation.js';
265
+ import { InlayHintsFeature } from './inlayHint.js';
266
+ import type { InlayHintsMiddleware, InlayHintsProviderShape } from './inlayHint.js';
267
+ import { InlineCompletionItemFeature } from './inlineCompletion.js';
268
+ import type { InlineCompletionMiddleware } from './inlineCompletion.js';
269
+ import { InlineValueFeature } from './inlineValue.js';
270
+ import type { InlineValueMiddleware, InlineValueProviderShape } from './inlineValue.js';
271
+ import { LinkedEditingFeature } from './linkedEditingRange.js';
272
+ import type { LinkedEditingRangeMiddleware } from './linkedEditingRange.js';
273
+ import { NotebookDocumentSyncFeature } from './notebook.js';
274
+ import type {
275
+ NotebookDocumentMiddleware,
276
+ $NotebookDocumentOptions,
277
+ NotebookDocumentProviderShape,
278
+ } from './notebook.js';
279
+ import { ProgressFeature } from './progress.js';
280
+ import { ProgressPart } from './progressPart.js';
281
+ import * as p2c from './protocolConverter.js';
282
+ import { ReferencesFeature } from './reference.js';
283
+ import type { ReferencesMiddleware } from './reference.js';
284
+ import { RenameFeature } from './rename.js';
285
+ import type { RenameMiddleware } from './rename.js';
286
+ import type { SelectionRangeProviderMiddleware } from './selectionRange.js';
287
+ import { SelectionRangeFeature } from './selectionRange.js';
288
+ import { SemanticTokensFeature } from './semanticTokens.js';
289
+ import type {
290
+ SemanticTokensMiddleware,
291
+ SemanticTokensProviderShape,
292
+ } from './semanticTokens.js';
293
+ import { SignatureHelpFeature } from './signatureHelp.js';
294
+ import type { SignatureHelpMiddleware } from './signatureHelp.js';
295
+ import {
296
+ DidChangeTextDocumentFeature,
297
+ DidCloseTextDocumentFeature,
298
+ DidOpenTextDocumentFeature,
299
+ DidSaveTextDocumentFeature,
300
+ WillSaveFeature,
301
+ WillSaveWaitUntilFeature,
302
+ } from './textSynchronization.js';
303
+ import type {
304
+ DidChangeTextDocumentFeatureShape,
305
+ DidCloseTextDocumentFeatureShape,
306
+ DidOpenTextDocumentFeatureShape,
307
+ DidSaveTextDocumentFeatureShape,
308
+ ResolvedTextDocumentSyncCapabilities,
309
+ TextDocumentSynchronizationMiddleware,
310
+ } from './textSynchronization.js';
311
+ import { TypeDefinitionFeature } from './typeDefinition.js';
312
+ import type { TypeDefinitionMiddleware } from './typeDefinition.js';
313
+ import { TypeHierarchyFeature } from './typeHierarchy.js';
314
+ import type { TypeHierarchyMiddleware } from './typeHierarchy.js';
315
+ import { Delayer, Semaphore } from './utils/async.js';
316
+ import * as Is from './utils/is.js';
317
+ import * as UUID from './utils/uuid.js';
318
+ import {
319
+ Uri,
320
+ version as VSCodeVersion,
321
+ CancellationError,
322
+ CancellationTokenSource,
323
+ workspace as Workspace,
324
+ window as Window,
325
+ env as Env,
326
+ languages as Languages,
327
+ } from './vscodeAdaptor/vscodeAdaptor.js';
328
+ import { WorkspaceFoldersFeature } from './workspaceFolder.js';
329
+ import type { WorkspaceFolderMiddleware } from './workspaceFolder.js';
330
+ import { WorkspaceSymbolFeature } from './workspaceSymbol.js';
331
+ import type { WorkspaceSymbolMiddleware } from './workspaceSymbol.js';
332
+
333
+ /**
334
+ * Controls when the output channel is revealed.
335
+ */
336
+ export enum RevealOutputChannelOn {
337
+ Debug = 0,
338
+ Info = 1,
339
+ Warn = 2,
340
+ Error = 3,
341
+ Never = 4,
342
+ }
343
+
344
+ /**
345
+ * A handler that is invoked when the initialization of the server failed.
346
+ */
347
+ export type InitializationFailedHandler =
348
+ /**
349
+ * @param error The error returned from the server
350
+ * @returns if true is returned the client tries to reinitialize the server.
351
+ * Implementors of a handler are responsible to not initialize the server
352
+ * infinitely. Return false if initialization should stop and an error
353
+ * should be reported.
354
+ */
355
+ (error: ResponseError<InitializeError> | Error | any) => boolean;
356
+
357
+ /**
358
+ * An action to be performed when the connection is producing errors.
359
+ */
360
+ export enum ErrorAction {
361
+ /**
362
+ * Continue running the server.
363
+ */
364
+ Continue = 1,
365
+
366
+ /**
367
+ * Shutdown the server.
368
+ */
369
+ Shutdown = 2,
370
+ }
371
+
372
+ export type ErrorHandlerResult = {
373
+ /**
374
+ * The action to take.
375
+ */
376
+ action: ErrorAction;
377
+
378
+ /**
379
+ * An optional message to be presented to the user.
380
+ */
381
+ message?: string;
382
+
383
+ /**
384
+ * If set to true the client assumes that the corresponding
385
+ * error handler has presented an appropriate message to the
386
+ * user and the message will only be log to the client's
387
+ * output channel.
388
+ */
389
+ handled?: boolean;
390
+ };
391
+
392
+ /**
393
+ * An action to be performed when the connection to a server got closed.
394
+ */
395
+ export enum CloseAction {
396
+ /**
397
+ * Don't restart the server. The connection stays closed.
398
+ */
399
+ DoNotRestart = 1,
400
+
401
+ /**
402
+ * Restart the server.
403
+ */
404
+ Restart = 2,
405
+ }
406
+
407
+ export type CloseHandlerResult = {
408
+ /**
409
+ * The action to take.
410
+ */
411
+ action: CloseAction;
412
+
413
+ /**
414
+ * An optional message to be presented to the user.
415
+ */
416
+ message?: string;
417
+
418
+ /**
419
+ * If set to true the client assumes that the corresponding
420
+ * close handler has presented an appropriate message to the
421
+ * user and the message will only be log to the client's
422
+ * output channel.
423
+ */
424
+ handled?: boolean;
425
+ };
426
+
427
+ /**
428
+ * A plugable error handler that is invoked when the connection is either
429
+ * producing errors or got closed.
430
+ */
431
+ export interface ErrorHandler {
432
+ /**
433
+ * An error has occurred while writing or reading from the connection.
434
+ *
435
+ * @param error - the error received
436
+ * @param message - the message to be delivered to the server if know.
437
+ * @param count - a count indicating how often an error is received. Will
438
+ * be reset if a message got successfully send or received.
439
+ */
440
+ error(
441
+ error: Error,
442
+ message: Message | undefined,
443
+ count: number | undefined,
444
+ ): ErrorHandlerResult | Promise<ErrorHandlerResult>;
445
+
446
+ /**
447
+ * The connection to the server got closed.
448
+ */
449
+ closed(): CloseHandlerResult | Promise<CloseHandlerResult>;
450
+ }
451
+
452
+ /**
453
+ * Signals in which state the language client is in.
454
+ */
455
+ export enum State {
456
+ /**
457
+ * The client is stopped or got never started.
458
+ */
459
+ Stopped = 1,
460
+ /**
461
+ * The client is starting but not ready yet.
462
+ */
463
+ Starting = 3,
464
+ /**
465
+ * The client is running and ready.
466
+ */
467
+ Running = 2,
468
+ }
469
+
470
+ /**
471
+ * An event signaling a state change.
472
+ */
473
+ export interface StateChangeEvent {
474
+ oldState: State;
475
+ newState: State;
476
+ }
477
+
478
+ export enum SuspendMode {
479
+ /**
480
+ * Don't allow suspend mode.
481
+ */
482
+ off = 'off',
483
+
484
+ /**
485
+ * Support suspend mode even if not all
486
+ * registered providers have a corresponding
487
+ * activation listener.
488
+ */
489
+ on = 'on',
490
+ }
491
+
492
+ export type SuspendOptions = {
493
+ /**
494
+ * Whether suspend mode is supported. If suspend mode is allowed
495
+ * the client will stop a running server when going into suspend mode.
496
+ * If omitted defaults to SuspendMode.off;
497
+ */
498
+ mode?: SuspendMode;
499
+
500
+ /**
501
+ * A callback that is invoked before actually suspending
502
+ * the server. If `false` is returned the client will not continue
503
+ * suspending the server.
504
+ */
505
+ callback?: () => Promise<boolean>;
506
+
507
+ /**
508
+ * The interval in milliseconds used to check if the server
509
+ * can be suspended. If the check passes three times in a row
510
+ * (e.g. the server can be suspended for 3 * interval ms) the
511
+ * server is suspended. Defaults to 60000ms, which is also the
512
+ * minimum allowed value.
513
+ */
514
+ interval?: number;
515
+ };
516
+
517
+ export interface DidChangeWatchedFileSignature {
518
+ (this: void, event: FileEvent): Promise<void>;
519
+ }
520
+
521
+ type _WorkspaceMiddleware = {
522
+ didChangeWatchedFile?: (
523
+ this: void,
524
+ event: FileEvent,
525
+ next: DidChangeWatchedFileSignature,
526
+ ) => Promise<void>;
527
+ handleApplyEdit?: (
528
+ this: void,
529
+ params: ApplyWorkspaceEditParams,
530
+ next: ApplyWorkspaceEditRequest.HandlerSignature,
531
+ ) => HandlerResult<ApplyWorkspaceEditResult, void>;
532
+ };
533
+
534
+ export type WorkspaceMiddleware = _WorkspaceMiddleware &
535
+ ConfigurationMiddleware &
536
+ DidChangeConfigurationMiddleware &
537
+ WorkspaceFolderMiddleware &
538
+ FileOperationsMiddleware;
539
+
540
+ interface _WindowMiddleware {
541
+ showDocument?: (
542
+ this: void,
543
+ params: ShowDocumentParams,
544
+ next: ShowDocumentRequest.HandlerSignature,
545
+ ) => Promise<ShowDocumentResult>;
546
+ }
547
+ export type WindowMiddleware = _WindowMiddleware;
548
+
549
+ export interface HandleDiagnosticsSignature {
550
+ (this: void, uri: Uri, diagnostics: VDiagnostic[]): void;
551
+ }
552
+
553
+ export interface HandleWorkDoneProgressSignature {
554
+ (
555
+ this: void,
556
+ token: ProgressToken,
557
+ params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd,
558
+ ): void;
559
+ }
560
+
561
+ interface _Middleware {
562
+ handleDiagnostics?: (
563
+ this: void,
564
+ uri: Uri,
565
+ diagnostics: VDiagnostic[],
566
+ next: HandleDiagnosticsSignature,
567
+ ) => void;
568
+ handleWorkDoneProgress?: (
569
+ this: void,
570
+ token: ProgressToken,
571
+ params: WorkDoneProgressBegin | WorkDoneProgressReport | WorkDoneProgressEnd,
572
+ next: HandleWorkDoneProgressSignature,
573
+ ) => void;
574
+ handleRegisterCapability?: (
575
+ this: void,
576
+ params: RegistrationParams,
577
+ next: RegistrationRequest.HandlerSignature,
578
+ ) => Promise<void>;
579
+ handleUnregisterCapability?: (
580
+ this: void,
581
+ params: UnregistrationParams,
582
+ next: UnregistrationRequest.HandlerSignature,
583
+ ) => Promise<void>;
584
+ workspace?: WorkspaceMiddleware;
585
+ window?: WindowMiddleware;
586
+ }
587
+
588
+ // A general middleware is applied to both requests and notifications
589
+ interface GeneralMiddleware {
590
+ sendRequest?<P, R>(
591
+ this: void,
592
+ type: string | MessageSignature,
593
+ param: P | undefined,
594
+ token: CancellationToken | undefined,
595
+ next: (
596
+ type: string | MessageSignature,
597
+ param?: P,
598
+ token?: CancellationToken,
599
+ ) => Promise<R>,
600
+ ): Promise<R>;
601
+
602
+ sendNotification?<R>(
603
+ this: void,
604
+ type: string | MessageSignature,
605
+ next: (type: string | MessageSignature, params?: R) => Promise<void>,
606
+ params: R,
607
+ ): Promise<void>;
608
+ }
609
+
610
+ /**
611
+ * The Middleware lets extensions intercept the request and notifications send and received
612
+ * from the server
613
+ */
614
+ export type Middleware = _Middleware &
615
+ TextDocumentSynchronizationMiddleware &
616
+ CompletionMiddleware &
617
+ HoverMiddleware &
618
+ DefinitionMiddleware &
619
+ SignatureHelpMiddleware &
620
+ DocumentHighlightMiddleware &
621
+ DocumentSymbolMiddleware &
622
+ WorkspaceSymbolMiddleware &
623
+ ReferencesMiddleware &
624
+ TypeDefinitionMiddleware &
625
+ ImplementationMiddleware &
626
+ ColorProviderMiddleware &
627
+ CodeActionMiddleware &
628
+ CodeLensMiddleware &
629
+ FormattingMiddleware &
630
+ RenameMiddleware &
631
+ DocumentLinkMiddleware &
632
+ ExecuteCommandMiddleware &
633
+ FoldingRangeProviderMiddleware &
634
+ DeclarationMiddleware &
635
+ SelectionRangeProviderMiddleware &
636
+ CallHierarchyMiddleware &
637
+ SemanticTokensMiddleware &
638
+ LinkedEditingRangeMiddleware &
639
+ TypeHierarchyMiddleware &
640
+ InlineValueMiddleware &
641
+ InlayHintsMiddleware &
642
+ NotebookDocumentMiddleware &
643
+ DiagnosticProviderMiddleware &
644
+ InlineCompletionMiddleware &
645
+ GeneralMiddleware;
646
+
647
+ export type LanguageClientOptions = {
648
+ documentSelector?: DocumentSelector | string[];
649
+ diagnosticCollectionName?: string;
650
+ outputChannel?: OutputChannel;
651
+ outputChannelName?: string;
652
+ traceOutputChannel?: OutputChannel;
653
+ revealOutputChannelOn?: RevealOutputChannelOn;
654
+ /**
655
+ * The encoding use to read stdout and stderr. Defaults
656
+ * to 'utf8' if omitted.
657
+ */
658
+ stdioEncoding?: string;
659
+ initializationOptions?: any | (() => any);
660
+ initializationFailedHandler?: InitializationFailedHandler;
661
+ progressOnInitialization?: boolean;
662
+ errorHandler?: ErrorHandler;
663
+ middleware?: Middleware;
664
+ uriConverters?: {
665
+ code2Protocol: c2p.URIConverter;
666
+ protocol2Code: p2c.URIConverter;
667
+ };
668
+ workspaceFolder?: VWorkspaceFolder;
669
+ connectionOptions?: {
670
+ cancellationStrategy?: CancellationStrategy;
671
+ messageStrategy?: MessageStrategy;
672
+ maxRestartCount?: number;
673
+ };
674
+ markdown?: {
675
+ isTrusted?: boolean | { readonly enabledCommands: readonly string[] };
676
+ supportHtml?: boolean;
677
+ };
678
+ } & $NotebookDocumentOptions &
679
+ $DiagnosticPullOptions &
680
+ $ConfigurationOptions;
681
+
682
+ // type TestOptions = {
683
+ // $testMode?: boolean;
684
+ // };
685
+
686
+ type ResolvedClientOptions = {
687
+ documentSelector?: DocumentSelector;
688
+ synchronize: SynchronizeOptions;
689
+ diagnosticCollectionName?: string;
690
+ outputChannelName: string;
691
+ revealOutputChannelOn: RevealOutputChannelOn;
692
+ stdioEncoding: string;
693
+ initializationOptions?: any | (() => any);
694
+ initializationFailedHandler?: InitializationFailedHandler;
695
+ progressOnInitialization: boolean;
696
+ errorHandler: ErrorHandler;
697
+ middleware: Middleware;
698
+ uriConverters?: {
699
+ code2Protocol: c2p.URIConverter;
700
+ protocol2Code: p2c.URIConverter;
701
+ };
702
+ workspaceFolder?: VWorkspaceFolder;
703
+ connectionOptions?: {
704
+ cancellationStrategy?: CancellationStrategy;
705
+ messageStrategy?: MessageStrategy;
706
+ maxRestartCount?: number;
707
+ };
708
+ markdown: {
709
+ isTrusted: boolean | { readonly enabledCommands: readonly string[] };
710
+ supportHtml: boolean;
711
+ };
712
+ } & Required<$NotebookDocumentOptions> &
713
+ Required<$DiagnosticPullOptions>;
714
+ namespace ResolvedClientOptions {
715
+ export function sanitizeIsTrusted(
716
+ isTrusted?: boolean | { readonly enabledCommands: readonly string[] },
717
+ ): boolean | { readonly enabledCommands: readonly string[] } {
718
+ if (isTrusted === undefined || isTrusted === null) {
719
+ return false;
720
+ }
721
+ if (
722
+ typeof isTrusted === 'boolean' ||
723
+ (typeof isTrusted === 'object' &&
724
+ isTrusted !== null &&
725
+ Is.stringArray(isTrusted.enabledCommands))
726
+ ) {
727
+ return isTrusted;
728
+ }
729
+ return false;
730
+ }
731
+ }
732
+
733
+ class DefaultErrorHandler implements ErrorHandler {
734
+ private readonly restarts: number[];
735
+
736
+ constructor(
737
+ private client: BaseLanguageClient,
738
+ private maxRestartCount: number,
739
+ ) {
740
+ this.restarts = [];
741
+ }
742
+
743
+ public error(_error: Error, _message: Message, count: number): ErrorHandlerResult {
744
+ if (count && count <= 3) {
745
+ return { action: ErrorAction.Continue };
746
+ }
747
+ return { action: ErrorAction.Shutdown };
748
+ }
749
+
750
+ public closed(): CloseHandlerResult {
751
+ this.restarts.push(Date.now());
752
+ if (this.restarts.length <= this.maxRestartCount) {
753
+ return { action: CloseAction.Restart };
754
+ } else {
755
+ const diff = this.restarts[this.restarts.length - 1] - this.restarts[0];
756
+ if (diff <= 3 * 60 * 1000) {
757
+ return {
758
+ action: CloseAction.DoNotRestart,
759
+ message: `The ${this.client.name} server crashed ${
760
+ this.maxRestartCount + 1
761
+ } times in the last 3 minutes. The server will not be restarted. See the output for more information.`,
762
+ };
763
+ } else {
764
+ this.restarts.shift();
765
+ return { action: CloseAction.Restart };
766
+ }
767
+ }
768
+ }
769
+ }
770
+
771
+ enum ClientState {
772
+ Initial = 'initial',
773
+ Starting = 'starting',
774
+ StartFailed = 'startFailed',
775
+ Running = 'running',
776
+ Stopping = 'stopping',
777
+ Stopped = 'stopped',
778
+ }
779
+
780
+ export interface MessageTransports {
781
+ reader: MessageReader;
782
+ writer: MessageWriter;
783
+ detached?: boolean;
784
+ }
785
+
786
+ export namespace MessageTransports {
787
+ export function is(value: any): value is MessageTransports {
788
+ const candidate: MessageTransports = value;
789
+ return (
790
+ candidate && MessageReader.is(value.reader) && MessageWriter.is(value.writer)
791
+ );
792
+ }
793
+ }
794
+
795
+ export abstract class BaseLanguageClient
796
+ implements FeatureClient<Middleware, LanguageClientOptions>
797
+ {
798
+ private _id: string;
799
+ private _name: string;
800
+ private _clientOptions: ResolvedClientOptions;
801
+
802
+ private _state: ClientState;
803
+ private _onStart: Promise<void> | undefined;
804
+ private _onStop: Promise<void> | undefined;
805
+ private _connection: Connection | undefined;
806
+ private _idleInterval: Disposable | undefined;
807
+ private readonly _ignoredRegistrations: Set<string>;
808
+ // private _idleStart: number | undefined;
809
+ private readonly _listeners: Disposable[];
810
+ private _disposed: 'disposing' | 'disposed' | undefined;
811
+
812
+ private readonly _notificationHandlers: Map<string, GenericNotificationHandler>;
813
+ private readonly _notificationDisposables: Map<string, Disposable>;
814
+ private readonly _pendingNotificationHandlers: Map<
815
+ string,
816
+ GenericNotificationHandler
817
+ >;
818
+ private readonly _requestHandlers: Map<
819
+ string,
820
+ GenericRequestHandler<unknown, unknown>
821
+ >;
822
+ private readonly _requestDisposables: Map<string, Disposable>;
823
+ private readonly _pendingRequestHandlers: Map<
824
+ string,
825
+ GenericRequestHandler<unknown, unknown>
826
+ >;
827
+ private readonly _progressHandlers: Map<
828
+ string | number,
829
+ { type: ProgressType<any>; handler: NotificationHandler<any> }
830
+ >;
831
+ private readonly _pendingProgressHandlers: Map<
832
+ string | number,
833
+ { type: ProgressType<any>; handler: NotificationHandler<any> }
834
+ >;
835
+ private readonly _progressDisposables: Map<string | number, Disposable>;
836
+
837
+ private _initializeResult: InitializeResult | undefined;
838
+ private _outputChannel: OutputChannel | undefined;
839
+ private _disposeOutputChannel: boolean;
840
+ private _traceOutputChannel: OutputChannel | undefined;
841
+ private _capabilities!: ServerCapabilities & ResolvedTextDocumentSyncCapabilities;
842
+
843
+ private _diagnostics: DiagnosticCollection | undefined;
844
+ private _syncedDocuments: Map<string, TextDocument>;
845
+
846
+ private _didChangeTextDocumentFeature: DidChangeTextDocumentFeature | undefined;
847
+ private readonly _pendingOpenNotifications: Set<string>;
848
+ private readonly _pendingChangeSemaphore: Semaphore<void>;
849
+ private readonly _pendingChangeDelayer: Delayer<void>;
850
+
851
+ private _fileEvents: FileEvent[];
852
+ private _fileEventDelayer: Delayer<void>;
853
+
854
+ private _telemetryEmitter: Emitter<any>;
855
+ private _stateChangeEmitter: Emitter<StateChangeEvent>;
856
+
857
+ private _trace: Trace;
858
+ private _traceFormat: TraceFormat = TraceFormat.Text;
859
+ private _tracer: Tracer;
860
+
861
+ private readonly _c2p: c2p.Converter;
862
+ private readonly _p2c: p2c.Converter;
863
+
864
+ public constructor(id: string, name: string, clientOptions: LanguageClientOptions) {
865
+ this._id = id;
866
+ this._name = name;
867
+
868
+ clientOptions = clientOptions || {};
869
+
870
+ const markdown: ResolvedClientOptions['markdown'] = {
871
+ isTrusted: false,
872
+ supportHtml: false,
873
+ };
874
+ if (clientOptions.markdown !== undefined) {
875
+ markdown.isTrusted = ResolvedClientOptions.sanitizeIsTrusted(
876
+ clientOptions.markdown.isTrusted,
877
+ );
878
+ markdown.supportHtml = clientOptions.markdown.supportHtml === true;
879
+ }
880
+
881
+ // const defaultInterval = (clientOptions as TestOptions).$testMode ? 50 : 60000;
882
+
883
+ this._clientOptions = {
884
+ documentSelector: clientOptions.documentSelector ?? [],
885
+ synchronize: clientOptions.synchronize ?? {},
886
+ diagnosticCollectionName: clientOptions.diagnosticCollectionName,
887
+ outputChannelName: clientOptions.outputChannelName ?? this._name,
888
+ revealOutputChannelOn:
889
+ clientOptions.revealOutputChannelOn ?? RevealOutputChannelOn.Error,
890
+ stdioEncoding: clientOptions.stdioEncoding ?? 'utf8',
891
+ initializationOptions: clientOptions.initializationOptions,
892
+ initializationFailedHandler: clientOptions.initializationFailedHandler,
893
+ progressOnInitialization: !!clientOptions.progressOnInitialization,
894
+ errorHandler:
895
+ clientOptions.errorHandler ??
896
+ this.createDefaultErrorHandler(
897
+ clientOptions.connectionOptions?.maxRestartCount,
898
+ ),
899
+ middleware: clientOptions.middleware ?? {},
900
+ uriConverters: clientOptions.uriConverters,
901
+ workspaceFolder: clientOptions.workspaceFolder,
902
+ connectionOptions: clientOptions.connectionOptions,
903
+ markdown,
904
+ // suspend: {
905
+ // mode: clientOptions.suspend?.mode ?? SuspendMode.off,
906
+ // callback: clientOptions.suspend?.callback ?? (() => Promise.resolve(true)),
907
+ // interval: clientOptions.suspend?.interval ? Math.max(clientOptions.suspend.interval, defaultInterval) : defaultInterval
908
+ // },
909
+ diagnosticPullOptions: clientOptions.diagnosticPullOptions ?? {
910
+ onChange: true,
911
+ onSave: false,
912
+ },
913
+ notebookDocumentOptions: clientOptions.notebookDocumentOptions ?? {},
914
+ };
915
+ this._clientOptions.synchronize = this._clientOptions.synchronize || {};
916
+
917
+ this._state = ClientState.Initial;
918
+ this._ignoredRegistrations = new Set();
919
+ this._listeners = [];
920
+
921
+ this._notificationHandlers = new Map();
922
+ this._pendingNotificationHandlers = new Map();
923
+ this._notificationDisposables = new Map();
924
+ this._requestHandlers = new Map();
925
+ this._pendingRequestHandlers = new Map();
926
+ this._requestDisposables = new Map();
927
+ this._progressHandlers = new Map();
928
+ this._pendingProgressHandlers = new Map();
929
+ this._progressDisposables = new Map();
930
+
931
+ this._connection = undefined;
932
+ // this._idleStart = undefined;
933
+ this._initializeResult = undefined;
934
+ if (clientOptions.outputChannel) {
935
+ this._outputChannel = clientOptions.outputChannel;
936
+ this._disposeOutputChannel = false;
937
+ } else {
938
+ this._outputChannel = undefined;
939
+ this._disposeOutputChannel = true;
940
+ }
941
+ this._traceOutputChannel = clientOptions.traceOutputChannel;
942
+ this._diagnostics = undefined;
943
+
944
+ this._pendingOpenNotifications = new Set();
945
+ this._pendingChangeSemaphore = new Semaphore(1);
946
+ this._pendingChangeDelayer = new Delayer<void>(250);
947
+
948
+ this._fileEvents = [];
949
+ this._fileEventDelayer = new Delayer<void>(250);
950
+ this._onStop = undefined;
951
+ this._telemetryEmitter = new Emitter<any>();
952
+ this._stateChangeEmitter = new Emitter<StateChangeEvent>();
953
+ this._trace = Trace.Off;
954
+ this._tracer = {
955
+ log: (messageOrDataObject: string | any, data?: string) => {
956
+ if (Is.string(messageOrDataObject)) {
957
+ this.logTrace(messageOrDataObject, data);
958
+ } else {
959
+ this.logObjectTrace(messageOrDataObject);
960
+ }
961
+ },
962
+ };
963
+ this._c2p = c2p.createConverter(
964
+ clientOptions.uriConverters
965
+ ? clientOptions.uriConverters.code2Protocol
966
+ : undefined,
967
+ );
968
+ this._p2c = p2c.createConverter(
969
+ clientOptions.uriConverters
970
+ ? clientOptions.uriConverters.protocol2Code
971
+ : undefined,
972
+ this._clientOptions.markdown.isTrusted,
973
+ this._clientOptions.markdown.supportHtml,
974
+ );
975
+ this._syncedDocuments = new Map<string, TextDocument>();
976
+ this.registerBuiltinFeatures();
977
+ }
978
+
979
+ public get name(): string {
980
+ return this._name;
981
+ }
982
+
983
+ public get middleware(): Middleware {
984
+ return this._clientOptions.middleware ?? Object.create(null);
985
+ }
986
+
987
+ public get clientOptions(): LanguageClientOptions {
988
+ return this._clientOptions;
989
+ }
990
+
991
+ public get protocol2CodeConverter(): p2c.Converter {
992
+ return this._p2c;
993
+ }
994
+
995
+ public get code2ProtocolConverter(): c2p.Converter {
996
+ return this._c2p;
997
+ }
998
+
999
+ public get onTelemetry(): Event<any> {
1000
+ return this._telemetryEmitter.event;
1001
+ }
1002
+
1003
+ public get onDidChangeState(): Event<StateChangeEvent> {
1004
+ return this._stateChangeEmitter.event;
1005
+ }
1006
+
1007
+ public get outputChannel(): OutputChannel {
1008
+ if (!this._outputChannel) {
1009
+ this._outputChannel = Window.createOutputChannel(
1010
+ this._clientOptions.outputChannelName
1011
+ ? this._clientOptions.outputChannelName
1012
+ : this._name,
1013
+ );
1014
+ }
1015
+ return this._outputChannel;
1016
+ }
1017
+
1018
+ public get traceOutputChannel(): OutputChannel {
1019
+ if (this._traceOutputChannel) {
1020
+ return this._traceOutputChannel;
1021
+ }
1022
+ return this.outputChannel;
1023
+ }
1024
+
1025
+ public get diagnostics(): DiagnosticCollection | undefined {
1026
+ return this._diagnostics;
1027
+ }
1028
+
1029
+ public get state(): State {
1030
+ return this.getPublicState();
1031
+ }
1032
+
1033
+ private get $state(): ClientState {
1034
+ return this._state;
1035
+ }
1036
+
1037
+ private set $state(value: ClientState) {
1038
+ const oldState = this.getPublicState();
1039
+ this._state = value;
1040
+ const newState = this.getPublicState();
1041
+ if (newState !== oldState) {
1042
+ this._stateChangeEmitter.fire({ oldState, newState });
1043
+ }
1044
+ }
1045
+
1046
+ private getPublicState(): State {
1047
+ switch (this.$state) {
1048
+ case ClientState.Starting:
1049
+ return State.Starting;
1050
+ case ClientState.Running:
1051
+ return State.Running;
1052
+ default:
1053
+ return State.Stopped;
1054
+ }
1055
+ }
1056
+
1057
+ public get initializeResult(): InitializeResult | undefined {
1058
+ return this._initializeResult;
1059
+ }
1060
+
1061
+ public sendRequest<R, PR, E, RO>(
1062
+ type: ProtocolRequestType0<R, PR, E, RO>,
1063
+ token?: CancellationToken,
1064
+ ): Promise<R>;
1065
+ public sendRequest<P, R, PR, E, RO>(
1066
+ type: ProtocolRequestType<P, R, PR, E, RO>,
1067
+ params: P,
1068
+ token?: CancellationToken,
1069
+ ): Promise<R>;
1070
+ public sendRequest<R, E>(
1071
+ type: RequestType0<R, E>,
1072
+ token?: CancellationToken,
1073
+ ): Promise<R>;
1074
+ public sendRequest<P, R, E>(
1075
+ type: RequestType<P, R, E>,
1076
+ params: P,
1077
+ token?: CancellationToken,
1078
+ ): Promise<R>;
1079
+ public sendRequest<R>(method: string, token?: CancellationToken): Promise<R>;
1080
+ public sendRequest<R>(
1081
+ method: string,
1082
+ param: any,
1083
+ token?: CancellationToken,
1084
+ ): Promise<R>;
1085
+ public async sendRequest<R>(
1086
+ type: string | MessageSignature,
1087
+ ...params: any[]
1088
+ ): Promise<R> {
1089
+ if (
1090
+ this.$state === ClientState.StartFailed ||
1091
+ this.$state === ClientState.Stopping ||
1092
+ this.$state === ClientState.Stopped
1093
+ ) {
1094
+ return Promise.reject(
1095
+ new ResponseError(ErrorCodes.ConnectionInactive, `Client is not running`),
1096
+ );
1097
+ }
1098
+
1099
+ // Ensure we have a connection before we force the document sync.
1100
+ const connection = await this.$start();
1101
+ // If any document is synced in full mode make sure we flush any pending
1102
+ // full document syncs.
1103
+ if (this._didChangeTextDocumentFeature!.syncKind === TextDocumentSyncKind.Full) {
1104
+ await this.sendPendingFullTextDocumentChanges(connection);
1105
+ }
1106
+
1107
+ let param: any | undefined = undefined;
1108
+ let token: CancellationToken | undefined = undefined;
1109
+ // Separate cancellation tokens from other parameters for a better client interface
1110
+ if (params.length === 1) {
1111
+ // CancellationToken is an interface, so we need to check if the first param complies to it
1112
+ if (ProtocolCancellationToken.is(params[0])) {
1113
+ token = params[0];
1114
+ } else {
1115
+ param = params[0];
1116
+ }
1117
+ } else if (params.length === 2) {
1118
+ param = params[0];
1119
+ token = params[1];
1120
+ }
1121
+ if (token !== undefined && token.isCancellationRequested) {
1122
+ return Promise.reject(
1123
+ new ResponseError(LSPErrorCodes.RequestCancelled, 'Request got cancelled'),
1124
+ );
1125
+ }
1126
+ const _sendRequest = this._clientOptions.middleware?.sendRequest;
1127
+ if (_sendRequest !== undefined) {
1128
+ // Return the general middleware invocation defining `next` as a utility function that reorganizes parameters to
1129
+ // pass them to the original sendRequest function.
1130
+ return _sendRequest(type, param, token, (type, param, token) => {
1131
+ const params: any[] = [];
1132
+
1133
+ // Add the parameters if there are any
1134
+ if (param !== undefined) {
1135
+ params.push(param);
1136
+ }
1137
+
1138
+ // Add the cancellation token if there is one
1139
+ if (token !== undefined) {
1140
+ params.push(token);
1141
+ }
1142
+
1143
+ return connection.sendRequest<R>(type, ...params);
1144
+ });
1145
+ } else {
1146
+ return connection.sendRequest<R>(type, ...params);
1147
+ }
1148
+ }
1149
+
1150
+ public onRequest<R, PR, E, RO>(
1151
+ type: ProtocolRequestType0<R, PR, E, RO>,
1152
+ handler: RequestHandler0<R, E>,
1153
+ ): Disposable;
1154
+ public onRequest<P, R, PR, E, RO>(
1155
+ type: ProtocolRequestType<P, R, PR, E, RO>,
1156
+ handler: RequestHandler<P, R, E>,
1157
+ ): Disposable;
1158
+ public onRequest<R, E>(
1159
+ type: RequestType0<R, E>,
1160
+ handler: RequestHandler0<R, E>,
1161
+ ): Disposable;
1162
+ public onRequest<P, R, E>(
1163
+ type: RequestType<P, R, E>,
1164
+ handler: RequestHandler<P, R, E>,
1165
+ ): Disposable;
1166
+ public onRequest<R, E>(
1167
+ method: string,
1168
+ handler: GenericRequestHandler<R, E>,
1169
+ ): Disposable;
1170
+ public onRequest<R, E>(
1171
+ type: string | MessageSignature,
1172
+ handler: GenericRequestHandler<R, E>,
1173
+ ): Disposable {
1174
+ const method = typeof type === 'string' ? type : type.method;
1175
+ this._requestHandlers.set(method, handler);
1176
+ const connection = this.activeConnection();
1177
+ let disposable: Disposable;
1178
+ if (connection !== undefined) {
1179
+ this._requestDisposables.set(method, connection.onRequest(type, handler));
1180
+ disposable = {
1181
+ dispose: () => {
1182
+ const disposable = this._requestDisposables.get(method);
1183
+ if (disposable !== undefined) {
1184
+ disposable.dispose();
1185
+ this._requestDisposables.delete(method);
1186
+ }
1187
+ },
1188
+ };
1189
+ } else {
1190
+ this._pendingRequestHandlers.set(method, handler);
1191
+ disposable = {
1192
+ dispose: () => {
1193
+ this._pendingRequestHandlers.delete(method);
1194
+ const disposable = this._requestDisposables.get(method);
1195
+ if (disposable !== undefined) {
1196
+ disposable.dispose();
1197
+ this._requestDisposables.delete(method);
1198
+ }
1199
+ },
1200
+ };
1201
+ }
1202
+ return {
1203
+ dispose: () => {
1204
+ this._requestHandlers.delete(method);
1205
+ disposable.dispose();
1206
+ },
1207
+ };
1208
+ }
1209
+
1210
+ public sendNotification<RO>(type: ProtocolNotificationType0<RO>): Promise<void>;
1211
+ public sendNotification<P, RO>(
1212
+ type: ProtocolNotificationType<P, RO>,
1213
+ params?: P,
1214
+ ): Promise<void>;
1215
+ public sendNotification(type: NotificationType0): Promise<void>;
1216
+ public sendNotification<P>(type: NotificationType<P>, params?: P): Promise<void>;
1217
+ public sendNotification(method: string): Promise<void>;
1218
+ public sendNotification(method: string, params: any): Promise<void>;
1219
+ public async sendNotification<P>(
1220
+ type: string | MessageSignature,
1221
+ params?: P,
1222
+ ): Promise<void> {
1223
+ if (
1224
+ this.$state === ClientState.StartFailed ||
1225
+ this.$state === ClientState.Stopping ||
1226
+ this.$state === ClientState.Stopped
1227
+ ) {
1228
+ return Promise.reject(
1229
+ new ResponseError(ErrorCodes.ConnectionInactive, `Client is not running`),
1230
+ );
1231
+ }
1232
+
1233
+ const needsPendingFullTextDocumentSync: boolean =
1234
+ this._didChangeTextDocumentFeature!.syncKind === TextDocumentSyncKind.Full;
1235
+ let openNotification: string | undefined;
1236
+ if (
1237
+ needsPendingFullTextDocumentSync &&
1238
+ typeof type !== 'string' &&
1239
+ type.method === DidOpenTextDocumentNotification.method
1240
+ ) {
1241
+ openNotification = (params as DidOpenTextDocumentParams)?.textDocument.uri;
1242
+ this._pendingOpenNotifications.add(openNotification);
1243
+ }
1244
+ // Ensure we have a connection before we force the document sync.
1245
+ const connection = await this.$start();
1246
+ // If any document is synced in full mode make sure we flush any pending
1247
+ // full document syncs.
1248
+ if (needsPendingFullTextDocumentSync) {
1249
+ await this.sendPendingFullTextDocumentChanges(connection);
1250
+ }
1251
+ // We need to remove the pending open notification before we actually
1252
+ // send the notification over the connection. Otherwise there could be
1253
+ // a request coming in that although the open notification got already put
1254
+ // onto the wire will ignore pending document changes.
1255
+ //
1256
+ // Since the code path of connection.sendNotification is actually sync
1257
+ // until the message is handed of to the writer and the writer as a semaphore
1258
+ // lock with a capacity of 1 no additional async scheduling can happen until
1259
+ // the message is actually handed of.
1260
+ if (openNotification !== undefined) {
1261
+ this._pendingOpenNotifications.delete(openNotification);
1262
+ }
1263
+
1264
+ const _sendNotification = this._clientOptions.middleware?.sendNotification;
1265
+
1266
+ return _sendNotification
1267
+ ? _sendNotification(type, connection.sendNotification.bind(connection), params)
1268
+ : connection.sendNotification(type, params);
1269
+ }
1270
+
1271
+ public onNotification<RO>(
1272
+ type: ProtocolNotificationType0<RO>,
1273
+ handler: NotificationHandler0,
1274
+ ): Disposable;
1275
+ public onNotification<P, RO>(
1276
+ type: ProtocolNotificationType<P, RO>,
1277
+ handler: NotificationHandler<P>,
1278
+ ): Disposable;
1279
+ public onNotification(
1280
+ type: NotificationType0,
1281
+ handler: NotificationHandler0,
1282
+ ): Disposable;
1283
+ public onNotification<P>(
1284
+ type: NotificationType<P>,
1285
+ handler: NotificationHandler<P>,
1286
+ ): Disposable;
1287
+ public onNotification(
1288
+ method: string,
1289
+ handler: GenericNotificationHandler,
1290
+ ): Disposable;
1291
+ public onNotification(
1292
+ type: string | MessageSignature,
1293
+ handler: GenericNotificationHandler,
1294
+ ): Disposable {
1295
+ const method = typeof type === 'string' ? type : type.method;
1296
+ this._notificationHandlers.set(method, handler);
1297
+ const connection = this.activeConnection();
1298
+ let disposable: Disposable;
1299
+ if (connection !== undefined) {
1300
+ this._notificationDisposables.set(
1301
+ method,
1302
+ connection.onNotification(type, handler),
1303
+ );
1304
+ disposable = {
1305
+ dispose: () => {
1306
+ const disposable = this._notificationDisposables.get(method);
1307
+ if (disposable !== undefined) {
1308
+ disposable.dispose();
1309
+ this._notificationDisposables.delete(method);
1310
+ }
1311
+ },
1312
+ };
1313
+ } else {
1314
+ this._pendingNotificationHandlers.set(method, handler);
1315
+ disposable = {
1316
+ dispose: () => {
1317
+ this._pendingNotificationHandlers.delete(method);
1318
+ const disposable = this._notificationDisposables.get(method);
1319
+ if (disposable !== undefined) {
1320
+ disposable.dispose();
1321
+ this._notificationDisposables.delete(method);
1322
+ }
1323
+ },
1324
+ };
1325
+ }
1326
+ return {
1327
+ dispose: () => {
1328
+ this._notificationHandlers.delete(method);
1329
+ disposable.dispose();
1330
+ },
1331
+ };
1332
+ }
1333
+
1334
+ public async sendProgress<P>(
1335
+ type: ProgressType<P>,
1336
+ token: string | number,
1337
+ value: P,
1338
+ ): Promise<void> {
1339
+ if (
1340
+ this.$state === ClientState.StartFailed ||
1341
+ this.$state === ClientState.Stopping ||
1342
+ this.$state === ClientState.Stopped
1343
+ ) {
1344
+ return Promise.reject(
1345
+ new ResponseError(ErrorCodes.ConnectionInactive, `Client is not running`),
1346
+ );
1347
+ }
1348
+ try {
1349
+ // Ensure we have a connection before we force the document sync.
1350
+ const connection = await this.$start();
1351
+ return connection.sendProgress(type, token, value);
1352
+ } catch (error) {
1353
+ this.error(`Sending progress for token ${token} failed.`, error);
1354
+ throw error;
1355
+ }
1356
+ }
1357
+
1358
+ public onProgress<P>(
1359
+ type: ProgressType<P>,
1360
+ token: string | number,
1361
+ handler: NotificationHandler<P>,
1362
+ ): Disposable {
1363
+ this._progressHandlers.set(token, { type, handler });
1364
+ const connection = this.activeConnection();
1365
+ let disposable: Disposable;
1366
+ const handleWorkDoneProgress =
1367
+ this._clientOptions.middleware?.handleWorkDoneProgress;
1368
+ const realHandler =
1369
+ WorkDoneProgress.is(type) && handleWorkDoneProgress !== undefined
1370
+ ? (params: P) => {
1371
+ handleWorkDoneProgress(token, params as any, () =>
1372
+ handler(params as unknown as P),
1373
+ );
1374
+ }
1375
+ : handler;
1376
+ if (connection !== undefined) {
1377
+ this._progressDisposables.set(
1378
+ token,
1379
+ connection.onProgress(type, token, realHandler),
1380
+ );
1381
+ disposable = {
1382
+ dispose: () => {
1383
+ const disposable = this._progressDisposables.get(token);
1384
+ if (disposable !== undefined) {
1385
+ disposable.dispose();
1386
+ this._progressDisposables.delete(token);
1387
+ }
1388
+ },
1389
+ };
1390
+ } else {
1391
+ this._pendingProgressHandlers.set(token, { type, handler });
1392
+ disposable = {
1393
+ dispose: () => {
1394
+ this._pendingProgressHandlers.delete(token);
1395
+ const disposable = this._progressDisposables.get(token);
1396
+ if (disposable !== undefined) {
1397
+ disposable.dispose();
1398
+ this._progressDisposables.delete(token);
1399
+ }
1400
+ },
1401
+ };
1402
+ }
1403
+ return {
1404
+ dispose: (): void => {
1405
+ this._progressHandlers.delete(token);
1406
+ disposable.dispose();
1407
+ },
1408
+ };
1409
+ }
1410
+
1411
+ public createDefaultErrorHandler(maxRestartCount?: number): ErrorHandler {
1412
+ if (maxRestartCount !== undefined && maxRestartCount < 0) {
1413
+ throw new Error(`Invalid maxRestartCount: ${maxRestartCount}`);
1414
+ }
1415
+ return new DefaultErrorHandler(this, maxRestartCount ?? 4);
1416
+ }
1417
+
1418
+ public async setTrace(value: Trace): Promise<void> {
1419
+ this._trace = value;
1420
+ const connection = this.activeConnection();
1421
+ if (connection !== undefined) {
1422
+ await connection.trace(this._trace, this._tracer, {
1423
+ sendNotification: false,
1424
+ traceFormat: this._traceFormat,
1425
+ });
1426
+ }
1427
+ }
1428
+
1429
+ private data2String(data: NonNullable<unknown>): string {
1430
+ if (data instanceof ResponseError) {
1431
+ const responseError = data as ResponseError<any>;
1432
+ return ` Message: ${responseError.message}\n Code: ${responseError.code} ${
1433
+ responseError.data ? '\n' + responseError.data.toString() : ''
1434
+ }`;
1435
+ }
1436
+ if (data instanceof Error) {
1437
+ if (Is.string(data.stack)) {
1438
+ return data.stack;
1439
+ }
1440
+ return (data as Error).message;
1441
+ }
1442
+ if (Is.string(data)) {
1443
+ return data;
1444
+ }
1445
+ return data.toString();
1446
+ }
1447
+
1448
+ public debug(message: string, data?: any, showNotification = true): void {
1449
+ this.logOutputMessage(
1450
+ MessageType.Debug,
1451
+ RevealOutputChannelOn.Debug,
1452
+ 'Debug',
1453
+ message,
1454
+ data,
1455
+ showNotification,
1456
+ );
1457
+ }
1458
+
1459
+ public info(message: string, data?: any, showNotification = true): void {
1460
+ this.logOutputMessage(
1461
+ MessageType.Info,
1462
+ RevealOutputChannelOn.Info,
1463
+ 'Info',
1464
+ message,
1465
+ data,
1466
+ showNotification,
1467
+ );
1468
+ }
1469
+
1470
+ public warn(message: string, data?: any, showNotification = true): void {
1471
+ this.logOutputMessage(
1472
+ MessageType.Warning,
1473
+ RevealOutputChannelOn.Warn,
1474
+ 'Warn',
1475
+ message,
1476
+ data,
1477
+ showNotification,
1478
+ );
1479
+ }
1480
+
1481
+ public error(
1482
+ message: string,
1483
+ data?: any,
1484
+ showNotification: boolean | 'force' = true,
1485
+ ): void {
1486
+ this.logOutputMessage(
1487
+ MessageType.Error,
1488
+ RevealOutputChannelOn.Error,
1489
+ 'Error',
1490
+ message,
1491
+ data,
1492
+ showNotification,
1493
+ );
1494
+ }
1495
+
1496
+ private logOutputMessage(
1497
+ type: MessageType,
1498
+ reveal: RevealOutputChannelOn,
1499
+ name: string,
1500
+ message: string,
1501
+ data: any | undefined,
1502
+ showNotification: boolean | 'force',
1503
+ ): void {
1504
+ this.outputChannel.appendLine(
1505
+ `[${name.padEnd(5)} - ${new Date().toLocaleTimeString()}] ${message}`,
1506
+ );
1507
+ if (data !== null && data !== undefined) {
1508
+ this.outputChannel.appendLine(this.data2String(data));
1509
+ }
1510
+ if (
1511
+ showNotification === 'force' ||
1512
+ (showNotification && this._clientOptions.revealOutputChannelOn <= reveal)
1513
+ ) {
1514
+ this.showNotificationMessage(type, message);
1515
+ }
1516
+ }
1517
+
1518
+ private showNotificationMessage(type: MessageType, message?: string) {
1519
+ message = message ?? 'A request has failed. See the output for more information.';
1520
+ const messageFunc =
1521
+ type === MessageType.Error
1522
+ ? Window.showErrorMessage
1523
+ : type === MessageType.Warning
1524
+ ? Window.showWarningMessage
1525
+ : Window.showInformationMessage;
1526
+ void messageFunc(message, 'Go to output').then((selection) => {
1527
+ if (selection !== undefined) {
1528
+ this.outputChannel.show(true);
1529
+ }
1530
+ });
1531
+ }
1532
+
1533
+ private logTrace(message: string, data?: any): void {
1534
+ this.traceOutputChannel.appendLine(
1535
+ `[Trace - ${new Date().toLocaleTimeString()}] ${message}`,
1536
+ );
1537
+ if (data) {
1538
+ this.traceOutputChannel.appendLine(this.data2String(data));
1539
+ }
1540
+ }
1541
+
1542
+ private logObjectTrace(data: any): void {
1543
+ if (data.isLSPMessage && data.type) {
1544
+ this.traceOutputChannel.append(`[LSP - ${new Date().toLocaleTimeString()}] `);
1545
+ } else {
1546
+ this.traceOutputChannel.append(`[Trace - ${new Date().toLocaleTimeString()}] `);
1547
+ }
1548
+ if (data) {
1549
+ this.traceOutputChannel.appendLine(`${JSON.stringify(data)}`);
1550
+ }
1551
+ }
1552
+
1553
+ public needsStart(): boolean {
1554
+ return (
1555
+ this.$state === ClientState.Initial ||
1556
+ this.$state === ClientState.Stopping ||
1557
+ this.$state === ClientState.Stopped
1558
+ );
1559
+ }
1560
+
1561
+ public needsStop(): boolean {
1562
+ return this.$state === ClientState.Starting || this.$state === ClientState.Running;
1563
+ }
1564
+
1565
+ private activeConnection(): Connection | undefined {
1566
+ return this.$state === ClientState.Running && this._connection !== undefined
1567
+ ? this._connection
1568
+ : undefined;
1569
+ }
1570
+
1571
+ public isRunning(): boolean {
1572
+ return this.$state === ClientState.Running;
1573
+ }
1574
+
1575
+ public async start(): Promise<void> {
1576
+ if (this._disposed === 'disposing' || this._disposed === 'disposed') {
1577
+ throw new Error(`Client got disposed and can't be restarted.`);
1578
+ }
1579
+ if (this.$state === ClientState.Stopping) {
1580
+ throw new Error(
1581
+ `Client is currently stopping. Can only restart a full stopped client`,
1582
+ );
1583
+ }
1584
+ // We are already running or are in the process of getting up
1585
+ // to speed.
1586
+ if (this._onStart !== undefined) {
1587
+ return this._onStart;
1588
+ }
1589
+ const [promise, resolve, reject] = this.createOnStartPromise();
1590
+ this._onStart = promise;
1591
+
1592
+ // If we restart then the diagnostics collection is reused.
1593
+ if (this._diagnostics === undefined) {
1594
+ this._diagnostics = this._clientOptions.diagnosticCollectionName
1595
+ ? Languages.createDiagnosticCollection(
1596
+ this._clientOptions.diagnosticCollectionName,
1597
+ )
1598
+ : Languages.createDiagnosticCollection();
1599
+ }
1600
+
1601
+ // When we start make all buffer handlers pending so that they
1602
+ // get added.
1603
+ for (const [method, handler] of this._notificationHandlers) {
1604
+ if (!this._pendingNotificationHandlers.has(method)) {
1605
+ this._pendingNotificationHandlers.set(method, handler);
1606
+ }
1607
+ }
1608
+ for (const [method, handler] of this._requestHandlers) {
1609
+ if (!this._pendingRequestHandlers.has(method)) {
1610
+ this._pendingRequestHandlers.set(method, handler);
1611
+ }
1612
+ }
1613
+ for (const [token, data] of this._progressHandlers) {
1614
+ if (!this._pendingProgressHandlers.has(token)) {
1615
+ this._pendingProgressHandlers.set(token, data);
1616
+ }
1617
+ }
1618
+
1619
+ this.$state = ClientState.Starting;
1620
+ try {
1621
+ const connection = await this.createConnection();
1622
+ connection.onNotification(LogMessageNotification.type, (message) => {
1623
+ switch (message.type) {
1624
+ case MessageType.Error:
1625
+ this.error(message.message, undefined, false);
1626
+ break;
1627
+ case MessageType.Warning:
1628
+ this.warn(message.message, undefined, false);
1629
+ break;
1630
+ case MessageType.Info:
1631
+ this.info(message.message, undefined, false);
1632
+ break;
1633
+ case MessageType.Debug:
1634
+ this.debug(message.message, undefined, false);
1635
+ break;
1636
+ default:
1637
+ this.outputChannel.appendLine(message.message);
1638
+ }
1639
+ });
1640
+ connection.onNotification(ShowMessageNotification.type, (message) => {
1641
+ switch (message.type) {
1642
+ case MessageType.Error:
1643
+ void Window.showErrorMessage(message.message);
1644
+ break;
1645
+ case MessageType.Warning:
1646
+ void Window.showWarningMessage(message.message);
1647
+ break;
1648
+ case MessageType.Info:
1649
+ void Window.showInformationMessage(message.message);
1650
+ break;
1651
+ default:
1652
+ void Window.showInformationMessage(message.message);
1653
+ }
1654
+ });
1655
+ connection.onRequest(ShowMessageRequest.type, (params) => {
1656
+ let messageFunc: <T extends MessageItem>(
1657
+ message: string,
1658
+ ...items: T[]
1659
+ ) => Thenable<T>;
1660
+ switch (params.type) {
1661
+ case MessageType.Error:
1662
+ messageFunc = Window.showErrorMessage;
1663
+ break;
1664
+ case MessageType.Warning:
1665
+ messageFunc = Window.showWarningMessage;
1666
+ break;
1667
+ case MessageType.Info:
1668
+ messageFunc = Window.showInformationMessage;
1669
+ break;
1670
+ default:
1671
+ messageFunc = Window.showInformationMessage;
1672
+ }
1673
+ const actions = params.actions || [];
1674
+ return messageFunc(params.message, ...actions);
1675
+ });
1676
+ connection.onNotification(TelemetryEventNotification.type, (data) => {
1677
+ this._telemetryEmitter.fire(data);
1678
+ });
1679
+ connection.onRequest(
1680
+ ShowDocumentRequest.type,
1681
+ async (params): Promise<ShowDocumentResult> => {
1682
+ const showDocument = async (
1683
+ params: ShowDocumentParams,
1684
+ ): Promise<ShowDocumentResult> => {
1685
+ const uri = this.protocol2CodeConverter.asUri(params.uri);
1686
+ try {
1687
+ if (params.external === true) {
1688
+ const success = await Env.openExternal(uri);
1689
+ return { success };
1690
+ } else {
1691
+ const options: TextDocumentShowOptions = {};
1692
+ if (params.selection !== undefined) {
1693
+ options.selection = this.protocol2CodeConverter.asRange(
1694
+ params.selection,
1695
+ );
1696
+ }
1697
+ if (params.takeFocus === undefined || params.takeFocus === false) {
1698
+ options.preserveFocus = true;
1699
+ } else if (params.takeFocus === true) {
1700
+ options.preserveFocus = false;
1701
+ }
1702
+ await Window.showTextDocument(uri, options);
1703
+ return { success: true };
1704
+ }
1705
+ } catch (error) {
1706
+ return { success: false };
1707
+ }
1708
+ };
1709
+ const middleware = this._clientOptions.middleware.window?.showDocument;
1710
+ if (middleware !== undefined) {
1711
+ return middleware(params, showDocument);
1712
+ } else {
1713
+ return showDocument(params);
1714
+ }
1715
+ },
1716
+ );
1717
+ connection.listen();
1718
+ await this.initialize(connection);
1719
+ resolve();
1720
+ } catch (error) {
1721
+ this.$state = ClientState.StartFailed;
1722
+ this.error(
1723
+ `${this._name} client: couldn't create connection to server.`,
1724
+ error,
1725
+ 'force',
1726
+ );
1727
+ reject(error);
1728
+ }
1729
+ return this._onStart;
1730
+ }
1731
+
1732
+ private createOnStartPromise(): [Promise<void>, () => void, (error: any) => void] {
1733
+ let resolve!: () => void;
1734
+ let reject!: (error: any) => void;
1735
+ const promise: Promise<void> = new Promise((_resolve, _reject) => {
1736
+ resolve = _resolve;
1737
+ reject = _reject;
1738
+ });
1739
+ return [promise, resolve, reject];
1740
+ }
1741
+
1742
+ private async initialize(connection: Connection): Promise<InitializeResult> {
1743
+ this.refreshTrace(connection, false);
1744
+ const initOption = this._clientOptions.initializationOptions;
1745
+ // If the client is locked to a workspace folder use it. In this case the workspace folder
1746
+ // feature is not registered and we need to initialize the value here.
1747
+ const [rootPath, workspaceFolders] =
1748
+ this._clientOptions.workspaceFolder !== undefined
1749
+ ? [
1750
+ this._clientOptions.workspaceFolder.uri.fsPath,
1751
+ [
1752
+ {
1753
+ uri: this._c2p.asUri(this._clientOptions.workspaceFolder.uri),
1754
+ name: this._clientOptions.workspaceFolder.name,
1755
+ },
1756
+ ],
1757
+ ]
1758
+ : [this._clientGetRootPath(), null];
1759
+ const initParams: InitializeParams = {
1760
+ processId: null,
1761
+ clientInfo: {
1762
+ name: Env.appName,
1763
+ version: VSCodeVersion,
1764
+ },
1765
+ locale: this.getLocale(),
1766
+ rootPath: rootPath ? rootPath : null,
1767
+ rootUri: rootPath ? this._c2p.asUri(Uri.file(rootPath)) : null,
1768
+ capabilities: this.computeClientCapabilities(),
1769
+ initializationOptions: Is.func(initOption) ? initOption() : initOption,
1770
+ trace: Trace.toString(this._trace),
1771
+ workspaceFolders: workspaceFolders,
1772
+ };
1773
+ this.fillInitializeParams(initParams);
1774
+ if (this._clientOptions.progressOnInitialization) {
1775
+ const token: ProgressToken = UUID.generateUuid();
1776
+ const part: ProgressPart = new ProgressPart(connection, token);
1777
+ initParams.workDoneToken = token;
1778
+ try {
1779
+ const result = await this.doInitialize(connection, initParams);
1780
+ part.done();
1781
+ return result;
1782
+ } catch (error) {
1783
+ part.cancel();
1784
+ throw error;
1785
+ }
1786
+ } else {
1787
+ return this.doInitialize(connection, initParams);
1788
+ }
1789
+ }
1790
+
1791
+ private async doInitialize(
1792
+ connection: Connection,
1793
+ initParams: InitializeParams,
1794
+ ): Promise<InitializeResult> {
1795
+ try {
1796
+ const result = await connection.initialize(initParams);
1797
+ if (
1798
+ result.capabilities.positionEncoding !== undefined &&
1799
+ result.capabilities.positionEncoding !== PositionEncodingKind.UTF16
1800
+ ) {
1801
+ throw new Error(
1802
+ `Unsupported position encoding (${result.capabilities.positionEncoding}) received from server ${this.name}`,
1803
+ );
1804
+ }
1805
+
1806
+ this._initializeResult = result;
1807
+ this.$state = ClientState.Running;
1808
+
1809
+ let textDocumentSyncOptions: TextDocumentSyncOptions | undefined = undefined;
1810
+ if (Is.number(result.capabilities.textDocumentSync)) {
1811
+ if (result.capabilities.textDocumentSync === TextDocumentSyncKind.None) {
1812
+ textDocumentSyncOptions = {
1813
+ openClose: false,
1814
+ change: TextDocumentSyncKind.None,
1815
+ save: undefined,
1816
+ };
1817
+ } else {
1818
+ textDocumentSyncOptions = {
1819
+ openClose: true,
1820
+ change: result.capabilities.textDocumentSync,
1821
+ save: {
1822
+ includeText: false,
1823
+ },
1824
+ };
1825
+ }
1826
+ } else if (
1827
+ result.capabilities.textDocumentSync !== undefined &&
1828
+ result.capabilities.textDocumentSync !== null
1829
+ ) {
1830
+ textDocumentSyncOptions = result.capabilities
1831
+ .textDocumentSync as TextDocumentSyncOptions;
1832
+ }
1833
+ this._capabilities = Object.assign({}, result.capabilities, {
1834
+ resolvedTextDocumentSync: textDocumentSyncOptions,
1835
+ });
1836
+
1837
+ connection.onNotification(PublishDiagnosticsNotification.type, (params) =>
1838
+ this.handleDiagnostics(params),
1839
+ );
1840
+ connection.onRequest(RegistrationRequest.type, (params) =>
1841
+ this.handleRegistrationRequest(params),
1842
+ );
1843
+ // See https://github.com/Microsoft/vscode-languageserver-node/issues/199
1844
+ connection.onRequest('client/registerFeature', (params) =>
1845
+ this.handleRegistrationRequest(params),
1846
+ );
1847
+ connection.onRequest(UnregistrationRequest.type, (params) =>
1848
+ this.handleUnregistrationRequest(params),
1849
+ );
1850
+ // See https://github.com/Microsoft/vscode-languageserver-node/issues/199
1851
+ connection.onRequest('client/unregisterFeature', (params) =>
1852
+ this.handleUnregistrationRequest(params),
1853
+ );
1854
+ connection.onRequest(ApplyWorkspaceEditRequest.type, (params) =>
1855
+ this.handleApplyWorkspaceEdit(params),
1856
+ );
1857
+
1858
+ // Add pending notification, request and progress handlers.
1859
+ for (const [method, handler] of this._pendingNotificationHandlers) {
1860
+ this._notificationDisposables.set(
1861
+ method,
1862
+ connection.onNotification(method, handler),
1863
+ );
1864
+ }
1865
+ this._pendingNotificationHandlers.clear();
1866
+ for (const [method, handler] of this._pendingRequestHandlers) {
1867
+ this._requestDisposables.set(method, connection.onRequest(method, handler));
1868
+ }
1869
+ this._pendingRequestHandlers.clear();
1870
+ for (const [token, data] of this._pendingProgressHandlers) {
1871
+ this._progressDisposables.set(
1872
+ token,
1873
+ connection.onProgress(data.type, token, data.handler),
1874
+ );
1875
+ }
1876
+ this._pendingProgressHandlers.clear();
1877
+
1878
+ // if (this._clientOptions.suspend.mode !== SuspendMode.off) {
1879
+ // this._idleInterval = RAL().timer.setInterval(() => this.checkSuspend(), this._clientOptions.suspend.interval);
1880
+ // }
1881
+
1882
+ await connection.sendNotification(InitializedNotification.type, {});
1883
+
1884
+ this.hookFileEvents(connection);
1885
+ this.hookConfigurationChanged(connection);
1886
+ this.initializeFeatures(connection);
1887
+
1888
+ return result;
1889
+ } catch (error: any) {
1890
+ if (this._clientOptions.initializationFailedHandler) {
1891
+ if (this._clientOptions.initializationFailedHandler(error)) {
1892
+ void this.initialize(connection);
1893
+ } else {
1894
+ void this.stop();
1895
+ }
1896
+ } else if (error instanceof ResponseError && error.data && error.data.retry) {
1897
+ void Window.showErrorMessage(error.message, {
1898
+ title: 'Retry',
1899
+ id: 'retry',
1900
+ }).then((item) => {
1901
+ if (item && item.id === 'retry') {
1902
+ void this.initialize(connection);
1903
+ } else {
1904
+ void this.stop();
1905
+ }
1906
+ });
1907
+ } else {
1908
+ if (error && error.message) {
1909
+ void Window.showErrorMessage(error.message);
1910
+ }
1911
+ this.error('Server initialization failed.', error);
1912
+ void this.stop();
1913
+ }
1914
+ throw error;
1915
+ }
1916
+ }
1917
+
1918
+ private _clientGetRootPath(): string | undefined {
1919
+ const folders = Workspace.workspaceFolders;
1920
+ if (!folders || folders.length === 0) {
1921
+ return undefined;
1922
+ }
1923
+ const folder = folders[0];
1924
+ if (folder.uri.scheme === 'file') {
1925
+ return folder.uri.fsPath;
1926
+ }
1927
+ return undefined;
1928
+ }
1929
+
1930
+ public stop(timeout = 2000): Promise<void> {
1931
+ // Wait 2 seconds on stop
1932
+ return this.shutdown('stop', timeout);
1933
+ }
1934
+
1935
+ public dispose(timeout = 2000): Promise<void> {
1936
+ try {
1937
+ this._disposed = 'disposing';
1938
+ return this.stop(timeout);
1939
+ } finally {
1940
+ this._disposed = 'disposed';
1941
+ }
1942
+ }
1943
+
1944
+ private async shutdown(mode: 'suspend' | 'stop', timeout: number): Promise<void> {
1945
+ // If the client is stopped or in its initial state return.
1946
+ if (this.$state === ClientState.Stopped || this.$state === ClientState.Initial) {
1947
+ return;
1948
+ }
1949
+
1950
+ // If we are stopping the client and have a stop promise return it.
1951
+ if (this.$state === ClientState.Stopping) {
1952
+ if (this._onStop !== undefined) {
1953
+ return this._onStop;
1954
+ } else {
1955
+ throw new Error(
1956
+ `Client ${this.name} is stopping but no stop promise available.`,
1957
+ );
1958
+ }
1959
+ }
1960
+
1961
+ const connection = this.activeConnection();
1962
+
1963
+ // We can't stop a client that is not running (e.g. has no connection). Especially not
1964
+ // on that us starting since it can't be correctly synchronized.
1965
+ if (connection === undefined || this.$state !== ClientState.Running) {
1966
+ throw new Error(
1967
+ `Client ${this.name} is not running and can't be stopped. It's current state is: ${this.$state}`,
1968
+ );
1969
+ }
1970
+
1971
+ this._initializeResult = undefined;
1972
+ this.$state = ClientState.Stopping;
1973
+ this.cleanUp(mode);
1974
+
1975
+ // eslint-disable-next-line promise/param-names
1976
+ const tp = new Promise<undefined>((c) => {
1977
+ RAL().timer.setTimeout(c, timeout);
1978
+ });
1979
+ const shutdown = (async (connection) => {
1980
+ await connection.shutdown();
1981
+ await connection.exit();
1982
+ return connection;
1983
+ })(connection);
1984
+
1985
+ return (this._onStop = Promise.race([tp, shutdown])
1986
+ .then(
1987
+ (connection) => {
1988
+ // The connection won the race with the timeout.
1989
+ if (connection !== undefined) {
1990
+ connection.end();
1991
+ connection.dispose();
1992
+ } else {
1993
+ this.error(`Stopping server timed out`, undefined, false);
1994
+ throw new Error(`Stopping the server timed out`);
1995
+ }
1996
+ },
1997
+ (error) => {
1998
+ this.error(`Stopping server failed`, error, false);
1999
+ throw error;
2000
+ },
2001
+ )
2002
+ .finally(() => {
2003
+ this.$state = ClientState.Stopped;
2004
+ mode === 'stop' && this.cleanUpChannel();
2005
+ this._onStart = undefined;
2006
+ this._onStop = undefined;
2007
+ this._connection = undefined;
2008
+ this._ignoredRegistrations.clear();
2009
+ }));
2010
+ }
2011
+
2012
+ private cleanUp(mode: 'restart' | 'suspend' | 'stop'): void {
2013
+ // purge outstanding file events.
2014
+ this._fileEvents = [];
2015
+ this._fileEventDelayer.cancel();
2016
+
2017
+ const disposables = this._listeners.splice(0, this._listeners.length);
2018
+ for (const disposable of disposables) {
2019
+ disposable.dispose();
2020
+ }
2021
+
2022
+ if (this._syncedDocuments) {
2023
+ this._syncedDocuments.clear();
2024
+ }
2025
+ // Clear features in reverse order;
2026
+ for (const feature of Array.from(this._features.entries())
2027
+ .map((entry) => entry[1])
2028
+ .reverse()) {
2029
+ feature.clear();
2030
+ }
2031
+ if (mode === 'stop' && this._diagnostics !== undefined) {
2032
+ this._diagnostics.dispose();
2033
+ this._diagnostics = undefined;
2034
+ }
2035
+
2036
+ if (this._idleInterval !== undefined) {
2037
+ this._idleInterval.dispose();
2038
+ this._idleInterval = undefined;
2039
+ }
2040
+ // this._idleStart = undefined;
2041
+ }
2042
+
2043
+ private cleanUpChannel(): void {
2044
+ if (this._outputChannel !== undefined && this._disposeOutputChannel) {
2045
+ this._outputChannel.dispose();
2046
+ this._outputChannel = undefined;
2047
+ }
2048
+ }
2049
+
2050
+ private notifyFileEvent(event: FileEvent): void {
2051
+ const client = this;
2052
+ async function didChangeWatchedFile(this: void, event: FileEvent): Promise<void> {
2053
+ client._fileEvents.push(event);
2054
+ return client._fileEventDelayer.trigger(async (): Promise<void> => {
2055
+ await client.sendNotification(DidChangeWatchedFilesNotification.type, {
2056
+ changes: client._fileEvents,
2057
+ });
2058
+ client._fileEvents = [];
2059
+ });
2060
+ }
2061
+ const workSpaceMiddleware = this.clientOptions.middleware?.workspace;
2062
+ (workSpaceMiddleware?.didChangeWatchedFile
2063
+ ? workSpaceMiddleware.didChangeWatchedFile(event, didChangeWatchedFile)
2064
+ : didChangeWatchedFile(event)
2065
+ ).catch((error) => {
2066
+ client.error(`Notify file events failed.`, error);
2067
+ });
2068
+ }
2069
+
2070
+ private async sendPendingFullTextDocumentChanges(
2071
+ connection: Connection,
2072
+ ): Promise<void> {
2073
+ return this._pendingChangeSemaphore.lock(async () => {
2074
+ try {
2075
+ const changes = this._didChangeTextDocumentFeature!.getPendingDocumentChanges(
2076
+ this._pendingOpenNotifications,
2077
+ );
2078
+ if (changes.length === 0) {
2079
+ return;
2080
+ }
2081
+ for (const document of changes) {
2082
+ const params =
2083
+ this.code2ProtocolConverter.asChangeTextDocumentParams(document);
2084
+ // We await the send and not the delivery since it is more or less the same for
2085
+ // notifications.
2086
+ await connection.sendNotification(
2087
+ DidChangeTextDocumentNotification.type,
2088
+ params,
2089
+ );
2090
+ this._didChangeTextDocumentFeature!.notificationSent(
2091
+ document,
2092
+ DidChangeTextDocumentNotification.type,
2093
+ params,
2094
+ );
2095
+ }
2096
+ } catch (error) {
2097
+ this.error(`Sending pending changes failed`, error, false);
2098
+ throw error;
2099
+ }
2100
+ });
2101
+ }
2102
+
2103
+ private triggerPendingChangeDelivery(): void {
2104
+ this._pendingChangeDelayer
2105
+ .trigger(async () => {
2106
+ const connection = this.activeConnection();
2107
+ if (connection === undefined) {
2108
+ this.triggerPendingChangeDelivery();
2109
+ return;
2110
+ }
2111
+ await this.sendPendingFullTextDocumentChanges(connection);
2112
+ })
2113
+ .catch((error) => this.error(`Delivering pending changes failed`, error, false));
2114
+ }
2115
+
2116
+ private _diagnosticQueue: Map<string, Diagnostic[]> = new Map();
2117
+ private _diagnosticQueueState:
2118
+ | { state: 'idle' }
2119
+ | { state: 'busy'; document: string; tokenSource: CancellationTokenSource } = {
2120
+ state: 'idle',
2121
+ };
2122
+ private handleDiagnostics(params: PublishDiagnosticsParams) {
2123
+ if (!this._diagnostics) {
2124
+ return;
2125
+ }
2126
+ const key = params.uri;
2127
+ if (
2128
+ this._diagnosticQueueState.state === 'busy' &&
2129
+ this._diagnosticQueueState.document === key
2130
+ ) {
2131
+ // Cancel the active run;
2132
+ this._diagnosticQueueState.tokenSource.cancel();
2133
+ }
2134
+ this._diagnosticQueue.set(params.uri, params.diagnostics);
2135
+ this.triggerDiagnosticQueue();
2136
+ }
2137
+
2138
+ private triggerDiagnosticQueue(): void {
2139
+ RAL().timer.setImmediate(() => {
2140
+ this.workDiagnosticQueue();
2141
+ });
2142
+ }
2143
+
2144
+ private workDiagnosticQueue(): void {
2145
+ if (this._diagnosticQueueState.state === 'busy') {
2146
+ return;
2147
+ }
2148
+ const next = this._diagnosticQueue.entries().next();
2149
+ if (next.done === true) {
2150
+ // Nothing in the queue
2151
+ return;
2152
+ }
2153
+ const [document, diagnostics] = next.value;
2154
+ this._diagnosticQueue.delete(document);
2155
+ const tokenSource = new CancellationTokenSource();
2156
+ this._diagnosticQueueState = { state: 'busy', document: document, tokenSource };
2157
+ this._p2c
2158
+ .asDiagnostics(diagnostics, tokenSource.token)
2159
+ .then((converted) => {
2160
+ if (!tokenSource.token.isCancellationRequested) {
2161
+ const uri = this._p2c.asUri(document);
2162
+ const middleware = this.clientOptions.middleware!;
2163
+ if (middleware.handleDiagnostics) {
2164
+ middleware.handleDiagnostics(uri, converted, (uri, diagnostics) =>
2165
+ this.setDiagnostics(uri, diagnostics),
2166
+ );
2167
+ } else {
2168
+ this.setDiagnostics(uri, converted);
2169
+ }
2170
+ }
2171
+ })
2172
+ .catch((error) => {
2173
+ this.error(`Processing diagnostic queue failed.`, error);
2174
+ })
2175
+ .finally(() => {
2176
+ this._diagnosticQueueState = { state: 'idle' };
2177
+ this.triggerDiagnosticQueue();
2178
+ });
2179
+ }
2180
+
2181
+ private setDiagnostics(uri: Uri, diagnostics: VDiagnostic[] | undefined) {
2182
+ if (!this._diagnostics) {
2183
+ return;
2184
+ }
2185
+ this._diagnostics.set(uri, diagnostics);
2186
+ }
2187
+
2188
+ protected getLocale(): string {
2189
+ return Env.language;
2190
+ }
2191
+
2192
+ protected abstract createMessageTransports(
2193
+ encoding: string,
2194
+ ): Promise<MessageTransports>;
2195
+
2196
+ private async $start(): Promise<Connection> {
2197
+ if (this.$state === ClientState.StartFailed) {
2198
+ throw new Error(`Previous start failed. Can't restart server.`);
2199
+ }
2200
+ await this.start();
2201
+ const connection = this.activeConnection();
2202
+ if (connection === undefined) {
2203
+ throw new Error(`Starting server failed`);
2204
+ }
2205
+ return connection;
2206
+ }
2207
+
2208
+ private async createConnection(): Promise<Connection> {
2209
+ const errorHandler = (
2210
+ error: Error,
2211
+ message: Message | undefined,
2212
+ count: number | undefined,
2213
+ ) => {
2214
+ this.handleConnectionError(error, message, count).catch((error) =>
2215
+ this.error(`Handling connection error failed`, error),
2216
+ );
2217
+ };
2218
+
2219
+ const closeHandler = () => {
2220
+ this.handleConnectionClosed().catch((error) =>
2221
+ this.error(`Handling connection close failed`, error),
2222
+ );
2223
+ };
2224
+
2225
+ const transports = await this.createMessageTransports(
2226
+ this._clientOptions.stdioEncoding || 'utf8',
2227
+ );
2228
+ this._connection = createConnection(
2229
+ transports.reader,
2230
+ transports.writer,
2231
+ errorHandler,
2232
+ closeHandler,
2233
+ this._clientOptions.connectionOptions,
2234
+ );
2235
+ return this._connection;
2236
+ }
2237
+
2238
+ protected async handleConnectionClosed(): Promise<void> {
2239
+ // Check whether this is a normal shutdown in progress or the client stopped normally.
2240
+ if (this.$state === ClientState.Stopped) {
2241
+ return;
2242
+ }
2243
+ try {
2244
+ if (this._connection !== undefined) {
2245
+ this._connection.dispose();
2246
+ }
2247
+ } catch (error) {
2248
+ // Disposing a connection could fail if error cases.
2249
+ }
2250
+ let handlerResult: CloseHandlerResult = { action: CloseAction.DoNotRestart };
2251
+ if (this.$state !== ClientState.Stopping) {
2252
+ try {
2253
+ handlerResult = await this._clientOptions.errorHandler!.closed();
2254
+ } catch (error) {
2255
+ // Ignore errors coming from the error handler.
2256
+ }
2257
+ }
2258
+ this._connection = undefined;
2259
+ if (handlerResult.action === CloseAction.DoNotRestart) {
2260
+ this.error(
2261
+ handlerResult.message ??
2262
+ 'Connection to server got closed. Server will not be restarted.',
2263
+ undefined,
2264
+ handlerResult.handled === true ? false : 'force',
2265
+ );
2266
+ this.cleanUp('stop');
2267
+ if (this.$state === ClientState.Starting) {
2268
+ this.$state = ClientState.StartFailed;
2269
+ } else {
2270
+ this.$state = ClientState.Stopped;
2271
+ }
2272
+ this._onStop = Promise.resolve();
2273
+ this._onStart = undefined;
2274
+ } else if (handlerResult.action === CloseAction.Restart) {
2275
+ this.info(
2276
+ handlerResult.message ??
2277
+ 'Connection to server got closed. Server will restart.',
2278
+ !handlerResult.handled,
2279
+ );
2280
+ this.cleanUp('restart');
2281
+ this.$state = ClientState.Initial;
2282
+ this._onStop = Promise.resolve();
2283
+ this._onStart = undefined;
2284
+ this.start().catch((error) =>
2285
+ this.error(`Restarting server failed`, error, 'force'),
2286
+ );
2287
+ }
2288
+ }
2289
+
2290
+ private async handleConnectionError(
2291
+ error: Error,
2292
+ message: Message | undefined,
2293
+ count: number | undefined,
2294
+ ): Promise<void> {
2295
+ const handlerResult: ErrorHandlerResult =
2296
+ await this._clientOptions.errorHandler!.error(error, message, count);
2297
+ if (handlerResult.action === ErrorAction.Shutdown) {
2298
+ this.error(
2299
+ handlerResult.message ??
2300
+ `Client ${this._name}: connection to server is erroring.\n${error.message}\nShutting down server.`,
2301
+ undefined,
2302
+ handlerResult.handled === true ? false : 'force',
2303
+ );
2304
+ this.stop().catch((error) => {
2305
+ this.error(`Stopping server failed`, error, false);
2306
+ });
2307
+ } else {
2308
+ this.error(
2309
+ handlerResult.message ??
2310
+ `Client ${this._name}: connection to server is erroring.\n${error.message}`,
2311
+ undefined,
2312
+ handlerResult.handled === true ? false : 'force',
2313
+ );
2314
+ }
2315
+ }
2316
+
2317
+ private hookConfigurationChanged(connection: Connection): void {
2318
+ this._listeners.push(
2319
+ Workspace.onDidChangeConfiguration(() => {
2320
+ this.refreshTrace(connection, true);
2321
+ }),
2322
+ );
2323
+ }
2324
+
2325
+ private refreshTrace(connection: Connection, sendNotification = false): void {
2326
+ const config = Workspace.getConfiguration(this._id);
2327
+ let trace: Trace = Trace.Off;
2328
+ let traceFormat: TraceFormat = TraceFormat.Text;
2329
+ if (config) {
2330
+ const traceConfig = config.get('trace.server', 'off');
2331
+
2332
+ if (typeof traceConfig === 'string') {
2333
+ trace = Trace.fromString(traceConfig);
2334
+ } else {
2335
+ trace = Trace.fromString(config.get('trace.server.verbosity', 'off'));
2336
+ traceFormat = TraceFormat.fromString(config.get('trace.server.format', 'text'));
2337
+ }
2338
+ }
2339
+ this._trace = trace;
2340
+ this._traceFormat = traceFormat;
2341
+ connection
2342
+ .trace(this._trace, this._tracer, {
2343
+ sendNotification,
2344
+ traceFormat: this._traceFormat,
2345
+ })
2346
+ .catch((error) => {
2347
+ this.error(`Updating trace failed with error`, error, false);
2348
+ });
2349
+ }
2350
+
2351
+ private hookFileEvents(_connection: Connection): void {
2352
+ const fileEvents = this._clientOptions.synchronize.fileEvents;
2353
+ if (!fileEvents) {
2354
+ return;
2355
+ }
2356
+ let watchers: VFileSystemWatcher[];
2357
+ if (Is.array(fileEvents)) {
2358
+ watchers = <VFileSystemWatcher[]>fileEvents;
2359
+ } else {
2360
+ watchers = [<VFileSystemWatcher>fileEvents];
2361
+ }
2362
+ if (!watchers) {
2363
+ return;
2364
+ }
2365
+ (
2366
+ this._dynamicFeatures.get(
2367
+ DidChangeWatchedFilesNotification.type.method,
2368
+ )! as FileSystemWatcherFeature
2369
+ ).registerRaw(UUID.generateUuid(), watchers);
2370
+ }
2371
+
2372
+ private readonly _features: (StaticFeature | DynamicFeature<any>)[] = [];
2373
+ private readonly _dynamicFeatures: Map<string, DynamicFeature<any>> = new Map<
2374
+ string,
2375
+ DynamicFeature<any>
2376
+ >();
2377
+
2378
+ public registerFeatures(features: (StaticFeature | DynamicFeature<any>)[]): void {
2379
+ for (const feature of features) {
2380
+ this.registerFeature(feature);
2381
+ }
2382
+ }
2383
+
2384
+ public registerFeature(feature: StaticFeature | DynamicFeature<any>): void {
2385
+ this._features.push(feature);
2386
+ if (DynamicFeature.is(feature)) {
2387
+ const registrationType = feature.registrationType;
2388
+ this._dynamicFeatures.set(registrationType.method, feature);
2389
+ }
2390
+ }
2391
+
2392
+ getFeature(
2393
+ request: typeof DidOpenTextDocumentNotification.method,
2394
+ ): DidOpenTextDocumentFeatureShape;
2395
+ getFeature(
2396
+ request: typeof DidChangeTextDocumentNotification.method,
2397
+ ): DidChangeTextDocumentFeatureShape;
2398
+ getFeature(
2399
+ request: typeof WillSaveTextDocumentNotification.method,
2400
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2401
+ TextDocumentSendFeature<(textDocument: TextDocument) => Promise<void>>;
2402
+ getFeature(
2403
+ request: typeof WillSaveTextDocumentWaitUntilRequest.method,
2404
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2405
+ TextDocumentSendFeature<
2406
+ (textDocument: TextDocument) => ProviderResult<VTextEdit[]>
2407
+ >;
2408
+ getFeature(
2409
+ request: typeof DidSaveTextDocumentNotification.method,
2410
+ ): DidSaveTextDocumentFeatureShape;
2411
+ getFeature(
2412
+ request: typeof DidCloseTextDocumentNotification.method,
2413
+ ): DidCloseTextDocumentFeatureShape;
2414
+ getFeature(
2415
+ request: typeof DidCreateFilesNotification.method,
2416
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2417
+ send: (event: FileCreateEvent) => Promise<void>;
2418
+ };
2419
+ getFeature(
2420
+ request: typeof DidRenameFilesNotification.method,
2421
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2422
+ send: (event: FileRenameEvent) => Promise<void>;
2423
+ };
2424
+ getFeature(
2425
+ request: typeof DidDeleteFilesNotification.method,
2426
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2427
+ send: (event: FileDeleteEvent) => Promise<void>;
2428
+ };
2429
+ getFeature(
2430
+ request: typeof WillCreateFilesRequest.method,
2431
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2432
+ send: (event: FileWillCreateEvent) => Promise<void>;
2433
+ };
2434
+ getFeature(
2435
+ request: typeof WillRenameFilesRequest.method,
2436
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2437
+ send: (event: FileWillRenameEvent) => Promise<void>;
2438
+ };
2439
+ getFeature(
2440
+ request: typeof WillDeleteFilesRequest.method,
2441
+ ): DynamicFeature<FileOperationRegistrationOptions> & {
2442
+ send: (event: FileWillDeleteEvent) => Promise<void>;
2443
+ };
2444
+ getFeature(
2445
+ request: typeof CompletionRequest.method,
2446
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2447
+ TextDocumentProviderFeature<CompletionItemProvider>;
2448
+ getFeature(
2449
+ request: typeof HoverRequest.method,
2450
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2451
+ TextDocumentProviderFeature<HoverProvider>;
2452
+ getFeature(
2453
+ request: typeof SignatureHelpRequest.method,
2454
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2455
+ TextDocumentProviderFeature<SignatureHelpProvider>;
2456
+ getFeature(
2457
+ request: typeof DefinitionRequest.method,
2458
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2459
+ TextDocumentProviderFeature<DefinitionProvider>;
2460
+ getFeature(
2461
+ request: typeof ReferencesRequest.method,
2462
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2463
+ TextDocumentProviderFeature<ReferenceProvider>;
2464
+ getFeature(
2465
+ request: typeof DocumentHighlightRequest.method,
2466
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2467
+ TextDocumentProviderFeature<DocumentHighlightProvider>;
2468
+ getFeature(
2469
+ request: typeof CodeActionRequest.method,
2470
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2471
+ TextDocumentProviderFeature<CodeActionProvider>;
2472
+ getFeature(
2473
+ request: typeof CodeLensRequest.method,
2474
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2475
+ TextDocumentProviderFeature<CodeLensProviderShape>;
2476
+ getFeature(
2477
+ request: typeof DocumentFormattingRequest.method,
2478
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2479
+ TextDocumentProviderFeature<DocumentFormattingEditProvider>;
2480
+ getFeature(
2481
+ request: typeof DocumentRangeFormattingRequest.method,
2482
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2483
+ TextDocumentProviderFeature<DocumentRangeFormattingEditProvider>;
2484
+ getFeature(
2485
+ request: typeof DocumentOnTypeFormattingRequest.method,
2486
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2487
+ TextDocumentProviderFeature<OnTypeFormattingEditProvider>;
2488
+ getFeature(
2489
+ request: typeof RenameRequest.method,
2490
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2491
+ TextDocumentProviderFeature<RenameProvider>;
2492
+ getFeature(
2493
+ request: typeof DocumentSymbolRequest.method,
2494
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2495
+ TextDocumentProviderFeature<DocumentSymbolProvider>;
2496
+ getFeature(
2497
+ request: typeof DocumentLinkRequest.method,
2498
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2499
+ TextDocumentProviderFeature<DocumentLinkProvider>;
2500
+ getFeature(
2501
+ request: typeof DocumentColorRequest.method,
2502
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2503
+ TextDocumentProviderFeature<DocumentColorProvider>;
2504
+ getFeature(
2505
+ request: typeof DeclarationRequest.method,
2506
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2507
+ TextDocumentProviderFeature<DeclarationProvider>;
2508
+ getFeature(
2509
+ request: typeof FoldingRangeRequest.method,
2510
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2511
+ TextDocumentProviderFeature<FoldingRangeProviderShape>;
2512
+ getFeature(
2513
+ request: typeof ImplementationRequest.method,
2514
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2515
+ TextDocumentProviderFeature<ImplementationProvider>;
2516
+ getFeature(
2517
+ request: typeof SelectionRangeRequest.method,
2518
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2519
+ TextDocumentProviderFeature<SelectionRangeProvider>;
2520
+ getFeature(
2521
+ request: typeof TypeDefinitionRequest.method,
2522
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2523
+ TextDocumentProviderFeature<TypeDefinitionProvider>;
2524
+ getFeature(
2525
+ request: typeof CallHierarchyPrepareRequest.method,
2526
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2527
+ TextDocumentProviderFeature<CallHierarchyProvider>;
2528
+ getFeature(
2529
+ request: typeof SemanticTokensRegistrationType.method,
2530
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2531
+ TextDocumentProviderFeature<SemanticTokensProviderShape>;
2532
+ getFeature(
2533
+ request: typeof LinkedEditingRangeRequest.method,
2534
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2535
+ TextDocumentProviderFeature<LinkedEditingRangeProvider>;
2536
+ getFeature(
2537
+ request: typeof TypeHierarchyPrepareRequest.method,
2538
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2539
+ TextDocumentProviderFeature<TypeHierarchyProvider>;
2540
+ getFeature(
2541
+ request: typeof InlineValueRequest.method,
2542
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2543
+ TextDocumentProviderFeature<InlineValueProviderShape>;
2544
+ getFeature(
2545
+ request: typeof InlayHintRequest.method,
2546
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2547
+ TextDocumentProviderFeature<InlayHintsProviderShape>;
2548
+ getFeature(
2549
+ request: typeof WorkspaceSymbolRequest.method,
2550
+ ): DynamicFeature<TextDocumentRegistrationOptions> &
2551
+ WorkspaceProviderFeature<WorkspaceSymbolProvider>;
2552
+ getFeature(
2553
+ request: typeof DocumentDiagnosticRequest.method,
2554
+ ):
2555
+ | (DynamicFeature<TextDocumentRegistrationOptions> &
2556
+ TextDocumentProviderFeature<DiagnosticProviderShape>)
2557
+ | undefined;
2558
+ getFeature(
2559
+ request: typeof NotebookDocumentSyncRegistrationType.method,
2560
+ ):
2561
+ | (DynamicFeature<NotebookDocumentSyncRegistrationOptions> &
2562
+ NotebookDocumentProviderShape)
2563
+ | undefined;
2564
+ getFeature(
2565
+ request: typeof InlineCompletionRequest.method,
2566
+ ): DynamicFeature<InlineCompletionRegistrationOptions> &
2567
+ TextDocumentProviderFeature<InlineCompletionItemProvider>;
2568
+ getFeature(
2569
+ request: typeof ExecuteCommandRequest.method,
2570
+ ): DynamicFeature<ExecuteCommandOptions>;
2571
+ public getFeature(request: string): DynamicFeature<any> | undefined {
2572
+ return this._dynamicFeatures.get(request);
2573
+ }
2574
+
2575
+ hasDedicatedTextSynchronizationFeature(textDocument: TextDocument): boolean {
2576
+ const feature = this.getFeature(NotebookDocumentSyncRegistrationType.method);
2577
+ if (feature === undefined || !(feature instanceof NotebookDocumentSyncFeature)) {
2578
+ return false;
2579
+ }
2580
+ return feature.handles(textDocument);
2581
+ }
2582
+
2583
+ protected registerBuiltinFeatures() {
2584
+ const pendingFullTextDocumentChanges: Map<string, TextDocument> = new Map();
2585
+ this.registerFeature(new ConfigurationFeature(this));
2586
+ this.registerFeature(new DidOpenTextDocumentFeature(this, this._syncedDocuments));
2587
+ this._didChangeTextDocumentFeature = new DidChangeTextDocumentFeature(
2588
+ this,
2589
+ pendingFullTextDocumentChanges,
2590
+ );
2591
+ this._didChangeTextDocumentFeature.onPendingChangeAdded(() => {
2592
+ this.triggerPendingChangeDelivery();
2593
+ });
2594
+ this.registerFeature(this._didChangeTextDocumentFeature);
2595
+ this.registerFeature(new WillSaveFeature(this));
2596
+ this.registerFeature(new WillSaveWaitUntilFeature(this));
2597
+ this.registerFeature(new DidSaveTextDocumentFeature(this));
2598
+ this.registerFeature(
2599
+ new DidCloseTextDocumentFeature(
2600
+ this,
2601
+ this._syncedDocuments,
2602
+ pendingFullTextDocumentChanges,
2603
+ ),
2604
+ );
2605
+ this.registerFeature(
2606
+ new FileSystemWatcherFeature(this, (event) => this.notifyFileEvent(event)),
2607
+ );
2608
+ this.registerFeature(new CompletionItemFeature(this));
2609
+ this.registerFeature(new HoverFeature(this));
2610
+ this.registerFeature(new SignatureHelpFeature(this));
2611
+ this.registerFeature(new DefinitionFeature(this));
2612
+ this.registerFeature(new ReferencesFeature(this));
2613
+ this.registerFeature(new DocumentHighlightFeature(this));
2614
+ this.registerFeature(new DocumentSymbolFeature(this));
2615
+ this.registerFeature(new WorkspaceSymbolFeature(this));
2616
+ this.registerFeature(new CodeActionFeature(this));
2617
+ this.registerFeature(new CodeLensFeature(this));
2618
+ this.registerFeature(new DocumentFormattingFeature(this));
2619
+ this.registerFeature(new DocumentRangeFormattingFeature(this));
2620
+ this.registerFeature(new DocumentOnTypeFormattingFeature(this));
2621
+ this.registerFeature(new RenameFeature(this));
2622
+ this.registerFeature(new DocumentLinkFeature(this));
2623
+ this.registerFeature(new ExecuteCommandFeature(this));
2624
+ this.registerFeature(new SyncConfigurationFeature(this));
2625
+ this.registerFeature(new TypeDefinitionFeature(this));
2626
+ this.registerFeature(new ImplementationFeature(this));
2627
+ this.registerFeature(new ColorProviderFeature(this));
2628
+ // We only register the workspace folder feature if the client is not locked
2629
+ // to a specific workspace folder.
2630
+ if (this.clientOptions.workspaceFolder === undefined) {
2631
+ this.registerFeature(new WorkspaceFoldersFeature(this));
2632
+ }
2633
+ this.registerFeature(new FoldingRangeFeature(this));
2634
+ this.registerFeature(new DeclarationFeature(this));
2635
+ this.registerFeature(new SelectionRangeFeature(this));
2636
+ this.registerFeature(new ProgressFeature(this));
2637
+ this.registerFeature(new CallHierarchyFeature(this));
2638
+ this.registerFeature(new SemanticTokensFeature(this));
2639
+ this.registerFeature(new LinkedEditingFeature(this));
2640
+ this.registerFeature(new DidCreateFilesFeature(this));
2641
+ this.registerFeature(new DidRenameFilesFeature(this));
2642
+ this.registerFeature(new DidDeleteFilesFeature(this));
2643
+ this.registerFeature(new WillCreateFilesFeature(this));
2644
+ this.registerFeature(new WillRenameFilesFeature(this));
2645
+ this.registerFeature(new WillDeleteFilesFeature(this));
2646
+ this.registerFeature(new TypeHierarchyFeature(this));
2647
+ this.registerFeature(new InlineValueFeature(this));
2648
+ this.registerFeature(new InlayHintsFeature(this));
2649
+ this.registerFeature(new DiagnosticFeature(this));
2650
+ this.registerFeature(new NotebookDocumentSyncFeature(this));
2651
+ }
2652
+
2653
+ public registerProposedFeatures() {
2654
+ this.registerFeatures(ProposedFeatures.createAll(this));
2655
+ }
2656
+
2657
+ protected fillInitializeParams(params: InitializeParams): void {
2658
+ for (const feature of this._features) {
2659
+ if (Is.func(feature.fillInitializeParams)) {
2660
+ feature.fillInitializeParams(params);
2661
+ }
2662
+ }
2663
+ }
2664
+
2665
+ private computeClientCapabilities(): ClientCapabilities {
2666
+ const result: ClientCapabilities = {};
2667
+ ensure(result, 'workspace')!.applyEdit = true;
2668
+
2669
+ const workspaceEdit = ensure(ensure(result, 'workspace')!, 'workspaceEdit')!;
2670
+ workspaceEdit.documentChanges = true;
2671
+ workspaceEdit.resourceOperations = [
2672
+ ResourceOperationKind.Create,
2673
+ ResourceOperationKind.Rename,
2674
+ ResourceOperationKind.Delete,
2675
+ ];
2676
+ workspaceEdit.failureHandling = FailureHandlingKind.TextOnlyTransactional;
2677
+ workspaceEdit.normalizesLineEndings = true;
2678
+ workspaceEdit.changeAnnotationSupport = {
2679
+ groupsOnLabel: true,
2680
+ };
2681
+
2682
+ const diagnostics = ensure(ensure(result, 'textDocument')!, 'publishDiagnostics')!;
2683
+ diagnostics.relatedInformation = true;
2684
+ diagnostics.versionSupport = false;
2685
+ diagnostics.tagSupport = {
2686
+ valueSet: [DiagnosticTag.Unnecessary, DiagnosticTag.Deprecated],
2687
+ };
2688
+ diagnostics.codeDescriptionSupport = true;
2689
+ diagnostics.dataSupport = true;
2690
+
2691
+ const windowCapabilities = ensure(result, 'window')!;
2692
+ const showMessage = ensure(windowCapabilities, 'showMessage')!;
2693
+ showMessage.messageActionItem = { additionalPropertiesSupport: true };
2694
+ const showDocument = ensure(windowCapabilities, 'showDocument')!;
2695
+ showDocument.support = true;
2696
+
2697
+ const generalCapabilities = ensure(result, 'general')!;
2698
+ generalCapabilities.staleRequestSupport = {
2699
+ cancel: true,
2700
+ retryOnContentModified: Array.from(
2701
+ BaseLanguageClient.RequestsToCancelOnContentModified,
2702
+ ),
2703
+ };
2704
+ generalCapabilities.regularExpressions = {
2705
+ engine: 'ECMAScript',
2706
+ version: 'ES2020',
2707
+ };
2708
+ generalCapabilities.markdown = {
2709
+ parser: 'marked',
2710
+ version: '1.1.0',
2711
+ };
2712
+ generalCapabilities.positionEncodings = ['utf-16'];
2713
+
2714
+ if (this._clientOptions.markdown.supportHtml) {
2715
+ generalCapabilities.markdown.allowedTags = [
2716
+ 'ul',
2717
+ 'li',
2718
+ 'p',
2719
+ 'code',
2720
+ 'blockquote',
2721
+ 'ol',
2722
+ 'h1',
2723
+ 'h2',
2724
+ 'h3',
2725
+ 'h4',
2726
+ 'h5',
2727
+ 'h6',
2728
+ 'hr',
2729
+ 'em',
2730
+ 'pre',
2731
+ 'table',
2732
+ 'thead',
2733
+ 'tbody',
2734
+ 'tr',
2735
+ 'th',
2736
+ 'td',
2737
+ 'div',
2738
+ 'del',
2739
+ 'a',
2740
+ 'strong',
2741
+ 'br',
2742
+ 'img',
2743
+ 'span',
2744
+ ];
2745
+ }
2746
+
2747
+ for (const feature of this._features) {
2748
+ feature.fillClientCapabilities(result);
2749
+ }
2750
+ return result;
2751
+ }
2752
+
2753
+ private initializeFeatures(_connection: Connection): void {
2754
+ const documentSelector = this._clientOptions.documentSelector;
2755
+ for (const feature of this._features) {
2756
+ if (Is.func(feature.preInitialize)) {
2757
+ feature.preInitialize(this._capabilities, documentSelector);
2758
+ }
2759
+ }
2760
+ for (const feature of this._features) {
2761
+ feature.initialize(this._capabilities, documentSelector);
2762
+ }
2763
+ }
2764
+
2765
+ private async handleRegistrationRequest(params: RegistrationParams): Promise<void> {
2766
+ const middleware = this.clientOptions.middleware?.handleRegisterCapability;
2767
+ if (middleware) {
2768
+ return middleware(params, (nextParams) => this.doRegisterCapability(nextParams));
2769
+ } else {
2770
+ return this.doRegisterCapability(params);
2771
+ }
2772
+ }
2773
+
2774
+ private async doRegisterCapability(params: RegistrationParams): Promise<void> {
2775
+ // We will not receive a registration call before a client is running
2776
+ // from a server. However if we stop or shutdown we might which might
2777
+ // try to restart the server. So ignore registrations if we are not running
2778
+ if (!this.isRunning()) {
2779
+ for (const registration of params.registrations) {
2780
+ this._ignoredRegistrations.add(registration.id);
2781
+ }
2782
+ return;
2783
+ }
2784
+
2785
+ interface WithDocumentSelector {
2786
+ documentSelector: DocumentSelector | undefined;
2787
+ }
2788
+ for (const registration of params.registrations) {
2789
+ const feature = this._dynamicFeatures.get(registration.method);
2790
+ if (feature === undefined) {
2791
+ return Promise.reject(
2792
+ new Error(
2793
+ `No feature implementation for ${registration.method} found. Registration failed.`,
2794
+ ),
2795
+ );
2796
+ }
2797
+ const options = registration.registerOptions ?? {};
2798
+ (options as unknown as WithDocumentSelector).documentSelector =
2799
+ (options as unknown as WithDocumentSelector).documentSelector ??
2800
+ this._clientOptions.documentSelector;
2801
+ const data: RegistrationData<any> = {
2802
+ id: registration.id,
2803
+ registerOptions: options,
2804
+ };
2805
+ try {
2806
+ feature.register(data);
2807
+ } catch (err) {
2808
+ return Promise.reject(err);
2809
+ }
2810
+ }
2811
+ }
2812
+
2813
+ private async handleUnregistrationRequest(
2814
+ params: UnregistrationParams,
2815
+ ): Promise<void> {
2816
+ const middleware = this.clientOptions.middleware?.handleUnregisterCapability;
2817
+ if (middleware) {
2818
+ return middleware(params, (nextParams) =>
2819
+ this.doUnregisterCapability(nextParams),
2820
+ );
2821
+ } else {
2822
+ return this.doUnregisterCapability(params);
2823
+ }
2824
+ }
2825
+
2826
+ private async doUnregisterCapability(params: UnregistrationParams): Promise<void> {
2827
+ for (const unregistration of params.unregisterations) {
2828
+ if (this._ignoredRegistrations.has(unregistration.id)) {
2829
+ continue;
2830
+ }
2831
+ const feature = this._dynamicFeatures.get(unregistration.method);
2832
+ if (!feature) {
2833
+ return Promise.reject(
2834
+ new Error(
2835
+ `No feature implementation for ${unregistration.method} found. Unregistration failed.`,
2836
+ ),
2837
+ );
2838
+ }
2839
+ feature.unregister(unregistration.id);
2840
+ }
2841
+ }
2842
+
2843
+ private async handleApplyWorkspaceEdit(
2844
+ params: ApplyWorkspaceEditParams,
2845
+ ): Promise<ApplyWorkspaceEditResult> {
2846
+ const middleware = this.clientOptions.middleware?.workspace?.handleApplyEdit;
2847
+ if (middleware) {
2848
+ const resultOrError = await middleware(params, (nextParams) =>
2849
+ this.doHandleApplyWorkspaceEdit(nextParams),
2850
+ );
2851
+ if (resultOrError instanceof ResponseError) {
2852
+ return Promise.reject(resultOrError);
2853
+ }
2854
+ return resultOrError;
2855
+ } else {
2856
+ return this.doHandleApplyWorkspaceEdit(params);
2857
+ }
2858
+ }
2859
+
2860
+ private workspaceEditLock: Semaphore<VWorkspaceEdit> = new Semaphore(1);
2861
+ private async doHandleApplyWorkspaceEdit(
2862
+ params: ApplyWorkspaceEditParams,
2863
+ ): Promise<ApplyWorkspaceEditResult> {
2864
+ const workspaceEdit: WorkspaceEdit = params.edit;
2865
+ // Make sure we convert workspace edits one after the other. Otherwise
2866
+ // we might execute a workspace edit received first after we received another
2867
+ // one since the conversion might race.
2868
+ const converted = await this.workspaceEditLock.lock(() => {
2869
+ return this._p2c.asWorkspaceEdit(workspaceEdit);
2870
+ });
2871
+
2872
+ // This is some sort of workaround since the version check should be done by VS Code in the Workspace.applyEdit.
2873
+ // However doing it here adds some safety since the server can lag more behind then an extension.
2874
+ const openTextDocuments: Map<string, TextDocument> = new Map<
2875
+ string,
2876
+ TextDocument
2877
+ >();
2878
+ Workspace.textDocuments.forEach((document) =>
2879
+ openTextDocuments.set(document.uri.toString(), document),
2880
+ );
2881
+ let versionMismatch = false;
2882
+ if (workspaceEdit.documentChanges) {
2883
+ for (const change of workspaceEdit.documentChanges) {
2884
+ if (
2885
+ TextDocumentEdit.is(change) &&
2886
+ change.textDocument.version &&
2887
+ change.textDocument.version >= 0
2888
+ ) {
2889
+ const changeUri = this._p2c.asUri(change.textDocument.uri).toString();
2890
+ const textDocument = openTextDocuments.get(changeUri);
2891
+ if (textDocument && textDocument.version !== change.textDocument.version) {
2892
+ versionMismatch = true;
2893
+ break;
2894
+ }
2895
+ }
2896
+ }
2897
+ }
2898
+ if (versionMismatch) {
2899
+ return Promise.resolve({ applied: false });
2900
+ }
2901
+ return Is.asPromise(
2902
+ Workspace.applyEdit(converted).then((value) => {
2903
+ return { applied: value };
2904
+ }),
2905
+ );
2906
+ }
2907
+
2908
+ private static RequestsToCancelOnContentModified: Set<string> = new Set([
2909
+ SemanticTokensRequest.method,
2910
+ SemanticTokensRangeRequest.method,
2911
+ SemanticTokensDeltaRequest.method,
2912
+ ]);
2913
+ private static CancellableResolveCalls: Set<string> = new Set([
2914
+ CompletionResolveRequest.method,
2915
+ CodeLensResolveRequest.method,
2916
+ CodeActionResolveRequest.method,
2917
+ InlayHintResolveRequest.method,
2918
+ DocumentLinkResolveRequest.method,
2919
+ WorkspaceSymbolResolveRequest.method,
2920
+ ]);
2921
+
2922
+ public handleFailedRequest<T>(
2923
+ type: MessageSignature,
2924
+ token: CancellationToken | undefined,
2925
+ error: any,
2926
+ defaultValue: T,
2927
+ showNotification = true,
2928
+ ): T {
2929
+ // If we get a request cancel or a content modified don't log anything.
2930
+ if (error instanceof ResponseError) {
2931
+ // The connection got disposed while we were waiting for a response.
2932
+ // Simply return the default value. Is the best we can do.
2933
+ if (
2934
+ error.code === ErrorCodes.PendingResponseRejected ||
2935
+ error.code === ErrorCodes.ConnectionInactive
2936
+ ) {
2937
+ return defaultValue;
2938
+ }
2939
+ if (
2940
+ error.code === LSPErrorCodes.RequestCancelled ||
2941
+ error.code === LSPErrorCodes.ServerCancelled
2942
+ ) {
2943
+ if (token !== undefined && token.isCancellationRequested) {
2944
+ return defaultValue;
2945
+ } else {
2946
+ if (error.data !== undefined) {
2947
+ throw new LSPCancellationError(error.data);
2948
+ } else {
2949
+ throw new CancellationError();
2950
+ }
2951
+ }
2952
+ } else if (error.code === LSPErrorCodes.ContentModified) {
2953
+ if (
2954
+ BaseLanguageClient.RequestsToCancelOnContentModified.has(type.method) ||
2955
+ BaseLanguageClient.CancellableResolveCalls.has(type.method)
2956
+ ) {
2957
+ throw new CancellationError();
2958
+ } else {
2959
+ return defaultValue;
2960
+ }
2961
+ }
2962
+ }
2963
+ this.error(`Request ${type.method} failed.`, error, showNotification);
2964
+ throw error;
2965
+ }
2966
+
2967
+ // private checkSuspend(): void {
2968
+ // if (this.$state !== ClientState.Running) {
2969
+ // return;
2970
+ // }
2971
+ // const connection = this.activeConnection();
2972
+ // if (connection === undefined) {
2973
+ // this._idleStart = undefined;
2974
+ // return;
2975
+ // }
2976
+ // // Since the last idle start we sent a request. Cancel the idle counting.
2977
+ // if (connection.hasPendingResponse() || (this._idleStart !== undefined && connection.lastUsed > this._idleStart)) {
2978
+ // this._idleStart = undefined;
2979
+ // return;
2980
+ // }
2981
+ // if (this.isIdle()) {
2982
+ // const production = (this.clientOptions as TestOptions).$testMode !== true;
2983
+ // // Only do this in production since in test cases we only have
2984
+ // // 2000 ms to suspend.
2985
+ // if (production) {
2986
+ // if (this._idleStart === undefined) {
2987
+ // this._idleStart = Date.now();
2988
+ // return;
2989
+ // }
2990
+
2991
+ // const interval = this._clientOptions.suspend.interval;
2992
+ // const diff = Date.now() - this._idleStart;
2993
+ // if (diff < interval * 3) {
2994
+ // return;
2995
+ // }
2996
+ // if (diff > interval * 5) {
2997
+ // // Avoid that we shutdown the server when a computer resumes from sleep.
2998
+ // this._idleStart = undefined;
2999
+ // return;
3000
+ // }
3001
+ // }
3002
+
3003
+ // this._idleStart = undefined;
3004
+ // this.info(`Suspending server`);
3005
+ // this._clientOptions.suspend.callback().then((approved) => {
3006
+ // if (!approved) {
3007
+ // this._idleStart = undefined;
3008
+ // return;
3009
+ // }
3010
+ // return this.suspend().then(() => {
3011
+ // this.info(`Server got suspended`);
3012
+ // });
3013
+ // }, (error) => {
3014
+ // this.error(`Suspending server failed`, error, 'force');
3015
+ // });
3016
+ // } else {
3017
+ // this._idleStart = undefined;
3018
+ // }
3019
+ // }
3020
+
3021
+ // private isIdle(): boolean {
3022
+ // const suspendMode = this._clientOptions.suspend.mode;
3023
+ // if (suspendMode === SuspendMode.off) {
3024
+ // return false;
3025
+ // }
3026
+
3027
+ // for (const feature of this._features) {
3028
+ // const state = feature.getState();
3029
+ // // 'static' feature don't depend on registrations. So they
3030
+ // // can't block suspend
3031
+ // if (state.kind === 'static') {
3032
+ // continue;
3033
+ // }
3034
+ // // The feature has no registrations. So no blocking of the
3035
+ // // suspend.
3036
+ // if (!state.registrations) {
3037
+ // continue;
3038
+ // }
3039
+
3040
+ // if (state.kind === 'document' && state.matches === true) {
3041
+ // return false;
3042
+ // }
3043
+ // }
3044
+ // return true;
3045
+ // }
3046
+ }
3047
+
3048
+ interface Connection {
3049
+ listen(): void;
3050
+
3051
+ sendRequest<R>(type: string | MessageSignature, ...params: any[]): Promise<R>;
3052
+ onRequest<R, E>(
3053
+ method: string | MessageSignature,
3054
+ handler: GenericRequestHandler<R, E>,
3055
+ ): Disposable;
3056
+
3057
+ hasPendingResponse(): boolean;
3058
+
3059
+ sendNotification(method: string | MessageSignature, params?: any): Promise<void>;
3060
+ onNotification(
3061
+ method: string | MessageSignature,
3062
+ handler: GenericNotificationHandler,
3063
+ ): Disposable;
3064
+
3065
+ onProgress<P>(
3066
+ type: ProgressType<P>,
3067
+ token: string | number,
3068
+ handler: NotificationHandler<P>,
3069
+ ): Disposable;
3070
+ sendProgress<P>(
3071
+ type: ProgressType<P>,
3072
+ token: string | number,
3073
+ value: P,
3074
+ ): Promise<void>;
3075
+
3076
+ trace(value: Trace, tracer: Tracer, sendNotification?: boolean): Promise<void>;
3077
+ trace(value: Trace, tracer: Tracer, traceOptions?: TraceOptions): Promise<void>;
3078
+
3079
+ initialize(params: InitializeParams): Promise<InitializeResult>;
3080
+ shutdown(): Promise<void>;
3081
+ exit(): Promise<void>;
3082
+
3083
+ end(): void;
3084
+ dispose(): void;
3085
+ }
3086
+
3087
+ class ConsoleLogger implements Logger {
3088
+ public error(message: string): void {
3089
+ RAL().console.error(message);
3090
+ }
3091
+ public warn(message: string): void {
3092
+ RAL().console.warn(message);
3093
+ }
3094
+ public info(message: string): void {
3095
+ RAL().console.info(message);
3096
+ }
3097
+ public log(message: string): void {
3098
+ RAL().console.log(message);
3099
+ }
3100
+ }
3101
+
3102
+ interface ConnectionErrorHandler {
3103
+ (error: Error, message: Message | undefined, count: number | undefined): void;
3104
+ }
3105
+
3106
+ interface ConnectionCloseHandler {
3107
+ (): void;
3108
+ }
3109
+
3110
+ function createConnection(
3111
+ input: MessageReader,
3112
+ output: MessageWriter,
3113
+ errorHandler: ConnectionErrorHandler,
3114
+ closeHandler: ConnectionCloseHandler,
3115
+ options?: ConnectionOptions,
3116
+ ): Connection {
3117
+ const logger = new ConsoleLogger();
3118
+ const connection = createProtocolConnection(input, output, logger, options);
3119
+ connection.onError((data) => {
3120
+ errorHandler(data[0], data[1], data[2]);
3121
+ });
3122
+ connection.onClose(closeHandler);
3123
+ const result: Connection = {
3124
+ listen: (): void => connection.listen(),
3125
+
3126
+ sendRequest: connection.sendRequest,
3127
+
3128
+ onRequest: connection.onRequest,
3129
+
3130
+ hasPendingResponse: connection.hasPendingResponse,
3131
+
3132
+ sendNotification: connection.sendNotification,
3133
+
3134
+ onNotification: connection.onNotification,
3135
+
3136
+ onProgress: connection.onProgress,
3137
+ sendProgress: connection.sendProgress,
3138
+
3139
+ trace: (
3140
+ value: Trace,
3141
+ tracer: Tracer,
3142
+ sendNotificationOrTraceOptions?: boolean | TraceOptions,
3143
+ ): Promise<void> => {
3144
+ const defaultTraceOptions: TraceOptions = {
3145
+ sendNotification: false,
3146
+ traceFormat: TraceFormat.Text,
3147
+ };
3148
+
3149
+ if (sendNotificationOrTraceOptions === undefined) {
3150
+ return connection.trace(value, tracer, defaultTraceOptions);
3151
+ } else if (Is.boolean(sendNotificationOrTraceOptions)) {
3152
+ return connection.trace(value, tracer, sendNotificationOrTraceOptions);
3153
+ } else {
3154
+ return connection.trace(value, tracer, sendNotificationOrTraceOptions);
3155
+ }
3156
+ },
3157
+
3158
+ initialize: (params: InitializeParams) => {
3159
+ // This needs to return and MUST not be await to avoid any async
3160
+ // scheduling. Otherwise messages might overtake each other.
3161
+ return connection.sendRequest(InitializeRequest.type, params);
3162
+ },
3163
+ shutdown: () => {
3164
+ // This needs to return and MUST not be await to avoid any async
3165
+ // scheduling. Otherwise messages might overtake each other.
3166
+ return connection.sendRequest(ShutdownRequest.type, undefined);
3167
+ },
3168
+ exit: () => {
3169
+ // This needs to return and MUST not be await to avoid any async
3170
+ // scheduling. Otherwise messages might overtake each other.
3171
+ return connection.sendNotification(ExitNotification.type);
3172
+ },
3173
+
3174
+ end: () => connection.end(),
3175
+ dispose: () => connection.dispose(),
3176
+ };
3177
+
3178
+ return result;
3179
+ }
3180
+
3181
+ // Exporting proposed protocol.
3182
+
3183
+ export namespace ProposedFeatures {
3184
+ export function createAll(
3185
+ _client: FeatureClient<Middleware, LanguageClientOptions>,
3186
+ ): (StaticFeature | DynamicFeature<any>)[] {
3187
+ const result: (StaticFeature | DynamicFeature<any>)[] = [
3188
+ new InlineCompletionItemFeature(_client),
3189
+ ];
3190
+ return result;
3191
+ }
3192
+ }