@theia/plugin-ext 1.70.0-next.7 → 1.70.0-next.71
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/plugin-api-rpc-model.d.ts +6 -1
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc-model.js +2 -1
- package/lib/common/plugin-api-rpc-model.js.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +25 -2
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/common/plugin-protocol.d.ts +8 -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 +2 -0
- package/lib/hosted/browser/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/browser/hosted-plugin.js +7 -0
- package/lib/hosted/browser/hosted-plugin.js.map +1 -1
- package/lib/hosted/common/hosted-plugin.d.ts +3 -0
- package/lib/hosted/common/hosted-plugin.d.ts.map +1 -1
- package/lib/hosted/common/hosted-plugin.js +13 -0
- package/lib/hosted/common/hosted-plugin.js.map +1 -1
- package/lib/hosted/common/hosted-plugin.spec.d.ts +2 -0
- package/lib/hosted/common/hosted-plugin.spec.d.ts.map +1 -0
- package/lib/hosted/common/hosted-plugin.spec.js +308 -0
- package/lib/hosted/common/hosted-plugin.spec.js.map +1 -0
- package/lib/hosted/node/hosted-plugin-process.d.ts +2 -0
- package/lib/hosted/node/hosted-plugin-process.d.ts.map +1 -1
- package/lib/hosted/node/hosted-plugin-process.js +8 -0
- package/lib/hosted/node/hosted-plugin-process.js.map +1 -1
- package/lib/hosted/node/plugin-host-navigator-override.d.ts +12 -0
- package/lib/hosted/node/plugin-host-navigator-override.d.ts.map +1 -0
- package/lib/hosted/node/plugin-host-navigator-override.js +37 -0
- package/lib/hosted/node/plugin-host-navigator-override.js.map +1 -0
- package/lib/hosted/node/plugin-host-navigator-override.spec.d.ts +2 -0
- package/lib/hosted/node/plugin-host-navigator-override.spec.d.ts.map +1 -0
- package/lib/hosted/node/plugin-host-navigator-override.spec.js +49 -0
- package/lib/hosted/node/plugin-host-navigator-override.spec.js.map +1 -0
- package/lib/hosted/node/plugin-host.js +3 -0
- package/lib/hosted/node/plugin-host.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.d.ts +1 -0
- package/lib/hosted/node/scanners/scanner-theia.d.ts.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.js +7 -0
- package/lib/hosted/node/scanners/scanner-theia.js.map +1 -1
- package/lib/hosted/node/scanners/scanner-theia.spec.d.ts +2 -0
- package/lib/hosted/node/scanners/scanner-theia.spec.d.ts.map +1 -0
- package/lib/hosted/node/scanners/scanner-theia.spec.js +93 -0
- package/lib/hosted/node/scanners/scanner-theia.spec.js.map +1 -0
- package/lib/main/browser/languages-main.d.ts +2 -2
- package/lib/main/browser/languages-main.d.ts.map +1 -1
- package/lib/main/browser/languages-main.js +14 -10
- package/lib/main/browser/languages-main.js.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.js +2 -0
- package/lib/main/browser/menus/menus-contribution-handler.js.map +1 -1
- package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -1
- package/lib/main/browser/menus/plugin-menu-command-adapter.js +3 -0
- package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -1
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +3 -2
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -1
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js +10 -2
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +6 -1
- package/lib/main/browser/plugin-contribution-handler.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 +26 -0
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/plugin-ext-widget.d.ts +1 -1
- package/lib/main/browser/plugin-ext-widget.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-widget.js +11 -4
- package/lib/main/browser/plugin-ext-widget.js.map +1 -1
- package/lib/main/browser/scm-main.d.ts +4 -2
- package/lib/main/browser/scm-main.d.ts.map +1 -1
- package/lib/main/browser/scm-main.js +8 -4
- package/lib/main/browser/scm-main.js.map +1 -1
- package/lib/main/browser/text-editor-main.d.ts +2 -0
- package/lib/main/browser/text-editor-main.d.ts.map +1 -1
- package/lib/main/browser/text-editor-main.js +15 -4
- package/lib/main/browser/text-editor-main.js.map +1 -1
- package/lib/main/browser/text-editors-main.d.ts +4 -0
- package/lib/main/browser/text-editors-main.d.ts.map +1 -1
- package/lib/main/browser/text-editors-main.js +121 -0
- package/lib/main/browser/text-editors-main.js.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.d.ts.map +1 -1
- package/lib/main/browser/view/plugin-view-registry.js +16 -0
- package/lib/main/browser/view/plugin-view-registry.js.map +1 -1
- package/lib/main/browser/webview/webview.js +1 -1
- package/lib/main/browser/webview/webview.js.map +1 -1
- package/lib/main/common/plugin-host-environment-preferences.d.ts +14 -0
- package/lib/main/common/plugin-host-environment-preferences.d.ts.map +1 -0
- package/lib/main/common/plugin-host-environment-preferences.js +43 -0
- package/lib/main/common/plugin-host-environment-preferences.js.map +1 -0
- package/lib/main/node/plugin-deployer-impl.d.ts.map +1 -1
- package/lib/main/node/plugin-deployer-impl.js +5 -0
- package/lib/main/node/plugin-deployer-impl.js.map +1 -1
- package/lib/main/node/plugin-ext-backend-module.d.ts.map +1 -1
- package/lib/main/node/plugin-ext-backend-module.js +5 -0
- package/lib/main/node/plugin-ext-backend-module.js.map +1 -1
- package/lib/main/node/plugin-host-navigator-state-initializer.d.ts +17 -0
- package/lib/main/node/plugin-host-navigator-state-initializer.d.ts.map +1 -0
- package/lib/main/node/plugin-host-navigator-state-initializer.js +53 -0
- package/lib/main/node/plugin-host-navigator-state-initializer.js.map +1 -0
- package/lib/plugin/command-registry.d.ts.map +1 -1
- package/lib/plugin/command-registry.js +11 -0
- package/lib/plugin/command-registry.js.map +1 -1
- package/lib/plugin/env.d.ts +5 -0
- package/lib/plugin/env.d.ts.map +1 -1
- package/lib/plugin/env.js +7 -0
- package/lib/plugin/env.js.map +1 -1
- package/lib/plugin/file-system-event-service-ext-impl.d.ts +1 -1
- package/lib/plugin/file-system-event-service-ext-impl.d.ts.map +1 -1
- package/lib/plugin/file-system-ext-impl.d.ts +1 -1
- package/lib/plugin/file-system-ext-impl.d.ts.map +1 -1
- package/lib/plugin/file-system-ext-impl.js +5 -1
- package/lib/plugin/file-system-ext-impl.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +3 -2
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/scm.d.ts +2 -1
- package/lib/plugin/scm.d.ts.map +1 -1
- package/lib/plugin/scm.js +20 -3
- package/lib/plugin/scm.js.map +1 -1
- package/lib/plugin/text-editors.d.ts +2 -2
- package/lib/plugin/text-editors.d.ts.map +1 -1
- package/lib/plugin/text-editors.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +2 -1
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js.map +1 -1
- package/package.json +30 -30
- package/src/common/plugin-api-rpc-model.ts +10 -1
- package/src/common/plugin-api-rpc.ts +21 -2
- package/src/common/plugin-protocol.ts +9 -1
- package/src/hosted/browser/hosted-plugin.ts +6 -0
- package/src/hosted/common/hosted-plugin.spec.ts +377 -0
- package/src/hosted/common/hosted-plugin.ts +18 -1
- package/src/hosted/node/hosted-plugin-process.ts +7 -0
- package/src/hosted/node/plugin-host-navigator-override.spec.ts +53 -0
- package/src/hosted/node/plugin-host-navigator-override.ts +34 -0
- package/src/hosted/node/plugin-host.ts +4 -0
- package/src/hosted/node/scanners/scanner-theia.spec.ts +112 -0
- package/src/hosted/node/scanners/scanner-theia.ts +8 -0
- package/src/main/browser/languages-main.ts +38 -52
- package/src/main/browser/menus/menus-contribution-handler.ts +2 -0
- package/src/main/browser/menus/plugin-menu-command-adapter.ts +3 -0
- package/src/main/browser/menus/vscode-theia-menu-mappings.ts +12 -2
- package/src/main/browser/plugin-contribution-handler.ts +6 -1
- package/src/main/browser/plugin-ext-frontend-module.ts +31 -1
- package/src/main/browser/plugin-ext-widget.tsx +14 -4
- package/src/main/browser/scm-main.ts +13 -6
- package/src/main/browser/style/plugin-sidebar.css +13 -0
- package/src/main/browser/text-editor-main.ts +14 -2
- package/src/main/browser/text-editors-main.ts +132 -0
- package/src/main/browser/view/plugin-view-registry.ts +18 -1
- package/src/main/browser/webview/pre/main.js +9 -9
- package/src/main/browser/webview/webview.ts +1 -1
- package/src/main/common/plugin-host-environment-preferences.ts +48 -0
- package/src/main/node/plugin-deployer-impl.ts +5 -0
- package/src/main/node/plugin-ext-backend-module.ts +5 -1
- package/src/main/node/plugin-host-navigator-state-initializer.ts +47 -0
- package/src/plugin/command-registry.ts +12 -1
- package/src/plugin/env.ts +8 -0
- package/src/plugin/file-system-event-service-ext-impl.ts +1 -1
- package/src/plugin/file-system-ext-impl.ts +1 -2
- package/src/plugin/plugin-context.ts +3 -2
- package/src/plugin/scm.ts +26 -4
- package/src/plugin/text-editors.ts +2 -2
- package/src/plugin/types-impl.ts +2 -1
|
@@ -120,6 +120,8 @@ export class PluginScmProvider implements ScmProvider {
|
|
|
120
120
|
|
|
121
121
|
private features: SourceControlProviderFeatures = {};
|
|
122
122
|
|
|
123
|
+
get providerContextValue(): string | undefined { return this.features.contextValue; }
|
|
124
|
+
|
|
123
125
|
get handle(): number { return this._handle; }
|
|
124
126
|
get label(): string { return this._label; }
|
|
125
127
|
get rootUri(): string { return this._rootUri ? this._rootUri.toString() : ''; }
|
|
@@ -164,7 +166,8 @@ export class PluginScmProvider implements ScmProvider {
|
|
|
164
166
|
private readonly _contextValue: string,
|
|
165
167
|
private readonly _label: string,
|
|
166
168
|
private readonly _rootUri: vscodeURI | undefined,
|
|
167
|
-
private disposables: DisposableCollection
|
|
169
|
+
private disposables: DisposableCollection,
|
|
170
|
+
readonly parentHandle?: number
|
|
168
171
|
) { }
|
|
169
172
|
|
|
170
173
|
updateSourceControl(features: SourceControlProviderFeatures): void {
|
|
@@ -330,17 +333,21 @@ export class ScmMainImpl implements ScmMain {
|
|
|
330
333
|
this.disposables.dispose();
|
|
331
334
|
}
|
|
332
335
|
|
|
333
|
-
async $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): Promise<void> {
|
|
334
|
-
const provider = new PluginScmProvider(
|
|
336
|
+
async $registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined, parentHandle?: number): Promise<void> {
|
|
337
|
+
const provider = new PluginScmProvider(
|
|
338
|
+
this.proxy, this.colors, this.sharedStyle, handle, id, label,
|
|
339
|
+
rootUri ? vscodeURI.revive(rootUri) : undefined, this.disposables, parentHandle
|
|
340
|
+
);
|
|
341
|
+
const parentRepo = parentHandle !== undefined ? this.repositories.get(parentHandle) : undefined;
|
|
335
342
|
const repository = this.scmService.registerScmProvider(provider, {
|
|
336
343
|
input: {
|
|
337
344
|
validator: async value => {
|
|
338
345
|
const result = await this.proxy.$validateInput(handle, value, value.length);
|
|
339
346
|
return result && { message: result[0], type: result[1] };
|
|
340
347
|
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
);
|
|
348
|
+
},
|
|
349
|
+
parentRootUri: parentRepo?.provider.rootUri
|
|
350
|
+
});
|
|
344
351
|
this.repositories.set(handle, repository);
|
|
345
352
|
|
|
346
353
|
const disposables = new DisposableCollection(
|
|
@@ -71,3 +71,16 @@
|
|
|
71
71
|
.plugins-tab-icon::before {
|
|
72
72
|
content: "\f0fe";
|
|
73
73
|
}
|
|
74
|
+
|
|
75
|
+
.theia-plugins .pluginHeaderContainer.pluginDisabledByTrust {
|
|
76
|
+
opacity: 0.6;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.theia-plugins .pluginRestrictedBadge {
|
|
80
|
+
font-size: var(--theia-ui-font-size0);
|
|
81
|
+
color: var(--theia-statusBarItem-prominentForeground);
|
|
82
|
+
background-color: var(--theia-statusBarItem-prominentBackground);
|
|
83
|
+
border-radius: 2px;
|
|
84
|
+
padding: calc(var(--theia-ui-padding) / 3 * 2);
|
|
85
|
+
white-space: nowrap;
|
|
86
|
+
}
|
|
@@ -95,8 +95,16 @@ export class TextEditorMain implements Disposable {
|
|
|
95
95
|
this.toDisposeOnEditor.push(this.editor.onSelectionChanged(_ => {
|
|
96
96
|
this.updateProperties();
|
|
97
97
|
}));
|
|
98
|
-
this.toDisposeOnEditor.push(monacoEditor.onDidChangeModel(
|
|
99
|
-
|
|
98
|
+
this.toDisposeOnEditor.push(monacoEditor.onDidChangeModel(e => {
|
|
99
|
+
// Ignore visibility-related model changes (null ↔ model) triggered by
|
|
100
|
+
// the setModel(null) workaround in MonacoEditor.handleVisibilityChanged().
|
|
101
|
+
// cf. https://github.com/eclipse-theia/theia/issues/14880
|
|
102
|
+
// Only react to genuine model swaps where both old and new models exist.
|
|
103
|
+
// In practice, this condition is never met because MonacoEditor instances
|
|
104
|
+
// are created with a fixed document and never swap to a different model.
|
|
105
|
+
if (e.oldModelUrl && e.newModelUrl) {
|
|
106
|
+
this.setEditor(undefined);
|
|
107
|
+
}
|
|
100
108
|
}));
|
|
101
109
|
this.toDisposeOnEditor.push(monacoEditor.onDidChangeCursorSelection(e => {
|
|
102
110
|
this.updateProperties(e.source);
|
|
@@ -139,6 +147,10 @@ export class TextEditorMain implements Disposable {
|
|
|
139
147
|
return this.editor.diffInformation;
|
|
140
148
|
}
|
|
141
149
|
|
|
150
|
+
getDiffEditor(): MonacoDiffEditor | undefined {
|
|
151
|
+
return this.editor instanceof MonacoDiffEditor ? this.editor : undefined;
|
|
152
|
+
}
|
|
153
|
+
|
|
142
154
|
setSelections(selections: Selection[]): void {
|
|
143
155
|
if (this.editor) {
|
|
144
156
|
this.editor.getControl().setSelections(selections);
|
|
@@ -49,6 +49,11 @@ import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/stan
|
|
|
49
49
|
import { ICodeEditorService } from '@theia/monaco-editor-core/esm/vs/editor/browser/services/codeEditorService';
|
|
50
50
|
import { type ILineChange } from '@theia/monaco-editor-core/esm/vs/editor/common/diff/legacyLinesDiffComputer';
|
|
51
51
|
import { ArrayUtils, URI } from '@theia/core';
|
|
52
|
+
import { DiffUris } from '@theia/core/lib/browser/diff-uris';
|
|
53
|
+
import { TextEditorChangeKind } from '../../plugin/types-impl';
|
|
54
|
+
import { Change } from '@theia/scm/lib/browser/dirty-diff/diff-computer';
|
|
55
|
+
import { DirtyDiffUpdate } from '@theia/scm/lib/browser/dirty-diff/dirty-diff-decorator';
|
|
56
|
+
import { ScmDecorationsService } from '@theia/scm/lib/browser/decorations/scm-decorations-service';
|
|
52
57
|
import { toNotebookWorspaceEdit } from './notebooks/notebooks-main';
|
|
53
58
|
import { interfaces } from '@theia/core/shared/inversify';
|
|
54
59
|
import { NotebookService } from '@theia/notebook/lib/browser';
|
|
@@ -62,6 +67,7 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
|
|
|
62
67
|
|
|
63
68
|
private readonly bulkEditService: MonacoBulkEditService;
|
|
64
69
|
private readonly notebookService: NotebookService;
|
|
70
|
+
private readonly scmDecorationsService: ScmDecorationsService;
|
|
65
71
|
|
|
66
72
|
constructor(
|
|
67
73
|
private readonly editorsAndDocuments: EditorsAndDocumentsMain,
|
|
@@ -73,10 +79,12 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
|
|
|
73
79
|
|
|
74
80
|
this.bulkEditService = container.get(MonacoBulkEditService);
|
|
75
81
|
this.notebookService = container.get(NotebookService);
|
|
82
|
+
this.scmDecorationsService = container.get(ScmDecorationsService);
|
|
76
83
|
|
|
77
84
|
this.toDispose.push(editorsAndDocuments);
|
|
78
85
|
this.toDispose.push(editorsAndDocuments.onTextEditorAdd(editors => editors.forEach(this.onTextEditorAdd, this)));
|
|
79
86
|
this.toDispose.push(editorsAndDocuments.onTextEditorRemove(editors => editors.forEach(this.onTextEditorRemove, this)));
|
|
87
|
+
this.toDispose.push(this.scmDecorationsService.onDirtyDiffUpdate(update => this.onDirtyDiffUpdate(update)));
|
|
80
88
|
}
|
|
81
89
|
|
|
82
90
|
dispose(): void {
|
|
@@ -93,6 +101,130 @@ export class TextEditorsMainImpl implements TextEditorsMain, Disposable {
|
|
|
93
101
|
);
|
|
94
102
|
this.editorsToDispose.set(id, toDispose);
|
|
95
103
|
this.toDispose.push(toDispose);
|
|
104
|
+
|
|
105
|
+
const diffEditor = editor.getDiffEditor();
|
|
106
|
+
if (diffEditor) {
|
|
107
|
+
const pushDiffEditorInfo = () => this.pushDiffEditorDiffInformation(id, editor);
|
|
108
|
+
toDispose.push(diffEditor.diffEditor.onDidUpdateDiff(pushDiffEditorInfo));
|
|
109
|
+
pushDiffEditorInfo();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private onDirtyDiffUpdate(update: DirtyDiffUpdate): void {
|
|
114
|
+
const editorUri = update.editor.uri.toString();
|
|
115
|
+
const editorIds = this.findEditorIdsByUri(editorUri, true);
|
|
116
|
+
if (editorIds.length === 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const originalUri = update.previousRevisionUri?.toComponents();
|
|
121
|
+
|
|
122
|
+
const changes = update.changes.map(change => {
|
|
123
|
+
let kind: TextEditorChangeKind;
|
|
124
|
+
if (Change.isAddition(change)) {
|
|
125
|
+
kind = TextEditorChangeKind.Addition;
|
|
126
|
+
} else if (Change.isRemoval(change)) {
|
|
127
|
+
kind = TextEditorChangeKind.Deletion;
|
|
128
|
+
} else {
|
|
129
|
+
kind = TextEditorChangeKind.Modification;
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
original: {
|
|
133
|
+
startLineNumber: change.previousRange.start + 1,
|
|
134
|
+
endLineNumberExclusive: change.previousRange.end + 1
|
|
135
|
+
},
|
|
136
|
+
modified: {
|
|
137
|
+
startLineNumber: change.currentRange.start + 1,
|
|
138
|
+
endLineNumberExclusive: change.currentRange.end + 1
|
|
139
|
+
},
|
|
140
|
+
kind
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// Push diff information to all editors with this URI (regular editors and diff editor modified sides).
|
|
145
|
+
for (const editorId of editorIds) {
|
|
146
|
+
const editor = this.editorsAndDocuments.getEditor(editorId);
|
|
147
|
+
if (!editor) {
|
|
148
|
+
continue;
|
|
149
|
+
}
|
|
150
|
+
const model = editor.getModel();
|
|
151
|
+
const modifiedUri = URI.fromComponents(model.uri).toComponents();
|
|
152
|
+
this.proxy.$acceptEditorDiffInformation(editorId, [{
|
|
153
|
+
documentVersion: model.getVersionId(),
|
|
154
|
+
original: originalUri,
|
|
155
|
+
modified: modifiedUri,
|
|
156
|
+
changes,
|
|
157
|
+
isStale: false
|
|
158
|
+
}]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private pushDiffEditorDiffInformation(id: string, editor: TextEditorMain): void {
|
|
163
|
+
const diffEditor = editor.getDiffEditor();
|
|
164
|
+
if (!diffEditor) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let originalUri: UriComponents | undefined;
|
|
169
|
+
let modifiedUri: UriComponents;
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
const [left, right] = DiffUris.decode(diffEditor.uri);
|
|
173
|
+
originalUri = left.toComponents();
|
|
174
|
+
modifiedUri = right.toComponents();
|
|
175
|
+
} catch {
|
|
176
|
+
// Not a valid DiffUri; fall back to model URIs
|
|
177
|
+
originalUri = new URI(diffEditor.originalModel.uri).toComponents();
|
|
178
|
+
modifiedUri = new URI(diffEditor.modifiedModel.uri).toComponents();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const lineChanges = diffEditor.diffInformation;
|
|
182
|
+
|
|
183
|
+
const changes = lineChanges.map(change => {
|
|
184
|
+
let kind: TextEditorChangeKind;
|
|
185
|
+
if (change.originalEndLineNumber === 0) {
|
|
186
|
+
kind = TextEditorChangeKind.Addition;
|
|
187
|
+
} else if (change.modifiedEndLineNumber === 0) {
|
|
188
|
+
kind = TextEditorChangeKind.Deletion;
|
|
189
|
+
} else {
|
|
190
|
+
kind = TextEditorChangeKind.Modification;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ILineChange uses 1-based lines where 0 means empty range.
|
|
194
|
+
// TextEditorLineRange uses 1-based startLineNumber and endLineNumberExclusive.
|
|
195
|
+
const toLineRange = (start: number, end: number) => end === 0
|
|
196
|
+
? { startLineNumber: start + 1, endLineNumberExclusive: start + 1 }
|
|
197
|
+
: { startLineNumber: start, endLineNumberExclusive: end + 1 };
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
original: toLineRange(change.originalStartLineNumber, change.originalEndLineNumber),
|
|
201
|
+
modified: toLineRange(change.modifiedStartLineNumber, change.modifiedEndLineNumber),
|
|
202
|
+
kind
|
|
203
|
+
};
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const model = editor.getModel();
|
|
207
|
+
this.proxy.$acceptEditorDiffInformation(id, [{
|
|
208
|
+
documentVersion: model.getVersionId(),
|
|
209
|
+
original: originalUri,
|
|
210
|
+
modified: modifiedUri,
|
|
211
|
+
changes,
|
|
212
|
+
isStale: false
|
|
213
|
+
}]);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private findEditorIdsByUri(uri: string, excludeDiffEditors = false): string[] {
|
|
217
|
+
const ids: string[] = [];
|
|
218
|
+
for (const id of this.editorsToDispose.keys()) {
|
|
219
|
+
const editor = this.editorsAndDocuments.getEditor(id);
|
|
220
|
+
if (editor && editor.getModel().uri.toString() === uri) {
|
|
221
|
+
if (excludeDiffEditors && editor.getDiffEditor()) {
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
ids.push(id);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return ids;
|
|
96
228
|
}
|
|
97
229
|
|
|
98
230
|
private onTextEditorRemove(id: string): void {
|
|
@@ -24,7 +24,9 @@ import { ViewContainer, View, ViewWelcome, PluginViewType } from '../../../commo
|
|
|
24
24
|
import { PluginSharedStyle } from '../plugin-shared-style';
|
|
25
25
|
import { DebugWidget } from '@theia/debug/lib/browser/view/debug-widget';
|
|
26
26
|
import { PluginViewWidget, PluginViewWidgetIdentifier } from './plugin-view-widget';
|
|
27
|
-
import { SCM_VIEW_CONTAINER_ID, ScmContribution } from '@theia/scm/lib/browser/scm-contribution';
|
|
27
|
+
import { SCM_VIEW_CONTAINER_ID, SCM_WIDGET_FACTORY_ID, ScmContribution } from '@theia/scm/lib/browser/scm-contribution';
|
|
28
|
+
import { ScmWidget } from '@theia/scm/lib/browser/scm-widget';
|
|
29
|
+
import { ScmTreeWidget } from '@theia/scm/lib/browser/scm-tree-widget';
|
|
28
30
|
import { EXPLORER_VIEW_CONTAINER_ID, FileNavigatorWidget, FILE_NAVIGATOR_ID } from '@theia/navigator/lib/browser';
|
|
29
31
|
import { FileNavigatorContribution } from '@theia/navigator/lib/browser/navigator-contribution';
|
|
30
32
|
import { DebugFrontendApplicationContribution } from '@theia/debug/lib/browser/debug-frontend-application-contribution';
|
|
@@ -187,6 +189,17 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
187
189
|
}));
|
|
188
190
|
disposable.push(event.widget.onDidDispose(() => disposable.dispose()));
|
|
189
191
|
}
|
|
192
|
+
if (event.widget instanceof ScmWidget) {
|
|
193
|
+
const disposable = new DisposableCollection();
|
|
194
|
+
disposable.push(this.registerViewWelcome({
|
|
195
|
+
view: 'scm',
|
|
196
|
+
content: nls.localizeByDefault('None of the registered source control providers work in Restricted Mode.')
|
|
197
|
+
+ `\n[${nls.localizeByDefault('Manage Workspace Trust')}](command:workspace:manageTrust)`,
|
|
198
|
+
when: '!isWorkspaceTrusted',
|
|
199
|
+
order: 0
|
|
200
|
+
}));
|
|
201
|
+
disposable.push(event.widget.onDidDispose(() => disposable.dispose()));
|
|
202
|
+
}
|
|
190
203
|
});
|
|
191
204
|
this.contextKeyService.onDidChange(e => {
|
|
192
205
|
for (const [, view] of this.views.values()) {
|
|
@@ -561,6 +574,10 @@ export class PluginViewRegistry implements FrontendApplicationContribution {
|
|
|
561
574
|
switch (viewId) {
|
|
562
575
|
case 'explorer':
|
|
563
576
|
return this.widgetManager.getWidget<TreeViewWelcomeWidget>(FILE_NAVIGATOR_ID);
|
|
577
|
+
case 'scm': {
|
|
578
|
+
const scmWidget = await this.widgetManager.getWidget<ScmWidget>(SCM_WIDGET_FACTORY_ID);
|
|
579
|
+
return scmWidget?.resourceWidget as ScmTreeWidget | undefined;
|
|
580
|
+
}
|
|
564
581
|
default:
|
|
565
582
|
return this.widgetManager.getWidget<TreeViewWelcomeWidget>(PLUGIN_VIEW_DATA_FACTORY_ID, { id: viewId });
|
|
566
583
|
}
|
|
@@ -154,29 +154,29 @@ globalThis.acquireVsCodeApi = (function() {
|
|
|
154
154
|
|
|
155
155
|
let state = ${state ? `JSON.parse(${JSON.stringify(state)})` : undefined};
|
|
156
156
|
|
|
157
|
-
const forwardConsoleLog = (level, msg, args) => {
|
|
157
|
+
const forwardConsoleLog = (level, msg, ...args) => {
|
|
158
158
|
let message, optionalParams;
|
|
159
159
|
try {
|
|
160
160
|
if (msg) {
|
|
161
161
|
message = JSON.stringify(msg) ?? null;
|
|
162
162
|
}
|
|
163
|
-
if (args) {
|
|
163
|
+
if (args.length > 0) {
|
|
164
164
|
optionalParams = JSON.stringify(args) ?? null;
|
|
165
165
|
}
|
|
166
166
|
} catch (e) {
|
|
167
167
|
// Log non serializable objects inside of view
|
|
168
|
-
originalConsole[level](msg, args);
|
|
168
|
+
originalConsole[level](msg, ...args);
|
|
169
169
|
return;
|
|
170
170
|
}
|
|
171
171
|
originalPostMessage({ command: 'onconsole', data: { level, message, optionalParams } }, targetOrigin);
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
-
console.log = (message, args) => forwardConsoleLog('log', message, args);
|
|
175
|
-
console.info = (message, args) => forwardConsoleLog('info', message, args);
|
|
176
|
-
console.warn = (message, args) => forwardConsoleLog('warn', message, args);
|
|
177
|
-
console.error = (message, args) => forwardConsoleLog('error', message, args);
|
|
178
|
-
console.debug = (message, args) => forwardConsoleLog('debug', message, args);
|
|
179
|
-
console.trace = (message, args) => forwardConsoleLog('trace', message, args);
|
|
174
|
+
console.log = (message, ...args) => forwardConsoleLog('log', message, ...args);
|
|
175
|
+
console.info = (message, ...args) => forwardConsoleLog('info', message, ...args);
|
|
176
|
+
console.warn = (message, ...args) => forwardConsoleLog('warn', message, ...args);
|
|
177
|
+
console.error = (message, ...args) => forwardConsoleLog('error', message, ...args);
|
|
178
|
+
console.debug = (message, ...args) => forwardConsoleLog('debug', message, ...args);
|
|
179
|
+
console.trace = (message, ...args) => forwardConsoleLog('trace', message, ...args);
|
|
180
180
|
|
|
181
181
|
return () => {
|
|
182
182
|
if (acquired) {
|
|
@@ -475,7 +475,7 @@ export class WebviewWidget extends BaseWidget implements StatefulWidget, Extract
|
|
|
475
475
|
protected forwardConsoleLog(log: WebviewConsoleLog): void {
|
|
476
476
|
const message = `[webview: ${this.identifier.id}] ${log.message ? JSON.parse(log.message) : undefined}`;
|
|
477
477
|
if (log.optionalParams !== undefined) {
|
|
478
|
-
console[log.level](message, JSON.parse(log.optionalParams));
|
|
478
|
+
console[log.level](message, ...JSON.parse(log.optionalParams));
|
|
479
479
|
} else {
|
|
480
480
|
console[log.level](message);
|
|
481
481
|
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 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-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { interfaces } from '@theia/core/shared/inversify';
|
|
18
|
+
import { PreferenceContribution, PreferenceSchema } from '@theia/core/lib/common/preferences';
|
|
19
|
+
import { nls } from '@theia/core/lib/common/nls';
|
|
20
|
+
|
|
21
|
+
export const SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF = 'extensions.supportNodeGlobalNavigator';
|
|
22
|
+
|
|
23
|
+
export const PluginHostEnvironmentPreferenceSchema: PreferenceSchema = {
|
|
24
|
+
properties: {
|
|
25
|
+
[SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF]: {
|
|
26
|
+
type: 'boolean',
|
|
27
|
+
description: nls.localize('theia/plugin-ext/supportNodeGlobalNavigator',
|
|
28
|
+
'If enabled, the global navigator object in the extension host will be defined as provided by Node.js. '
|
|
29
|
+
+ 'Extensions may use the presence of the navigator object as a hint that code is running in a browser. '
|
|
30
|
+
+ 'Disabling this (the default) undefines the navigator in the extension host to preserve this assumption.'),
|
|
31
|
+
default: false,
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Mutable state holder for the navigator preference, injected as a constant value
|
|
38
|
+
* so it can be safely resolved in connection-scoped containers (no async dependencies).
|
|
39
|
+
*/
|
|
40
|
+
export const PluginHostNavigatorState = Symbol('PluginHostNavigatorState');
|
|
41
|
+
export interface PluginHostNavigatorState {
|
|
42
|
+
supportNodeGlobalNavigator: boolean;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function bindPluginHostEnvironmentPreferences(bind: interfaces.Bind): void {
|
|
46
|
+
bind(PreferenceContribution).toConstantValue({ schema: PluginHostEnvironmentPreferenceSchema });
|
|
47
|
+
bind(PluginHostNavigatorState).toConstantValue({ supportNodeGlobalNavigator: false });
|
|
48
|
+
}
|
|
@@ -181,6 +181,7 @@ export class PluginDeployerImpl implements PluginDeployer {
|
|
|
181
181
|
const hasBeenVisited = (id: string) => visited.has(id) || (visited.add(id), false);
|
|
182
182
|
const pluginsToDeploy = new Map<PluginIdentifiers.VersionedId, PluginDeployerEntry>();
|
|
183
183
|
const unversionedIdsHandled = new Map<PluginIdentifiers.UnversionedId, string[]>();
|
|
184
|
+
const errors: Error[] = [];
|
|
184
185
|
|
|
185
186
|
const queue: UnresolvedPluginEntry[] = [...plugins];
|
|
186
187
|
while (queue.length) {
|
|
@@ -215,6 +216,7 @@ export class PluginDeployerImpl implements PluginDeployer {
|
|
|
215
216
|
}
|
|
216
217
|
} catch (e) {
|
|
217
218
|
console.error(`Failed to resolve plugins from '${entry.id}'`, e);
|
|
219
|
+
errors.push(e instanceof Error ? e : new Error(String(e)));
|
|
218
220
|
}
|
|
219
221
|
}));
|
|
220
222
|
queue.length = 0;
|
|
@@ -229,6 +231,9 @@ export class PluginDeployerImpl implements PluginDeployer {
|
|
|
229
231
|
}
|
|
230
232
|
}
|
|
231
233
|
}
|
|
234
|
+
if (pluginsToDeploy.size === 0 && errors.length > 0) {
|
|
235
|
+
throw errors[0];
|
|
236
|
+
}
|
|
232
237
|
return [...pluginsToDeploy.values()];
|
|
233
238
|
}
|
|
234
239
|
|
|
@@ -47,6 +47,8 @@ import { RemoteCliContribution } from '@theia/core/lib/node/remote/remote-cli-co
|
|
|
47
47
|
import { PluginRemoteCopyContribution } from './plugin-remote-copy-contribution';
|
|
48
48
|
import { RemoteCopyContribution } from '@theia/core/lib/node/remote/remote-copy-contribution';
|
|
49
49
|
import { bindWebviewPreferences } from '../common/webview-preferences';
|
|
50
|
+
import { bindPluginHostEnvironmentPreferences } from '../common/plugin-host-environment-preferences';
|
|
51
|
+
import { PluginHostNavigatorStateInitializer } from './plugin-host-navigator-state-initializer';
|
|
50
52
|
|
|
51
53
|
export function bindMainBackend(bind: interfaces.Bind, unbind: interfaces.Unbind, isBound: interfaces.IsBound, rebind: interfaces.Rebind): void {
|
|
52
54
|
bind(PluginApiContribution).toSelf().inSingletonScope();
|
|
@@ -104,5 +106,7 @@ export function bindMainBackend(bind: interfaces.Bind, unbind: interfaces.Unbind
|
|
|
104
106
|
|
|
105
107
|
rebind(LocalizationServerImpl).to(PluginLocalizationServer).inSingletonScope();
|
|
106
108
|
bindWebviewPreferences(bind);
|
|
107
|
-
|
|
109
|
+
bindPluginHostEnvironmentPreferences(bind);
|
|
110
|
+
bind(PluginHostNavigatorStateInitializer).toSelf().inSingletonScope();
|
|
111
|
+
bind(BackendApplicationContribution).toService(PluginHostNavigatorStateInitializer);
|
|
108
112
|
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 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-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { inject, injectable } from '@theia/core/shared/inversify';
|
|
18
|
+
import { PreferenceService } from '@theia/core/lib/common/preferences';
|
|
19
|
+
import { BackendApplicationContribution } from '@theia/core/lib/node';
|
|
20
|
+
import { PluginHostNavigatorState, SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF } from '../common/plugin-host-environment-preferences';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Keeps {@link PluginHostNavigatorState} in sync with the navigator preference.
|
|
24
|
+
*
|
|
25
|
+
* `PreferenceService` has async dependencies and cannot be injected in
|
|
26
|
+
* connection-scoped containers. This contribution runs in the root container
|
|
27
|
+
* and mutates the shared state object by reference so that
|
|
28
|
+
* `HostedPluginProcess` (connection-scoped) always sees the latest value.
|
|
29
|
+
*/
|
|
30
|
+
@injectable()
|
|
31
|
+
export class PluginHostNavigatorStateInitializer implements BackendApplicationContribution {
|
|
32
|
+
|
|
33
|
+
@inject(PreferenceService)
|
|
34
|
+
protected readonly preferences: PreferenceService;
|
|
35
|
+
|
|
36
|
+
@inject(PluginHostNavigatorState)
|
|
37
|
+
protected readonly state: PluginHostNavigatorState;
|
|
38
|
+
|
|
39
|
+
onStart(): void {
|
|
40
|
+
this.state.supportNodeGlobalNavigator = this.preferences.get<boolean>(SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF, false);
|
|
41
|
+
this.preferences.onPreferenceChanged(e => {
|
|
42
|
+
if (e.preferenceName === SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF) {
|
|
43
|
+
this.state.supportNodeGlobalNavigator = this.preferences.get<boolean>(SUPPORT_NODE_GLOBAL_NAVIGATOR_PREF, false);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -22,10 +22,11 @@ import * as theia from '@theia/plugin';
|
|
|
22
22
|
import * as model from '../common/plugin-api-rpc-model';
|
|
23
23
|
import { CommandRegistryExt, PLUGIN_RPC_CONTEXT as Ext, CommandRegistryMain } from '../common/plugin-api-rpc';
|
|
24
24
|
import { RPCProtocol } from '../common/rpc-protocol';
|
|
25
|
-
import { Disposable } from './types-impl';
|
|
25
|
+
import { Disposable, URI } from './types-impl';
|
|
26
26
|
import { DisposableCollection } from '@theia/core';
|
|
27
27
|
import { KnownCommands } from './known-commands';
|
|
28
28
|
import { ArgumentProcessor } from '../common/commands';
|
|
29
|
+
import { isUriComponents } from './type-converters';
|
|
29
30
|
|
|
30
31
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
31
32
|
export type Handler = <T>(...args: any[]) => T | PromiseLike<T | undefined>;
|
|
@@ -42,6 +43,16 @@ export class CommandRegistryImpl implements CommandRegistryExt {
|
|
|
42
43
|
this.proxy = rpc.getProxy(Ext.COMMAND_REGISTRY_MAIN);
|
|
43
44
|
this.argumentProcessors = [];
|
|
44
45
|
this.commandsConverter = new CommandsConverter(this);
|
|
46
|
+
this.registerArgumentProcessor({
|
|
47
|
+
processArgument: arg => {
|
|
48
|
+
// Revive URI-like plain objects that lost their class identity during RPC/JSON serialization
|
|
49
|
+
// (e.g. command arguments from markdown links parsed by CommandOpenHandler)
|
|
50
|
+
if (isUriComponents(arg) && !(arg instanceof URI)) {
|
|
51
|
+
return URI.revive(arg);
|
|
52
|
+
}
|
|
53
|
+
return arg;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
45
56
|
}
|
|
46
57
|
|
|
47
58
|
get converter(): CommandsConverter {
|
package/src/plugin/env.ts
CHANGED
|
@@ -108,6 +108,14 @@ export abstract class EnvExtImpl {
|
|
|
108
108
|
|
|
109
109
|
abstract get isNewAppInstall(): boolean;
|
|
110
110
|
|
|
111
|
+
/**
|
|
112
|
+
* @stubbed
|
|
113
|
+
* Portable mode detection is not yet communicated to the plugin host.
|
|
114
|
+
*/
|
|
115
|
+
get isAppPortable(): boolean {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
|
|
111
119
|
get appHost(): string {
|
|
112
120
|
return this.host;
|
|
113
121
|
}
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
|
|
31
31
|
import { Emitter, WaitUntilEvent, AsyncEmitter, WaitUntilData } from '@theia/core/lib/common/event';
|
|
32
32
|
import { IRelativePattern, parse } from '@theia/core/lib/common/glob';
|
|
33
|
-
import { UriComponents } from '
|
|
33
|
+
import { UriComponents } from '../common/uri-components';
|
|
34
34
|
import { Disposable, URI, WorkspaceEdit } from './types-impl';
|
|
35
35
|
import { EditorsAndDocumentsExtImpl as ExtHostDocumentsAndEditors } from './editors-and-documents';
|
|
36
36
|
import type * as vscode from '@theia/plugin';
|
|
@@ -28,14 +28,13 @@
|
|
|
28
28
|
/* eslint-disable @typescript-eslint/tslint/config */
|
|
29
29
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
30
30
|
|
|
31
|
-
import { UriComponents } from '
|
|
31
|
+
import { Schemes as Schemas, UriComponents } from '../common/uri-components';
|
|
32
32
|
import { FileChangeType, FileSystemError, URI } from './types-impl';
|
|
33
33
|
import { RPCProtocol } from '../common/rpc-protocol';
|
|
34
34
|
import { PLUGIN_RPC_CONTEXT, FileSystemExt, FileSystemMain, IFileChangeDto } from '../common/plugin-api-rpc';
|
|
35
35
|
import * as vscode from '@theia/plugin';
|
|
36
36
|
import * as files from '@theia/filesystem/lib/common/files';
|
|
37
37
|
import * as typeConverter from './type-converters';
|
|
38
|
-
import { Schemes as Schemas } from '../common/uri-components';
|
|
39
38
|
import { State, StateMachine, LinkComputer, Edge } from '../common/link-computer';
|
|
40
39
|
import { commonPrefixLength } from '@theia/core/lib/common/strings';
|
|
41
40
|
import { CharCode } from '@theia/core/lib/common/char-code';
|
|
@@ -930,6 +930,7 @@ export function createAPIFactory(
|
|
|
930
930
|
get appHost(): string { return envExt.appHost; },
|
|
931
931
|
get language(): string { return envExt.language; },
|
|
932
932
|
get isNewAppInstall(): boolean { return envExt.isNewAppInstall; },
|
|
933
|
+
get isAppPortable(): boolean { return envExt.isAppPortable; },
|
|
933
934
|
get isTelemetryEnabled(): boolean { return telemetryExt.isTelemetryEnabled; },
|
|
934
935
|
get onDidChangeTelemetryEnabled(): theia.Event<boolean> {
|
|
935
936
|
return telemetryExt.onDidChangeTelemetryEnabled;
|
|
@@ -1285,8 +1286,8 @@ export function createAPIFactory(
|
|
|
1285
1286
|
throw new Error('Input box not found!');
|
|
1286
1287
|
}
|
|
1287
1288
|
},
|
|
1288
|
-
createSourceControl(id: string, label: string, rootUri?: URI): theia.SourceControl {
|
|
1289
|
-
return createAPIObject(scmExt.createSourceControl(plugin, id, label, rootUri));
|
|
1289
|
+
createSourceControl(id: string, label: string, rootUri?: URI, iconPath?: theia.IconPath, parent?: theia.SourceControl): theia.SourceControl {
|
|
1290
|
+
return createAPIObject(scmExt.createSourceControl(plugin, id, label, rootUri, iconPath, parent));
|
|
1290
1291
|
}
|
|
1291
1292
|
};
|
|
1292
1293
|
|
package/src/plugin/scm.ts
CHANGED
|
@@ -676,12 +676,23 @@ class SourceControlImpl implements theia.SourceControl {
|
|
|
676
676
|
private readonly onDidChangeSelectionEmitter = new Emitter<boolean>();
|
|
677
677
|
readonly onDidChangeSelection = this.onDidChangeSelectionEmitter.event;
|
|
678
678
|
|
|
679
|
+
private _contextValue: string | undefined = undefined;
|
|
680
|
+
|
|
681
|
+
get contextValue(): string | undefined {
|
|
682
|
+
return this._contextValue;
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
set contextValue(contextValue: string | undefined) {
|
|
686
|
+
this._contextValue = contextValue;
|
|
687
|
+
this.proxy.$updateSourceControl(this.handle, { contextValue });
|
|
688
|
+
}
|
|
689
|
+
|
|
679
690
|
private readonly onDidDisposeEmitter = new Emitter<void>();
|
|
680
691
|
readonly onDidDispose = this.onDidDisposeEmitter.event;
|
|
681
692
|
|
|
682
693
|
readonly onDidDisposeParent: Event<void>;
|
|
683
694
|
|
|
684
|
-
|
|
695
|
+
readonly handle: number = SourceControlImpl.handlePool++;
|
|
685
696
|
|
|
686
697
|
constructor(
|
|
687
698
|
private plugin: Plugin,
|
|
@@ -694,7 +705,7 @@ class SourceControlImpl implements theia.SourceControl {
|
|
|
694
705
|
_parent?: SourceControlImpl
|
|
695
706
|
) {
|
|
696
707
|
this.inputBox = new ScmInputBoxImpl(plugin, this.proxy, this.handle);
|
|
697
|
-
this.proxy.$registerSourceControl(this.handle, _id, _label, _rootUri);
|
|
708
|
+
this.proxy.$registerSourceControl(this.handle, _id, _label, _rootUri, _parent?.handle);
|
|
698
709
|
this.onDidDisposeParent = _parent ? _parent.onDidDispose : Event.None;
|
|
699
710
|
}
|
|
700
711
|
|
|
@@ -824,9 +835,11 @@ export class ScmExtImpl implements ScmExt {
|
|
|
824
835
|
});
|
|
825
836
|
}
|
|
826
837
|
|
|
827
|
-
createSourceControl(extension: Plugin, id: string, label: string, rootUri: theia.Uri | undefined
|
|
838
|
+
createSourceControl(extension: Plugin, id: string, label: string, rootUri: theia.Uri | undefined,
|
|
839
|
+
iconPath?: theia.IconPath, parent?: theia.SourceControl): theia.SourceControl {
|
|
828
840
|
const handle = ScmExtImpl.handlePool++;
|
|
829
|
-
const
|
|
841
|
+
const parentImpl = parent ? this.findSourceControlImpl(parent) : undefined;
|
|
842
|
+
const sourceControl = new SourceControlImpl(extension, this.proxy, this.commands, id, label, rootUri, iconPath, parentImpl);
|
|
830
843
|
this.sourceControls.set(handle, sourceControl);
|
|
831
844
|
|
|
832
845
|
const sourceControls = this.sourceControlsByExtension.get(extension.model.id) || [];
|
|
@@ -836,6 +849,15 @@ export class ScmExtImpl implements ScmExt {
|
|
|
836
849
|
return sourceControl;
|
|
837
850
|
}
|
|
838
851
|
|
|
852
|
+
private findSourceControlImpl(apiObject: theia.SourceControl): SourceControlImpl | undefined {
|
|
853
|
+
for (const impl of this.sourceControls.values()) {
|
|
854
|
+
if (impl.id === apiObject.id && impl.rootUri?.toString() === apiObject.rootUri?.toString()) {
|
|
855
|
+
return impl;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return undefined;
|
|
859
|
+
}
|
|
860
|
+
|
|
839
861
|
getLastInputBox(extension: Plugin): ScmInputBoxImpl | undefined {
|
|
840
862
|
const sourceControls = this.sourceControlsByExtension.get(extension.model.id);
|
|
841
863
|
const sourceControl = sourceControls && sourceControls[sourceControls.length - 1];
|