@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
@@ -28,9 +28,10 @@ import {
28
28
  DecorationRenderOptions,
29
29
  ThemeDecorationInstanceRenderOptions,
30
30
  DecorationOptions,
31
- WorkspaceEditDto
31
+ WorkspaceEditDto,
32
+ DocumentsMain,
32
33
  } from '../../common/plugin-api-rpc';
33
- import { Range } from '../../common/plugin-api-rpc-model';
34
+ import { Range, TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
34
35
  import { EditorsAndDocumentsMain } from './editors-and-documents-main';
35
36
  import { RPCProtocol } from '../../common/rpc-protocol';
36
37
  import { Disposable, DisposableCollection } from '@theia/core/lib/common/disposable';
@@ -54,6 +55,7 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
54
55
 
55
56
  constructor(
56
57
  private readonly editorsAndDocuments: EditorsAndDocumentsMain,
58
+ private readonly documents: DocumentsMain,
57
59
  rpc: RPCProtocol,
58
60
  private readonly bulkEditService: MonacoBulkEditService,
59
61
  private readonly monacoEditorService: MonacoEditorService,
@@ -87,6 +89,10 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
87
89
  }
88
90
  }
89
91
 
92
+ $tryShowTextDocument(uri: UriComponents, options?: TextDocumentShowOptions): Promise<void> {
93
+ return this.documents.$tryShowDocument(uri, options);
94
+ }
95
+
90
96
  $trySetOptions(id: string, options: TextEditorConfigurationUpdate): Promise<void> {
91
97
  if (!this.editorsAndDocuments.getEditor(id)) {
92
98
  return Promise.reject(disposed(`TextEditor: ${id}`));
@@ -173,6 +179,10 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
173
179
  this.monacoEditorService.removeDecorationType(key);
174
180
  }
175
181
 
182
+ $tryHideEditor(id: string): Promise<void> {
183
+ return this.editorsAndDocuments.hideEditor(id);
184
+ }
185
+
176
186
  $trySetDecorations(id: string, key: string, ranges: DecorationOptions[]): Promise<void> {
177
187
  if (!this.editorsAndDocuments.getEditor(id)) {
178
188
  return Promise.reject(disposed(`TextEditor(${id})`));
@@ -30,14 +30,10 @@ export class ThemingMainImpl implements ThemingMain {
30
30
  private readonly proxy: ThemingExt;
31
31
  private readonly themeChangeListener: Disposable;
32
32
 
33
- constructor(
34
- rpc: RPCProtocol
35
- ) {
33
+ constructor(rpc: RPCProtocol, themeService: ThemeService) {
36
34
  this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.THEMING_EXT);
37
- this.themeChangeListener = ThemeService.get().onDidColorThemeChange(e => {
38
- this.proxy.$onColorThemeChange(e.newTheme.type);
39
- });
40
- this.proxy.$onColorThemeChange(ThemeService.get().getCurrentTheme().type);
35
+ this.themeChangeListener = themeService.onDidColorThemeChange(e => this.proxy.$onColorThemeChange(e.newTheme.type));
36
+ this.proxy.$onColorThemeChange(themeService.getCurrentTheme().type);
41
37
  }
42
38
 
43
39
  dispose(): void {
@@ -33,7 +33,7 @@ export class PluginTreeViewNodeLabelProvider implements LabelProviderContributio
33
33
 
34
34
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
35
  canHandle(element: TreeViewNode | any): number {
36
- if (TreeNode.is(element) && ('resourceUri' in element || 'themeIconId' in element)) {
36
+ if (TreeNode.is(element) && ('resourceUri' in element || 'themeIcon' in element)) {
37
37
  return this.treeLabelProvider.canHandle(element) + 1;
38
38
  }
39
39
  return 0;
@@ -43,12 +43,14 @@ export class PluginTreeViewNodeLabelProvider implements LabelProviderContributio
43
43
  if (node.icon) {
44
44
  return node.icon;
45
45
  }
46
- if (node.themeIconId) {
47
- if (node.themeIconId === 'file' || node.themeIconId === 'folder') {
46
+ if (node.themeIcon) {
47
+ if (node.themeIcon.id === 'file' || node.themeIcon.id === 'folder') {
48
48
  const uri = node.resourceUri && new URI(node.resourceUri) || undefined;
49
- return this.labelProvider.getIcon(URIIconReference.create(node.themeIconId, uri));
49
+ if (uri) {
50
+ return this.labelProvider.getIcon(URIIconReference.create(node.themeIcon.id, uri));
51
+ }
50
52
  }
51
- return ThemeIcon.asClassName({ id: node.themeIconId });
53
+ return ThemeIcon.asClassName(node.themeIcon);
52
54
  }
53
55
  if (node.resourceUri) {
54
56
  return this.labelProvider.getIcon(new URI(node.resourceUri));
@@ -35,7 +35,7 @@ import { Emitter, Event } from '@theia/core/lib/common/event';
35
35
  import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
36
36
  import { ViewContextKeyService } from './view-context-key-service';
37
37
  import { PROBLEMS_WIDGET_ID } from '@theia/markers/lib/browser/problem/problem-widget';
38
- import { OUTPUT_WIDGET_KIND } from '@theia/output/lib/browser/output-widget';
38
+ import { OutputWidget } from '@theia/output/lib/browser/output-widget';
39
39
  import { DebugConsoleContribution } from '@theia/debug/lib/browser/console/debug-console-contribution';
40
40
  import { TERMINAL_WIDGET_FACTORY_ID } from '@theia/terminal/lib/browser/terminal-widget-impl';
41
41
  import { TreeViewWidget } from './tree-view-widget';
@@ -45,6 +45,7 @@ import { WebviewView, WebviewViewResolver } from '../webview-views/webview-views
45
45
  import { WebviewWidget, WebviewWidgetIdentifier } from '../webview/webview';
46
46
  import { CancellationToken } from '@theia/core/lib/common/cancellation';
47
47
  import { v4 } from 'uuid';
48
+ import { nls } from '@theia/core';
48
49
 
49
50
  export const PLUGIN_VIEW_FACTORY_ID = 'plugin-view';
50
51
  export const PLUGIN_VIEW_CONTAINER_FACTORY_ID = 'plugin-view-container';
@@ -113,7 +114,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
113
114
 
114
115
  // VS Code Panels
115
116
  this.trackVisibleWidget(PROBLEMS_WIDGET_ID, { panelId: 'workbench.panel.markers' });
116
- this.trackVisibleWidget(OUTPUT_WIDGET_KIND, { panelId: 'workbench.panel.output' });
117
+ this.trackVisibleWidget(OutputWidget.ID, { panelId: 'workbench.panel.output' });
117
118
  this.trackVisibleWidget(DebugConsoleContribution.options.id, { panelId: 'workbench.panel.repl' });
118
119
  this.trackVisibleWidget(TERMINAL_WIDGET_FACTORY_ID, { panelId: 'workbench.panel.terminal' });
119
120
  // TODO workbench.panel.comments - Theia does not have a proper comments view yet
@@ -144,12 +145,13 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
144
145
  });
145
146
  this.widgetManager.onDidCreateWidget(event => {
146
147
  if (event.widget instanceof FileNavigatorWidget) {
147
- this.registerViewWelcome({
148
+ const disposable = new DisposableCollection();
149
+ disposable.push(this.registerViewWelcome({
148
150
  view: 'explorer',
149
- // eslint-disable-next-line max-len
150
- content: 'You have not yet opened a folder.\n[Open Folder](command:workbench.action.files.openFolder)',
151
+ content: nls.localizeByDefault('You have not yet opened a folder.\n[Open Folder](command:{0})', 'workbench.action.files.openFolder'),
151
152
  order: 0
152
- });
153
+ }));
154
+ disposable.push(event.widget.onDidDispose(() => disposable.dispose()));
153
155
  }
154
156
  });
155
157
  this.doRegisterViewContainer('test', 'left', {
@@ -401,6 +403,9 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
401
403
  const toDispose = new DisposableCollection();
402
404
 
403
405
  const viewsWelcome = this.viewsWelcome.get(viewWelcome.view) || [];
406
+ if (viewsWelcome.some(e => e.content === viewWelcome.content)) {
407
+ return toDispose;
408
+ }
404
409
  viewsWelcome.push(viewWelcome);
405
410
  this.viewsWelcome.set(viewWelcome.view, viewsWelcome);
406
411
  this.handleViewWelcomeChange(viewWelcome.view);
@@ -715,7 +720,7 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
715
720
  }
716
721
 
717
722
  /**
718
- * retrieve restored layout state from previous user session but close widgets
723
+ * retrieve restored layout state from previous user session but close widgets
719
724
  * widgets should be opened only when view data providers are registered
720
725
  */
721
726
  onDidInitializeLayout(): void {
@@ -16,7 +16,7 @@
16
16
 
17
17
  import { URI } from '@theia/core/shared/vscode-uri';
18
18
  import { injectable, inject, postConstruct } from '@theia/core/shared/inversify';
19
- import { TreeViewsExt, TreeViewItemCollapsibleState, TreeViewItem, TreeViewSelection } from '../../../common/plugin-api-rpc';
19
+ import { TreeViewsExt, TreeViewItemCollapsibleState, TreeViewItem, TreeViewSelection, ThemeIcon } from '../../../common/plugin-api-rpc';
20
20
  import { Command } from '../../../common/plugin-api-rpc-model';
21
21
  import {
22
22
  TreeNode,
@@ -46,6 +46,9 @@ import * as markdownit from '@theia/core/shared/markdown-it';
46
46
  import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
47
47
  import { LabelParser } from '@theia/core/lib/browser/label-parser';
48
48
  import { AccessibilityInformation } from '@theia/plugin';
49
+ import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
50
+ import { DecoratedTreeNode } from '@theia/core/lib/browser/tree/tree-decorator';
51
+ import { WidgetDecoration } from '@theia/core/lib/browser/widget-decoration';
49
52
 
50
53
  export const TREE_NODE_HYPERLINK = 'theia-TreeNodeHyperlink';
51
54
  export const VIEW_ITEM_CONTEXT_MENU: MenuPath = ['view-item-context-menu'];
@@ -56,11 +59,11 @@ export interface SelectionEventHandler {
56
59
  readonly contextSelection: boolean;
57
60
  }
58
61
 
59
- export interface TreeViewNode extends SelectableTreeNode {
62
+ export interface TreeViewNode extends SelectableTreeNode, DecoratedTreeNode {
60
63
  contextValue?: string;
61
64
  command?: Command;
62
65
  resourceUri?: string;
63
- themeIconId?: string | 'folder' | 'file';
66
+ themeIcon?: ThemeIcon;
64
67
  tooltip?: string;
65
68
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
69
  description?: string | boolean | any;
@@ -68,7 +71,7 @@ export interface TreeViewNode extends SelectableTreeNode {
68
71
  }
69
72
  export namespace TreeViewNode {
70
73
  export function is(arg: TreeNode | undefined): arg is TreeViewNode {
71
- return !!arg && SelectableTreeNode.is(arg) && !ExpandableTreeNode.is(arg) && !CompositeTreeNode.is(arg);
74
+ return !!arg && SelectableTreeNode.is(arg) && DecoratedTreeNode.is(arg);
72
75
  }
73
76
  }
74
77
 
@@ -78,7 +81,7 @@ export interface CompositeTreeViewNode extends TreeViewNode, ExpandableTreeNode,
78
81
  }
79
82
  export namespace CompositeTreeViewNode {
80
83
  export function is(arg: TreeNode | undefined): arg is CompositeTreeViewNode {
81
- return !!arg && SelectableTreeNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
84
+ return TreeViewNode.is(arg) && ExpandableTreeNode.is(arg) && CompositeTreeNode.is(arg);
82
85
  }
83
86
  }
84
87
 
@@ -149,14 +152,16 @@ export class PluginTree extends TreeImpl {
149
152
  }
150
153
 
151
154
  protected createTreeNode(item: TreeViewItem, parent: CompositeTreeNode): TreeNode {
155
+ const decorationData = this.toDecorationData(item);
152
156
  const icon = this.toIconClass(item);
153
157
  const resourceUri = item.resourceUri && URI.revive(item.resourceUri).toString();
154
- const themeIconId = item.themeIconId ? item.themeIconId : item.collapsibleState !== TreeViewItemCollapsibleState.None ? 'folder' : 'file';
158
+ const themeIcon = item.themeIcon ? item.themeIcon : item.collapsibleState !== TreeViewItemCollapsibleState.None ? { id: 'folder' } : undefined;
155
159
  const update: Partial<TreeViewNode> = {
156
160
  name: item.label,
161
+ decorationData,
157
162
  icon,
158
163
  description: item.description,
159
- themeIconId,
164
+ themeIcon,
160
165
  resourceUri,
161
166
  tooltip: item.tooltip,
162
167
  contextValue: item.contextValue,
@@ -178,7 +183,7 @@ export class PluginTree extends TreeImpl {
178
183
  command: item.command
179
184
  }, update);
180
185
  }
181
- if (TreeViewNode.is(node)) {
186
+ if (TreeViewNode.is(node) && !ExpandableTreeNode.is(node)) {
182
187
  return Object.assign(node, update, { command: item.command });
183
188
  }
184
189
  return Object.assign({
@@ -190,6 +195,17 @@ export class PluginTree extends TreeImpl {
190
195
  }, update);
191
196
  }
192
197
 
198
+ protected toDecorationData(item: TreeViewItem): WidgetDecoration.Data {
199
+ let decoration: WidgetDecoration.Data = {};
200
+ if (item.highlights) {
201
+ const highlight = {
202
+ ranges: item.highlights.map(h => ({ offset: h[0], length: h[1] - h[0] }))
203
+ };
204
+ decoration = { highlight };
205
+ }
206
+ return decoration;
207
+ }
208
+
193
209
  protected toIconClass(item: TreeViewItem): string | undefined {
194
210
  if (item.icon) {
195
211
  return 'fa ' + item.icon;
@@ -257,6 +273,9 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
257
273
  @inject(LabelParser)
258
274
  protected readonly labelParser: LabelParser;
259
275
 
276
+ @inject(ColorRegistry)
277
+ protected readonly colorRegistry: ColorRegistry;
278
+
260
279
  protected readonly markdownIt = markdownit();
261
280
 
262
281
  @postConstruct()
@@ -286,7 +305,14 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
286
305
  protected override renderIcon(node: TreeNode, props: NodeProps): React.ReactNode {
287
306
  const icon = this.toNodeIcon(node);
288
307
  if (icon) {
289
- return <div className={icon + ' theia-tree-view-icon'}></div>;
308
+ let style: React.CSSProperties | undefined;
309
+ if (TreeViewNode.is(node) && node.themeIcon?.color) {
310
+ const color = this.colorRegistry.getCurrentColor(node.themeIcon.color.id);
311
+ if (color) {
312
+ style = { color };
313
+ }
314
+ }
315
+ return <div className={icon + ' theia-tree-view-icon'} style={style}></div>;
290
316
  }
291
317
  return undefined;
292
318
  }
@@ -358,8 +384,10 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
358
384
  const inlineCommands = menu.children.filter((item): item is ActionMenuNode => item instanceof ActionMenuNode);
359
385
  const tailDecorations = super.renderTailDecorations(node, props);
360
386
  return <React.Fragment>
361
- {inlineCommands.length > 0 && <div className={TREE_NODE_SEGMENT_CLASS}>{inlineCommands.map((item, index) => this.renderInlineCommand(item, index, arg))}</div>}
362
- {tailDecorations !== undefined && <div className={TREE_NODE_SEGMENT_CLASS}>{super.renderTailDecorations(node, props)}</div>}
387
+ {inlineCommands.length > 0 && <div className={TREE_NODE_SEGMENT_CLASS + ' flex'}>
388
+ {inlineCommands.map((item, index) => this.renderInlineCommand(item, index, this.focusService.hasFocus(node), arg))}
389
+ </div>}
390
+ {tailDecorations !== undefined && <div className={TREE_NODE_SEGMENT_CLASS + ' flex'}>{tailDecorations}</div>}
363
391
  </React.Fragment>;
364
392
  });
365
393
  }
@@ -369,13 +397,14 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
369
397
  }
370
398
 
371
399
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
372
- protected renderInlineCommand(node: ActionMenuNode, index: number, arg: any): React.ReactNode {
400
+ protected renderInlineCommand(node: ActionMenuNode, index: number, tabbable: boolean, arg: any): React.ReactNode {
373
401
  const { icon } = node;
374
402
  if (!icon || !this.commands.isVisible(node.action.commandId, arg) || !node.action.when || !this.contextKeys.match(node.action.when)) {
375
403
  return false;
376
404
  }
377
405
  const className = [TREE_NODE_SEGMENT_CLASS, TREE_NODE_TAIL_CLASS, icon, ACTION_ITEM, 'theia-tree-view-inline-action'].join(' ');
378
- return <div key={index} className={className} title={node.label} onClick={e => {
406
+ const tabIndex = tabbable ? 0 : undefined;
407
+ return <div key={index} className={className} title={node.label} tabIndex={tabIndex} onClick={e => {
379
408
  e.stopPropagation();
380
409
  this.commands.executeCommand(node.action.commandId, arg);
381
410
  }} />;
@@ -404,13 +433,12 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
404
433
  this.tryExecuteCommand();
405
434
  }
406
435
 
407
- override handleClickEvent(node: TreeNode, event: React.MouseEvent<HTMLElement>): void {
408
- super.handleClickEvent(node, event);
409
- // If clicked on item (not collapsable icon) - execute command or toggle expansion if item has no command
436
+ protected override tapNode(node?: TreeNode): void {
437
+ super.tapNode(node);
410
438
  const commandMap = this.findCommands(node);
411
439
  if (commandMap.size > 0) {
412
440
  this.tryExecuteCommandMap(commandMap);
413
- } else if (this.isExpandable(node) && !this.hasShiftMask(event) && !this.hasCtrlCmdMask(event)) {
441
+ } else if (node && this.isExpandable(node)) {
414
442
  this.model.toggleNodeExpansion(node);
415
443
  }
416
444
  }
@@ -22,7 +22,8 @@
22
22
  import { inject, postConstruct, injectable } from '@theia/core/shared/inversify';
23
23
  import { Emitter } from '@theia/core/lib/common/event';
24
24
  import { EditorPreferences, EditorConfiguration } from '@theia/editor/lib/browser/editor-preferences';
25
- import { Theme, ThemeService } from '@theia/core/lib/browser/theming';
25
+ import { ThemeService } from '@theia/core/lib/browser/theming';
26
+ import { Theme } from '@theia/core/lib/common/theme';
26
27
  import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
27
28
  import { ColorApplicationContribution } from '@theia/core/lib/browser/color-application-contribution';
28
29
 
@@ -39,14 +40,10 @@ export class WebviewThemeDataProvider {
39
40
  protected readonly onDidChangeThemeDataEmitter = new Emitter<void>();
40
41
  readonly onDidChangeThemeData = this.onDidChangeThemeDataEmitter.event;
41
42
 
42
- @inject(EditorPreferences)
43
- protected readonly editorPreferences: EditorPreferences;
44
-
45
- @inject(ColorRegistry)
46
- protected readonly colors: ColorRegistry;
47
-
48
- @inject(ColorApplicationContribution)
49
- protected readonly colorContribution: ColorApplicationContribution;
43
+ @inject(EditorPreferences) protected readonly editorPreferences: EditorPreferences;
44
+ @inject(ColorRegistry) protected readonly colors: ColorRegistry;
45
+ @inject(ColorApplicationContribution) protected readonly colorContribution: ColorApplicationContribution;
46
+ @inject(ThemeService) protected readonly themeService: ThemeService;
50
47
 
51
48
  protected themeData: WebviewThemeData | undefined;
52
49
 
@@ -113,7 +110,7 @@ export class WebviewThemeDataProvider {
113
110
  }
114
111
 
115
112
  protected getActiveTheme(): Theme {
116
- return ThemeService.get().getCurrentTheme();
113
+ return this.themeService.getCurrentTheme();
117
114
  }
118
115
 
119
116
  protected getThemeType(theme: Theme): WebviewThemeType {
@@ -14,18 +14,24 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ import * as path from 'path';
18
+ import * as filenamify from 'filenamify';
19
+ import * as fs from '@theia/core/shared/fs-extra';
20
+ import { inject, injectable } from '@theia/core/shared/inversify';
21
+ import { FileUri } from '@theia/core/lib/node';
17
22
  import {
18
- PluginDeployerDirectoryHandler,
19
- PluginDeployerEntry, PluginPackage, PluginDeployerDirectoryHandlerContext,
20
- PluginDeployerEntryType
23
+ PluginDeployerDirectoryHandler, PluginDeployerEntry, PluginPackage, PluginDeployerDirectoryHandlerContext, PluginDeployerEntryType, PluginType, PluginIdentifiers
21
24
  } from '../../../common/plugin-protocol';
22
- import { injectable } from '@theia/core/shared/inversify';
23
- import * as fs from '@theia/core/shared/fs-extra';
24
- import * as path from 'path';
25
+ import { PluginCliContribution } from '../plugin-cli-contribution';
26
+ import { getTempDir } from '../temp-dir-util';
25
27
 
26
28
  @injectable()
27
29
  export class PluginTheiaDirectoryHandler implements PluginDeployerDirectoryHandler {
28
30
 
31
+ protected readonly deploymentDirectory = FileUri.create(getTempDir('theia-copied'));
32
+
33
+ @inject(PluginCliContribution) protected readonly pluginCli: PluginCliContribution;
34
+
29
35
  accept(resolvedPlugin: PluginDeployerEntry): boolean {
30
36
 
31
37
  console.log('PluginTheiaDirectoryHandler: accepting plugin with path', resolvedPlugin.path());
@@ -37,33 +43,26 @@ export class PluginTheiaDirectoryHandler implements PluginDeployerDirectoryHandl
37
43
 
38
44
  // is there a package.json ?
39
45
  const packageJsonPath = path.resolve(resolvedPlugin.path(), 'package.json');
40
- const existsPackageJson: boolean = fs.existsSync(packageJsonPath);
41
- if (!existsPackageJson) {
42
- return false;
43
- }
44
-
45
- let packageJson: PluginPackage = resolvedPlugin.getValue('package.json');
46
- if (!packageJson) {
47
- packageJson = fs.readJSONSync(packageJsonPath);
48
- resolvedPlugin.storeValue('package.json', packageJson);
49
- }
50
46
 
51
- if (!packageJson.engines) {
52
- return false;
53
- }
54
-
55
- if (packageJson.engines && packageJson.engines.theiaPlugin) {
56
- return true;
57
- }
47
+ try {
48
+ let packageJson = resolvedPlugin.getValue<PluginPackage>('package.json');
49
+ if (!packageJson) {
50
+ packageJson = fs.readJSONSync(packageJsonPath);
51
+ packageJson.publisher ??= PluginIdentifiers.UNPUBLISHED;
52
+ resolvedPlugin.storeValue('package.json', packageJson);
53
+ }
58
54
 
55
+ if (packageJson?.engines?.theiaPlugin) {
56
+ return true;
57
+ }
58
+ } catch { /* Failed to read file. Fall through. */ }
59
59
  return false;
60
-
61
60
  }
62
61
 
63
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
64
- handle(context: PluginDeployerDirectoryHandlerContext): Promise<any> {
62
+ async handle(context: PluginDeployerDirectoryHandlerContext): Promise<void> {
63
+ await this.copyDirectory(context);
65
64
  const types: PluginDeployerEntryType[] = [];
66
- const packageJson: PluginPackage = context.pluginEntry().getValue('package.json');
65
+ const packageJson = context.pluginEntry().getValue<PluginPackage>('package.json');
67
66
  if (packageJson.theiaPlugin && packageJson.theiaPlugin.backend) {
68
67
  types.push(PluginDeployerEntryType.BACKEND);
69
68
  }
@@ -72,6 +71,35 @@ export class PluginTheiaDirectoryHandler implements PluginDeployerDirectoryHandl
72
71
  }
73
72
 
74
73
  context.pluginEntry().accept(...types);
75
- return Promise.resolve(true);
74
+ }
75
+
76
+ protected async copyDirectory(context: PluginDeployerDirectoryHandlerContext): Promise<void> {
77
+ if (this.pluginCli.copyUncompressedPlugins() && context.pluginEntry().type === PluginType.User) {
78
+ const entry = context.pluginEntry();
79
+ const id = entry.id();
80
+ const pathToRestore = entry.path();
81
+ const origin = entry.originalPath();
82
+ const targetDir = await this.getExtensionDir(context);
83
+ try {
84
+ if (fs.existsSync(targetDir) || !entry.path().startsWith(origin)) {
85
+ console.log(`[${id}]: already copied.`);
86
+ } else {
87
+ console.log(`[${id}]: copying to "${targetDir}"`);
88
+ await fs.mkdirp(FileUri.fsPath(this.deploymentDirectory));
89
+ await context.copy(origin, targetDir);
90
+ entry.updatePath(targetDir);
91
+ if (!this.accept(entry)) {
92
+ throw new Error('Unable to resolve plugin metadata after copying');
93
+ }
94
+ }
95
+ } catch (e) {
96
+ console.warn(`[${id}]: Error when copying.`, e);
97
+ entry.updatePath(pathToRestore);
98
+ }
99
+ }
100
+ }
101
+
102
+ protected async getExtensionDir(context: PluginDeployerDirectoryHandlerContext): Promise<string> {
103
+ return FileUri.fsPath(this.deploymentDirectory.resolve(filenamify(context.pluginEntry().id(), { replacement: '_' })));
76
104
  }
77
105
  }
@@ -14,6 +14,7 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ import * as path from 'path';
17
18
  import { PluginDeployerFileHandler, PluginDeployerEntry, PluginDeployerFileHandlerContext, PluginType } from '../../../common/plugin-protocol';
18
19
  import { injectable, inject } from '@theia/core/shared/inversify';
19
20
  import { getTempDir } from '../temp-dir-util';
@@ -21,6 +22,7 @@ import * as fs from '@theia/core/shared/fs-extra';
21
22
  import * as filenamify from 'filenamify';
22
23
  import { FileUri } from '@theia/core/lib/node/file-uri';
23
24
  import { PluginTheiaEnvironment } from '../../common/plugin-theia-environment';
25
+ import URI from '@theia/core/lib/common/uri';
24
26
 
25
27
  @injectable()
26
28
  export class PluginTheiaFileHandler implements PluginDeployerFileHandler {
@@ -35,6 +37,7 @@ export class PluginTheiaFileHandler implements PluginDeployerFileHandler {
35
37
  }
36
38
 
37
39
  async handle(context: PluginDeployerFileHandlerContext): Promise<void> {
40
+ await this.ensureDiscoverability(context);
38
41
  const id = context.pluginEntry().id();
39
42
  const pluginDir = await this.getPluginDir(context);
40
43
  console.log(`[${id}]: trying to decompress into "${pluginDir}"...`);
@@ -48,11 +51,30 @@ export class PluginTheiaFileHandler implements PluginDeployerFileHandler {
48
51
  context.pluginEntry().updatePath(pluginDir);
49
52
  }
50
53
 
51
- protected async getPluginDir(context: PluginDeployerFileHandlerContext): Promise<string> {
52
- let pluginsDirUri = this.systemPluginsDirUri;
54
+ /**
55
+ * Ensures that a user-installed plugin file is transferred to the user extension folder.
56
+ */
57
+ protected async ensureDiscoverability(context: PluginDeployerFileHandlerContext): Promise<void> {
53
58
  if (context.pluginEntry().type === PluginType.User) {
54
- pluginsDirUri = await this.environment.getPluginsDirUri();
59
+ const userExtensionsDir = await this.environment.getPluginsDirUri();
60
+ const currentPath = context.pluginEntry().path();
61
+ if (!userExtensionsDir.isEqualOrParent(new URI(currentPath)) && !userExtensionsDir.isEqualOrParent(new URI(context.pluginEntry().originalPath()))) {
62
+ try {
63
+ const newPath = FileUri.fsPath(userExtensionsDir.resolve(path.basename(currentPath)));
64
+ await fs.mkdirp(FileUri.fsPath(userExtensionsDir));
65
+ await new Promise<void>((resolve, reject) => {
66
+ fs.copyFile(currentPath, newPath, error => error ? reject(error) : resolve());
67
+ });
68
+ context.pluginEntry().updatePath(newPath);
69
+ context.pluginEntry().storeValue('sourceLocations', [newPath]);
70
+ } catch (e) {
71
+ console.error(`[${context.pluginEntry().id}]: Failed to copy to user directory. Future sessions may not have access to this plugin.`);
72
+ }
73
+ }
55
74
  }
56
- return FileUri.fsPath(pluginsDirUri.resolve(filenamify(context.pluginEntry().id(), { replacement: '_' })));
75
+ }
76
+
77
+ protected async getPluginDir(context: PluginDeployerFileHandlerContext): Promise<string> {
78
+ return FileUri.fsPath(this.systemPluginsDirUri.resolve(filenamify(context.pluginEntry().id(), { replacement: '_' })));
57
79
  }
58
80
  }
@@ -24,6 +24,7 @@ export class PluginCliContribution implements CliContribution {
24
24
 
25
25
  static PLUGINS = 'plugins';
26
26
  static PLUGIN_MAX_SESSION_LOGS_FOLDERS = 'plugin-max-session-logs-folders';
27
+ static UNCOMPRESSED_PLUGINS_IN_PLACE = 'uncompressed-plugins-in-place';
27
28
  /**
28
29
  * This is the default value used in VSCode, see:
29
30
  * - https://github.com/Microsoft/vscode/blob/613447d6b3f458ef7fee227e3876303bf5184580/src/vs/code/electron-browser/sharedProcess/contrib/logsDataCleaner.ts#L32
@@ -32,6 +33,7 @@ export class PluginCliContribution implements CliContribution {
32
33
 
33
34
  protected _localDir: string | undefined;
34
35
  protected _maxSessionLogsFolders: number;
36
+ protected _keepUncompressedInPlace = false;
35
37
 
36
38
  configure(conf: Argv): void {
37
39
  conf.option(PluginCliContribution.PLUGINS, {
@@ -48,6 +50,12 @@ export class PluginCliContribution implements CliContribution {
48
50
  default: PluginCliContribution.DEFAULT_PLUGIN_MAX_SESSION_LOGS_FOLDERS,
49
51
  nargs: 1
50
52
  });
53
+
54
+ conf.option(PluginCliContribution.UNCOMPRESSED_PLUGINS_IN_PLACE, {
55
+ description: 'Whether user plugins that are stored on disk as uncompressed directories should be run in place or copied to temporary folder.',
56
+ type: 'boolean',
57
+ default: false,
58
+ });
51
59
  }
52
60
 
53
61
  setArguments(args: Arguments): void {
@@ -60,6 +68,7 @@ export class PluginCliContribution implements CliContribution {
60
68
  if (maxSessionLogsFoldersArg && Number.isInteger(maxSessionLogsFoldersArg) && maxSessionLogsFoldersArg > 0) {
61
69
  this._maxSessionLogsFolders = maxSessionLogsFoldersArg;
62
70
  }
71
+ this._keepUncompressedInPlace = Boolean(args[PluginCliContribution.UNCOMPRESSED_PLUGINS_IN_PLACE]);
63
72
  }
64
73
 
65
74
  localDir(): string | undefined {
@@ -70,4 +79,7 @@ export class PluginCliContribution implements CliContribution {
70
79
  return this._maxSessionLogsFolders;
71
80
  }
72
81
 
82
+ copyUncompressedPlugins(): boolean {
83
+ return !this._keepUncompressedInPlace;
84
+ }
73
85
  }
@@ -14,12 +14,28 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
+ import * as path from 'path';
18
+ import * as fs from '@theia/core/shared/fs-extra';
17
19
  import { PluginDeployerEntry, PluginDeployerDirectoryHandlerContext } from '../../common/plugin-protocol';
18
20
 
19
21
  export class PluginDeployerDirectoryHandlerContextImpl implements PluginDeployerDirectoryHandlerContext {
20
22
 
21
- constructor(private readonly pluginDeployerEntry: PluginDeployerEntry) {
23
+ constructor(private readonly pluginDeployerEntry: PluginDeployerEntry) { }
22
24
 
25
+ async copy(origin: string, target: string): Promise<void> {
26
+ const contents = await fs.readdir(origin);
27
+ await fs.mkdirp(target);
28
+ await Promise.all(contents.map(async item => {
29
+ const itemPath = path.resolve(origin, item);
30
+ const targetPath = path.resolve(target, item);
31
+ const stat = await fs.stat(itemPath);
32
+ if (stat.isDirectory()) {
33
+ return this.copy(itemPath, targetPath);
34
+ }
35
+ if (stat.isFile()) {
36
+ return new Promise<void>((resolve, reject) => fs.copyFile(itemPath, targetPath, e => e === null ? resolve() : reject(e)));
37
+ }
38
+ }));
23
39
  }
24
40
 
25
41
  pluginEntry(): PluginDeployerEntry {
@@ -25,7 +25,6 @@ export class PluginDeployerFileHandlerContextImpl implements PluginDeployerFileH
25
25
 
26
26
  async unzip(sourcePath: string, destPath: string): Promise<void> {
27
27
  await decompress(sourcePath, destPath);
28
- return Promise.resolve();
29
28
  }
30
29
 
31
30
  pluginEntry(): PluginDeployerEntry {