@theia/plugin-ext 1.37.0 → 1.37.2
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.d.ts +8 -0
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js +3 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/main/browser/debug/plugin-debug-service.d.ts +2 -2
- package/lib/main/browser/debug/plugin-debug-service.d.ts.map +1 -1
- package/lib/main/browser/debug/plugin-debug-service.js +4 -4
- package/lib/main/browser/debug/plugin-debug-service.js.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.d.ts +3 -1
- package/lib/main/browser/plugin-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/plugin-contribution-handler.js +24 -4
- 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 +2 -0
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/plugin-frontend-contribution.d.ts +5 -2
- package/lib/main/browser/plugin-frontend-contribution.d.ts.map +1 -1
- package/lib/main/browser/plugin-frontend-contribution.js +36 -2
- package/lib/main/browser/plugin-frontend-contribution.js.map +1 -1
- package/lib/main/browser/view/plugin-view-widget.d.ts +4 -2
- package/lib/main/browser/view/plugin-view-widget.d.ts.map +1 -1
- package/lib/main/browser/view/plugin-view-widget.js +6 -0
- package/lib/main/browser/view/plugin-view-widget.js.map +1 -1
- package/lib/main/browser/view/tree-view-widget.d.ts +2 -0
- package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
- package/lib/main/browser/view/tree-view-widget.js +3 -0
- package/lib/main/browser/view/tree-view-widget.js.map +1 -1
- package/lib/main/browser/view/tree-views-main.d.ts.map +1 -1
- package/lib/main/browser/view/tree-views-main.js +1 -0
- package/lib/main/browser/view/tree-views-main.js.map +1 -1
- package/lib/plugin/env.d.ts +0 -5
- package/lib/plugin/env.d.ts.map +1 -1
- package/lib/plugin/env.js +0 -10
- package/lib/plugin/env.js.map +1 -1
- package/lib/plugin/languages.d.ts +2 -0
- package/lib/plugin/languages.d.ts.map +1 -1
- package/lib/plugin/languages.js +6 -0
- package/lib/plugin/languages.js.map +1 -1
- package/lib/plugin/plugin-context.d.ts.map +1 -1
- package/lib/plugin/plugin-context.js +38 -4
- package/lib/plugin/plugin-context.js.map +1 -1
- package/lib/plugin/telemetry-ext.d.ts +44 -0
- package/lib/plugin/telemetry-ext.d.ts.map +1 -0
- package/lib/plugin/telemetry-ext.js +252 -0
- package/lib/plugin/telemetry-ext.js.map +1 -0
- package/lib/plugin/terminal-ext.d.ts +2 -0
- package/lib/plugin/terminal-ext.d.ts.map +1 -1
- package/lib/plugin/terminal-ext.js +4 -0
- package/lib/plugin/terminal-ext.js.map +1 -1
- package/lib/plugin/tree/tree-views.d.ts.map +1 -1
- package/lib/plugin/tree/tree-views.js +6 -24
- package/lib/plugin/tree/tree-views.js.map +1 -1
- package/lib/plugin/types-impl.d.ts +56 -0
- package/lib/plugin/types-impl.d.ts.map +1 -1
- package/lib/plugin/types-impl.js +54 -4
- package/lib/plugin/types-impl.js.map +1 -1
- package/lib/plugin/workspace.d.ts +2 -0
- package/lib/plugin/workspace.d.ts.map +1 -1
- package/lib/plugin/workspace.js +4 -0
- package/lib/plugin/workspace.js.map +1 -1
- package/package.json +27 -27
- package/src/common/plugin-api-rpc.ts +11 -1
- package/src/main/browser/debug/plugin-debug-service.ts +4 -4
- package/src/main/browser/plugin-contribution-handler.ts +24 -5
- package/src/main/browser/plugin-ext-frontend-module.ts +2 -0
- package/src/main/browser/plugin-frontend-contribution.ts +37 -2
- package/src/main/browser/view/plugin-view-widget.ts +9 -2
- package/src/main/browser/view/tree-view-widget.tsx +5 -0
- package/src/main/browser/view/tree-views-main.ts +1 -0
- package/src/plugin/env.ts +0 -13
- package/src/plugin/languages.ts +10 -0
- package/src/plugin/plugin-context.ts +46 -5
- package/src/plugin/telemetry-ext.ts +299 -0
- package/src/plugin/terminal-ext.ts +5 -0
- package/src/plugin/tree/tree-views.ts +7 -25
- package/src/plugin/types-impl.ts +79 -0
- package/src/plugin/workspace.ts +6 -1
|
@@ -0,0 +1,299 @@
|
|
|
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
|
+
import { Event, Emitter } from '@theia/core/lib/common/event';
|
|
17
|
+
import { cloneAndChange } from '@theia/core';
|
|
18
|
+
import { mixin } from '../common/types';
|
|
19
|
+
import { TelemetryTrustedValue, TelemetryLoggerOptions } from './types-impl';
|
|
20
|
+
|
|
21
|
+
export class TelemetryExtImpl {
|
|
22
|
+
|
|
23
|
+
_isTelemetryEnabled: boolean = false; // telemetry not activated by default
|
|
24
|
+
private readonly onDidChangeTelemetryEnabledEmitter = new Emitter<boolean>();
|
|
25
|
+
readonly onDidChangeTelemetryEnabled: Event<boolean> = this.onDidChangeTelemetryEnabledEmitter.event;
|
|
26
|
+
|
|
27
|
+
get isTelemetryEnabled(): boolean {
|
|
28
|
+
return this._isTelemetryEnabled;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
set isTelemetryEnabled(isTelemetryEnabled: boolean) {
|
|
32
|
+
if (this._isTelemetryEnabled !== isTelemetryEnabled) {
|
|
33
|
+
this._isTelemetryEnabled = isTelemetryEnabled;
|
|
34
|
+
this.onDidChangeTelemetryEnabledEmitter.fire(this._isTelemetryEnabled);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
createTelemetryLogger(sender: TelemetrySender, options?: TelemetryLoggerOptions | undefined): TelemetryLogger {
|
|
39
|
+
const logger = new TelemetryLogger(sender, this._isTelemetryEnabled, options);
|
|
40
|
+
this.onDidChangeTelemetryEnabled(isEnabled => {
|
|
41
|
+
logger.telemetryEnabled = isEnabled;
|
|
42
|
+
});
|
|
43
|
+
return logger;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class TelemetryLogger {
|
|
48
|
+
private sender: TelemetrySender | undefined;
|
|
49
|
+
readonly options: TelemetryLoggerOptions | undefined;
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
51
|
+
readonly commonProperties: Record<string, any>;
|
|
52
|
+
telemetryEnabled: boolean;
|
|
53
|
+
|
|
54
|
+
private readonly onDidChangeEnableStatesEmitter: Emitter<TelemetryLogger> = new Emitter();
|
|
55
|
+
readonly onDidChangeEnableStates: Event<TelemetryLogger> = this.onDidChangeEnableStatesEmitter.event;
|
|
56
|
+
private _isUsageEnabled: boolean;
|
|
57
|
+
private _isErrorsEnabled: boolean;
|
|
58
|
+
|
|
59
|
+
constructor(sender: TelemetrySender, telemetryEnabled: boolean, options?: TelemetryLoggerOptions) {
|
|
60
|
+
this.sender = sender;
|
|
61
|
+
this.options = options;
|
|
62
|
+
this.commonProperties = this.getCommonProperties();
|
|
63
|
+
this._isErrorsEnabled = true;
|
|
64
|
+
this._isUsageEnabled = true;
|
|
65
|
+
this.telemetryEnabled = telemetryEnabled;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
get isUsageEnabled(): boolean {
|
|
69
|
+
return this._isUsageEnabled;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
set isUsageEnabled(isUsageEnabled: boolean) {
|
|
73
|
+
if (this._isUsageEnabled !== isUsageEnabled) {
|
|
74
|
+
this._isUsageEnabled = isUsageEnabled;
|
|
75
|
+
this.onDidChangeEnableStatesEmitter.fire(this);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get isErrorsEnabled(): boolean {
|
|
80
|
+
return this._isErrorsEnabled;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
set isErrorsEnabled(isErrorsEnabled: boolean) {
|
|
84
|
+
if (this._isErrorsEnabled !== isErrorsEnabled) {
|
|
85
|
+
this._isErrorsEnabled = isErrorsEnabled;
|
|
86
|
+
this.onDidChangeEnableStatesEmitter.fire(this);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
91
|
+
logUsage(eventName: string, data?: Record<string, any | TelemetryTrustedValue<any>>): void {
|
|
92
|
+
if (!this.telemetryEnabled || !this.isUsageEnabled) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this.logEvent(eventName, data);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
99
|
+
logError(eventNameOrException: string | Error, data?: Record<string, any | TelemetryTrustedValue<any>>): void {
|
|
100
|
+
if (!this.telemetryEnabled || !this.isErrorsEnabled || !this.sender) {
|
|
101
|
+
// no sender available or error shall not be sent
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (typeof eventNameOrException === 'string') {
|
|
105
|
+
this.logEvent(eventNameOrException, data);
|
|
106
|
+
} else {
|
|
107
|
+
this.sender.sendErrorData(eventNameOrException, data);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
dispose(): void {
|
|
112
|
+
if (this.sender?.flush) {
|
|
113
|
+
let tempSender: TelemetrySender | undefined = this.sender;
|
|
114
|
+
this.sender = undefined;
|
|
115
|
+
Promise.resolve(tempSender.flush!()).then(tempSender = undefined);
|
|
116
|
+
} else {
|
|
117
|
+
this.sender = undefined;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
private logEvent(eventName: string, data?: Record<string, any>): void {
|
|
123
|
+
// No sender means likely disposed of, we should no-op
|
|
124
|
+
if (!this.sender) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
data = mixInCommonPropsAndCleanData(data || {}, this.options?.additionalCommonProperties, this.options?.ignoreBuiltInCommonProperties ? undefined : this.commonProperties);
|
|
128
|
+
this.sender?.sendEventData(eventName, data);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
132
|
+
private getCommonProperties(): Record<string, any> {
|
|
133
|
+
return [];
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
interface TelemetrySender {
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
139
|
+
sendEventData(eventName: string, data?: Record<string, any>): void;
|
|
140
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
141
|
+
sendErrorData(error: Error, data?: Record<string, any>): void;
|
|
142
|
+
flush?(): void | Thenable<void>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// copied and modified from https://github.com/microsoft/vscode/blob/1.76.0/src/vs/workbench/api/common/extHostTelemetry.ts
|
|
146
|
+
/*---------------------------------------------------------------------------------------------
|
|
147
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
148
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
149
|
+
*--------------------------------------------------------------------------------------------*/
|
|
150
|
+
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
152
|
+
function mixInCommonPropsAndCleanData(data: Record<string, any>, additionalProperties?: Record<string, any>, commonProperties?: Record<string, any>): Record<string, any> {
|
|
153
|
+
let updatedData = data.properties ?? data;
|
|
154
|
+
|
|
155
|
+
// We don't clean measurements since they are just numbers
|
|
156
|
+
updatedData = cleanData(updatedData, []);
|
|
157
|
+
|
|
158
|
+
if (additionalProperties) {
|
|
159
|
+
updatedData = mixin(updatedData, additionalProperties);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (commonProperties) {
|
|
163
|
+
updatedData = mixin(updatedData, commonProperties);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if (data.properties) {
|
|
167
|
+
data.properties = updatedData;
|
|
168
|
+
} else {
|
|
169
|
+
data = updatedData;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return data;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// copied and modified from https://github.com/microsoft/vscode/blob/1.76.0/src/vs/platform/telemetry/common/telemetryUtils.ts#L321-L442
|
|
176
|
+
/*---------------------------------------------------------------------------------------------
|
|
177
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
178
|
+
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
179
|
+
*--------------------------------------------------------------------------------------------*/
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Cleans a given stack of possible paths
|
|
183
|
+
* @param stack The stack to sanitize
|
|
184
|
+
* @param cleanupPatterns Cleanup patterns to remove from the stack
|
|
185
|
+
* @returns The cleaned stack
|
|
186
|
+
*/
|
|
187
|
+
function anonymizeFilePaths(stack: string, cleanupPatterns: RegExp[]): string {
|
|
188
|
+
|
|
189
|
+
// Fast check to see if it is a file path to avoid doing unnecessary heavy regex work
|
|
190
|
+
if (!stack || (!stack.includes('/') && !stack.includes('\\'))) {
|
|
191
|
+
return stack;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
let updatedStack = stack;
|
|
195
|
+
|
|
196
|
+
const cleanUpIndexes: [number, number][] = [];
|
|
197
|
+
for (const regexp of cleanupPatterns) {
|
|
198
|
+
while (true) {
|
|
199
|
+
const result = regexp.exec(stack);
|
|
200
|
+
if (!result) {
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
cleanUpIndexes.push([result.index, regexp.lastIndex]);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const nodeModulesRegex = /^[\\\/]?(node_modules|node_modules\.asar)[\\\/]/;
|
|
208
|
+
const fileRegex = /(file:\/\/)?([a-zA-Z]:(\\\\|\\|\/)|(\\\\|\\|\/))?([\w-\._]+(\\\\|\\|\/))+[\w-\._]*/g;
|
|
209
|
+
let lastIndex = 0;
|
|
210
|
+
updatedStack = '';
|
|
211
|
+
|
|
212
|
+
while (true) {
|
|
213
|
+
const result = fileRegex.exec(stack);
|
|
214
|
+
if (!result) {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// Check to see if the any cleanupIndexes partially overlap with this match
|
|
219
|
+
const overlappingRange = cleanUpIndexes.some(([start, end]) => result.index < end && start < fileRegex.lastIndex);
|
|
220
|
+
|
|
221
|
+
// anonymize user file paths that do not need to be retained or cleaned up.
|
|
222
|
+
if (!nodeModulesRegex.test(result[0]) && !overlappingRange) {
|
|
223
|
+
updatedStack += stack.substring(lastIndex, result.index) + '<REDACTED: user-file-path>';
|
|
224
|
+
lastIndex = fileRegex.lastIndex;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if (lastIndex < stack.length) {
|
|
228
|
+
updatedStack += stack.substr(lastIndex);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return updatedStack;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Attempts to remove commonly leaked PII
|
|
236
|
+
* @param property The property which will be removed if it contains user data
|
|
237
|
+
* @returns The new value for the property
|
|
238
|
+
*/
|
|
239
|
+
function removePropertiesWithPossibleUserInfo(property: string): string {
|
|
240
|
+
// If for some reason it is undefined we skip it (this shouldn't be possible);
|
|
241
|
+
if (!property) {
|
|
242
|
+
return property;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
const value = property.toLowerCase();
|
|
246
|
+
|
|
247
|
+
const userDataRegexes = [
|
|
248
|
+
{ label: 'Google API Key', regex: /AIza[0-9A-Za-z-_]{35}/ },
|
|
249
|
+
{ label: 'Slack Token', regex: /xox[pbar]\-[A-Za-z0-9]/ },
|
|
250
|
+
{ label: 'Generic Secret', regex: /(key|token|sig|secret|signature|password|passwd|pwd|android:value)[^a-zA-Z0-9]/ },
|
|
251
|
+
{ label: 'Email', regex: /@[a-zA-Z0-9-]+\.[a-zA-Z0-9-]+/ } // Regex which matches @*.site
|
|
252
|
+
];
|
|
253
|
+
|
|
254
|
+
// Check for common user data in the telemetry events
|
|
255
|
+
for (const secretRegex of userDataRegexes) {
|
|
256
|
+
if (secretRegex.regex.test(value)) {
|
|
257
|
+
return `<REDACTED: ${secretRegex.label}>`;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return property;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Does a best possible effort to clean a data object from any possible PII.
|
|
266
|
+
* @param data The data object to clean
|
|
267
|
+
* @param paths Any additional patterns that should be removed from the data set
|
|
268
|
+
* @returns A new object with the PII removed
|
|
269
|
+
*/
|
|
270
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
271
|
+
export function cleanData(data: Record<string, any>, cleanUpPatterns: RegExp[]): Record<string, any> {
|
|
272
|
+
return cloneAndChange(data, value => {
|
|
273
|
+
|
|
274
|
+
// If it's a trusted value it means it's okay to skip cleaning so we don't clean it
|
|
275
|
+
if (value instanceof TelemetryTrustedValue) {
|
|
276
|
+
return value.value;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// We only know how to clean strings
|
|
280
|
+
if (typeof value === 'string') {
|
|
281
|
+
let updatedProperty = value.replace(/%20/g, ' ');
|
|
282
|
+
|
|
283
|
+
// First we anonymize any possible file paths
|
|
284
|
+
updatedProperty = anonymizeFilePaths(updatedProperty, cleanUpPatterns);
|
|
285
|
+
|
|
286
|
+
// Then we do a simple regex replace with the defined patterns
|
|
287
|
+
for (const regexp of cleanUpPatterns) {
|
|
288
|
+
updatedProperty = updatedProperty.replace(regexp, '');
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Lastly, remove commonly leaked PII
|
|
292
|
+
updatedProperty = removePropertiesWithPossibleUserInfo(updatedProperty);
|
|
293
|
+
|
|
294
|
+
return updatedProperty;
|
|
295
|
+
}
|
|
296
|
+
return undefined;
|
|
297
|
+
}, new Set());
|
|
298
|
+
}
|
|
299
|
+
|
|
@@ -246,6 +246,11 @@ export class TerminalServiceExtImpl implements TerminalServiceExt {
|
|
|
246
246
|
});
|
|
247
247
|
}
|
|
248
248
|
|
|
249
|
+
/** @stubbed */
|
|
250
|
+
registerTerminalQuickFixProvider(id: string, provider: theia.TerminalQuickFixProvider): theia.Disposable {
|
|
251
|
+
return Disposable.NULL;
|
|
252
|
+
}
|
|
253
|
+
|
|
249
254
|
protected isExtensionTerminalOptions(options: theia.TerminalOptions | theia.ExtensionTerminalOptions): options is theia.ExtensionTerminalOptions {
|
|
250
255
|
return 'pty' in options;
|
|
251
256
|
}
|
|
@@ -234,7 +234,7 @@ class TreeViewExtImpl<T> implements Disposable {
|
|
|
234
234
|
// make copies of optionally provided MIME types:
|
|
235
235
|
const dragMimeTypes = options.dragAndDropController?.dragMimeTypes?.slice();
|
|
236
236
|
const dropMimeTypes = options.dragAndDropController?.dropMimeTypes?.slice();
|
|
237
|
-
proxy.$registerTreeDataProvider(treeViewId, { canSelectMany: options.canSelectMany, dragMimeTypes, dropMimeTypes });
|
|
237
|
+
proxy.$registerTreeDataProvider(treeViewId, { showCollapseAll: options.showCollapseAll, canSelectMany: options.canSelectMany, dragMimeTypes, dropMimeTypes });
|
|
238
238
|
this.toDispose.push(Disposable.create(() => this.proxy.$unregisterTreeDataProvider(treeViewId)));
|
|
239
239
|
options.treeDataProvider.onDidChangeTreeData?.(() => {
|
|
240
240
|
this.pendingRefresh = proxy.$refresh(treeViewId);
|
|
@@ -247,11 +247,14 @@ class TreeViewExtImpl<T> implements Disposable {
|
|
|
247
247
|
|
|
248
248
|
async reveal(element: T, options?: Partial<TreeViewRevealOptions>): Promise<void> {
|
|
249
249
|
await this.pendingRefresh;
|
|
250
|
+
const select = options?.select !== false; // default to true
|
|
251
|
+
const focus = !!options?.focus;
|
|
252
|
+
const expand = typeof options?.expand === 'undefined' ? false : options!.expand;
|
|
250
253
|
|
|
251
254
|
const elementParentChain = await this.calculateRevealParentChain(element);
|
|
252
255
|
if (elementParentChain) {
|
|
253
256
|
return this.proxy.$reveal(this.treeViewId, elementParentChain, {
|
|
254
|
-
select
|
|
257
|
+
select, focus, expand, ...options
|
|
255
258
|
});
|
|
256
259
|
}
|
|
257
260
|
}
|
|
@@ -308,37 +311,16 @@ class TreeViewExtImpl<T> implements Disposable {
|
|
|
308
311
|
*
|
|
309
312
|
* @param element element to reveal
|
|
310
313
|
*/
|
|
311
|
-
private async calculateRevealParentChain(element: T | undefined): Promise<string[]
|
|
314
|
+
private async calculateRevealParentChain(element: T | undefined): Promise<string[]> {
|
|
312
315
|
if (!element) {
|
|
313
316
|
// root
|
|
314
317
|
return [];
|
|
315
318
|
}
|
|
316
319
|
const parent = await this.options.treeDataProvider.getParent?.(element) ?? undefined;
|
|
317
320
|
const chain = await this.calculateRevealParentChain(parent);
|
|
318
|
-
if (!chain) {
|
|
319
|
-
// parents are inconsistent
|
|
320
|
-
return undefined;
|
|
321
|
-
}
|
|
322
321
|
const parentId = chain.length ? chain[chain.length - 1] : '';
|
|
323
322
|
const treeItem = await this.options.treeDataProvider.getTreeItem(element);
|
|
324
|
-
|
|
325
|
-
return chain.concat(treeItem.id);
|
|
326
|
-
}
|
|
327
|
-
const cachedParentNode = this.nodes.get(parentId);
|
|
328
|
-
// first try to get children length from cache since getChildren disposes old nodes, which can cause a race
|
|
329
|
-
// condition if command is executed together with reveal.
|
|
330
|
-
// If not in cache, getChildren fills this.nodes and generate ids for them which are needed later
|
|
331
|
-
const children = cachedParentNode?.children || await this.getChildren(parentId);
|
|
332
|
-
if (!children) {
|
|
333
|
-
// parent is inconsistent
|
|
334
|
-
return undefined;
|
|
335
|
-
}
|
|
336
|
-
const candidateId = this.buildTreeItemId(parentId, treeItem, false);
|
|
337
|
-
if (this.nodes.has(candidateId)) {
|
|
338
|
-
return chain.concat(candidateId);
|
|
339
|
-
}
|
|
340
|
-
// couldn't calculate consistent parent chain and id
|
|
341
|
-
return undefined;
|
|
323
|
+
return chain.concat(this.buildTreeItemId(parentId, treeItem, false));
|
|
342
324
|
}
|
|
343
325
|
|
|
344
326
|
private getTreeItemLabel(treeItem: TreeItem): string | undefined {
|
package/src/plugin/types-impl.ts
CHANGED
|
@@ -229,6 +229,13 @@ export enum SourceControlInputBoxValidationType {
|
|
|
229
229
|
Information = 2
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
+
export enum ExternalUriOpenerPriority {
|
|
233
|
+
None = 0,
|
|
234
|
+
Option = 1,
|
|
235
|
+
Default = 2,
|
|
236
|
+
Preferred = 3,
|
|
237
|
+
}
|
|
238
|
+
|
|
232
239
|
@es5ClassCompat
|
|
233
240
|
export class ColorTheme implements theia.ColorTheme {
|
|
234
241
|
constructor(public readonly kind: ColorThemeKind) { }
|
|
@@ -2059,6 +2066,11 @@ export enum TerminalExitReason {
|
|
|
2059
2066
|
Extension = 4,
|
|
2060
2067
|
}
|
|
2061
2068
|
|
|
2069
|
+
export enum TerminalQuickFixType {
|
|
2070
|
+
command = 'command',
|
|
2071
|
+
opener = 'opener'
|
|
2072
|
+
}
|
|
2073
|
+
|
|
2062
2074
|
@es5ClassCompat
|
|
2063
2075
|
export class FileDecoration {
|
|
2064
2076
|
|
|
@@ -3413,6 +3425,54 @@ export class WebviewEditorTabInput {
|
|
|
3413
3425
|
constructor(readonly viewType: string) { }
|
|
3414
3426
|
}
|
|
3415
3427
|
|
|
3428
|
+
export class TelemetryTrustedValue<T> {
|
|
3429
|
+
readonly value: T;
|
|
3430
|
+
|
|
3431
|
+
constructor(value: T) {
|
|
3432
|
+
this.value = value;
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
|
|
3436
|
+
export class TelemetryLogger {
|
|
3437
|
+
readonly onDidChangeEnableStates: theia.Event<TelemetryLogger>;
|
|
3438
|
+
readonly isUsageEnabled: boolean;
|
|
3439
|
+
readonly isErrorsEnabled: boolean;
|
|
3440
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3441
|
+
logUsage(eventName: string, data?: Record<string, any | TelemetryTrustedValue<any>>): void { }
|
|
3442
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3443
|
+
logError(eventNameOrError: string | Error, data?: Record<string, any | TelemetryTrustedValue<any>>): void { }
|
|
3444
|
+
dispose(): void { }
|
|
3445
|
+
constructor(readonly sender: TelemetrySender, readonly options?: TelemetryLoggerOptions) { }
|
|
3446
|
+
}
|
|
3447
|
+
|
|
3448
|
+
export interface TelemetrySender {
|
|
3449
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3450
|
+
sendEventData(eventName: string, data?: Record<string, any>): void;
|
|
3451
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3452
|
+
sendErrorData(error: Error, data?: Record<string, any>): void;
|
|
3453
|
+
flush?(): void | Thenable<void>;
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3456
|
+
export interface TelemetryLoggerOptions {
|
|
3457
|
+
/**
|
|
3458
|
+
* Whether or not you want to avoid having the built-in common properties such as os, extension name, etc injected into the data object.
|
|
3459
|
+
* Defaults to `false` if not defined.
|
|
3460
|
+
*/
|
|
3461
|
+
readonly ignoreBuiltInCommonProperties?: boolean;
|
|
3462
|
+
|
|
3463
|
+
/**
|
|
3464
|
+
* Whether or not unhandled errors on the extension host caused by your extension should be logged to your sender.
|
|
3465
|
+
* Defaults to `false` if not defined.
|
|
3466
|
+
*/
|
|
3467
|
+
readonly ignoreUnhandledErrors?: boolean;
|
|
3468
|
+
|
|
3469
|
+
/**
|
|
3470
|
+
* Any additional common properties which should be injected into the data object.
|
|
3471
|
+
*/
|
|
3472
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
3473
|
+
readonly additionalCommonProperties?: Record<string, any>;
|
|
3474
|
+
}
|
|
3475
|
+
|
|
3416
3476
|
export class NotebookEditorTabInput {
|
|
3417
3477
|
constructor(readonly uri: URI, readonly notebookType: string) { }
|
|
3418
3478
|
}
|
|
@@ -3429,3 +3489,22 @@ export class InteractiveWindowInput {
|
|
|
3429
3489
|
}
|
|
3430
3490
|
|
|
3431
3491
|
// #endregion
|
|
3492
|
+
|
|
3493
|
+
// #region DocumentPaste
|
|
3494
|
+
@es5ClassCompat
|
|
3495
|
+
export class DocumentPasteEdit {
|
|
3496
|
+
constructor(insertText: string | SnippetString) {
|
|
3497
|
+
this.insertText = insertText;
|
|
3498
|
+
}
|
|
3499
|
+
insertText: string | SnippetString;
|
|
3500
|
+
additionalEdit?: WorkspaceEdit;
|
|
3501
|
+
}
|
|
3502
|
+
// #endregion
|
|
3503
|
+
|
|
3504
|
+
// #region DocumentPaste
|
|
3505
|
+
export enum EditSessionIdentityMatch {
|
|
3506
|
+
Complete = 100,
|
|
3507
|
+
Partial = 50,
|
|
3508
|
+
None = 0
|
|
3509
|
+
}
|
|
3510
|
+
// #endregion
|
package/src/plugin/workspace.ts
CHANGED
|
@@ -34,7 +34,7 @@ import { Path } from '@theia/core/lib/common/path';
|
|
|
34
34
|
import { RPCProtocol } from '../common/rpc-protocol';
|
|
35
35
|
import { WorkspaceRootsChangeEvent, SearchInWorkspaceResult, Range } from '../common/plugin-api-rpc-model';
|
|
36
36
|
import { EditorsAndDocumentsExtImpl } from './editors-and-documents';
|
|
37
|
-
import { URI } from './types-impl';
|
|
37
|
+
import { Disposable, URI } from './types-impl';
|
|
38
38
|
import { normalize } from '@theia/core/lib/common/paths';
|
|
39
39
|
import { relative } from '../common/paths-util';
|
|
40
40
|
import { Schemes } from '../common/uri-components';
|
|
@@ -449,4 +449,9 @@ export class WorkspaceExtImpl implements WorkspaceExt {
|
|
|
449
449
|
}
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
+
/** @stubbed */
|
|
453
|
+
$registerEditSessionIdentityProvider(scheme: string, provider: theia.EditSessionIdentityProvider): theia.Disposable {
|
|
454
|
+
return Disposable.NULL;
|
|
455
|
+
}
|
|
456
|
+
|
|
452
457
|
}
|