@theia/plugin-ext 1.37.0-next.8 → 1.37.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.
- package/lib/common/language-pack-service.d.ts +16 -0
- package/lib/common/language-pack-service.d.ts.map +1 -0
- package/lib/common/language-pack-service.js +21 -0
- package/lib/common/language-pack-service.js.map +1 -0
- package/lib/common/plugin-api-rpc-model.d.ts +6 -0
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc-model.js +6 -1
- package/lib/common/plugin-api-rpc-model.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +22 -1
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js +2 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +2 -0
- package/lib/common/plugin-protocol.d.ts.map +1 -1
- package/lib/common/plugin-protocol.js.map +1 -1
- package/lib/hosted/browser/hosted-plugin.d.ts +6 -2
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +26 -5
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/browser/worker/worker-main.js +4 -2
- package/lib/hosted/browser/worker/worker-main.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-deployer-handler.js +2 -2
- package/lib/hosted/node/hosted-plugin-deployer-handler.js.map +1 -1
- package/lib/hosted/node/hosted-plugin-localization-service.d.ts +13 -1
- package/lib/hosted/node/hosted-plugin-localization-service.d.ts.map +1 -1
- package/lib/hosted/node/hosted-plugin-localization-service.js +122 -10
- package/lib/hosted/node/hosted-plugin-localization-service.js.map +1 -1
- package/lib/hosted/node/plugin-ext-hosted-backend-module.d.ts.map +1 -1
- package/lib/hosted/node/plugin-ext-hosted-backend-module.js +7 -0
- package/lib/hosted/node/plugin-ext-hosted-backend-module.js.map +1 -1
- package/lib/hosted/node/plugin-host-rpc.d.ts +2 -2
- package/lib/hosted/node/plugin-host-rpc.d.ts.map +1 -1
- package/lib/hosted/node/plugin-host-rpc.js +6 -4
- package/lib/hosted/node/plugin-host-rpc.js.map +1 -1
- package/lib/hosted/node/plugin-language-pack-service.d.ts +8 -0
- package/lib/hosted/node/plugin-language-pack-service.d.ts.map +1 -0
- package/lib/hosted/node/plugin-language-pack-service.js +54 -0
- package/lib/hosted/node/plugin-language-pack-service.js.map +1 -0
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +1 -0
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.d.ts.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.js +5 -1
- package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
- package/lib/main/browser/comments/comments-main.d.ts +6 -1
- package/lib/main/browser/comments/comments-main.d.ts.map +1 -1
- package/lib/main/browser/comments/comments-main.js +15 -0
- package/lib/main/browser/comments/comments-main.js.map +1 -1
- package/lib/main/browser/localization-main.d.ts +9 -0
- package/lib/main/browser/localization-main.d.ts.map +1 -0
- package/lib/main/browser/localization-main.js +32 -0
- package/lib/main/browser/localization-main.js.map +1 -0
- package/lib/main/browser/main-context.d.ts.map +1 -1
- package/lib/main/browser/main-context.js +3 -0
- package/lib/main/browser/main-context.js.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.js +5 -0
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
- package/lib/main/browser/view/tree-view-widget.js +10 -1
- package/lib/main/browser/view/tree-view-widget.js.map +1 -1
- package/lib/main/electron-browser/webview/electron-webview-widget-factory.d.ts +1 -0
- package/lib/main/electron-browser/webview/electron-webview-widget-factory.d.ts.map +1 -1
- package/lib/main/electron-browser/webview/electron-webview-widget-factory.js +4 -15
- package/lib/main/electron-browser/webview/electron-webview-widget-factory.js.map +1 -1
- package/lib/main/node/plugin-github-resolver.d.ts +3 -1
- package/lib/main/node/plugin-github-resolver.d.ts.map +1 -1
- package/lib/main/node/plugin-github-resolver.js +64 -71
- package/lib/main/node/plugin-github-resolver.js.map +1 -1
- package/lib/main/node/plugin-http-resolver.d.ts +2 -0
- package/lib/main/node/plugin-http-resolver.d.ts.map +1 -1
- package/lib/main/node/plugin-http-resolver.js +31 -31
- package/lib/main/node/plugin-http-resolver.js.map +1 -1
- package/lib/main/node/plugins-key-value-storage.js +1 -1
- package/lib/main/node/plugins-key-value-storage.js.map +1 -1
- package/lib/plugin/comments.d.ts +3 -0
- package/lib/plugin/comments.d.ts.map +1 -1
- package/lib/plugin/comments.js +24 -0
- package/lib/plugin/comments.js.map +1 -1
- package/lib/plugin/localization-ext.d.ts +17 -0
- package/lib/plugin/localization-ext.d.ts.map +1 -0
- package/lib/plugin/localization-ext.js +74 -0
- package/lib/plugin/localization-ext.js.map +1 -0
- package/lib/plugin/output-channel/log-output-channel.d.ts +24 -0
- package/lib/plugin/output-channel/log-output-channel.d.ts.map +1 -0
- package/lib/plugin/output-channel/log-output-channel.js +92 -0
- package/lib/plugin/output-channel/log-output-channel.js.map +1 -0
- package/lib/plugin/output-channel/output-channel-item.d.ts +3 -3
- package/lib/plugin/output-channel/output-channel-item.d.ts.map +1 -1
- package/lib/plugin/output-channel/output-channel-item.js.map +1 -1
- package/lib/plugin/output-channel-registry.d.ts +7 -2
- package/lib/plugin/output-channel-registry.d.ts.map +1 -1
- package/lib/plugin/output-channel-registry.js +15 -6
- package/lib/plugin/output-channel-registry.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts +2 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +26 -3
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/plugin-manager.d.ts +3 -2
- package/lib/plugin/plugin-manager.d.ts.map +1 -1
- package/lib/plugin/plugin-manager.js +4 -1
- package/lib/plugin/plugin-manager.js.map +1 -1
- package/lib/plugin/preference-registry.d.ts +1 -1
- package/lib/plugin/preference-registry.js +1 -1
- package/lib/plugin/stubs/tests-api.d.ts +2 -1
- package/lib/plugin/stubs/tests-api.d.ts.map +1 -1
- package/lib/plugin/stubs/tests-api.js +2 -1
- package/lib/plugin/stubs/tests-api.js.map +1 -1
- package/lib/plugin/tree/tree-views.d.ts +2 -0
- package/lib/plugin/tree/tree-views.d.ts.map +1 -1
- package/lib/plugin/tree/tree-views.js +10 -3
- package/lib/plugin/tree/tree-views.js.map +1 -1
- package/lib/plugin/type-converters.d.ts.map +1 -1
- package/lib/plugin/type-converters.js +6 -3
- package/lib/plugin/type-converters.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +8 -4
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +12 -7
- package/lib/plugin/types-impl.js.map +1 -1
- package/package.json +28 -30
- package/src/common/language-pack-service.ts +34 -0
- package/src/common/plugin-api-rpc-model.ts +7 -0
- package/src/common/plugin-api-rpc.ts +25 -2
- package/src/common/plugin-protocol.ts +2 -0
- package/src/hosted/browser/hosted-plugin.ts +27 -6
- package/src/hosted/browser/worker/worker-main.ts +5 -2
- package/src/hosted/node/hosted-plugin-deployer-handler.ts +2 -2
- package/src/hosted/node/hosted-plugin-localization-service.ts +132 -11
- package/src/hosted/node/plugin-ext-hosted-backend-module.ts +12 -0
- package/src/hosted/node/plugin-host-rpc.ts +8 -5
- package/src/hosted/node/plugin-language-pack-service.ts +43 -0
- package/src/hosted/node/scanners/scanner-theia.ts +1 -0
- package/src/main/browser/comments/comment-thread-widget.tsx +6 -1
- package/src/main/browser/comments/comments-main.ts +18 -1
- package/src/main/browser/localization-main.ts +34 -0
- package/src/main/browser/main-context.ts +4 -0
- package/src/main/browser/plugin-ext-frontend-module.ts +6 -0
- package/src/main/browser/view/tree-view-widget.tsx +11 -1
- package/src/main/electron-browser/webview/electron-webview-widget-factory.ts +4 -15
- package/src/main/node/plugin-github-resolver.ts +65 -81
- package/src/main/node/plugin-http-resolver.ts +29 -35
- package/src/main/node/plugins-key-value-storage.ts +1 -1
- package/src/plugin/comments.ts +32 -1
- package/src/plugin/localization-ext.ts +84 -0
- package/src/plugin/output-channel/log-output-channel.ts +108 -0
- package/src/plugin/output-channel/output-channel-item.ts +2 -2
- package/src/plugin/output-channel-registry.ts +20 -7
- package/src/plugin/plugin-context.ts +31 -3
- package/src/plugin/plugin-manager.ts +5 -1
- package/src/plugin/preference-registry.ts +1 -1
- package/src/plugin/stubs/tests-api.ts +3 -1
- package/src/plugin/tree/tree-views.ts +12 -3
- package/src/plugin/type-converters.ts +5 -3
- package/src/plugin/types-impl.ts +8 -3
- package/LICENSE +0 -642
|
@@ -632,13 +632,23 @@ export class TreeViewWidget extends TreeViewWelcomeWidget {
|
|
|
632
632
|
|
|
633
633
|
handleDragEnd(node: TreeViewNode, event: React.DragEvent<HTMLElement>): void {
|
|
634
634
|
this.applicationShell.clearAdditionalDraggedEditorUris();
|
|
635
|
+
this.model.proxy!.$dragEnd(this.id);
|
|
635
636
|
}
|
|
636
637
|
|
|
637
638
|
handleDragOver(event: React.DragEvent<HTMLElement>): void {
|
|
639
|
+
const hasFiles = (items: DataTransferItemList) => {
|
|
640
|
+
for (let i = 0; i < items.length; i++) {
|
|
641
|
+
if (items[i].kind === 'file') {
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return false;
|
|
646
|
+
};
|
|
647
|
+
|
|
638
648
|
if (event.dataTransfer) {
|
|
639
649
|
const canDrop = event.dataTransfer.types.some(type => this.options.dropMimeTypes!.includes(type)) ||
|
|
640
650
|
event.dataTransfer.types.includes(this.treeDragType) ||
|
|
641
|
-
this.options.dropMimeTypes!.includes('files') && event.dataTransfer.
|
|
651
|
+
this.options.dropMimeTypes!.includes('files') && hasFiles(event.dataTransfer.items);
|
|
642
652
|
if (canDrop) {
|
|
643
653
|
event.preventDefault();
|
|
644
654
|
event.dataTransfer.dropEffect = 'move';
|
|
@@ -14,12 +14,11 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import * as electronRemote from '@theia/core/electron-shared/@electron/remote';
|
|
18
|
-
import { ElectronSecurityToken } from '@theia/core/lib/electron-common/electron-token';
|
|
19
17
|
import { WebviewWidgetFactory } from '../../browser/webview/webview-widget-factory';
|
|
20
18
|
import { WebviewWidgetIdentifier, WebviewWidget } from '../../browser/webview/webview';
|
|
21
19
|
import { CustomEditorWidgetFactory } from '../../browser/custom-editors/custom-editor-widget-factory';
|
|
22
20
|
import { CustomEditorWidget } from '../../browser/custom-editors/custom-editor-widget';
|
|
21
|
+
import '@theia/core/lib/electron-common/electron-api';
|
|
23
22
|
|
|
24
23
|
export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
|
|
25
24
|
|
|
@@ -34,13 +33,8 @@ export class ElectronWebviewWidgetFactory extends WebviewWidgetFactory {
|
|
|
34
33
|
*
|
|
35
34
|
* @param endpoint cookie's target url
|
|
36
35
|
*/
|
|
37
|
-
protected
|
|
38
|
-
|
|
39
|
-
url: endpoint,
|
|
40
|
-
name: ElectronSecurityToken,
|
|
41
|
-
value: JSON.stringify(this.container.get(ElectronSecurityToken)),
|
|
42
|
-
httpOnly: true
|
|
43
|
-
});
|
|
36
|
+
protected attachElectronSecurityCookie(endpoint: string): Promise<void> {
|
|
37
|
+
return window.electronTheiaCore.attachSecurityToken(endpoint);
|
|
44
38
|
}
|
|
45
39
|
|
|
46
40
|
}
|
|
@@ -59,12 +53,7 @@ export class ElectronCustomEditorWidgetFactory extends CustomEditorWidgetFactory
|
|
|
59
53
|
* @param endpoint cookie's target url
|
|
60
54
|
*/
|
|
61
55
|
protected async attachElectronSecurityCookie(endpoint: string): Promise<void> {
|
|
62
|
-
|
|
63
|
-
url: endpoint,
|
|
64
|
-
name: ElectronSecurityToken,
|
|
65
|
-
value: JSON.stringify(this.container.get(ElectronSecurityToken)),
|
|
66
|
-
httpOnly: true
|
|
67
|
-
});
|
|
56
|
+
return window.electronTheiaCore.attachSecurityToken(endpoint);
|
|
68
57
|
}
|
|
69
58
|
|
|
70
59
|
}
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
17
|
+
import { RequestContext, RequestService } from '@theia/core/shared/@theia/request';
|
|
18
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
19
|
+
import { promises as fs, existsSync, mkdirSync } from 'fs';
|
|
19
20
|
import * as os from 'os';
|
|
20
21
|
import * as path from 'path';
|
|
21
|
-
import * as request from 'request';
|
|
22
22
|
import { PluginDeployerResolver, PluginDeployerResolverContext } from '../../common';
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -35,10 +35,13 @@ export class GithubPluginDeployerResolver implements PluginDeployerResolver {
|
|
|
35
35
|
|
|
36
36
|
private unpackedFolder: string;
|
|
37
37
|
|
|
38
|
+
@inject(RequestService)
|
|
39
|
+
protected readonly request: RequestService;
|
|
40
|
+
|
|
38
41
|
constructor() {
|
|
39
42
|
this.unpackedFolder = path.resolve(os.tmpdir(), 'github-remote');
|
|
40
|
-
if (!
|
|
41
|
-
|
|
43
|
+
if (!existsSync(this.unpackedFolder)) {
|
|
44
|
+
mkdirSync(this.unpackedFolder);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
47
|
|
|
@@ -48,95 +51,76 @@ export class GithubPluginDeployerResolver implements PluginDeployerResolver {
|
|
|
48
51
|
async resolve(pluginResolverContext: PluginDeployerResolverContext): Promise<void> {
|
|
49
52
|
|
|
50
53
|
// download the file
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
54
|
+
// extract data
|
|
55
|
+
const extracted = /^github:(.*)\/(.*)\/(.*)$/gm.exec(pluginResolverContext.getOriginId());
|
|
56
|
+
if (!extracted || extracted === null || extracted.length !== 4) {
|
|
57
|
+
throw new Error('Invalid extension' + pluginResolverContext.getOriginId());
|
|
58
|
+
}
|
|
58
59
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
60
|
+
const orgName = extracted[1];
|
|
61
|
+
const repoName = extracted[2];
|
|
62
|
+
const file = extracted[3];
|
|
63
|
+
|
|
64
|
+
// get version if any
|
|
65
|
+
const splitFile = file.split('@');
|
|
66
|
+
let version;
|
|
67
|
+
let filename: string;
|
|
68
|
+
if (splitFile.length === 1) {
|
|
69
|
+
filename = file;
|
|
70
|
+
version = 'latest';
|
|
71
|
+
} else {
|
|
72
|
+
filename = splitFile[0];
|
|
73
|
+
version = splitFile[1];
|
|
74
|
+
}
|
|
75
|
+
// latest version, need to get the redirect
|
|
76
|
+
const url = GithubPluginDeployerResolver.GITHUB_ENDPOINT + orgName + '/' + repoName + '/releases/latest';
|
|
76
77
|
|
|
78
|
+
// if latest, resolve first the real version
|
|
79
|
+
if (version === 'latest') {
|
|
77
80
|
// disable redirect to grab the release
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (!taggedValueArray || taggedValueArray.length !== 2) {
|
|
96
|
-
reject(new Error('The redirect link for latest is invalid ' + redirectLocation));
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// grab version of tag
|
|
101
|
-
this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, taggedValueArray[1], resolve, reject);
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
} else {
|
|
106
|
-
this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, version, resolve, reject);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
});
|
|
81
|
+
const followRedirects = 0;
|
|
82
|
+
const response = await this.request.request({ url, followRedirects });
|
|
83
|
+
// should have a redirect
|
|
84
|
+
if (response.res.statusCode === 302) {
|
|
85
|
+
const redirectLocation = response.res.headers.location;
|
|
86
|
+
if (!redirectLocation) {
|
|
87
|
+
throw new Error('Invalid github link with latest not being found');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// parse redirect link
|
|
91
|
+
const taggedValueArray = /^https:\/\/.*tag\/(.*)/gm.exec(redirectLocation);
|
|
92
|
+
if (!taggedValueArray || taggedValueArray.length !== 2) {
|
|
93
|
+
throw new Error('The redirect link for latest is invalid ' + redirectLocation);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// grab version of tag
|
|
97
|
+
return this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, taggedValueArray[1]);
|
|
110
98
|
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
return this.grabGithubFile(pluginResolverContext, orgName, repoName, filename, version);
|
|
102
|
+
}
|
|
111
103
|
}
|
|
112
104
|
|
|
113
105
|
/*
|
|
114
106
|
* Grab the github file specified by the plugin's ID
|
|
115
107
|
*/
|
|
116
|
-
protected grabGithubFile(pluginResolverContext: PluginDeployerResolverContext, orgName: string, repoName: string, filename: string, version: string
|
|
117
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
-
resolve: (value?: void | PromiseLike<void>) => void, reject: (reason?: any) => void): void {
|
|
119
|
-
|
|
108
|
+
protected async grabGithubFile(pluginResolverContext: PluginDeployerResolverContext, orgName: string, repoName: string, filename: string, version: string): Promise<void> {
|
|
120
109
|
const unpackedPath = path.resolve(this.unpackedFolder, path.basename(version + filename));
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// use of cache. If file is already there use it directly
|
|
127
|
-
if (fs.existsSync(unpackedPath)) {
|
|
128
|
-
finish();
|
|
110
|
+
try {
|
|
111
|
+
await fs.access(unpackedPath);
|
|
112
|
+
// use of cache. If file is already there use it directly
|
|
129
113
|
return;
|
|
130
|
-
}
|
|
131
|
-
const dest = fs.createWriteStream(unpackedPath);
|
|
114
|
+
} catch { }
|
|
132
115
|
|
|
133
|
-
dest.addListener('finish', finish);
|
|
134
116
|
const url = GithubPluginDeployerResolver.GITHUB_ENDPOINT + orgName + '/' + repoName + '/releases/download/' + version + '/' + filename;
|
|
135
|
-
request.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
117
|
+
const response = await this.request.request({ url });
|
|
118
|
+
if (RequestContext.isSuccess(response)) {
|
|
119
|
+
await fs.writeFile(unpackedPath, response.buffer);
|
|
120
|
+
pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
|
|
121
|
+
} else {
|
|
122
|
+
throw new Error(`Could not download the plugin from GitHub. URL: ${url}. HTTP status code: ${response.res.statusCode}`);
|
|
123
|
+
}
|
|
140
124
|
}
|
|
141
125
|
|
|
142
126
|
/**
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
17
|
+
import { RequestContext, RequestService } from '@theia/core/shared/@theia/request';
|
|
18
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
19
|
+
import { promises as fs, existsSync, mkdirSync } from 'fs';
|
|
19
20
|
import * as os from 'os';
|
|
20
21
|
import * as path from 'path';
|
|
21
22
|
import * as url from 'url';
|
|
22
|
-
import * as request from 'request';
|
|
23
|
-
|
|
24
23
|
import { PluginDeployerResolver, PluginDeployerResolverContext } from '../../common';
|
|
25
24
|
|
|
26
25
|
/**
|
|
@@ -33,10 +32,13 @@ export class HttpPluginDeployerResolver implements PluginDeployerResolver {
|
|
|
33
32
|
|
|
34
33
|
private unpackedFolder: string;
|
|
35
34
|
|
|
35
|
+
@inject(RequestService)
|
|
36
|
+
protected readonly request: RequestService;
|
|
37
|
+
|
|
36
38
|
constructor() {
|
|
37
39
|
this.unpackedFolder = path.resolve(os.tmpdir(), 'http-remote');
|
|
38
|
-
if (!
|
|
39
|
-
|
|
40
|
+
if (!existsSync(this.unpackedFolder)) {
|
|
41
|
+
mkdirSync(this.unpackedFolder);
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
@@ -46,39 +48,31 @@ export class HttpPluginDeployerResolver implements PluginDeployerResolver {
|
|
|
46
48
|
async resolve(pluginResolverContext: PluginDeployerResolverContext): Promise<void> {
|
|
47
49
|
|
|
48
50
|
// download the file
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
reject(new Error('invalid link URI' + urlPath));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const dirname = path.dirname(link.pathname);
|
|
60
|
-
const basename = path.basename(link.pathname);
|
|
61
|
-
const filename = dirname.replace(/\W/g, '_') + ('-') + basename;
|
|
62
|
-
const unpackedPath = path.resolve(this.unpackedFolder, path.basename(filename));
|
|
51
|
+
// keep filename of the url
|
|
52
|
+
const urlPath = pluginResolverContext.getOriginId();
|
|
53
|
+
const link = url.parse(urlPath);
|
|
54
|
+
if (!link.pathname) {
|
|
55
|
+
throw new Error('invalid link URI' + urlPath);
|
|
56
|
+
}
|
|
63
57
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
const dirname = path.dirname(link.pathname);
|
|
59
|
+
const basename = path.basename(link.pathname);
|
|
60
|
+
const filename = dirname.replace(/\W/g, '_') + ('-') + basename;
|
|
61
|
+
const unpackedPath = path.resolve(this.unpackedFolder, path.basename(filename));
|
|
68
62
|
|
|
63
|
+
try {
|
|
64
|
+
await fs.access(unpackedPath);
|
|
69
65
|
// use of cache. If file is already there use it directly
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const dest = fs.createWriteStream(unpackedPath);
|
|
66
|
+
return;
|
|
67
|
+
} catch { }
|
|
75
68
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
const response = await this.request.request({ url: pluginResolverContext.getOriginId() });
|
|
70
|
+
if (RequestContext.isSuccess(response)) {
|
|
71
|
+
await fs.writeFile(unpackedPath, response.buffer);
|
|
72
|
+
pluginResolverContext.addPlugin(pluginResolverContext.getOriginId(), unpackedPath);
|
|
73
|
+
} else {
|
|
74
|
+
throw new Error(`Could not download the plugin from ${pluginResolverContext.getOriginId()}. HTTP status code: ${response.res.statusCode}`);
|
|
75
|
+
}
|
|
82
76
|
|
|
83
77
|
}
|
|
84
78
|
|
package/src/plugin/comments.ts
CHANGED
|
@@ -18,10 +18,11 @@ import * as theia from '@theia/plugin';
|
|
|
18
18
|
import { RPCProtocol } from '../common/rpc-protocol';
|
|
19
19
|
import { CommandRegistryImpl } from './command-registry';
|
|
20
20
|
import { UriComponents } from '../common/uri-components';
|
|
21
|
-
import { CommentThreadCollapsibleState, URI } from './types-impl';
|
|
21
|
+
import { CommentThreadCollapsibleState, CommentThreadState, URI } from './types-impl';
|
|
22
22
|
import {
|
|
23
23
|
Range,
|
|
24
24
|
Comment,
|
|
25
|
+
CommentThreadState as CommentThreadStateModel,
|
|
25
26
|
CommentThreadCollapsibleState as CommentThreadCollapsibleStateModel,
|
|
26
27
|
CommentOptions
|
|
27
28
|
} from '../common/plugin-api-rpc-model';
|
|
@@ -185,6 +186,7 @@ type CommentThreadModification = Partial<{
|
|
|
185
186
|
contextValue: string | undefined,
|
|
186
187
|
comments: theia.Comment[],
|
|
187
188
|
collapsibleState: theia.CommentThreadCollapsibleState
|
|
189
|
+
state: theia.CommentThreadState
|
|
188
190
|
canReply: boolean;
|
|
189
191
|
}>;
|
|
190
192
|
|
|
@@ -276,6 +278,20 @@ export class ExtHostCommentThread implements theia.CommentThread, theia.Disposab
|
|
|
276
278
|
this._onDidUpdateCommentThread.fire();
|
|
277
279
|
}
|
|
278
280
|
|
|
281
|
+
private _state?: theia.CommentThreadState;
|
|
282
|
+
|
|
283
|
+
get state(): theia.CommentThreadState {
|
|
284
|
+
return this._state!;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
set state(newState: theia.CommentThreadState) {
|
|
288
|
+
if (this._state !== newState) {
|
|
289
|
+
this._state = newState;
|
|
290
|
+
this.modifications.state = newState;
|
|
291
|
+
this._onDidUpdateCommentThread.fire();
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
279
295
|
private localDisposables: Disposable[];
|
|
280
296
|
|
|
281
297
|
private _isDisposed: boolean;
|
|
@@ -357,6 +373,9 @@ export class ExtHostCommentThread implements theia.CommentThread, theia.Disposab
|
|
|
357
373
|
if (modified('collapsibleState')) {
|
|
358
374
|
formattedModifications.collapseState = convertToCollapsibleState(this.collapseState);
|
|
359
375
|
}
|
|
376
|
+
if (modified('state')) {
|
|
377
|
+
formattedModifications.state = convertToState(this._state);
|
|
378
|
+
}
|
|
360
379
|
if (modified('canReply')) {
|
|
361
380
|
formattedModifications.canReply = this.canReply;
|
|
362
381
|
}
|
|
@@ -516,3 +535,15 @@ function convertToCollapsibleState(kind: theia.CommentThreadCollapsibleState | u
|
|
|
516
535
|
}
|
|
517
536
|
return CommentThreadCollapsibleStateModel.Collapsed;
|
|
518
537
|
}
|
|
538
|
+
|
|
539
|
+
function convertToState(kind: theia.CommentThreadState | undefined): CommentThreadStateModel {
|
|
540
|
+
if (kind !== undefined) {
|
|
541
|
+
switch (kind) {
|
|
542
|
+
case CommentThreadState.Resolved:
|
|
543
|
+
return CommentThreadStateModel.Resolved;
|
|
544
|
+
case CommentThreadState.Unresolved:
|
|
545
|
+
return CommentThreadStateModel.Unresolved;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
return CommentThreadStateModel.Unresolved;
|
|
549
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 TypeFox 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
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
|
+
|
|
19
|
+
import { nls } from '@theia/core';
|
|
20
|
+
import { Localization } from '@theia/core/lib/common/i18n/localization';
|
|
21
|
+
import { LocalizationExt, LocalizationMain, Plugin, PLUGIN_RPC_CONTEXT, StringDetails } from '../common';
|
|
22
|
+
import { LanguagePackBundle } from '../common/language-pack-service';
|
|
23
|
+
import { RPCProtocol } from '../common/rpc-protocol';
|
|
24
|
+
import { URI } from './types-impl';
|
|
25
|
+
|
|
26
|
+
export class LocalizationExtImpl implements LocalizationExt {
|
|
27
|
+
|
|
28
|
+
private readonly _proxy: LocalizationMain;
|
|
29
|
+
private currentLanguage?: string;
|
|
30
|
+
private isDefaultLanguage = true;
|
|
31
|
+
private readonly bundleCache = new Map<string, LanguagePackBundle | undefined>();
|
|
32
|
+
|
|
33
|
+
constructor(rpc: RPCProtocol) {
|
|
34
|
+
this._proxy = rpc.getProxy(PLUGIN_RPC_CONTEXT.LOCALIZATION_MAIN);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
translateMessage(pluginId: string, details: StringDetails): string {
|
|
38
|
+
const { message, args, comment } = details;
|
|
39
|
+
if (this.isDefaultLanguage) {
|
|
40
|
+
return Localization.format(message, (args ?? {}));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let key = message;
|
|
44
|
+
if (comment && comment.length > 0) {
|
|
45
|
+
key += `/${Array.isArray(comment) ? comment.join() : comment}`;
|
|
46
|
+
}
|
|
47
|
+
const str = this.bundleCache.get(pluginId)?.contents[key];
|
|
48
|
+
return Localization.format(str ?? message, (args ?? {}));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
getBundle(pluginId: string): { [key: string]: string } | undefined {
|
|
52
|
+
return this.bundleCache.get(pluginId)?.contents;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
getBundleUri(pluginId: string): URI | undefined {
|
|
56
|
+
const uri = this.bundleCache.get(pluginId)?.uri;
|
|
57
|
+
return uri ? URI.parse(uri) : undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async initializeLocalizedMessages(plugin: Plugin, currentLanguage: string): Promise<void> {
|
|
61
|
+
this.currentLanguage ??= currentLanguage;
|
|
62
|
+
this.isDefaultLanguage = this.currentLanguage === nls.defaultLocale;
|
|
63
|
+
|
|
64
|
+
if (this.isDefaultLanguage) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (this.bundleCache.has(plugin.model.id)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let bundle: LanguagePackBundle | undefined;
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
bundle = await this._proxy.$fetchBundle(plugin.model.id);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.error(`Failed to load translations for ${plugin.model.id}: ${e.message}`);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
this.bundleCache.set(plugin.model.id, bundle);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2023 STMicroelectronics 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
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
17
|
+
|
|
18
|
+
import { Emitter } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
19
|
+
import * as theia from '@theia/plugin';
|
|
20
|
+
|
|
21
|
+
import { OutputChannelRegistryMain, PluginInfo } from '../../common/plugin-api-rpc';
|
|
22
|
+
import { OutputChannelImpl } from './output-channel-item';
|
|
23
|
+
import { LogLevel } from '../types-impl';
|
|
24
|
+
import { isArray, isObject } from '@theia/core';
|
|
25
|
+
|
|
26
|
+
export class LogOutputChannelImpl extends OutputChannelImpl implements theia.LogOutputChannel {
|
|
27
|
+
|
|
28
|
+
readonly onDidChangeLogLevelEmitter: Emitter<theia.LogLevel> = new Emitter<theia.LogLevel>();
|
|
29
|
+
readonly onDidChangeLogLevel: theia.Event<theia.LogLevel> = this.onDidChangeLogLevelEmitter.event;
|
|
30
|
+
public logLevel: theia.LogLevel;
|
|
31
|
+
|
|
32
|
+
constructor(name: string, proxy: OutputChannelRegistryMain, pluginInfo: PluginInfo) {
|
|
33
|
+
super(name, proxy, pluginInfo);
|
|
34
|
+
this.setLogLevel(LogLevel.Info);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
setLogLevel(level: theia.LogLevel): void {
|
|
38
|
+
if (this.logLevel !== level) {
|
|
39
|
+
this.logLevel = level;
|
|
40
|
+
this.onDidChangeLogLevelEmitter.fire(this.logLevel);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getLogLevel(): theia.LogLevel {
|
|
45
|
+
return this.logLevel;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override append(value: string): void {
|
|
49
|
+
super.validate();
|
|
50
|
+
this.info(value);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
override appendLine(value: string): void {
|
|
54
|
+
super.validate();
|
|
55
|
+
this.append(value + '\n');
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
override dispose(): void {
|
|
59
|
+
super.dispose();
|
|
60
|
+
this.onDidChangeLogLevelEmitter.dispose();
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected log(level: theia.LogLevel, message: string): void {
|
|
64
|
+
super.validate();
|
|
65
|
+
if (this.checkLogLevel(level)) {
|
|
66
|
+
const now = new Date();
|
|
67
|
+
const eol = message.endsWith('\n') ? '' : '\n';
|
|
68
|
+
const logMessage = `${now.toISOString()} [${LogLevel[level]}] ${message}${eol}`;
|
|
69
|
+
this.proxy.$append(this.name, logMessage, this.pluginInfo);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private checkLogLevel(level: theia.LogLevel): boolean {
|
|
74
|
+
return this.logLevel <= level;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
trace(message: string, ...args: any[]): void {
|
|
78
|
+
this.log(LogLevel.Trace, this.format(message, args));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
debug(message: string, ...args: any[]): void {
|
|
82
|
+
this.log(LogLevel.Debug, this.format(message, args));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
info(message: string, ...args: any[]): void {
|
|
86
|
+
this.log(LogLevel.Info, this.format(message, args));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
warn(message: string, ...args: any[]): void {
|
|
90
|
+
this.log(LogLevel.Warning, this.format(message, args));
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
error(errorMsg: string | Error, ...args: any[]): void {
|
|
94
|
+
if (errorMsg instanceof Error) {
|
|
95
|
+
this.log(LogLevel.Error, this.format(errorMsg.stack || errorMsg.message, args));
|
|
96
|
+
} else {
|
|
97
|
+
this.log(LogLevel.Error, this.format(errorMsg, args));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private format(message: string, args: any[]): string {
|
|
102
|
+
if (args.length > 0) {
|
|
103
|
+
return `${message} ${args.map((arg: any) => isObject(arg) || isArray(arg) ? JSON.stringify(arg) : arg).join(' ')}`;
|
|
104
|
+
}
|
|
105
|
+
return message;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
}
|
|
@@ -20,7 +20,7 @@ export class OutputChannelImpl implements theia.OutputChannel {
|
|
|
20
20
|
|
|
21
21
|
private disposed: boolean;
|
|
22
22
|
|
|
23
|
-
constructor(readonly name: string,
|
|
23
|
+
constructor(readonly name: string, protected readonly proxy: OutputChannelRegistryMain, protected readonly pluginInfo: PluginInfo) {
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
dispose(): void {
|
|
@@ -65,7 +65,7 @@ export class OutputChannelImpl implements theia.OutputChannel {
|
|
|
65
65
|
this.proxy.$close(this.name);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
protected validate(): void {
|
|
69
69
|
if (this.disposed) {
|
|
70
70
|
throw new Error('Channel has been closed');
|
|
71
71
|
}
|