@theia/plugin-ext 1.27.0-next.9 → 1.27.0

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 (273) hide show
  1. package/lib/common/connection.d.ts +3 -3
  2. package/lib/common/connection.d.ts.map +1 -1
  3. package/lib/common/connection.js +0 -1
  4. package/lib/common/connection.js.map +1 -1
  5. package/lib/common/plugin-api-rpc.d.ts +18 -8
  6. package/lib/common/plugin-api-rpc.d.ts.map +1 -1
  7. package/lib/common/plugin-api-rpc.js.map +1 -1
  8. package/lib/common/plugin-identifiers.d.ts +41 -0
  9. package/lib/common/plugin-identifiers.d.ts.map +1 -0
  10. package/lib/common/plugin-identifiers.js +81 -0
  11. package/lib/common/plugin-identifiers.js.map +1 -0
  12. package/lib/common/plugin-protocol.d.ts +50 -11
  13. package/lib/common/plugin-protocol.d.ts.map +1 -1
  14. package/lib/common/plugin-protocol.js +3 -1
  15. package/lib/common/plugin-protocol.js.map +1 -1
  16. package/lib/hosted/browser/hosted-plugin.d.ts +2 -2
  17. package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
  18. package/lib/hosted/browser/hosted-plugin.js +26 -18
  19. package/lib/hosted/browser/hosted-plugin.js.map +1 -1
  20. package/lib/hosted/browser/worker/debug-stub.d.ts +1 -1
  21. package/lib/hosted/browser/worker/debug-stub.d.ts.map +1 -1
  22. package/lib/hosted/browser/worker/debug-stub.js +2 -2
  23. package/lib/hosted/browser/worker/debug-stub.js.map +1 -1
  24. package/lib/hosted/browser/worker/plugin-manifest-loader.d.ts.map +1 -1
  25. package/lib/hosted/browser/worker/plugin-manifest-loader.js +4 -1
  26. package/lib/hosted/browser/worker/plugin-manifest-loader.js.map +1 -1
  27. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts +17 -9
  28. package/lib/hosted/node/hosted-plugin-deployer-handler.d.ts.map +1 -1
  29. package/lib/hosted/node/hosted-plugin-deployer-handler.js +99 -18
  30. package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
  31. package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
  32. package/lib/hosted/node/hosted-plugin-localization-service.js +2 -4
  33. package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
  34. package/lib/hosted/node/hosted-plugin-process.d.ts +2 -2
  35. package/lib/hosted/node/hosted-plugin-process.d.ts.map +1 -1
  36. package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
  37. package/lib/hosted/node/hosted-plugin.d.ts +2 -2
  38. package/lib/hosted/node/hosted-plugin.d.ts.map +1 -1
  39. package/lib/hosted/node/hosted-plugin.js.map +1 -1
  40. package/lib/hosted/node/metadata-scanner.d.ts +3 -2
  41. package/lib/hosted/node/metadata-scanner.d.ts.map +1 -1
  42. package/lib/hosted/node/metadata-scanner.js +8 -3
  43. package/lib/hosted/node/metadata-scanner.js.map +1 -1
  44. package/lib/hosted/node/plugin-host-rpc.js +2 -2
  45. package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
  46. package/lib/hosted/node/plugin-manifest-loader.d.ts.map +1 -1
  47. package/lib/hosted/node/plugin-manifest-loader.js +3 -0
  48. package/lib/hosted/node/plugin-manifest-loader.js.map +1 -1
  49. package/lib/hosted/node/plugin-service.d.ts +18 -4
  50. package/lib/hosted/node/plugin-service.d.ts.map +1 -1
  51. package/lib/hosted/node/plugin-service.js +73 -18
  52. package/lib/hosted/node/plugin-service.js.map +1 -1
  53. package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
  54. package/lib/hosted/node/scanners/scanner-theia.js +6 -3
  55. package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
  56. package/lib/main/browser/custom-editors/custom-editor-opener.d.ts.map +1 -1
  57. package/lib/main/browser/custom-editors/custom-editor-opener.js +2 -2
  58. package/lib/main/browser/custom-editors/custom-editor-opener.js.map +1 -1
  59. package/lib/main/browser/debug/plugin-debug-session-factory.d.ts +3 -3
  60. package/lib/main/browser/debug/plugin-debug-session-factory.d.ts.map +1 -1
  61. package/lib/main/browser/debug/plugin-debug-session-factory.js.map +1 -1
  62. package/lib/main/browser/documents-main.d.ts +1 -2
  63. package/lib/main/browser/documents-main.d.ts.map +1 -1
  64. package/lib/main/browser/documents-main.js +26 -6
  65. package/lib/main/browser/documents-main.js.map +1 -1
  66. package/lib/main/browser/editors-and-documents-main.d.ts +2 -0
  67. package/lib/main/browser/editors-and-documents-main.d.ts.map +1 -1
  68. package/lib/main/browser/editors-and-documents-main.js +14 -2
  69. package/lib/main/browser/editors-and-documents-main.js.map +1 -1
  70. package/lib/main/browser/languages-main.d.ts.map +1 -1
  71. package/lib/main/browser/languages-main.js +2 -1
  72. package/lib/main/browser/languages-main.js.map +1 -1
  73. package/lib/main/browser/main-context.d.ts.map +1 -1
  74. package/lib/main/browser/main-context.js +5 -4
  75. package/lib/main/browser/main-context.js.map +1 -1
  76. package/lib/main/browser/plugin-contribution-handler.d.ts +2 -0
  77. package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
  78. package/lib/main/browser/plugin-contribution-handler.js +36 -1
  79. package/lib/main/browser/plugin-contribution-handler.js.map +1 -1
  80. package/lib/main/browser/plugin-shared-style.d.ts +4 -2
  81. package/lib/main/browser/plugin-shared-style.d.ts.map +1 -1
  82. package/lib/main/browser/plugin-shared-style.js +15 -4
  83. package/lib/main/browser/plugin-shared-style.js.map +1 -1
  84. package/lib/main/browser/text-editors-main.d.ts +6 -3
  85. package/lib/main/browser/text-editors-main.d.ts.map +1 -1
  86. package/lib/main/browser/text-editors-main.js +8 -1
  87. package/lib/main/browser/text-editors-main.js.map +1 -1
  88. package/lib/main/browser/theming-main.d.ts +2 -1
  89. package/lib/main/browser/theming-main.d.ts.map +1 -1
  90. package/lib/main/browser/theming-main.js +3 -6
  91. package/lib/main/browser/theming-main.js.map +1 -1
  92. package/lib/main/browser/view/plugin-tree-view-node-label-provider.d.ts.map +1 -1
  93. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js +7 -5
  94. package/lib/main/browser/view/plugin-tree-view-node-label-provider.js.map +1 -1
  95. package/lib/main/browser/view/plugin-view-registry.d.ts +1 -1
  96. package/lib/main/browser/view/plugin-view-registry.d.ts.map +1 -1
  97. package/lib/main/browser/view/plugin-view-registry.js +11 -6
  98. package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
  99. package/lib/main/browser/view/tree-view-widget.d.ts +10 -5
  100. package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
  101. package/lib/main/browser/view/tree-view-widget.js +40 -14
  102. package/lib/main/browser/view/tree-view-widget.js.map +1 -1
  103. package/lib/main/browser/webview/webview-theme-data-provider.d.ts +3 -1
  104. package/lib/main/browser/webview/webview-theme-data-provider.d.ts.map +1 -1
  105. package/lib/main/browser/webview/webview-theme-data-provider.js +5 -1
  106. package/lib/main/browser/webview/webview-theme-data-provider.js.map +1 -1
  107. package/lib/main/node/handlers/plugin-theia-directory-handler.d.ts +6 -1
  108. package/lib/main/node/handlers/plugin-theia-directory-handler.d.ts.map +1 -1
  109. package/lib/main/node/handlers/plugin-theia-directory-handler.js +61 -20
  110. package/lib/main/node/handlers/plugin-theia-directory-handler.js.map +1 -1
  111. package/lib/main/node/handlers/plugin-theia-file-handler.d.ts +4 -0
  112. package/lib/main/node/handlers/plugin-theia-file-handler.d.ts.map +1 -1
  113. package/lib/main/node/handlers/plugin-theia-file-handler.js +26 -4
  114. package/lib/main/node/handlers/plugin-theia-file-handler.js.map +1 -1
  115. package/lib/main/node/plugin-cli-contribution.d.ts +3 -0
  116. package/lib/main/node/plugin-cli-contribution.d.ts.map +1 -1
  117. package/lib/main/node/plugin-cli-contribution.js +13 -0
  118. package/lib/main/node/plugin-cli-contribution.js.map +1 -1
  119. package/lib/main/node/plugin-deployer-directory-handler-context-impl.d.ts +1 -0
  120. package/lib/main/node/plugin-deployer-directory-handler-context-impl.d.ts.map +1 -1
  121. package/lib/main/node/plugin-deployer-directory-handler-context-impl.js +17 -0
  122. package/lib/main/node/plugin-deployer-directory-handler-context-impl.js.map +1 -1
  123. package/lib/main/node/plugin-deployer-file-handler-context-impl.d.ts.map +1 -1
  124. package/lib/main/node/plugin-deployer-file-handler-context-impl.js +0 -1
  125. package/lib/main/node/plugin-deployer-file-handler-context-impl.js.map +1 -1
  126. package/lib/main/node/plugin-deployer-impl.d.ts +10 -7
  127. package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
  128. package/lib/main/node/plugin-deployer-impl.js +84 -38
  129. package/lib/main/node/plugin-deployer-impl.js.map +1 -1
  130. package/lib/main/node/plugin-ext-backend-module.d.ts.map +1 -1
  131. package/lib/main/node/plugin-ext-backend-module.js +2 -0
  132. package/lib/main/node/plugin-ext-backend-module.js.map +1 -1
  133. package/lib/main/node/plugin-server-handler.d.ts +5 -4
  134. package/lib/main/node/plugin-server-handler.d.ts.map +1 -1
  135. package/lib/main/node/plugin-server-handler.js +12 -5
  136. package/lib/main/node/plugin-server-handler.js.map +1 -1
  137. package/lib/main/node/plugin-uninstallation-manager.d.ts +15 -0
  138. package/lib/main/node/plugin-uninstallation-manager.d.ts.map +1 -0
  139. package/lib/main/node/plugin-uninstallation-manager.js +85 -0
  140. package/lib/main/node/plugin-uninstallation-manager.js.map +1 -0
  141. package/lib/plugin/{node/debug/debug.d.ts → debug/debug-ext.d.ts} +15 -13
  142. package/lib/plugin/debug/debug-ext.d.ts.map +1 -0
  143. package/lib/plugin/{node/debug/debug.js → debug/debug-ext.js} +17 -51
  144. package/lib/plugin/debug/debug-ext.js.map +1 -0
  145. package/lib/plugin/debug/plugin-debug-adapter-creator.d.ts +11 -0
  146. package/lib/plugin/debug/plugin-debug-adapter-creator.d.ts.map +1 -0
  147. package/lib/plugin/debug/plugin-debug-adapter-creator.js +42 -0
  148. package/lib/plugin/debug/plugin-debug-adapter-creator.js.map +1 -0
  149. package/lib/plugin/{node/debug → debug}/plugin-debug-adapter-session.d.ts +4 -4
  150. package/lib/plugin/debug/plugin-debug-adapter-session.d.ts.map +1 -0
  151. package/lib/plugin/{node/debug → debug}/plugin-debug-adapter-session.js +1 -1
  152. package/lib/plugin/debug/plugin-debug-adapter-session.js.map +1 -0
  153. package/lib/plugin/{node/debug → debug}/plugin-debug-adapter-tracker.d.ts +0 -0
  154. package/lib/plugin/debug/plugin-debug-adapter-tracker.d.ts.map +1 -0
  155. package/lib/plugin/{node/debug → debug}/plugin-debug-adapter-tracker.js +0 -0
  156. package/lib/plugin/debug/plugin-debug-adapter-tracker.js.map +1 -0
  157. package/lib/plugin/languages-utils.d.ts.map +1 -1
  158. package/lib/plugin/languages-utils.js +3 -2
  159. package/lib/plugin/languages-utils.js.map +1 -1
  160. package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.d.ts +18 -0
  161. package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.d.ts.map +1 -0
  162. package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.js +155 -0
  163. package/lib/plugin/node/debug/plugin-node-debug-adapter-creator.js.map +1 -0
  164. package/lib/plugin/plugin-context.d.ts +1 -1
  165. package/lib/plugin/plugin-context.d.ts.map +1 -1
  166. package/lib/plugin/plugin-context.js +1 -2
  167. package/lib/plugin/plugin-context.js.map +1 -1
  168. package/lib/plugin/plugin-manager.d.ts.map +1 -1
  169. package/lib/plugin/plugin-manager.js +5 -9
  170. package/lib/plugin/plugin-manager.js.map +1 -1
  171. package/lib/plugin/text-editor.d.ts +2 -0
  172. package/lib/plugin/text-editor.d.ts.map +1 -1
  173. package/lib/plugin/text-editor.js +9 -0
  174. package/lib/plugin/text-editor.js.map +1 -1
  175. package/lib/plugin/theming.d.ts +1 -1
  176. package/lib/plugin/theming.d.ts.map +1 -1
  177. package/lib/plugin/tree/tree-views.d.ts +1 -0
  178. package/lib/plugin/tree/tree-views.d.ts.map +1 -1
  179. package/lib/plugin/tree/tree-views.js +10 -9
  180. package/lib/plugin/tree/tree-views.js.map +1 -1
  181. package/lib/plugin/types-impl.d.ts +1 -0
  182. package/lib/plugin/types-impl.d.ts.map +1 -1
  183. package/lib/plugin/types-impl.js +3 -2
  184. package/lib/plugin/types-impl.js.map +1 -1
  185. package/package.json +26 -25
  186. package/src/common/connection.ts +3 -4
  187. package/src/common/plugin-api-rpc.ts +20 -12
  188. package/src/common/plugin-identifiers.ts +84 -0
  189. package/src/common/plugin-protocol.ts +57 -12
  190. package/src/hosted/browser/hosted-plugin.ts +28 -21
  191. package/src/hosted/browser/worker/debug-stub.ts +1 -1
  192. package/src/hosted/browser/worker/plugin-manifest-loader.ts +4 -2
  193. package/src/hosted/node/hosted-plugin-deployer-handler.ts +109 -28
  194. package/src/hosted/node/hosted-plugin-localization-service.ts +4 -6
  195. package/src/hosted/node/hosted-plugin-process.ts +4 -4
  196. package/src/hosted/node/hosted-plugin.ts +2 -2
  197. package/src/hosted/node/metadata-scanner.ts +8 -6
  198. package/src/hosted/node/plugin-host-rpc.ts +2 -2
  199. package/src/hosted/node/plugin-manifest-loader.ts +2 -0
  200. package/src/hosted/node/plugin-service.ts +79 -23
  201. package/src/hosted/node/scanners/scanner-theia.ts +7 -4
  202. package/src/main/browser/custom-editors/custom-editor-opener.tsx +2 -2
  203. package/src/main/browser/debug/plugin-debug-session-factory.ts +2 -2
  204. package/src/main/browser/documents-main.ts +26 -8
  205. package/src/main/browser/editors-and-documents-main.ts +16 -2
  206. package/src/main/browser/languages-main.ts +2 -1
  207. package/src/main/browser/main-context.ts +4 -3
  208. package/src/main/browser/plugin-contribution-handler.ts +41 -3
  209. package/src/main/browser/plugin-icon-theme-service.ts +1 -1
  210. package/src/main/browser/plugin-shared-style.ts +9 -5
  211. package/src/main/browser/text-editors-main.ts +12 -2
  212. package/src/main/browser/theming-main.ts +3 -7
  213. package/src/main/browser/view/plugin-tree-view-node-label-provider.ts +7 -5
  214. package/src/main/browser/view/plugin-view-registry.ts +12 -7
  215. package/src/main/browser/view/tree-view-widget.tsx +45 -17
  216. package/src/main/browser/webview/webview-theme-data-provider.ts +7 -10
  217. package/src/main/node/handlers/plugin-theia-directory-handler.ts +56 -28
  218. package/src/main/node/handlers/plugin-theia-file-handler.ts +26 -4
  219. package/src/main/node/plugin-cli-contribution.ts +12 -0
  220. package/src/main/node/plugin-deployer-directory-handler-context-impl.ts +17 -1
  221. package/src/main/node/plugin-deployer-file-handler-context-impl.ts +0 -1
  222. package/src/main/node/plugin-deployer-impl.ts +88 -41
  223. package/src/main/node/plugin-ext-backend-module.ts +3 -0
  224. package/src/main/node/plugin-server-handler.ts +15 -7
  225. package/src/main/node/plugin-uninstallation-manager.ts +74 -0
  226. package/src/plugin/{node/debug/debug.ts → debug/debug-ext.ts} +25 -56
  227. package/src/plugin/debug/plugin-debug-adapter-creator.ts +50 -0
  228. package/src/plugin/{node/debug → debug}/plugin-debug-adapter-session.ts +4 -4
  229. package/src/plugin/{node/debug → debug}/plugin-debug-adapter-tracker.ts +0 -0
  230. package/src/plugin/languages-utils.ts +3 -2
  231. package/src/plugin/node/debug/plugin-node-debug-adapter-creator.ts +167 -0
  232. package/src/plugin/plugin-context.ts +2 -3
  233. package/src/plugin/plugin-manager.ts +5 -9
  234. package/src/plugin/text-editor.ts +16 -5
  235. package/src/plugin/theming.ts +1 -1
  236. package/src/plugin/tree/tree-views.ts +15 -12
  237. package/src/plugin/types-impl.ts +1 -1
  238. package/lib/main/browser/custom-editors/glob.d.ts +0 -51
  239. package/lib/main/browser/custom-editors/glob.d.ts.map +0 -1
  240. package/lib/main/browser/custom-editors/glob.js +0 -593
  241. package/lib/main/browser/custom-editors/glob.js.map +0 -1
  242. package/lib/main/browser/custom-editors/paths.d.ts +0 -25
  243. package/lib/main/browser/custom-editors/paths.d.ts.map +0 -1
  244. package/lib/main/browser/custom-editors/paths.js +0 -227
  245. package/lib/main/browser/custom-editors/paths.js.map +0 -1
  246. package/lib/main/browser/editor/untitled-resource.d.ts +0 -3
  247. package/lib/main/browser/editor/untitled-resource.d.ts.map +0 -1
  248. package/lib/main/browser/editor/untitled-resource.js +0 -24
  249. package/lib/main/browser/editor/untitled-resource.js.map +0 -1
  250. package/lib/plugin/node/debug/debug.d.ts.map +0 -1
  251. package/lib/plugin/node/debug/debug.js.map +0 -1
  252. package/lib/plugin/node/debug/plugin-debug-adapter-executable-resolver.d.ts +0 -7
  253. package/lib/plugin/node/debug/plugin-debug-adapter-executable-resolver.d.ts.map +0 -1
  254. package/lib/plugin/node/debug/plugin-debug-adapter-executable-resolver.js +0 -57
  255. package/lib/plugin/node/debug/plugin-debug-adapter-executable-resolver.js.map +0 -1
  256. package/lib/plugin/node/debug/plugin-debug-adapter-session.d.ts.map +0 -1
  257. package/lib/plugin/node/debug/plugin-debug-adapter-session.js.map +0 -1
  258. package/lib/plugin/node/debug/plugin-debug-adapter-starter.d.ts +0 -15
  259. package/lib/plugin/node/debug/plugin-debug-adapter-starter.d.ts.map +0 -1
  260. package/lib/plugin/node/debug/plugin-debug-adapter-starter.js +0 -85
  261. package/lib/plugin/node/debug/plugin-debug-adapter-starter.js.map +0 -1
  262. package/lib/plugin/node/debug/plugin-debug-adapter-tracker.d.ts.map +0 -1
  263. package/lib/plugin/node/debug/plugin-debug-adapter-tracker.js.map +0 -1
  264. package/lib/plugin/node/debug/plugin-inline-debug-adapter.d.ts +0 -19
  265. package/lib/plugin/node/debug/plugin-inline-debug-adapter.d.ts.map +0 -1
  266. package/lib/plugin/node/debug/plugin-inline-debug-adapter.js +0 -45
  267. package/lib/plugin/node/debug/plugin-inline-debug-adapter.js.map +0 -1
  268. package/src/main/browser/custom-editors/glob.ts +0 -743
  269. package/src/main/browser/custom-editors/paths.ts +0 -250
  270. package/src/main/browser/editor/untitled-resource.ts +0 -18
  271. package/src/plugin/node/debug/plugin-debug-adapter-executable-resolver.ts +0 -58
  272. package/src/plugin/node/debug/plugin-debug-adapter-starter.ts +0 -86
  273. package/src/plugin/node/debug/plugin-inline-debug-adapter.ts +0 -47
@@ -0,0 +1,84 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2022 Ericsson and others.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ export namespace PluginIdentifiers {
18
+ export interface Components {
19
+ publisher?: string;
20
+ name: string;
21
+ version: string;
22
+ }
23
+
24
+ export interface IdAndVersion {
25
+ id: UnversionedId;
26
+ version: string;
27
+ }
28
+
29
+ export type VersionedId = `${string}.${string}@${string}`;
30
+ export type UnversionedId = `${string}.${string}`;
31
+ /** Unpublished plugins (not from Open VSX or VSCode plugin store) may not have a `publisher` field. */
32
+ export const UNPUBLISHED = '<unpublished>';
33
+
34
+ /**
35
+ * @returns a string in the format `<publisher>.<name>`
36
+ */
37
+ export function componentsToUnversionedId({ publisher = UNPUBLISHED, name }: Components): UnversionedId {
38
+ return `${publisher.toLowerCase()}.${name.toLowerCase()}`;
39
+ }
40
+ /**
41
+ * @returns a string in the format `<publisher>.<name>@<version>`.
42
+ */
43
+ export function componentsToVersionedId({ publisher = UNPUBLISHED, name, version }: Components): VersionedId {
44
+ return `${publisher.toLowerCase()}.${name.toLowerCase()}@${version}`;
45
+ }
46
+ export function componentsToVersionWithId(components: Components): IdAndVersion {
47
+ return { id: componentsToUnversionedId(components), version: components.version };
48
+ }
49
+ /**
50
+ * @returns a string in the format `<id>@<version>`.
51
+ */
52
+ export function idAndVersionToVersionedId({ id, version }: IdAndVersion): VersionedId {
53
+ return `${id}@${version}`;
54
+ }
55
+ /**
56
+ * @returns a string in the format `<publisher>.<name>`.
57
+ */
58
+ export function unversionedFromVersioned(id: VersionedId): UnversionedId {
59
+ const endOfId = id.indexOf('@');
60
+ return id.slice(0, endOfId) as UnversionedId;
61
+ }
62
+ /**
63
+ * @returns `undefined` if it looks like the string passed in does not have the format returned by {@link PluginIdentifiers.toVersionedId}.
64
+ */
65
+ export function identifiersFromVersionedId(probablyId: string): Components | undefined {
66
+ const endOfPublisher = probablyId.indexOf('.');
67
+ const endOfName = probablyId.indexOf('@', endOfPublisher);
68
+ if (endOfPublisher === -1 || endOfName === -1) {
69
+ return undefined;
70
+ }
71
+ return { publisher: probablyId.slice(0, endOfPublisher), name: probablyId.slice(endOfPublisher + 1, endOfName), version: probablyId.slice(endOfName + 1) };
72
+ }
73
+ /**
74
+ * @returns `undefined` if it looks like the string passed in does not have the format returned by {@link PluginIdentifiers.toVersionedId}.
75
+ */
76
+ export function idAndVersionFromVersionedId(probablyId: string): IdAndVersion | undefined {
77
+ const endOfPublisher = probablyId.indexOf('.');
78
+ const endOfName = probablyId.indexOf('@', endOfPublisher);
79
+ if (endOfPublisher === -1 || endOfName === -1) {
80
+ return undefined;
81
+ }
82
+ return { id: probablyId.slice(0, endOfName) as UnversionedId, version: probablyId.slice(endOfName + 1) };
83
+ }
84
+ }
@@ -25,7 +25,9 @@ import { PreferenceSchema, PreferenceSchemaProperties } from '@theia/core/lib/co
25
25
  import { ProblemMatcherContribution, ProblemPatternContribution, TaskDefinition } from '@theia/task/lib/common';
26
26
  import { ColorDefinition } from '@theia/core/lib/common/color';
27
27
  import { ResourceLabelFormatter } from '@theia/core/lib/common/label-protocol';
28
+ import { PluginIdentifiers } from './plugin-identifiers';
28
29
 
30
+ export { PluginIdentifiers };
29
31
  export const hostedServicePath = '/services/hostedPlugin';
30
32
 
31
33
  /**
@@ -38,7 +40,8 @@ export type PluginEngine = string;
38
40
  */
39
41
  export interface PluginPackage {
40
42
  name: string;
41
- publisher: string;
43
+ // The publisher is not guaranteed to be defined for unpublished plugins. https://github.com/microsoft/vscode-vsce/commit/a38657ece04c20e4fbde15d5ac1ed39ca51cb856
44
+ publisher: string | undefined;
42
45
  version: string;
43
46
  engines: {
44
47
  [type in PluginEngine]: string;
@@ -271,6 +274,7 @@ export interface PluginPackageLanguageContributionConfiguration {
271
274
  wordPattern?: string;
272
275
  indentationRules?: IndentationRules;
273
276
  folding?: FoldingRules;
277
+ onEnterRules?: OnEnterRule[];
274
278
  }
275
279
 
276
280
  export interface PluginTaskDefinitionContribution {
@@ -339,7 +343,7 @@ export interface PluginDeployerResolver {
339
343
 
340
344
  accept(pluginSourceId: string): boolean;
341
345
 
342
- resolve(pluginResolverContext: PluginDeployerResolverContext): Promise<void>;
346
+ resolve(pluginResolverContext: PluginDeployerResolverContext, options?: PluginDeployOptions): Promise<void>;
343
347
 
344
348
  }
345
349
 
@@ -486,6 +490,8 @@ export interface PluginDeployerFileHandlerContext {
486
490
 
487
491
  export interface PluginDeployerDirectoryHandlerContext {
488
492
 
493
+ copy(origin: string, target: string): Promise<void>;
494
+
489
495
  pluginEntry(): PluginDeployerEntry;
490
496
 
491
497
  }
@@ -622,6 +628,7 @@ export interface LanguageConfiguration {
622
628
  comments?: CommentRule;
623
629
  folding?: FoldingRules;
624
630
  wordPattern?: string;
631
+ onEnterRules?: OnEnterRule[];
625
632
  }
626
633
 
627
634
  /**
@@ -670,6 +677,19 @@ export interface FoldingRules {
670
677
  markers?: FoldingMarkers;
671
678
  }
672
679
 
680
+ export interface OnEnterRule {
681
+ beforeText: string;
682
+ afterText?: string;
683
+ previousLineText?: string;
684
+ action: EnterAction;
685
+ }
686
+
687
+ export interface EnterAction {
688
+ indent: 'none' | 'indent' | 'outdent' | 'indentOutdent';
689
+ appendText?: string;
690
+ removeText?: number;
691
+ }
692
+
673
693
  /**
674
694
  * Custom Editors contribution
675
695
  */
@@ -796,6 +816,7 @@ export interface PluginMetadata {
796
816
  model: PluginModel;
797
817
  lifecycle: PluginLifecycle;
798
818
  isUnderDevelopment?: boolean;
819
+ outOfSync: boolean;
799
820
  }
800
821
 
801
822
  export const MetadataProcessor = Symbol('MetadataProcessor');
@@ -822,22 +843,38 @@ export interface HostedPluginClient {
822
843
 
823
844
  export interface PluginDependencies {
824
845
  metadata: PluginMetadata
846
+ /**
847
+ * Actual listing of plugin dependencies.
848
+ * Mapping from {@link PluginIdentifiers.UnversionedId external representation} of plugin identity to a string
849
+ * that can be used to identify the resolver for the specific plugin case, e.g. with scheme `vscode://<id>`.
850
+ */
825
851
  mapping?: Map<string, string>
826
852
  }
827
853
 
828
854
  export const PluginDeployerHandler = Symbol('PluginDeployerHandler');
829
855
  export interface PluginDeployerHandler {
830
- deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<void>;
831
- deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise<void>;
856
+ deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<number | undefined>;
857
+ deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise<number | undefined>;
858
+
859
+ getDeployedPluginsById(pluginId: string): DeployedPlugin[];
832
860
 
833
- getDeployedPlugin(pluginId: string): DeployedPlugin | undefined;
834
- undeployPlugin(pluginId: string): Promise<boolean>;
861
+ getDeployedPlugin(pluginId: PluginIdentifiers.VersionedId): DeployedPlugin | undefined;
862
+ /**
863
+ * Removes the plugin from the location it originally resided on disk.
864
+ * Unless `--uncompressed-plugins-in-place` is passed to the CLI, this operation is safe.
865
+ */
866
+ uninstallPlugin(pluginId: PluginIdentifiers.VersionedId): Promise<boolean>;
867
+ /**
868
+ * Removes the plugin from the locations to which it had been deployed.
869
+ * This operation is not safe - references to deleted assets may remain.
870
+ */
871
+ undeployPlugin(pluginId: PluginIdentifiers.VersionedId): Promise<boolean>;
835
872
 
836
873
  getPluginDependencies(pluginToBeInstalled: PluginDeployerEntry): Promise<PluginDependencies | undefined>;
837
874
  }
838
875
 
839
876
  export interface GetDeployedPluginsParams {
840
- pluginIds: string[]
877
+ pluginIds: PluginIdentifiers.VersionedId[]
841
878
  }
842
879
 
843
880
  export interface DeployedPlugin {
@@ -852,7 +889,9 @@ export interface DeployedPlugin {
852
889
  export const HostedPluginServer = Symbol('HostedPluginServer');
853
890
  export interface HostedPluginServer extends JsonRpcServer<HostedPluginClient> {
854
891
 
855
- getDeployedPluginIds(): Promise<string[]>;
892
+ getDeployedPluginIds(): Promise<PluginIdentifiers.VersionedId[]>;
893
+
894
+ getUninstalledPluginIds(): Promise<readonly PluginIdentifiers.VersionedId[]>;
856
895
 
857
896
  getDeployedPlugins(params: GetDeployedPluginsParams): Promise<DeployedPlugin[]>;
858
897
 
@@ -871,6 +910,12 @@ export interface WorkspaceStorageKind {
871
910
  export type GlobalStorageKind = undefined;
872
911
  export type PluginStorageKind = GlobalStorageKind | WorkspaceStorageKind;
873
912
 
913
+ export interface PluginDeployOptions {
914
+ version: string;
915
+ /** Instructs the deployer to ignore any existing plugins with different versions */
916
+ ignoreOtherVersions?: boolean;
917
+ }
918
+
874
919
  /**
875
920
  * The JSON-RPC workspace interface.
876
921
  */
@@ -883,9 +928,9 @@ export interface PluginServer {
883
928
  *
884
929
  * @param type whether a plugin is installed by a system or a user, defaults to a user
885
930
  */
886
- deploy(pluginEntry: string, type?: PluginType): Promise<void>;
887
-
888
- undeploy(pluginId: string): Promise<void>;
931
+ deploy(pluginEntry: string, type?: PluginType, options?: PluginDeployOptions): Promise<void>;
932
+ uninstall(pluginId: PluginIdentifiers.VersionedId): Promise<void>;
933
+ undeploy(pluginId: PluginIdentifiers.VersionedId): Promise<void>;
889
934
 
890
935
  setStorageValue(key: string, value: KeysToAnyValues, kind: PluginStorageKind): Promise<boolean>;
891
936
  getStorageValue(key: string, kind: PluginStorageKind): Promise<KeysToAnyValues>;
@@ -910,7 +955,7 @@ export interface ServerPluginRunner {
910
955
  /**
911
956
  * Provides additional plugin ids.
912
957
  */
913
- getExtraDeployedPluginIds(): Promise<string[]>;
958
+ getExtraDeployedPluginIds(): Promise<PluginIdentifiers.VersionedId[]>;
914
959
 
915
960
  }
916
961
 
@@ -25,7 +25,7 @@ import debounce = require('@theia/core/shared/lodash.debounce');
25
25
  import { UUID } from '@theia/core/shared/@phosphor/coreutils';
26
26
  import { injectable, inject, interfaces, named, postConstruct } from '@theia/core/shared/inversify';
27
27
  import { PluginWorker } from './plugin-worker';
28
- import { PluginMetadata, getPluginId, HostedPluginServer, DeployedPlugin, PluginServer } from '../../common/plugin-protocol';
28
+ import { PluginMetadata, getPluginId, HostedPluginServer, DeployedPlugin, PluginServer, PluginIdentifiers } from '../../common/plugin-protocol';
29
29
  import { HostedPluginWatcher } from './hosted-plugin-watcher';
30
30
  import { MAIN_RPC_CONTEXT, PluginManagerExt, ConfigStorage, UIKind } from '../../common/plugin-api-rpc';
31
31
  import { setUpPluginApi } from '../../main/browser/main-context';
@@ -165,7 +165,7 @@ export class HostedPluginSupport {
165
165
 
166
166
  protected readonly managers = new Map<string, PluginManagerExt>();
167
167
 
168
- private readonly contributions = new Map<string, PluginContributions>();
168
+ private readonly contributions = new Map<PluginIdentifiers.UnversionedId, PluginContributions>();
169
169
 
170
170
  protected readonly activationEvents = new Set<string>();
171
171
 
@@ -240,7 +240,7 @@ export class HostedPluginSupport {
240
240
  return plugins;
241
241
  }
242
242
 
243
- getPlugin(id: string): DeployedPlugin | undefined {
243
+ getPlugin(id: PluginIdentifiers.UnversionedId): DeployedPlugin | undefined {
244
244
  const contributions = this.contributions.get(id);
245
245
  return contributions && contributions.plugin;
246
246
  }
@@ -312,27 +312,38 @@ export class HostedPluginSupport {
312
312
  let syncPluginsMeasurement: Measurement | undefined;
313
313
 
314
314
  const toUnload = new Set(this.contributions.keys());
315
+ let didChangeInstallationStatus = false;
315
316
  try {
316
- const pluginIds: string[] = [];
317
- const deployedPluginIds = await this.server.getDeployedPluginIds();
317
+ const newPluginIds: PluginIdentifiers.VersionedId[] = [];
318
+ const [deployedPluginIds, uninstalledPluginIds] = await Promise.all([this.server.getDeployedPluginIds(), this.server.getUninstalledPluginIds()]);
318
319
  waitPluginsMeasurement.log('Waiting for backend deployment');
319
320
  syncPluginsMeasurement = this.measure('syncPlugins');
320
- for (const pluginId of deployedPluginIds) {
321
- toUnload.delete(pluginId);
322
- if (!this.contributions.has(pluginId)) {
323
- pluginIds.push(pluginId);
321
+ for (const versionedId of deployedPluginIds) {
322
+ const unversionedId = PluginIdentifiers.unversionedFromVersioned(versionedId);
323
+ toUnload.delete(unversionedId);
324
+ if (!this.contributions.has(unversionedId)) {
325
+ newPluginIds.push(versionedId);
324
326
  }
325
327
  }
326
328
  for (const pluginId of toUnload) {
327
- const contribution = this.contributions.get(pluginId);
328
- if (contribution) {
329
- contribution.dispose();
329
+ this.contributions.get(pluginId)?.dispose();
330
+ }
331
+ for (const versionedId of uninstalledPluginIds) {
332
+ const plugin = this.getPlugin(PluginIdentifiers.unversionedFromVersioned(versionedId));
333
+ if (plugin && PluginIdentifiers.componentsToVersionedId(plugin.metadata.model) === versionedId && !plugin.metadata.outOfSync) {
334
+ plugin.metadata.outOfSync = didChangeInstallationStatus = true;
335
+ }
336
+ }
337
+ for (const contribution of this.contributions.values()) {
338
+ if (contribution.plugin.metadata.outOfSync && !uninstalledPluginIds.includes(PluginIdentifiers.componentsToVersionedId(contribution.plugin.metadata.model))) {
339
+ contribution.plugin.metadata.outOfSync = false;
340
+ didChangeInstallationStatus = true;
330
341
  }
331
342
  }
332
- if (pluginIds.length) {
333
- const plugins = await this.server.getDeployedPlugins({ pluginIds });
343
+ if (newPluginIds.length) {
344
+ const plugins = await this.server.getDeployedPlugins({ pluginIds: newPluginIds });
334
345
  for (const plugin of plugins) {
335
- const pluginId = plugin.metadata.model.id;
346
+ const pluginId = PluginIdentifiers.componentsToUnversionedId(plugin.metadata.model);
336
347
  const contributions = new PluginContributions(plugin);
337
348
  this.contributions.set(pluginId, contributions);
338
349
  contributions.push(Disposable.create(() => this.contributions.delete(pluginId)));
@@ -340,7 +351,7 @@ export class HostedPluginSupport {
340
351
  }
341
352
  }
342
353
  } finally {
343
- if (initialized || toUnload.size) {
354
+ if (initialized || toUnload.size || didChangeInstallationStatus) {
344
355
  this.onDidChangePluginsEmitter.fire(undefined);
345
356
  }
346
357
 
@@ -567,11 +578,7 @@ export class HostedPluginSupport {
567
578
  return;
568
579
  }
569
580
  this.activationEvents.add(activationEvent);
570
- const activation: Promise<void>[] = [];
571
- for (const manager of this.managers.values()) {
572
- activation.push(manager.$activateByEvent(activationEvent));
573
- }
574
- await Promise.all(activation);
581
+ await Promise.all(Array.from(this.managers.values(), manager => manager.$activateByEvent(activationEvent)));
575
582
  }
576
583
 
577
584
  async activateByViewContainer(viewContainerId: string): Promise<void> {
@@ -15,7 +15,7 @@
15
15
  // *****************************************************************************
16
16
 
17
17
  // eslint-disable-next-line @theia/runtime-import-check
18
- import { DebugExtImpl } from '../../../plugin/node/debug/debug';
18
+ import { DebugExtImpl } from '../../../plugin/debug/debug-ext';
19
19
  import { RPCProtocol } from '../../../common/rpc-protocol';
20
20
 
21
21
  /* eslint-disable @typescript-eslint/no-explicit-any */
@@ -16,7 +16,7 @@
16
16
 
17
17
  /* eslint-disable @typescript-eslint/no-explicit-any */
18
18
 
19
- import { PluginModel, PluginPackage } from '../../../common/plugin-protocol';
19
+ import { PluginIdentifiers, PluginModel, PluginPackage } from '../../../common/plugin-protocol';
20
20
  import { Endpoint } from '@theia/core/lib/browser/endpoint';
21
21
  import URI from '@theia/core/lib/common/uri';
22
22
 
@@ -54,7 +54,9 @@ function readContents(uri: string): Promise<string> {
54
54
 
55
55
  async function readPluginJson(pluginModel: PluginModel, relativePath: string): Promise<any> {
56
56
  const content = await readPluginFile(pluginModel, relativePath);
57
- return JSON.parse(content);
57
+ const json = JSON.parse(content) as PluginPackage;
58
+ json.publisher ??= PluginIdentifiers.UNPUBLISHED;
59
+ return json;
58
60
  }
59
61
 
60
62
  export async function loadManifest(pluginModel: PluginModel): Promise<any> {
@@ -17,11 +17,15 @@
17
17
  import * as fs from '@theia/core/shared/fs-extra';
18
18
  import { injectable, inject } from '@theia/core/shared/inversify';
19
19
  import { ILogger } from '@theia/core';
20
- import { PluginDeployerHandler, PluginDeployerEntry, PluginEntryPoint, DeployedPlugin, PluginDependencies, PluginType } from '../../common/plugin-protocol';
20
+ import {
21
+ PluginDeployerHandler, PluginDeployerEntry, PluginEntryPoint, DeployedPlugin,
22
+ PluginDependencies, PluginType, PluginIdentifiers
23
+ } from '../../common/plugin-protocol';
21
24
  import { HostedPluginReader } from './plugin-reader';
22
25
  import { Deferred } from '@theia/core/lib/common/promise-util';
23
26
  import { HostedPluginLocalizationService } from './hosted-plugin-localization-service';
24
27
  import { Stopwatch } from '@theia/core/lib/common';
28
+ import { PluginUninstallationManager } from '../../main/node/plugin-uninstallation-manager';
25
29
 
26
30
  @injectable()
27
31
  export class HostedPluginDeployerHandler implements PluginDeployerHandler {
@@ -38,42 +42,56 @@ export class HostedPluginDeployerHandler implements PluginDeployerHandler {
38
42
  @inject(Stopwatch)
39
43
  protected readonly stopwatch: Stopwatch;
40
44
 
41
- private readonly deployedLocations = new Map<string, Set<string>>();
45
+ @inject(PluginUninstallationManager)
46
+ protected readonly uninstallationManager: PluginUninstallationManager;
47
+
48
+ private readonly deployedLocations = new Map<PluginIdentifiers.VersionedId, Set<string>>();
49
+ protected readonly sourceLocations = new Map<PluginIdentifiers.VersionedId, Set<string>>();
42
50
 
43
51
  /**
44
52
  * Managed plugin metadata backend entries.
45
53
  */
46
- private readonly deployedBackendPlugins = new Map<string, DeployedPlugin>();
54
+ private readonly deployedBackendPlugins = new Map<PluginIdentifiers.VersionedId, DeployedPlugin>();
47
55
 
48
56
  /**
49
57
  * Managed plugin metadata frontend entries.
50
58
  */
51
- private readonly deployedFrontendPlugins = new Map<string, DeployedPlugin>();
59
+ private readonly deployedFrontendPlugins = new Map<PluginIdentifiers.VersionedId, DeployedPlugin>();
52
60
 
53
61
  private backendPluginsMetadataDeferred = new Deferred<void>();
54
62
 
55
63
  private frontendPluginsMetadataDeferred = new Deferred<void>();
56
64
 
57
- async getDeployedFrontendPluginIds(): Promise<string[]> {
65
+ async getDeployedFrontendPluginIds(): Promise<PluginIdentifiers.VersionedId[]> {
58
66
  // await first deploy
59
67
  await this.frontendPluginsMetadataDeferred.promise;
60
68
  // fetch the last deployed state
61
- return [...this.deployedFrontendPlugins.keys()];
69
+ return Array.from(this.deployedFrontendPlugins.keys());
62
70
  }
63
71
 
64
- async getDeployedBackendPluginIds(): Promise<string[]> {
72
+ async getDeployedBackendPluginIds(): Promise<PluginIdentifiers.VersionedId[]> {
65
73
  // await first deploy
66
74
  await this.backendPluginsMetadataDeferred.promise;
67
75
  // fetch the last deployed state
68
- return [...this.deployedBackendPlugins.keys()];
76
+ return Array.from(this.deployedBackendPlugins.keys());
69
77
  }
70
78
 
71
- getDeployedPlugin(pluginId: string): DeployedPlugin | undefined {
72
- const metadata = this.deployedBackendPlugins.get(pluginId);
73
- if (metadata) {
74
- return metadata;
75
- }
76
- return this.deployedFrontendPlugins.get(pluginId);
79
+ getDeployedPluginsById(pluginId: string): DeployedPlugin[] {
80
+ const matches: DeployedPlugin[] = [];
81
+ const handle = (plugins: Iterable<DeployedPlugin>): void => {
82
+ for (const plugin of plugins) {
83
+ if (PluginIdentifiers.componentsToVersionWithId(plugin.metadata.model).id === pluginId) {
84
+ matches.push(plugin);
85
+ }
86
+ }
87
+ };
88
+ handle(this.deployedFrontendPlugins.values());
89
+ handle(this.deployedBackendPlugins.values());
90
+ return matches;
91
+ }
92
+
93
+ getDeployedPlugin(pluginId: PluginIdentifiers.VersionedId): DeployedPlugin | undefined {
94
+ return this.deployedBackendPlugins.get(pluginId) ?? this.deployedFrontendPlugins.get(pluginId);
77
95
  }
78
96
 
79
97
  /**
@@ -99,62 +117,115 @@ export class HostedPluginDeployerHandler implements PluginDeployerHandler {
99
117
  }
100
118
  }
101
119
 
102
- async deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<void> {
120
+ async deployFrontendPlugins(frontendPlugins: PluginDeployerEntry[]): Promise<number> {
121
+ let successes = 0;
103
122
  for (const plugin of frontendPlugins) {
104
- await this.deployPlugin(plugin, 'frontend');
123
+ if (await this.deployPlugin(plugin, 'frontend')) { successes++; }
105
124
  }
106
125
  // resolve on first deploy
107
126
  this.frontendPluginsMetadataDeferred.resolve(undefined);
127
+ return successes;
108
128
  }
109
129
 
110
- async deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise<void> {
130
+ async deployBackendPlugins(backendPlugins: PluginDeployerEntry[]): Promise<number> {
131
+ let successes = 0;
111
132
  for (const plugin of backendPlugins) {
112
- await this.deployPlugin(plugin, 'backend');
133
+ if (await this.deployPlugin(plugin, 'backend')) { successes++; }
113
134
  }
114
135
  // rebuild translation config after deployment
115
136
  this.localizationService.buildTranslationConfig([...this.deployedBackendPlugins.values()]);
116
137
  // resolve on first deploy
117
138
  this.backendPluginsMetadataDeferred.resolve(undefined);
139
+ return successes;
118
140
  }
119
141
 
120
142
  /**
121
- * @throws never! in order to isolate plugin deployment
143
+ * @throws never! in order to isolate plugin deployment.
144
+ * @returns whether the plugin is deployed after running this function. If the plugin was already installed, will still return `true`.
122
145
  */
123
- protected async deployPlugin(entry: PluginDeployerEntry, entryPoint: keyof PluginEntryPoint): Promise<void> {
146
+ protected async deployPlugin(entry: PluginDeployerEntry, entryPoint: keyof PluginEntryPoint): Promise<boolean> {
124
147
  const pluginPath = entry.path();
125
148
  const deployPlugin = this.stopwatch.start('deployPlugin');
149
+ let id;
150
+ let success = true;
126
151
  try {
127
152
  const manifest = await this.reader.readPackage(pluginPath);
128
153
  if (!manifest) {
129
154
  deployPlugin.error(`Failed to read ${entryPoint} plugin manifest from '${pluginPath}''`);
130
- return;
155
+ return success = false;
131
156
  }
132
157
 
133
158
  const metadata = this.reader.readMetadata(manifest);
134
159
  metadata.isUnderDevelopment = entry.getValue('isUnderDevelopment') ?? false;
135
160
 
136
- const deployedLocations = this.deployedLocations.get(metadata.model.id) || new Set<string>();
161
+ id = PluginIdentifiers.componentsToVersionedId(metadata.model);
162
+
163
+ const deployedLocations = this.deployedLocations.get(id) ?? new Set<string>();
137
164
  deployedLocations.add(entry.rootPath);
138
- this.deployedLocations.set(metadata.model.id, deployedLocations);
165
+ this.deployedLocations.set(id, deployedLocations);
166
+ this.setSourceLocationsForPlugin(id, entry);
139
167
 
140
168
  const deployedPlugins = entryPoint === 'backend' ? this.deployedBackendPlugins : this.deployedFrontendPlugins;
141
- if (deployedPlugins.has(metadata.model.id)) {
169
+ if (deployedPlugins.has(id)) {
142
170
  deployPlugin.debug(`Skipped ${entryPoint} plugin ${metadata.model.name} already deployed`);
143
- return;
171
+ return true;
144
172
  }
145
173
 
146
174
  const { type } = entry;
147
175
  const deployed: DeployedPlugin = { metadata, type };
148
176
  deployed.contributes = this.reader.readContribution(manifest);
149
177
  this.localizationService.deployLocalizations(deployed);
150
- deployedPlugins.set(metadata.model.id, deployed);
151
- deployPlugin.log(`Deployed ${entryPoint} plugin "${metadata.model.name}@${metadata.model.version}" from "${metadata.model.entryPoint[entryPoint] || pluginPath}"`);
178
+ deployedPlugins.set(id, deployed);
179
+ deployPlugin.log(`Deployed ${entryPoint} plugin "${id}" from "${metadata.model.entryPoint[entryPoint] || pluginPath}"`);
152
180
  } catch (e) {
153
181
  deployPlugin.error(`Failed to deploy ${entryPoint} plugin from '${pluginPath}' path`, e);
182
+ return success = false;
183
+ } finally {
184
+ if (success && id) {
185
+ this.markAsInstalled(id);
186
+ }
187
+ }
188
+ return success;
189
+ }
190
+
191
+ async uninstallPlugin(pluginId: PluginIdentifiers.VersionedId): Promise<boolean> {
192
+ try {
193
+ const sourceLocations = this.sourceLocations.get(pluginId);
194
+ if (!sourceLocations) {
195
+ return false;
196
+ }
197
+ await Promise.all(Array.from(sourceLocations,
198
+ location => fs.remove(location).catch(err => console.error(`Failed to remove source for ${pluginId} at ${location}`, err))));
199
+ this.sourceLocations.delete(pluginId);
200
+ this.uninstallationManager.markAsUninstalled(pluginId);
201
+ return true;
202
+ } catch (e) {
203
+ console.error('Error uninstalling plugin', e);
204
+ return false;
154
205
  }
155
206
  }
156
207
 
157
- async undeployPlugin(pluginId: string): Promise<boolean> {
208
+ protected markAsInstalled(id: PluginIdentifiers.VersionedId): void {
209
+ const metadata = PluginIdentifiers.idAndVersionFromVersionedId(id);
210
+ if (metadata) {
211
+ const toMarkAsUninstalled: PluginIdentifiers.VersionedId[] = [];
212
+ const checkForDifferentVersions = (others: Iterable<PluginIdentifiers.VersionedId>) => {
213
+ for (const other of others) {
214
+ const otherMetadata = PluginIdentifiers.idAndVersionFromVersionedId(other);
215
+ if (metadata.id === otherMetadata?.id && metadata.version !== otherMetadata.version) {
216
+ toMarkAsUninstalled.push(other);
217
+ }
218
+ }
219
+ };
220
+ checkForDifferentVersions(this.deployedFrontendPlugins.keys());
221
+ checkForDifferentVersions(this.deployedBackendPlugins.keys());
222
+ this.uninstallationManager.markAsUninstalled(...toMarkAsUninstalled);
223
+ this.uninstallationManager.markAsInstalled(id);
224
+ toMarkAsUninstalled.forEach(pluginToUninstall => this.uninstallPlugin(pluginToUninstall));
225
+ }
226
+ }
227
+
228
+ async undeployPlugin(pluginId: PluginIdentifiers.VersionedId): Promise<boolean> {
158
229
  this.deployedBackendPlugins.delete(pluginId);
159
230
  this.deployedFrontendPlugins.delete(pluginId);
160
231
  const deployedLocations = this.deployedLocations.get(pluginId);
@@ -176,4 +247,14 @@ export class HostedPluginDeployerHandler implements PluginDeployerHandler {
176
247
 
177
248
  return true;
178
249
  }
250
+
251
+ protected setSourceLocationsForPlugin(id: PluginIdentifiers.VersionedId, entry: PluginDeployerEntry): void {
252
+ const knownLocations = this.sourceLocations.get(id) ?? new Set();
253
+ const maybeStoredLocations = entry.getValue('sourceLocations');
254
+ const storedLocations = Array.isArray(maybeStoredLocations) && maybeStoredLocations.every(location => typeof location === 'string')
255
+ ? maybeStoredLocations.concat(entry.originalPath())
256
+ : [entry.originalPath()];
257
+ storedLocations.forEach(location => knownLocations.add(location));
258
+ this.sourceLocations.set(id, knownLocations);
259
+ }
179
260
  }
@@ -19,7 +19,7 @@ import * as fs from '@theia/core/shared/fs-extra';
19
19
  import { LocalizationProvider } from '@theia/core/lib/node/i18n/localization-provider';
20
20
  import { Localization } from '@theia/core/lib/common/i18n/localization';
21
21
  import { inject, injectable } from '@theia/core/shared/inversify';
22
- import { DeployedPlugin, Localization as PluginLocalization, PluginContribution } from '../../common';
22
+ import { DeployedPlugin, Localization as PluginLocalization } from '../../common';
23
23
  import { URI } from '@theia/core/shared/vscode-uri';
24
24
  import { EnvVariablesServer } from '@theia/core/lib/common/env-variables';
25
25
 
@@ -55,18 +55,16 @@ export class HostedPluginLocalizationService {
55
55
  const localization = this.localizationProvider.loadLocalization(currentLanguage);
56
56
  const pluginPath = URI.parse(plugin.metadata.model.packageUri).fsPath;
57
57
  const pluginId = plugin.metadata.model.id;
58
- // create a shallow copy to not override the original plugin's contributes property.
59
- const shallowCopy = { ...plugin };
60
58
  try {
61
59
  const translations = await loadPackageTranslations(pluginPath, currentLanguage);
62
- shallowCopy.contributes = localizePackage(shallowCopy.contributes, translations, (key, original) => {
60
+ plugin = localizePackage(plugin, translations, (key, original) => {
63
61
  const fullKey = `${pluginId}/package/${key}`;
64
62
  return Localization.localize(localization, fullKey, original);
65
- }) as PluginContribution;
63
+ }) as DeployedPlugin;
66
64
  } catch (err) {
67
65
  console.error(`Failed to localize plugin '${pluginId}'.`, err);
68
66
  }
69
- return shallowCopy;
67
+ return plugin;
70
68
  }
71
69
 
72
70
  getNlsConfig(): VSCodeNlsConfig {